Skip to content

Commit eaee8ce

Browse files
author
Sam Pullara
committed
add a test that implements dyanmic partial behavior
1 parent 84625ea commit eaee8ce

1 file changed

Lines changed: 90 additions & 14 deletions

File tree

‎compiler/src/test/java/com/github/mustachejava/InterpreterTest.java‎

Lines changed: 90 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,27 @@
1818
import org.junit.Assert;
1919
import org.junit.Test;
2020

21-
import java.io.*;
22-
import java.util.*;
21+
import java.io.File;
22+
import java.io.IOException;
23+
import java.io.OutputStreamWriter;
24+
import java.io.Reader;
25+
import java.io.StringReader;
26+
import java.io.StringWriter;
27+
import java.io.Writer;
28+
import java.util.ArrayList;
29+
import java.util.Arrays;
30+
import java.util.Collections;
31+
import java.util.HashMap;
32+
import java.util.HashSet;
33+
import java.util.Iterator;
34+
import java.util.List;
35+
import java.util.Locale;
36+
import java.util.Map;
37+
import java.util.Optional;
38+
import java.util.Set;
2339
import java.util.concurrent.Callable;
40+
import java.util.concurrent.ConcurrentHashMap;
41+
import java.util.concurrent.ConcurrentMap;
2442
import java.util.concurrent.CountDownLatch;
2543
import java.util.concurrent.ExecutionException;
2644
import java.util.concurrent.Executors;
@@ -80,7 +98,7 @@ public Reader getReader(String resourceName) {
8098
// First look with locale
8199
Reader reader = super.getReader(newResourceName);
82100

83-
if(reader == null) {
101+
if (reader == null) {
84102
// Fallback to non-localized resourceName
85103
reader = super.getReader(resourceName);
86104
}
@@ -427,7 +445,7 @@ public void testOptional() throws IOException {
427445
StringReader template = new StringReader("{{person}}{{#person}} is present{{/person}}{{^person}}Is not present{{/person}}");
428446
Mustache m = c.compile(template, "test");
429447
StringWriter sw = new StringWriter();
430-
m.execute(sw, new Object() {
448+
m.execute(sw, new Object() {
431449
Optional<String> person = Optional.of("Test");
432450
});
433451
assertEquals("Test is present", sw.toString());
@@ -626,6 +644,60 @@ public void testSerialCallable() throws MustacheException, IOException {
626644
assertEquals(getContents(root, "complex.txt"), sw.toString());
627645
}
628646

647+
public void testDynamicPartial() throws MustacheException, IOException {
648+
// Implement >+ syntax that dynamically includes template files at runtime
649+
MustacheFactory c = new DefaultMustacheFactory(root) {
650+
@Override
651+
public MustacheVisitor createMustacheVisitor() {
652+
return new DefaultMustacheVisitor(this) {
653+
@Override
654+
public void partial(TemplateContext tc, String variable) {
655+
if (variable.startsWith("+")) {
656+
// This is a dynamic partial rather than a static one
657+
TemplateContext partialTC = new TemplateContext("{{", "}}", tc.file(), tc.line(), tc.startOfLine());
658+
list.add(new PartialCode(partialTC, df, variable.substring(1).trim()) {
659+
@Override
660+
public synchronized void init() {
661+
filterText();
662+
// Treat the actual text as a Mustache with single [ ] as the delimiter
663+
// so we can do interpoliation of things like [foo]/[bar].txt
664+
partial = df.compile(new StringReader(name), "__dynpartial__", "[", "]");
665+
if (partial == null) {
666+
throw new MustacheException("Failed to parse partial name template: " + name);
667+
}
668+
}
669+
670+
ConcurrentMap<String, Mustache> dynamicaPartialCache = new ConcurrentHashMap<>();
671+
672+
@Override
673+
public Writer execute(Writer writer, List<Object> scopes) {
674+
// Calculate the name of the dynamic partial
675+
StringWriter sw = new StringWriter();
676+
partial.execute(sw, scopes);
677+
Mustache mustache = dynamicaPartialCache.computeIfAbsent(sw.toString(), df::compilePartial);
678+
Writer execute = mustache.execute(writer, scopes);
679+
return appendText(execute);
680+
}
681+
});
682+
} else {
683+
super.partial(tc, variable);
684+
}
685+
}
686+
};
687+
}
688+
};
689+
Mustache m = c.compile(new StringReader("{{>+ [foo].html}}"), "test.html");
690+
StringWriter sw = new StringWriter();
691+
m.execute(sw, new HashMap<String, Object>() {{
692+
put("name", "Chris");
693+
put("value", 10000);
694+
put("taxed_value", 6000);
695+
put("in_ca", true);
696+
put("foo", "simple");
697+
}});
698+
assertEquals(getContents(root, "simple.txt"), sw.toString());
699+
}
700+
629701
/*
630702
@SuppressWarnings("serial")
631703
public void testCurrentElementInArray() throws IOException, MustacheException {
@@ -914,20 +986,20 @@ public MustacheVisitor createMustacheVisitor() {
914986
public void testPragmaWhiteSpaceHandling() throws IOException {
915987
DefaultMustacheFactory mf = new DefaultMustacheFactory() {
916988
@Override
917-
public MustacheVisitor createMustacheVisitor() {
989+
public MustacheVisitor createMustacheVisitor() {
918990
DefaultMustacheVisitor visitor = new DefaultMustacheVisitor(this);
919-
// Add a pragma handler that simply renders a dash to visualize the output
920-
visitor.addPragmaHandler("pragma", (tc, pragma, args) -> new WriteCode(tc, this, "-"));
991+
// Add a pragma handler that simply renders a dash to visualize the output
992+
visitor.addPragmaHandler("pragma", (tc, pragma, args) -> new WriteCode(tc, this, "-"));
921993
return visitor;
922994
}
923-
};
995+
};
924996

925-
Mustache m = mf.compile(new StringReader(" {{% pragma}} {{% pragma}} "), "testPragma");
926-
StringWriter sw = new StringWriter();
927-
m.execute(sw, "").close();
997+
Mustache m = mf.compile(new StringReader(" {{% pragma}} {{% pragma}} "), "testPragma");
998+
StringWriter sw = new StringWriter();
999+
m.execute(sw, "").close();
9281000

929-
// Pragma rendering should preserve template whitespace
930-
assertEquals(" - - ", sw.toString());
1001+
// Pragma rendering should preserve template whitespace
1002+
assertEquals(" - - ", sw.toString());
9311003
}
9321004

9331005
public void testNotIterableCallable() throws IOException {
@@ -1185,6 +1257,7 @@ public void testTemplateFunctionWithData() {
11851257
public TemplateFunction parse() {
11861258
return s -> "blablabla {{anotherVar}}, blablabla {{yetAnotherVar}}";
11871259
}
1260+
11881261
String anotherVar = "banana";
11891262
String yetAnotherVar = "apple";
11901263
});
@@ -1201,6 +1274,7 @@ public MustacheVisitor createMustacheVisitor() {
12011274
public void iterable(final TemplateContext templateContext, String variable, Mustache mustache) {
12021275
list.add(new IterableCode(templateContext, df, mustache, variable) {
12031276
Binding binding = oh.createBinding("params", templateContext, this);
1277+
12041278
protected Writer handleFunction(Writer writer, Function function, List<Object> scopes) {
12051279
boolean added = addScope(scopes, binding.get(scopes));
12061280
try {
@@ -1220,7 +1294,9 @@ protected Writer handleFunction(Writer writer, Function function, List<Object> s
12201294
public TemplateFunction parse() {
12211295
return s -> "blablabla {{anotherVar}}, blablabla {{yetAnotherVar}}";
12221296
}
1297+
12231298
Map<String, Object> params = new HashMap<>();
1299+
12241300
{
12251301
params.put("anotherVar", "banana");
12261302
params.put("yetAnotherVar", "apple");
@@ -1239,7 +1315,7 @@ public void testPropertyWithDot() throws IOException {
12391315
mustache.execute(writer, new Object[]{properties}).close();
12401316
Assert.assertEquals("value=some.value", writer.toString());
12411317
}
1242-
1318+
12431319
public void testLeavingAloneMissingVariables() throws IOException {
12441320
DefaultMustacheFactory dmf = new DefaultMustacheFactory(root) {
12451321
@Override

0 commit comments

Comments
 (0)