From fb4e2958a9580c013a686ccc2b82f94bd5e2d522 Mon Sep 17 00:00:00 2001 From: Ilya Brin Date: Tue, 3 Mar 2020 15:48:29 -0800 Subject: [PATCH 1/4] add internal data --- .../com/github/jknack/handlebars/Context.java | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/Context.java b/handlebars/src/main/java/com/github/jknack/handlebars/Context.java index 1e3eec24c..af4851202 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/Context.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/Context.java @@ -75,6 +75,7 @@ protected BlockParam(final Context parent, final Map hash) { this.extendedContext.resolver = parent.resolver; this.parent = parent; this.data = parent.data; + this.internalData = parent.internalData; this.resolver = parent.resolver; } @@ -152,6 +153,7 @@ protected PartialCtx(final Context parent, final Object model, final Map data; + /** + * Functions similarly to data, but not resolved during rendering. + */ + protected Map internalData; + /** * Additional, data can be stored here. */ @@ -470,6 +477,7 @@ private static Context root(final Object model) { root.data.put(INLINE_PARTIALS, partials); root.data.put(INVOCATION_STACK, new LinkedList()); root.data.put("root", model); + root.internalData = new HashMap<>(); return root; } @@ -535,6 +543,41 @@ public Context data(final Map attributes) { return this; } + /** + * Read the attribute from the internal data storage. + * + * @param name The attribute's name. + * @param Data type. + * @return The attribute value or null. + */ + @SuppressWarnings("unchecked") + public T internalData(final String name) { + return (T) internalData.get(name); + } + + /** + * Set an attribute in the internal data storage. + * + * @param name The attribute's name. Required. + * @param value The attribute's value. Required. + * @return This context. + */ + public Context internalData(final String name, final Object value) { + internalData.put(name, value); + return this; + } + + /** + * Store the map in the internal data storage. + * + * @param attributes The attributes to add. Required. + * @return This context. + */ + public Context internalData(final Map attributes) { + internalData.putAll(attributes); + return this; + } + /** * Resolved as '.' or 'this' inside templates. * @@ -692,6 +735,9 @@ public void destroy() { if (data != null) { data.clear(); } + if (internalData != null) { + internalData.clear(); + } } if (extendedContext != null) { extendedContext.destroy(); @@ -790,6 +836,7 @@ private Context newChild(final Object model) { child.setResolver(this.resolver); child.parent = this; child.data = this.data; + child.internalData = this.internalData; return child; } @@ -813,6 +860,7 @@ protected Context newChildContext(final Object model) { public static Context copy(final Context context, final Object model) { Context ctx = Context.newContext(model); ctx.data = context.data; + ctx.internalData = context.internalData; ctx.resolver = context.resolver; return ctx; } From 5ed8e5254f302221af0d1a677944c3ef88eeb1eb Mon Sep 17 00:00:00 2001 From: Ilya Brin Date: Tue, 3 Mar 2020 16:13:14 -0800 Subject: [PATCH 2/4] add tests --- .../jknack/handlebars/InternalDataTest.java | 56 +++++++++++++++++++ 1 file changed, 56 insertions(+) create mode 100644 handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java diff --git a/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java b/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java new file mode 100644 index 000000000..5ef9a5d18 --- /dev/null +++ b/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java @@ -0,0 +1,56 @@ +package com.github.jknack.handlebars; + +import com.github.jknack.handlebars.context.FieldValueResolver; +import com.github.jknack.handlebars.context.JavaBeanValueResolver; +import com.github.jknack.handlebars.context.MapValueResolver; +import com.github.jknack.handlebars.context.MethodValueResolver; +import java.io.IOException; + +import org.junit.Test; + +public class InternalDataTest extends AbstractTest { + + @Override + protected Handlebars newHandlebars() { + Handlebars handlebars = new Handlebars(); + handlebars.registerHelper("printFooAndBar", (context, options) -> + String.format("%s %s", options.context.data("foo"), options.context.internalData("bar"))); + return handlebars; + } + + @Override + protected Object configureContext(final Object model) { + return Context.newBuilder(model) + .resolver( + MapValueResolver.INSTANCE, + JavaBeanValueResolver.INSTANCE, + FieldValueResolver.INSTANCE, + MethodValueResolver.INSTANCE) + .build() + .data("foo", "foo") + .internalData("bar", "bar"); + } + + @Test + public void dataAvailableForRendering() throws IOException { + shouldCompileTo("{{foo}}", "", "foo"); + } + + @Test + public void internalDataNotAvailableForRendering() throws IOException { + shouldCompileTo("{{bar}}", "", ""); + shouldCompileTo("{{./bar}}", "", ""); + shouldCompileTo("{{../bar}}", "", ""); + shouldCompileTo("{{.././bar}}", "", ""); + shouldCompileTo("{{this.bar}}", "", ""); + shouldCompileTo("{{internalData}}", "", ""); + shouldCompileTo("{{internalData.bar}}", "", ""); + shouldCompileTo("{{this.internalData}}", "", ""); + shouldCompileTo("{{this.internalData.bar}}", "", ""); + } + + @Test + public void percentFormat() throws IOException { + shouldCompileTo("{{printFooAndBar}}", "", "foo bar"); + } +} From 25f80baa0d5d42b24b1a2ceb5b3d083ab66678ec Mon Sep 17 00:00:00 2001 From: Ilya Brin Date: Tue, 3 Mar 2020 16:18:59 -0800 Subject: [PATCH 3/4] add tests against direct context lookup --- .../java/com/github/jknack/handlebars/InternalDataTest.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java b/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java index 5ef9a5d18..139446afa 100644 --- a/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java +++ b/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java @@ -8,6 +8,9 @@ import org.junit.Test; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + public class InternalDataTest extends AbstractTest { @Override @@ -34,6 +37,7 @@ protected Object configureContext(final Object model) { @Test public void dataAvailableForRendering() throws IOException { shouldCompileTo("{{foo}}", "", "foo"); + assertEquals("foo", ((Context)configureContext("")).get("foo")); } @Test @@ -47,6 +51,7 @@ public void internalDataNotAvailableForRendering() throws IOException { shouldCompileTo("{{internalData.bar}}", "", ""); shouldCompileTo("{{this.internalData}}", "", ""); shouldCompileTo("{{this.internalData.bar}}", "", ""); + assertNull(((Context)configureContext("")).get("bar")); } @Test From ca2937d7ce607fe28ab7e6e1407fe8738899fc80 Mon Sep 17 00:00:00 2001 From: Ilya Brin Date: Tue, 3 Mar 2020 17:01:17 -0800 Subject: [PATCH 4/4] fix test name --- .../java/com/github/jknack/handlebars/InternalDataTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java b/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java index 139446afa..10376d11f 100644 --- a/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java +++ b/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java @@ -55,7 +55,7 @@ public void internalDataNotAvailableForRendering() throws IOException { } @Test - public void percentFormat() throws IOException { + public void helperAbleToAccessInternalData() throws IOException { shouldCompileTo("{{printFooAndBar}}", "", "foo bar"); } }