diff --git a/src/main/gwt/com/samskivert/super/java/io/Writer.java b/src/main/gwt/com/samskivert/super/java/io/Writer.java index e9cd6df..c399fe6 100644 --- a/src/main/gwt/com/samskivert/super/java/io/Writer.java +++ b/src/main/gwt/com/samskivert/super/java/io/Writer.java @@ -9,4 +9,6 @@ package java.io; public abstract class Writer { public abstract void write (String text) throws IOException; + + public abstract Writer append (CharSequence text) throws IOException; } diff --git a/src/main/java/com/samskivert/mustache/Mustache.java b/src/main/java/com/samskivert/mustache/Mustache.java index 6a2b3b0..0b3525a 100644 --- a/src/main/java/com/samskivert/mustache/Mustache.java +++ b/src/main/java/com/samskivert/mustache/Mustache.java @@ -207,10 +207,25 @@ public class Mustache { * then empty strings are considered falsey. If {@link #zeroIsFalse} is true, then zero * values are considered falsey. */ public boolean isFalsey (Object value) { - return ((emptyStringIsFalse && "".equals(formatter.format(value))) || + return ((emptyStringIsFalse && isEmptyCharSequence(formatter.format(value))) || (zeroIsFalse && (value instanceof Number) && ((Number)value).longValue() == 0)); } + /** + * Replaces "".equals(value). E.g. only not null values with length 0 + */ + private boolean isEmptyCharSequence(Object value) { + if (value == null) { + return false; + } + + if(value instanceof CharSequence) { + return ((CharSequence) value).length() == 0; + } + + return false; + } + /** Loads and compiles the template {@code name} using this compiler's configured template * loader. Note that this does no caching: the caller should cache the loaded template if * they expect to use it multiple times. @@ -259,8 +274,8 @@ public class Mustache { /** Handles converting objects to strings when rendering templates. */ public interface Formatter { - /** Converts {@code value} to a string for inclusion in a template. */ - String format (Object value); + /** Converts {@code value} to a CharSequence for inclusion in a template. */ + CharSequence format (Object value); } /** Handles lambdas. */ @@ -299,6 +314,11 @@ public class Mustache { /** Returns {@code raw} with the appropriate characters replaced with escape sequences. */ String escape (String raw); + + /** Returns {@code raw} with the appropriate characters replaced with escape sequences. **/ + default CharSequence escape (CharSequence raw) { + return escape(raw.toString()); + } } /** Handles loading partial templates. */ diff --git a/src/main/java/com/samskivert/mustache/Template.java b/src/main/java/com/samskivert/mustache/Template.java index bae9935..4dfc520 100644 --- a/src/main/java/com/samskivert/mustache/Template.java +++ b/src/main/java/com/samskivert/mustache/Template.java @@ -384,9 +384,9 @@ public class Template { abstract void visit (Mustache.Visitor visitor); - protected static void write (Writer out, String data) { + protected static void write (Writer out, CharSequence data) { try { - out.write(data); + out.append(data); } catch (IOException ioe) { throw new MustacheException(ioe); } diff --git a/src/test/java/com/samskivert/mustache/MustacheTest.java b/src/test/java/com/samskivert/mustache/MustacheTest.java index cb1b208..d2a2f23 100644 --- a/src/test/java/com/samskivert/mustache/MustacheTest.java +++ b/src/test/java/com/samskivert/mustache/MustacheTest.java @@ -17,9 +17,6 @@ import java.util.Optional; import java.util.TimeZone; import org.junit.Test; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertTrue; -import static org.junit.Assert.fail; /** * Mustache tests that can only be run on the JVM. Most tests should go in BaseMustacheTest so @@ -54,6 +51,14 @@ public class MustacheTest extends SharedTests }); } + @Test public void testCharSequenceVariable() { + Map ctx = new HashMap<>(); + StringBuffer stringBuffer = new StringBuffer(); + stringBuffer.append("bar"); + ctx.put("foo", stringBuffer); + test("bar", "{{foo}}", ctx); + } + public interface HasDefault { default String getFoo () { return "bar"; } }