diff --git a/examples/comments.js b/examples/comments.js index bcf196d..f85f979 100644 --- a/examples/comments.js +++ b/examples/comments.js @@ -2,4 +2,4 @@ var comments = { title: function() { return "A Comedy of Errors"; } -}; \ No newline at end of file +}; diff --git a/examples/escaped.rb b/examples/escaped.rb deleted file mode 100644 index d3b3010..0000000 --- a/examples/escaped.rb +++ /dev/null @@ -1,14 +0,0 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' -require 'mustache' - -class Escaped < Mustache - self.path = File.dirname(__FILE__) - - def title - "Bear > Shark" - end -end - -if $0 == __FILE__ - puts Escaped.to_html -end diff --git a/examples/inner_partial.html b/examples/inner_partial.html deleted file mode 100644 index 2863764..0000000 --- a/examples/inner_partial.html +++ /dev/null @@ -1 +0,0 @@ -Again, {{title}}! \ No newline at end of file diff --git a/examples/simple.rb b/examples/simple.rb deleted file mode 100644 index 8072466..0000000 --- a/examples/simple.rb +++ /dev/null @@ -1,26 +0,0 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' -require 'mustache' - -class Simple < Mustache - self.path = File.dirname(__FILE__) - - def name - "Chris" - end - - def value - 10_000 - end - - def taxed_value - value - (value * 0.4) - end - - def in_ca - true - end -end - -if $0 == __FILE__ - puts Simple.to_html -end diff --git a/examples/template_partial.js b/examples/template_partial.js new file mode 100644 index 0000000..ce2287e --- /dev/null +++ b/examples/template_partial.js @@ -0,0 +1,7 @@ +var template_partial = { + title: function() { + return "Welcome"; + } +} + +var inner_partial = "Again, {{title}}!"; \ No newline at end of file diff --git a/examples/template_partial.rb b/examples/template_partial.rb deleted file mode 100644 index 572a58b..0000000 --- a/examples/template_partial.rb +++ /dev/null @@ -1,14 +0,0 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' -require 'mustache' - -class TemplatePartial < Mustache - self.path = File.dirname(__FILE__) - - def title - "Welcome" - end -end - -if $0 == __FILE__ - puts TemplatePartial.to_html -end diff --git a/examples/template_partial.txt b/examples/template_partial.txt new file mode 100644 index 0000000..62321ae --- /dev/null +++ b/examples/template_partial.txt @@ -0,0 +1,2 @@ +

Welcome

+Again, Welcome! diff --git a/examples/unescaped.rb b/examples/unescaped.rb deleted file mode 100644 index 538ada8..0000000 --- a/examples/unescaped.rb +++ /dev/null @@ -1,14 +0,0 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' -require 'mustache' - -class Unescaped < Mustache - self.path = File.dirname(__FILE__) - - def title - "Bear > Shark" - end -end - -if $0 == __FILE__ - puts Unescaped.to_html -end diff --git a/examples/view_partial.js b/examples/view_partial.js new file mode 100644 index 0000000..ea7e505 --- /dev/null +++ b/examples/view_partial.js @@ -0,0 +1,24 @@ +var view_partial = { + greeting: function() { + return "Welcome"; + }, + + farewell: function() { + return "Fair enough, right?"; + } +}; + +var simple = { + name: "Chris", + value: 10000, + taxed_value: function() { + return this.value - (this.value * 0.4); + }, + in_ca: true +}; + +var simple_template = "Hello {{name}}\n" + +"You have just won ${{value}}!\n" + +"{{#in_ca}}\n" + +"Well, ${{ taxed_value }}, after taxes.\n" + +"{{/in_ca}}\n"; diff --git a/examples/view_partial.rb b/examples/view_partial.rb deleted file mode 100644 index 4decbaa..0000000 --- a/examples/view_partial.rb +++ /dev/null @@ -1,18 +0,0 @@ -$LOAD_PATH.unshift File.dirname(__FILE__) + '/../lib' -require 'mustache' - -class ViewPartial < Mustache - self.path = File.dirname(__FILE__) - - def greeting - "Welcome" - end - - def farewell - "Fair enough, right?" - end -end - -if $0 == __FILE__ - puts ViewPartial.to_html -end diff --git a/examples/view_partial.txt b/examples/view_partial.txt new file mode 100644 index 0000000..160b0b6 --- /dev/null +++ b/examples/view_partial.txt @@ -0,0 +1,6 @@ +

Welcome

+Hello Chris +You have just won $10000! +Well, $6000, after taxes. + +

Fair enough, right?

diff --git a/mustache.js b/mustache.js index f310d89..33012ee 100644 --- a/mustache.js +++ b/mustache.js @@ -3,7 +3,7 @@ by Jan Lehnardt Thanks @defunkt for the awesome code - TBD: License + TBD: MIT, see LICENSE ChangeLog: - 04.10.2009: Ininitial port at http://devhouseberlin.de/ @@ -16,7 +16,7 @@ var Mustache = { debug: true, stack: " ", context: {}, - to_html: function(view, template) { + to_html: function(template, view) { return this.render(template, view); }, @@ -29,10 +29,23 @@ var Mustache = { this.context = context = this.merge((this.context || {}), view); var html = this.render_section(template); // restore context, recursion might have messed it up - // this.context = context; + this.context = context; return this.render_tags(html); }, + render_partial: function(name) { + var evil_name = eval(name) + switch(typeof evil_name) { + case "string": + return this.to_html(evil_name, ""); + case "object": + var tpl = name + "_template"; + return this.to_html(eval(tpl), evil_name); + default: + throw("Unknown partial type."); + } + }, + merge: function(a, b) { for(var name in b) { if(b.hasOwnProperty(name)) { @@ -47,11 +60,8 @@ var Mustache = { return template; } var that = this; - return template.replace(/\{\{\#(.+)\}\}\s*(.+)\s*\{\{\/\1\}\}\s*/mg, + return template.replace(/\{\{\#(.+)\}\}\s*([\s\S]+)\{\{\/\1\}\}\s*/mg, function(match, name, content) { - print(match); - print(name); - print(content); var value = that.find(name); if(that.is_array(value)) { return value.map(function(row) { @@ -65,10 +75,10 @@ var Mustache = { } ); }, - + is_array: function(a) { - return (a && - typeof a === 'object' && + return (a && + typeof a === 'object' && a.constructor === Array); }, @@ -77,18 +87,30 @@ var Mustache = { var that = this; return template.replace(/\{\{(!|<|\{)?([^\/#]+?)\1?\}\}+/mg, function (match, operator, name) { - switch(operator) { - case "!": // ignore comments - return match; - // TODO: partials - // case "<": // render partial - // return this.render_partial() - case '{': // the triple mustache is unescaped - return that.find(name); - default: // escape the value - return that.find(name); + switch(operator) { + case "!": // ignore comments + return match; + case "<": // render partial + return that.render_partial(name); + case '{': // the triple mustache is unescaped + return that.find(name); + default: // escape the value + return that.escape(that.find(name)); + } + }, this); + }, + + escape: function(s) { + return s.toString().replace(/[&"<>\\]/g, function(s) { + switch(s) { + case "&": return "&"; + case "\\": return "\\\\";; + case '"': return '\"';; + case "<": return "<"; + case ">": return ">"; + default: return s; } - }, this); + }); }, find: function(name) { diff --git a/runner.js b/runner.js index 81c628d..9a17c2c 100644 --- a/runner.js +++ b/runner.js @@ -3,7 +3,7 @@ by Jan Lehnardt Thanks @defunkt for the awesome code - TBD: License + TBD: MIT, see LICENSE ChangeLog: - 04.10.2009: Ininitial port at http://devhouseberlin.de/ @@ -16,7 +16,7 @@ var Mustache = { debug: true, stack: " ", context: {}, - to_html: function(view, template) { + to_html: function(template, view) { return this.render(template, view); }, @@ -29,10 +29,23 @@ var Mustache = { this.context = context = this.merge((this.context || {}), view); var html = this.render_section(template); // restore context, recursion might have messed it up - // this.context = context; + this.context = context; return this.render_tags(html); }, + render_partial: function(name) { + var evil_name = eval(name) + switch(typeof evil_name) { + case "string": + return this.to_html(evil_name, ""); + case "object": + var tpl = name + "_template"; + return this.to_html(eval(tpl), evil_name); + default: + throw("Unknown partial type."); + } + }, + merge: function(a, b) { for(var name in b) { if(b.hasOwnProperty(name)) { @@ -47,11 +60,8 @@ var Mustache = { return template; } var that = this; - return template.replace(/\{\{\#(.+)\}\}\s*(.+)\s*\{\{\/\1\}\}\s*/mg, + return template.replace(/\{\{\#(.+)\}\}\s*([\s\S]+)\{\{\/\1\}\}\s*/mg, function(match, name, content) { - print(match); - print(name); - print(content); var value = that.find(name); if(that.is_array(value)) { return value.map(function(row) { @@ -65,10 +75,10 @@ var Mustache = { } ); }, - + is_array: function(a) { - return (a && - typeof a === 'object' && + return (a && + typeof a === 'object' && a.constructor === Array); }, @@ -77,18 +87,30 @@ var Mustache = { var that = this; return template.replace(/\{\{(!|<|\{)?([^\/#]+?)\1?\}\}+/mg, function (match, operator, name) { - switch(operator) { - case "!": // ignore comments - return match; - // TODO: partials - // case "<": // render partial - // return this.render_partial() - case '{': // the triple mustache is unescaped - return that.find(name); - default: // escape the value - return that.find(name); + switch(operator) { + case "!": // ignore comments + return match; + case "<": // render partial + return that.render_partial(name); + case '{': // the triple mustache is unescaped + return that.find(name); + default: // escape the value + return that.escape(that.find(name)); + } + }, this); + }, + + escape: function(s) { + return s.toString().replace(/[&"<>\\]/g, function(s) { + switch(s) { + case "&": return "&"; + case "\\": return "\\\\";; + case '"': return '\"';; + case "<": return "<"; + case ">": return ">"; + default: return s; } - }, this); + }); }, find: function(name) { @@ -109,32 +131,31 @@ var Mustache = { }, }; -var complex = { - header: function() { - return "Colors"; +var view_partial = { + greeting: function() { + return "Welcome"; }, - item: [ - {name: "red", current: true, url: "#Red"}, - {name: "green", current: false, url: "#Green"}, - {name: "blue", current: false, url: "#Blue"} - ], - link: function() { - var v = this["current"] === true; - // print("link() returns " + v); - return v; - }, - list: function() { - var v = this.item.length !== 0; - // print("list() returns " + v); - return v; - }, - empty: function() { - var v = this.item.length === 0; - // print("empty() returns " + v); - return v; + + farewell: function() { + return "Fair enough, right?"; } }; -var template = "

{{header}}<\/h1>\n{{#list}}\n