From 5fc751219e9e99838b61a0ef4b3ea8f3bc3d80c7 Mon Sep 17 00:00:00 2001 From: Sean Scanlon Date: Sun, 27 Mar 2011 15:53:04 -0700 Subject: [PATCH] Add template loader hook for partials {{>template}} support. This is implemented so that by default, the library does not support template loading (which it already does not) but instead of treating partial calls as a context lookup for a ">key", an exception is thrown. --- .../com/samskivert/mustache/Mustache.java | 26 ++++++++++++++++++- .../mustache/MustacheTemplateLoader.java | 19 ++++++++++++++ .../mustache/UnsupportedTemplateLoader.java | 19 ++++++++++++++ .../com/samskivert/mustache/MustacheTest.java | 24 +++++++++++++++-- 4 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/samskivert/mustache/MustacheTemplateLoader.java create mode 100644 src/main/java/com/samskivert/mustache/UnsupportedTemplateLoader.java diff --git a/src/main/java/com/samskivert/mustache/Mustache.java b/src/main/java/com/samskivert/mustache/Mustache.java index 33df1f7..df5ee44 100644 --- a/src/main/java/com/samskivert/mustache/Mustache.java +++ b/src/main/java/com/samskivert/mustache/Mustache.java @@ -244,6 +244,12 @@ public class Mustache protected static final int MATCHING_END = 2; protected static final int TAG = 3; + private static MustacheTemplateLoader templateLoader = UnsupportedTemplateLoader.INSTANCE; + + public static void setTemplateLoader(MustacheTemplateLoader _templateLoader) { + templateLoader = _templateLoader; + } + protected static class Accumulator { public Accumulator (Compiler compiler) { _compiler = compiler; @@ -262,7 +268,7 @@ public class Mustache } } - public Accumulator addTagSegment (StringBuilder accum, final int tagLine) { + public Accumulator addTagSegment (final StringBuilder accum, final int tagLine) { final Accumulator outer = this; String tag = accum.toString().trim(); final String tag1 = tag.substring(1).trim(); @@ -287,6 +293,10 @@ public class Mustache } }; + case '>': + _segs.add(new IncludedTemplateSegment(tag1, _compiler)); + return this; + case '^': requireNoNewlines(tag, tagLine); return new Accumulator(_compiler) { @@ -364,6 +374,20 @@ public class Mustache protected final String _text; } + protected static class IncludedTemplateSegment extends Template.Segment { + public IncludedTemplateSegment (final String templateName, final Compiler compiler) { + try { + template = compiler.compile(templateLoader.getTemplate(templateName)); + } catch (Exception e) { + throw new IllegalArgumentException("unable to load " + templateName, e); + } + } + @Override public void execute (Template tmpl, Template.Context ctx, Writer out) { + template.execute(ctx.data, out); + } + private final Template template; + } + /** A helper class for named segments. */ protected static abstract class NamedSegment extends Template.Segment { protected NamedSegment (String name, int line) { diff --git a/src/main/java/com/samskivert/mustache/MustacheTemplateLoader.java b/src/main/java/com/samskivert/mustache/MustacheTemplateLoader.java new file mode 100644 index 0000000..81901bc --- /dev/null +++ b/src/main/java/com/samskivert/mustache/MustacheTemplateLoader.java @@ -0,0 +1,19 @@ +package com.samskivert.mustache; + +import java.io.Reader; + +/** + * + * @author Sean Scanlon + */ +public interface MustacheTemplateLoader { + + /** + * load a {@code Mustache} template from a given file. + * + * @param filename + * @return a string {@code Mustache} template + */ + public Reader getTemplate(String filename) throws Exception; + +} diff --git a/src/main/java/com/samskivert/mustache/UnsupportedTemplateLoader.java b/src/main/java/com/samskivert/mustache/UnsupportedTemplateLoader.java new file mode 100644 index 0000000..8b9e2d8 --- /dev/null +++ b/src/main/java/com/samskivert/mustache/UnsupportedTemplateLoader.java @@ -0,0 +1,19 @@ +package com.samskivert.mustache; + +import java.io.Reader; + +/** + * loading partials/other templates is not supported. in this {@link MustacheTemplateLoader} + * + * @author Sean Scanlon + * + */ +public enum UnsupportedTemplateLoader implements MustacheTemplateLoader { + + INSTANCE; + + public Reader getTemplate(String filename) { + throw new UnsupportedOperationException("template loading is not supported"); + } + +} diff --git a/src/test/java/com/samskivert/mustache/MustacheTest.java b/src/test/java/com/samskivert/mustache/MustacheTest.java index ea7d4ff..2c11850 100644 --- a/src/test/java/com/samskivert/mustache/MustacheTest.java +++ b/src/test/java/com/samskivert/mustache/MustacheTest.java @@ -3,19 +3,39 @@ package com.samskivert.mustache; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.junit.Assert.fail; + +import java.io.Reader; +import java.io.StringReader; import java.util.Arrays; import java.util.Collections; import java.util.HashMap; import java.util.Map; -import org.junit.*; -import static org.junit.Assert.*; +import org.junit.Test; /** * Various unit tests. */ public class MustacheTest { + @Test(expected = IllegalArgumentException.class) + public void testDefaultTemplateIncludeBehavior () { + test(null, "{{>foo}}", null); + } + + @Test + public void testTemplateIncludeBehavior () { + Mustache.setTemplateLoader(new MustacheTemplateLoader() { + public Reader getTemplate(String filename) { + return new StringReader("inside:{{bar}}"); + } + }); + test("foo inside:foo foo", "{{bar}} {{>foo}} {{bar}}", context("bar", "foo")); + } + @Test public void testSimpleVariable () { test("bar", "{{foo}}", context("foo", "bar")); }