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.
This commit is contained in:
Sean Scanlon
2011-03-27 15:53:04 -07:00
parent 76f86ea665
commit 5fc751219e
4 changed files with 85 additions and 3 deletions
@@ -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) {
@@ -0,0 +1,19 @@
package com.samskivert.mustache;
import java.io.Reader;
/**
*
* @author Sean Scanlon <sean.scanlon@gmail.com>
*/
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;
}
@@ -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 <sean.scanlon@gmail.com>
*
*/
public enum UnsupportedTemplateLoader implements MustacheTemplateLoader {
INSTANCE;
public Reader getTemplate(String filename) {
throw new UnsupportedOperationException("template loading is not supported");
}
}
@@ -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"));
}