diff --git a/handlebars/src/main/antlr4/com/github/jknack/handlebars/internal/HbsLexer.g4 b/handlebars/src/main/antlr4/com/github/jknack/handlebars/internal/HbsLexer.g4 index bc6727a7b..7957519c8 100644 --- a/handlebars/src/main/antlr4/com/github/jknack/handlebars/internal/HbsLexer.g4 +++ b/handlebars/src/main/antlr4/com/github/jknack/handlebars/internal/HbsLexer.g4 @@ -76,6 +76,11 @@ lexer grammar HbsLexer; } private boolean varEscape(final String start, final String end) { + // Support escaping raw expressions (TVar) and normal expressions (VAR) + return consumeVarEscape(start + "{", end + "}") || consumeVarEscape(start, end); + } + + private boolean consumeVarEscape(final String start, final String end) { if (ahead("\\" + start)) { int offset = start.length(); while (!isEOF(offset)) { 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 bfd16be3e..515bb3720 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/Context.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/Context.java @@ -76,6 +76,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; } @@ -153,6 +154,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; } diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/Param.java b/handlebars/src/main/java/com/github/jknack/handlebars/Param.java similarity index 91% rename from handlebars/src/main/java/com/github/jknack/handlebars/internal/Param.java rename to handlebars/src/main/java/com/github/jknack/handlebars/Param.java index d50e811ae..8393cc80d 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/Param.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/Param.java @@ -15,12 +15,10 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.github.jknack.handlebars.internal; +package com.github.jknack.handlebars; import java.io.IOException; -import com.github.jknack.handlebars.Context; - /** * Helper or hash param. * diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/Tag.java b/handlebars/src/main/java/com/github/jknack/handlebars/Tag.java new file mode 100644 index 000000000..bff2edbd8 --- /dev/null +++ b/handlebars/src/main/java/com/github/jknack/handlebars/Tag.java @@ -0,0 +1,86 @@ +/** + * Copyright (c) 2012-2015 Edgar Espina + * + * This file is part of Handlebars.java. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.github.jknack.handlebars; + +import java.util.List; + +/** + * A Handlebars tag with its associated parameters and tag type. + * + */ +public class Tag { + + /** + * The tag itself. + */ + private String tag; + + /** + * A list of params for the tag. + */ + private List params; + + /** + * The tag type of the tag. + */ + private TagType tagType; + + /** + * Creates a new {@link Tag}. + * + * @param tag The tag itself. + * @param params The associated parameters for the tag. + * @param tagType The tag type for the tag. + */ + public Tag(final String tag, final List params, final TagType tagType) { + this.tag = tag; + this.params = params; + this.tagType = tagType; + } + + /** + * The tag. + * @return The tag. + */ + public String getTag() { + return tag; + } + + /** + * The tag's parameters. + * @return The tag's parameters. + */ + public List getParams() { + return params; + } + + /** + * The tag type. + * @return The tag's type. + */ + public TagType getTagType() { + return tagType; + } + + @Override + public String toString() { + return "Tag(" + this.tag + ", " + + this.params.toString() + ", " + this.tagType + ")"; + } + +} diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/Template.java b/handlebars/src/main/java/com/github/jknack/handlebars/Template.java index 20ad53593..31fa799b5 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/Template.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/Template.java @@ -102,10 +102,21 @@ public List collect(final TagType... tagType) { return Collections.emptyList(); } + @Override + public List collectWithParameters(final TagType... tagType) { + return Collections.emptyList(); + } + @Override public List collectReferenceParameters() { return Collections.emptyList(); } + + @Override + public List collectAllParameters() { + return Collections.emptyList(); + } + }; /** @@ -201,9 +212,42 @@ public List collectReferenceParameters() { * * @param tagType The tag type. Required. * @return A list with tag names. + * + * @deprecated Use {@link #collectWithParameters(TagType...)} instead. */ + @Deprecated List collect(TagType... tagType); + /** + * Collect all the tag names under the given tagType and their parameters. + *

+ * Usage: + *

+ * + *
+   * {{hello}}
+   * {{var 1}}
+   * {{{tripleVar}}}
+   * 
+ *

+ * collectWithParameters(TagType.VAR) returns + * [Tag(hello, [], TagType.VAR), Tag(var, [1], TagType.VAR)] + *

+ *

+ * collect(TagType.TRIPLE_VAR) returns + * [Tag(tripleVar, [], TagType.TRIPLE_VAR)] + *

+ *

+ * collect(TagType.VAR, TagType.TRIPLE_VAR) returns + * [Tag(hello, [], TagType.VAR), Tag(var, [1], TagType.VAR), + * Tag(tripleVar, [], TagType.TRIPLE_VAR)] + *

+ * + * @param tagType The tag type. Required. + * @return A list of Tag. + */ + List collectWithParameters(TagType... tagType); + /** * Collects all the parameters which are also variables. *

@@ -222,6 +266,24 @@ public List collectReferenceParameters() { */ List collectReferenceParameters(); + /** + * Collects all the parameters. + *

+ * Usage: + *

+ * + *
+   * {{#if v1}}{{/if}}
+   * {{#each v2 "test"}}{{/each}}
+   * 
+ *

+ * collectAllParameters() returns [v1, v2] + *

+ * + * @return A list of Param. + */ + List collectAllParameters(); + /** * @return The template file's name. */ diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/BaseTemplate.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/BaseTemplate.java index 4a40c04a5..c9e43f6af 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/BaseTemplate.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/BaseTemplate.java @@ -45,6 +45,8 @@ import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.HandlebarsError; import com.github.jknack.handlebars.HandlebarsException; +import com.github.jknack.handlebars.Param; +import com.github.jknack.handlebars.Tag; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; import com.github.jknack.handlebars.TypeSafeTemplate; @@ -353,6 +355,16 @@ public List collect(final TagType... tagType) { return new ArrayList<>(tagNames); } + @Override + public List collectWithParameters(final TagType... tagType) { + isTrue(tagType.length > 0, "At least one tag type is required."); + List tagsWithParams = new ArrayList<>(); + for (TagType tt : tagType) { + collectWithParameters(tagsWithParams, tt); + } + return new ArrayList<>(tagsWithParams); + } + /** * Child classes might want to check if they apply to the tagtype and append them self to the * result list. @@ -363,6 +375,14 @@ public List collect(final TagType... tagType) { protected void collect(final Collection result, final TagType tagType) { } + /** + * @param result The result list of Tag. + * @param tagType The matching tagtype. + */ + protected void collectWithParameters(final Collection result, + final TagType tagType) { + } + @Override public List collectReferenceParameters() { Set paramNames = new LinkedHashSet<>(); @@ -370,12 +390,25 @@ public List collectReferenceParameters() { return new ArrayList<>(paramNames); } + @Override + public List collectAllParameters() { + Set params = new LinkedHashSet<>(); + collectAllParameters(params); + return new ArrayList<>(params); + } + /** * @param result The result list to add new parameters to. */ protected void collectReferenceParameters(final Collection result) { } + /** + * @param result The result list of Params to add new Params to. + */ + protected void collectAllParameters(final Collection result) { + } + @Override public String toJavaScript() { if (javaScript == null) { diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/Block.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/Block.java index 2986f004b..7a7c34e15 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/Block.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/Block.java @@ -36,8 +36,10 @@ import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.Lambda; import com.github.jknack.handlebars.Options; +import com.github.jknack.handlebars.Param; import com.github.jknack.handlebars.PathCompiler; import com.github.jknack.handlebars.PathExpression; +import com.github.jknack.handlebars.Tag; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; import com.github.jknack.handlebars.helper.EachHelper; @@ -387,6 +389,17 @@ public List collect(final TagType... tagType) { return new ArrayList<>(tagNames); } + @Override + public List collectWithParameters(final TagType... tagType) { + List tagNames = new ArrayList(); + if (body != null) { + tagNames.addAll(body.collectWithParameters(tagType)); + } + tagNames.addAll(inverse.collectWithParameters(tagType)); + tagNames.addAll(super.collectWithParameters(tagType)); + return new ArrayList(tagNames); + } + @Override protected void collect(final Collection result, final TagType tagType) { if (tagType == this.tagType) { @@ -395,6 +408,15 @@ protected void collect(final Collection result, final TagType tagType) { super.collect(result, tagType); } + @Override + protected void collectWithParameters(final Collection result, + final TagType tagType) { + if (tagType == this.tagType) { + result.add(new Tag(name, collectAllParameters(), tagType)); + } + super.collectWithParameters(result, tagType); + } + @Override public List collectReferenceParameters() { Set paramNames = new LinkedHashSet<>(); @@ -405,4 +427,15 @@ public List collectReferenceParameters() { paramNames.addAll(super.collectReferenceParameters()); return new ArrayList<>(paramNames); } + + @Override + public List collectAllParameters() { + Set paramNames = new LinkedHashSet<>(); + if (body != null) { + paramNames.addAll(body.collectAllParameters()); + } + paramNames.addAll(inverse.collectAllParameters()); + paramNames.addAll(super.collectAllParameters()); + return new ArrayList<>(paramNames); + } } diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/BlockDecorator.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/BlockDecorator.java index 7f3ebb3fc..a5063adad 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/BlockDecorator.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/BlockDecorator.java @@ -26,6 +26,7 @@ import com.github.jknack.handlebars.Decorator; import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.Options; +import com.github.jknack.handlebars.Param; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/DefParam.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/DefParam.java index df567fdd2..1eb735e12 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/DefParam.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/DefParam.java @@ -20,6 +20,7 @@ import java.io.IOException; import com.github.jknack.handlebars.Context; +import com.github.jknack.handlebars.Param; /** * Int or boolean param. diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/ForwardingTemplate.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/ForwardingTemplate.java index 01915aafe..b956f862f 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/ForwardingTemplate.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/ForwardingTemplate.java @@ -24,6 +24,8 @@ import java.util.List; import com.github.jknack.handlebars.Context; +import com.github.jknack.handlebars.Param; +import com.github.jknack.handlebars.Tag; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; import com.github.jknack.handlebars.TypeSafeTemplate; @@ -188,6 +190,16 @@ public List collect(final TagType... tagType) { return template.collect(tagType); } + @Override + public List collectAllParameters() { + return template.collectAllParameters(); + } + + @Override + public List collectWithParameters(final TagType... tagType) { + return template.collectWithParameters(tagType); + } + @Override public List collectReferenceParameters() { return template.collectReferenceParameters(); diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/HelperResolver.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/HelperResolver.java index 3e6e52354..6d56f3f4c 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/HelperResolver.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/HelperResolver.java @@ -32,6 +32,8 @@ import com.github.jknack.handlebars.HandlebarsException; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.HelperRegistry; +import com.github.jknack.handlebars.Param; +import com.github.jknack.handlebars.Tag; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; @@ -263,6 +265,16 @@ protected void collect(final Collection result, final TagType tagType) { } } + @Override + protected void collectWithParameters(final Collection result, + final TagType tagType) { + for (Object param : this.params) { + if (param instanceof VarParam) { + ((VarParam) param).fn.collectWithParameters(result, tagType); + } + } + } + @Override protected void collectReferenceParameters(final Collection result) { for (Object param : params) { @@ -279,4 +291,16 @@ protected void collectReferenceParameters(final Collection result) { } } + @Override + protected void collectAllParameters(final Collection result) { + for (Param param : params) { + if (param instanceof VarParam) { + ((VarParam) param).fn.collectAllParameters(result); + } else { + result.add(param); + } + } + result.addAll(hash.values()); + } + } diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/Partial.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/Partial.java index 160990df6..c9260c31f 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/Partial.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/Partial.java @@ -35,6 +35,7 @@ import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.HandlebarsError; import com.github.jknack.handlebars.HandlebarsException; +import com.github.jknack.handlebars.Param; import com.github.jknack.handlebars.PathCompiler; import com.github.jknack.handlebars.PathExpression; import com.github.jknack.handlebars.Template; diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/RefParam.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/RefParam.java index 136d2ce6b..026695ecf 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/RefParam.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/RefParam.java @@ -21,6 +21,7 @@ import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.PathExpression; +import com.github.jknack.handlebars.Param; /** * Look param in the given context. diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/StrParam.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/StrParam.java index 1c52db2f0..17a9a4498 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/StrParam.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/StrParam.java @@ -20,6 +20,7 @@ import java.io.IOException; import com.github.jknack.handlebars.Context; +import com.github.jknack.handlebars.Param; /** * String or char literals. diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateBuilder.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateBuilder.java index 76ab0f574..e5862814b 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateBuilder.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateBuilder.java @@ -24,6 +24,7 @@ import com.github.jknack.handlebars.HandlebarsException; import com.github.jknack.handlebars.Helper; import com.github.jknack.handlebars.HelperRegistry; +import com.github.jknack.handlebars.Param; import com.github.jknack.handlebars.PathCompiler; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateList.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateList.java index 1cc3d06ad..ce88d6c09 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateList.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/TemplateList.java @@ -19,6 +19,8 @@ import com.github.jknack.handlebars.Context; import com.github.jknack.handlebars.Handlebars; +import com.github.jknack.handlebars.Param; +import com.github.jknack.handlebars.Tag; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; @@ -133,6 +135,15 @@ public List collect(final TagType... tagType) { return new ArrayList<>(tagNames); } + @Override + public List collectWithParameters(final TagType... tagType) { + List tagNames = new ArrayList<>(); + for (Template node : nodes) { + tagNames.addAll(node.collectWithParameters(tagType)); + } + return new ArrayList<>(tagNames); + } + @Override public List collectReferenceParameters() { Set paramNames = new LinkedHashSet<>(); @@ -142,6 +153,15 @@ public List collectReferenceParameters() { return new ArrayList<>(paramNames); } + @Override + public List collectAllParameters() { + List paramNames = new ArrayList<>(); + for (Template node : nodes) { + paramNames.addAll(node.collectAllParameters()); + } + return new ArrayList<>(paramNames); + } + @Override public String toString() { return nodes.toString(); diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/VarDecorator.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/VarDecorator.java index 196a2d272..a1e8cc3da 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/VarDecorator.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/VarDecorator.java @@ -27,6 +27,7 @@ import com.github.jknack.handlebars.Decorator; import com.github.jknack.handlebars.Handlebars; import com.github.jknack.handlebars.Options; +import com.github.jknack.handlebars.Param; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/VarParam.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/VarParam.java index 79c831097..17859fbec 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/VarParam.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/VarParam.java @@ -20,6 +20,7 @@ import java.io.IOException; import com.github.jknack.handlebars.Context; +import com.github.jknack.handlebars.Param; /** * Var sub-expr param. diff --git a/handlebars/src/main/java/com/github/jknack/handlebars/internal/Variable.java b/handlebars/src/main/java/com/github/jknack/handlebars/internal/Variable.java index 9d447ef93..787491c93 100644 --- a/handlebars/src/main/java/com/github/jknack/handlebars/internal/Variable.java +++ b/handlebars/src/main/java/com/github/jknack/handlebars/internal/Variable.java @@ -32,8 +32,10 @@ import com.github.jknack.handlebars.HelperRegistry; import com.github.jknack.handlebars.Lambda; import com.github.jknack.handlebars.Options; +import com.github.jknack.handlebars.Param; import com.github.jknack.handlebars.PathCompiler; import com.github.jknack.handlebars.PathExpression; +import com.github.jknack.handlebars.Tag; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; @@ -216,6 +218,15 @@ protected void collect(final Collection result, final TagType tagType) { super.collect(result, tagType); } + @Override + protected void collectWithParameters(final Collection result, + final TagType tagType) { + if (this.type == tagType) { + result.add(new Tag(name, collectAllParameters(), tagType)); + } + super.collectWithParameters(result, tagType); + } + /** * Format and escape a var (if need it). * diff --git a/handlebars/src/test/java/com/github/jknack/handlebars/AbstractTest.java b/handlebars/src/test/java/com/github/jknack/handlebars/AbstractTest.java index 338d233d8..b78a2ed11 100644 --- a/handlebars/src/test/java/com/github/jknack/handlebars/AbstractTest.java +++ b/handlebars/src/test/java/com/github/jknack/handlebars/AbstractTest.java @@ -87,7 +87,7 @@ public void shouldCompileTo(final String template, final Object context, throws IOException { Template t = compile(template, helpers, partials); String result = t.apply(configureContext(context)); - assertEquals("'" + expected + "' should === '" + result + "': " + message, expected, result); + assertEquals("'" + result + "' should === '" + expected + "': " + message, expected, result); } protected Object configureContext(final Object context) { 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..10376d11f --- /dev/null +++ b/handlebars/src/test/java/com/github/jknack/handlebars/InternalDataTest.java @@ -0,0 +1,61 @@ +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; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +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"); + assertEquals("foo", ((Context)configureContext("")).get("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}}", "", ""); + assertNull(((Context)configureContext("")).get("bar")); + } + + @Test + public void helperAbleToAccessInternalData() throws IOException { + shouldCompileTo("{{printFooAndBar}}", "", "foo bar"); + } +} diff --git a/handlebars/src/test/java/com/github/jknack/handlebars/i1084/Issue1084.java b/handlebars/src/test/java/com/github/jknack/handlebars/i1084/Issue1084.java new file mode 100644 index 000000000..97b92bd51 --- /dev/null +++ b/handlebars/src/test/java/com/github/jknack/handlebars/i1084/Issue1084.java @@ -0,0 +1,47 @@ +package com.github.jknack.handlebars.i1084; + +import com.github.jknack.handlebars.AbstractTest; +import org.junit.Test; + +import java.io.IOException; + +import static org.junit.Assert.assertEquals; + +public class Issue1084 extends AbstractTest { + + @Test + public void escapeRawVars() throws IOException { + shouldCompileTo("\\{{{foo}}}", $, "{{{foo}}}"); + } + + @Test + public void escapeRawVarsWithText() throws IOException { + shouldCompileTo("before \\{{{foo}}} after", $, "before {{{foo}}} after"); + } + + @Test + public void escapeRawVsUnescape() throws IOException { + shouldCompileTo("\\{{{foo}}} {{{foo}}}", $("foo", "bar"), "{{{foo}}} bar"); + } + + @Test + public void escapeRawMultiline() throws IOException { + shouldCompileTo("\\{{{foo\n}}}", $("foo", "bar"), "{{{foo\n}}}"); + } + + @Test + public void rawBlockEscape() throws IOException { + shouldCompileTo("\\{{{#foo}}}", $("foo", "bar"), "{{{#foo}}}"); + } + + @Test + public void rawBlockEscapeWithParams() throws IOException { + shouldCompileTo("\\{{{#foo x a x}}}", $("foo", "bar"), "{{{#foo x a x}}}"); + } + + @Test + public void escapeRawVarToText() throws IOException { + assertEquals("\\{{{foo}}}", compile("\\{{{foo}}}").text()); + } + +} diff --git a/handlebars/src/test/java/com/github/jknack/handlebars/internal/TemplateTest.java b/handlebars/src/test/java/com/github/jknack/handlebars/internal/TemplateTest.java index 954141f5f..3eed9efdf 100644 --- a/handlebars/src/test/java/com/github/jknack/handlebars/internal/TemplateTest.java +++ b/handlebars/src/test/java/com/github/jknack/handlebars/internal/TemplateTest.java @@ -18,17 +18,17 @@ package com.github.jknack.handlebars.internal; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; import java.io.IOException; -import java.util.Arrays; -import java.util.HashSet; -import java.util.List; -import java.util.Set; +import java.util.*; import org.junit.Test; import com.github.jknack.handlebars.AbstractTest; import com.github.jknack.handlebars.Handlebars; +import com.github.jknack.handlebars.Param; +import com.github.jknack.handlebars.Tag; import com.github.jknack.handlebars.TagType; import com.github.jknack.handlebars.Template; @@ -77,6 +77,93 @@ public void nestedVarTest() throws IOException { Arrays.asList("v1", "v2", "v3", "v4", "v5", "v6", "v7")); } + @Test + public void collectWithParamsTest() throws IOException { + List tagsWithParams = getTagsWithParameters("{{i18n \"foo\"}}"); + assertEquals(tagsWithParams.size(), 1); + Tag tag = tagsWithParams.get(0); + assertEquals(tag.getTagType(), TagType.VAR); + assertEquals(tag.getTag(), "i18n"); + assertEquals(tag.getParams().size(), 1); + Param param = tag.getParams().get(0); + StrParam strParam = (StrParam) param; + assertEquals(strParam.apply(null), "foo"); + } + + @Test + public void collectWithParamsForEachTest() throws IOException { + List tagsWithParams = getTagsWithParameters("{{#each shoppingCartItems as |item|}}{{i18n item}}{{/each}}"); + assertEquals(tagsWithParams.size(), 2); + + Tag i18NTag = tagsWithParams.get(0); + System.out.println("i18nTag.getParams() is "+ i18NTag.getParams()); + assertEquals(i18NTag.getTagType(), TagType.VAR); + assertEquals(i18NTag.getTag(), "i18n"); + assertEquals(i18NTag.getParams().size(), 1); + Param i18nParam = i18NTag.getParams().get(0); + RefParam i18nRefParam = (RefParam) i18nParam; + assertEquals(i18nRefParam.toString(), "item"); + + Tag eachTag = tagsWithParams.get(1); + assertEquals(eachTag.getTagType(), TagType.SECTION); + assertEquals(eachTag.getTag(), "each"); + assertEquals(eachTag.getParams().size(), 2); + System.out.println("eachTag.getParams() is "+ eachTag.getParams()); + Param param1 = eachTag.getParams().get(0); + RefParam refParam1 = (RefParam) param1; + assertEquals(refParam1.toString(), "item"); + Param param2 = eachTag.getParams().get(1); + RefParam refParam2 = (RefParam) param2; + assertEquals(refParam2.toString(), "shoppingCartItems"); + + } + + @Test + public void collectWithParamsMultipleParamsTest() throws IOException { + List tagsWithParams = getTagsWithParameters("{{embedded foo bar baz}}{{i18n \"value1\"}}"); + assertEquals(tagsWithParams.size(), 2); + + Tag embeddedTag = tagsWithParams.get(0); + assertEquals(embeddedTag.getTagType(), TagType.VAR); + assertEquals(embeddedTag.getTag(), "embedded"); + assertEquals(embeddedTag.getParams().size(), 3); + + Param param1 = embeddedTag.getParams().get(0); + RefParam refParam1 = (RefParam) param1; + assertEquals(refParam1.toString(), "foo"); + + Param param2 = embeddedTag.getParams().get(1); + RefParam refParam2 = (RefParam) param2; + assertEquals(refParam2.toString(), "bar"); + + Param param3 = embeddedTag.getParams().get(2); + RefParam refParam3 = (RefParam) param3; + assertEquals(refParam3.toString(), "baz"); + + Tag i18NTag = tagsWithParams.get(1); + assertEquals(i18NTag.getTagType(), TagType.VAR); + assertEquals(i18NTag.getTag(), "i18n"); + assertEquals(i18NTag.getParams().size(), 1); + Param param = i18NTag.getParams().get(0); + StrParam strParam = (StrParam) param; + assertEquals(strParam.apply(null), "value1"); + } + + @Test + public void collectWithParamsNoParamsTest() throws IOException { + List tagsWithParams = getTagsWithParameters("{{test}}"); + assertEquals(tagsWithParams.size(), 1); + Tag tag = tagsWithParams.get(0); + assertEquals(tag.getTag(), "test"); + assertTrue(tag.getParams().isEmpty()); + } + + private List getTagsWithParameters(String input) throws IOException { + Handlebars hb = newHandlebars(); + Template template = hb.compileInline(input); + return new ArrayList<>(template.collectWithParameters(TagType.values())); + } + private void assertVariables(String input, List expected) throws IOException { Handlebars hb = newHandlebars(); Template template = hb.compileInline(input);