diff --git a/CHANGES.md b/CHANGES.md index 6785339..a4c113c 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -2,6 +2,7 @@ ## 0.3.0 (??-??-????) +* Added inverted sections. * Avoid double encoding of entities. * Use sections to dereference subcontexts. * Added higher order sections. diff --git a/README.md b/README.md index cfca7be..43a2239 100644 --- a/README.md +++ b/README.md @@ -150,6 +150,27 @@ Here is the result: +### Inverted Sections + +An inverted section opens with `{{^section}}` instead of `{{#section}}` and uses a +boolean negative to evaluate. Empty arrays are considered falsy. + +View: + + var inverted_section = { + "repo": [] + } + +Template: + + {{#repo}}{{name}}{{/repo}} + {{^repo}}No repos :({{/repo}} + +Result: + + No repos :( + + ### View Partials mustache.js supports a quite powerful but yet simple view partial mechanism. Use the diff --git a/examples/inverted_section.html b/examples/inverted_section.html new file mode 100644 index 0000000..beec558 --- /dev/null +++ b/examples/inverted_section.html @@ -0,0 +1,2 @@ +{{#repo}}{{name}}{{/repo}} +{{^repo}}No repos :({{/repo}} diff --git a/examples/inverted_section.js b/examples/inverted_section.js new file mode 100644 index 0000000..cb96ecf --- /dev/null +++ b/examples/inverted_section.js @@ -0,0 +1,3 @@ +var inverted_section = { + "repo": [] +} diff --git a/examples/inverted_section.txt b/examples/inverted_section.txt new file mode 100644 index 0000000..5fd0de1 --- /dev/null +++ b/examples/inverted_section.txt @@ -0,0 +1 @@ +No repos :( diff --git a/mustache.js b/mustache.js index e0a361d..cc59bdd 100644 --- a/mustache.js +++ b/mustache.js @@ -93,35 +93,45 @@ var Mustache = function() { Renders inverted (^) and normal (#) sections */ render_section: function(template, context, partials) { - if(!this.includes("#", template)) { + if(!this.includes("#", template) && !this.includes("^", template)) { return template; } var that = this; // CSW - Added "+?" so it finds the tighest bound, not the widest - var regex = new RegExp(this.otag + "\\#(.+)" + this.ctag + - "\\s*([\\s\\S]+?)" + this.otag + "\\/\\1" + this.ctag + "\\s*", "mg"); + var regex = new RegExp(this.otag + "(\\^|\\#)(.+)" + this.ctag + + "\\s*([\\s\\S]+?)" + this.otag + "\\/\\2" + this.ctag + + "\\s*", "mg"); // for each {{#foo}}{{/foo}} section do... - return template.replace(regex, function(match, name, content) { + return template.replace(regex, function(match, type, name, content) { var value = that.find(name, context); - if(that.is_array(value)) { // Enumerable, Let's loop! - return that.map(value, function(row) { - return that.render(content, that.merge(context, - that.create_context(row)), partials, true); - }).join(""); - } else if(that.is_object(value)) { // Object, Use it as subcontext! - return that.render(content, - that.merge(context, that.create_context(value)), partials, true); - } else if(typeof value === "function") { - // higher order section - return value.call(context, content, function(text) { - return that.render(text, context, partials, true); - }) - } else if(value) { // boolean section - return that.render(content, context, partials, true); - } else { - return ""; + if(type == "^") { // inverted section + if(!value || that.is_array(value) && value.length == 0) { + // false or empty list, render it + return that.render(content, context, partials, true); + } else { + return ""; + } + } else if(type == "#") { // normal section + if(that.is_array(value)) { // Enumerable, Let's loop! + return that.map(value, function(row) { + return that.render(content, that.merge(context, + that.create_context(row)), partials, true); + }).join(""); + } else if(that.is_object(value)) { // Object, Use it as subcontext! + return that.render(content, + that.merge(context, that.create_context(value)), partials, true); + } else if(typeof value === "function") { + // higher order section + return value.call(context, content, function(text) { + return that.render(text, context, partials, true); + }) + } else if(value) { // boolean section + return that.render(content, context, partials, true); + } else { + return ""; + } } }); }, @@ -134,7 +144,7 @@ var Mustache = function() { var that = this; var new_regex = function() { - return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\/#]+?)\\1?" + + return new RegExp(that.otag + "(=|!|>|\\{|%)?([^\/#\^]+?)\\1?" + that.ctag + "+", "g"); };