diff --git a/src/main/java/com/samskivert/mustache/Mustache.java b/src/main/java/com/samskivert/mustache/Mustache.java index d8715b4..125db0f 100644 --- a/src/main/java/com/samskivert/mustache/Mustache.java +++ b/src/main/java/com/samskivert/mustache/Mustache.java @@ -54,6 +54,10 @@ public class Mustache * mustache implementation. Default is false. */ public final boolean emptyStringIsFalse; + /** If this value is true, zero will be treated as a false value, as in JavaScript + * mustache implementation. Default is false. */ + public final boolean zeroIsFalse; + /** The template loader in use during this compilation. */ public final TemplateLoader loader; @@ -76,7 +80,7 @@ public class Mustache /** Returns a compiler that either does or does not escape HTML by default. */ public Compiler escapeHTML (boolean escapeHTML) { return new Compiler(escapeHTML, this.standardsMode, this.nullValue, this.missingIsNull, - this.emptyStringIsFalse, this.loader, this.collector, this.delims); + this.emptyStringIsFalse, this.zeroIsFalse, this.loader, this.collector, this.delims); } /** Returns a compiler that either does or does not use standards mode. Standards mode @@ -84,7 +88,7 @@ public class Mustache * context. */ public Compiler standardsMode (boolean standardsMode) { return new Compiler(this.escapeHTML, standardsMode, this.nullValue, this.missingIsNull, - this.emptyStringIsFalse, this.loader, this.collector, this.delims); + this.emptyStringIsFalse, this.zeroIsFalse, this.loader, this.collector, this.delims); } /** Returns a compiler that will use the given value for any variable that is missing, or @@ -92,7 +96,7 @@ public class Mustache * supplied default for missing keys and existing keys that return null values. */ public Compiler defaultValue (String defaultValue) { return new Compiler(this.escapeHTML, this.standardsMode, defaultValue, true, - this.emptyStringIsFalse, this.loader, this.collector, this.delims); + this.emptyStringIsFalse, this.zeroIsFalse, this.loader, this.collector, this.delims); } /** Returns a compiler that will use the given value for any variable that resolves to @@ -108,27 +112,34 @@ public class Mustache * */ public Compiler nullValue (String nullValue) { return new Compiler(this.escapeHTML, this.standardsMode, nullValue, false, - this.emptyStringIsFalse, this.loader, this.collector, this.delims); + this.emptyStringIsFalse, this.zeroIsFalse, this.loader, this.collector, this.delims); } /** Returns a compiler that will treat empty string as a false value if parameter is true. */ public Compiler emptyStringIsFalse (boolean emptyStringIsFalse) { return new Compiler(this.escapeHTML, this.standardsMode, this.nullValue, - this.missingIsNull, emptyStringIsFalse, this.loader, this.collector, + this.missingIsNull, emptyStringIsFalse, this.zeroIsFalse, this.loader, this.collector, + this.delims); + } + + /** Returns a compiler that will treat zero as a false value if parameter is true. */ + public Compiler zeroIsFalse (boolean zeroIsFalse) { + return new Compiler(this.escapeHTML, this.standardsMode, this.nullValue, + this.missingIsNull, this.emptyStringIsFalse, zeroIsFalse, this.loader, this.collector, this.delims); } /** Returns a compiler configured to use the supplied template loader to handle partials. */ public Compiler withLoader (TemplateLoader loader) { return new Compiler(this.escapeHTML, this.standardsMode, this.nullValue, - this.missingIsNull, this.emptyStringIsFalse, loader, this.collector, + this.missingIsNull, this.emptyStringIsFalse, this.zeroIsFalse, loader, this.collector, this.delims); } /** Returns a compiler configured to use the supplied collector. */ public Compiler withCollector (Collector collector) { return new Compiler(this.escapeHTML, this.standardsMode, this.nullValue, - this.missingIsNull, this.emptyStringIsFalse, this.loader, collector, + this.missingIsNull, this.emptyStringIsFalse, this.zeroIsFalse, this.loader, collector, this.delims); } @@ -137,7 +148,7 @@ public class Mustache * opening delims and C and D are closing delims. */ public Compiler withDelims (String delims) { return new Compiler(this.escapeHTML, this.standardsMode, this.nullValue, - this.missingIsNull, this.emptyStringIsFalse, this.loader, + this.missingIsNull, this.emptyStringIsFalse, this.zeroIsFalse, this.loader, this.collector, new Delims().updateDelims(delims)); } @@ -148,13 +159,14 @@ public class Mustache } protected Compiler (boolean escapeHTML, boolean standardsMode, String nullValue, - boolean missingIsNull, boolean emptyStringIsFalse, TemplateLoader loader, + boolean missingIsNull, boolean emptyStringIsFalse, boolean zeroIsFalse, TemplateLoader loader, Collector collector, Delims delims) { this.escapeHTML = escapeHTML; this.standardsMode = standardsMode; this.nullValue = nullValue; this.missingIsNull = missingIsNull; this.emptyStringIsFalse = emptyStringIsFalse; + this.zeroIsFalse = zeroIsFalse; this.loader = loader; this.collector = collector; this.delims = delims; @@ -210,7 +222,7 @@ public class Mustache * Returns a compiler that escapes HTML by default and does not use standards mode. */ public static Compiler compiler () { - return new Compiler(true, false, null, true, false, FAILING_LOADER, new DefaultCollector(), + return new Compiler(true, false, null, true, false, false, FAILING_LOADER, new DefaultCollector(), new Delims()); } @@ -698,6 +710,8 @@ public class Mustache } } else if (_compiler.emptyStringIsFalse && "".equals(value)) { // omit the section + } else if (value != null && value instanceof Number && ((Number) value).longValue() == 0) { + // omit the section } else { executeSegs(tmpl, ctx.nest(value, 0, false, false), out); } diff --git a/src/test/java/com/samskivert/mustache/MustacheTest.java b/src/test/java/com/samskivert/mustache/MustacheTest.java index 4908684..ac6eda5 100644 --- a/src/test/java/com/samskivert/mustache/MustacheTest.java +++ b/src/test/java/com/samskivert/mustache/MustacheTest.java @@ -145,6 +145,30 @@ public class MustacheTest }); } + @Test public void testSectionWithLongValueZero () { + test(Mustache.compiler().zeroIsFalse(true), "", "{{#foo}}test{{/foo}}", new Object() { + Long foo = 0L; + }); + } + + @Test public void testSectionWithIntegerValueZero () { + test(Mustache.compiler().zeroIsFalse(true), "", "{{#foo}}test{{/foo}}", new Object() { + Integer foo = 0; + }); + } + + @Test public void testSectionWithFloatValueZero () { + test(Mustache.compiler().zeroIsFalse(true), "", "{{#foo}}test{{/foo}}", new Object() { + Float foo = 0F; + }); + } + + @Test public void testSectionWithDoubleValueZero () { + test(Mustache.compiler().zeroIsFalse(true), "", "{{#foo}}test{{/foo}}", new Object() { + Double foo = 0D; + }); + } + @Test public void testMissingSection () { test("", "{{#foo}}{{bar}}{{/foo}}", new Object() { // no foo