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");
};