Skip to content

Commit

Permalink
Merge pull request #518 from jasmith-hs/preserve-raw-first-pass
Browse files Browse the repository at this point in the history
Preserve Raw Tags config
  • Loading branch information
jasmith-hs authored Oct 26, 2020
2 parents da08daa + 05b5b9c commit cc5905f
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 3 deletions.
20 changes: 18 additions & 2 deletions src/main/java/com/hubspot/jinjava/JinjavaConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public class JinjavaConfig {
private TokenScannerSymbols tokenScannerSymbols;
private ELResolver elResolver;
private final boolean iterateOverMapKeys;
private final boolean preserveForSecondPass;

public static Builder newBuilder() {
return new Builder();
Expand Down Expand Up @@ -85,6 +86,7 @@ public JinjavaConfig(InterpreterFactory interpreterFactory) {
interpreterFactory,
new DefaultTokenScannerSymbols(),
JinjavaInterpreterResolver.DEFAULT_RESOLVER_READ_ONLY,
false,
false
);
}
Expand Down Expand Up @@ -114,6 +116,7 @@ public JinjavaConfig(
new JinjavaInterpreterFactory(),
new DefaultTokenScannerSymbols(),
JinjavaInterpreterResolver.DEFAULT_RESOLVER_READ_ONLY,
false,
false
);
}
Expand All @@ -137,7 +140,8 @@ private JinjavaConfig(
InterpreterFactory interpreterFactory,
TokenScannerSymbols tokenScannerSymbols,
ELResolver elResolver,
boolean iterateOverMapKeys
boolean iterateOverMapKeys,
boolean preserveForSecondPass
) {
this.charset = charset;
this.locale = locale;
Expand All @@ -158,6 +162,7 @@ private JinjavaConfig(
this.tokenScannerSymbols = tokenScannerSymbols;
this.elResolver = elResolver;
this.iterateOverMapKeys = iterateOverMapKeys;
this.preserveForSecondPass = preserveForSecondPass;
}

public Charset getCharset() {
Expand Down Expand Up @@ -240,6 +245,10 @@ public boolean isIterateOverMapKeys() {
return iterateOverMapKeys;
}

public boolean isPreserveForSecondPass() {
return preserveForSecondPass;
}

public static class Builder {
private Charset charset = StandardCharsets.UTF_8;
private Locale locale = Locale.ENGLISH;
Expand All @@ -263,6 +272,7 @@ public static class Builder {
private TokenScannerSymbols tokenScannerSymbols = new DefaultTokenScannerSymbols();
private ELResolver elResolver = JinjavaInterpreterResolver.DEFAULT_RESOLVER_READ_ONLY;
private boolean iterateOverMapKeys;
private boolean preserveForSecondPass;

private Builder() {}

Expand Down Expand Up @@ -371,6 +381,11 @@ public Builder withIterateOverMapKeys(boolean iterateOverMapKeys) {
return this;
}

public Builder withPreserveForSecondPass(boolean preserveForSecondPass) {
this.preserveForSecondPass = preserveForSecondPass;
return this;
}

public JinjavaConfig build() {
return new JinjavaConfig(
charset,
Expand All @@ -391,7 +406,8 @@ public JinjavaConfig build() {
interpreterFactory,
tokenScannerSymbols,
elResolver,
iterateOverMapKeys
iterateOverMapKeys,
preserveForSecondPass
);
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/main/java/com/hubspot/jinjava/lib/tag/RawTag.java
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,10 @@ public String getName() {

@Override
public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) {
if (interpreter.getConfig().isPreserveForSecondPass()) {
return renderNodeRaw(tagNode);
}

LengthLimitingStringBuilder result = new LengthLimitingStringBuilder(
interpreter.getConfig().getMaxOutputSize()
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,4 +220,23 @@ public void itLimitsOutputSizeWhenSumOfNodeSizesExceedsMax() {
assertThat(renderResult.getErrors().get(0).getMessage())
.contains("OutputTooBigException");
}

@Test
public void itCanPreserveRawTags() {
JinjavaConfig preserveConfig = JinjavaConfig
.newBuilder()
.withPreserveForSecondPass(true)
.build();
String input = "1{% raw %}2{% endraw %}3";
String normalOutput = "123";
String preservedOutput = "1{% raw %}2{% endraw %}3";

RenderResult renderResult = new Jinjava().renderForResult(input, new HashMap<>());
assertThat(renderResult.getOutput()).isEqualTo(normalOutput);
assertThat(renderResult.hasErrors()).isFalse();

renderResult = new Jinjava(preserveConfig).renderForResult(input, new HashMap<>());
assertThat(renderResult.getOutput()).isEqualTo(preservedOutput);
assertThat(renderResult.hasErrors()).isFalse();
}
}
79 changes: 78 additions & 1 deletion src/test/java/com/hubspot/jinjava/lib/tag/RawTagTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import com.google.common.io.Resources;
import com.hubspot.jinjava.Jinjava;
import com.hubspot.jinjava.JinjavaConfig;
import com.hubspot.jinjava.interpret.DeferredValue;
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
import com.hubspot.jinjava.tree.Node;
import com.hubspot.jinjava.tree.TagNode;
Expand All @@ -17,12 +19,14 @@
import org.junit.Test;

public class RawTagTest {
Jinjava jinjava;
JinjavaInterpreter interpreter;
RawTag tag;

@Before
public void setup() {
interpreter = new Jinjava().newInterpreter();
jinjava = new Jinjava();
interpreter = jinjava.newInterpreter();
tag = new RawTag();
}

Expand Down Expand Up @@ -91,6 +95,79 @@ public void itDoesntProcessJinjaCommentsWithinARawBlock() {
.contains("{{#each people}}");
}

@Test
public void itPreservesRawTags() {
TagNode tagNode = fixture("hubl");
JinjavaInterpreter preserveInterpreter = new JinjavaInterpreter(
jinjava,
jinjava.getGlobalContextCopy(),
JinjavaConfig.newBuilder().withPreserveForSecondPass(true).build()
);
String result = tag.interpret(tagNode, preserveInterpreter);
try {
assertThat(result)
.isEqualTo(
Resources.toString(
Resources.getResource("tags/rawtag/hubl.jinja"),
StandardCharsets.UTF_8
)
);
} catch (IOException e) {
throw new RuntimeException(e);
}
}

@Test
public void itPreservesDeferredWhilePreservingRawTags() {
TagNode tagNode = fixture("deferred");
JinjavaInterpreter preserveInterpreter = new JinjavaInterpreter(
jinjava,
jinjava.getGlobalContextCopy(),
JinjavaConfig.newBuilder().withPreserveForSecondPass(true).build()
);
preserveInterpreter.getContext().put("deferred", DeferredValue.instance());
interpreter.getContext().put("deferred", DeferredValue.instance());

String preservedResult = tag.interpret(tagNode, preserveInterpreter);
String nonPreservedResult = tag.interpret(tagNode, interpreter);
try {
assertThat(preservedResult)
.isEqualTo(
Resources
.toString(
Resources.getResource("tags/rawtag/deferred.jinja"),
StandardCharsets.UTF_8
)
.trim()
);
} catch (IOException e) {
throw new RuntimeException(e);
}
assertThat(nonPreservedResult).isEqualTo("{{ deferred }}");

// Should not get evaluated because it's wrapped in a raw tag.
String deferredRealValue = "Resolved value.";
preserveInterpreter.getContext().put("deferred", deferredRealValue);
interpreter.getContext().put("deferred", deferredRealValue);
String preservedIdempotent = tag.interpret(
(TagNode) new TreeParser(preserveInterpreter, preservedResult)
.buildTree()
.getChildren()
.getFirst(),
preserveInterpreter
);
String secondPass = tag.interpret(
(TagNode) new TreeParser(interpreter, preservedResult)
.buildTree()
.getChildren()
.getFirst(),
interpreter
);

assertThat(preservedIdempotent).isEqualTo(preservedResult);
assertThat(secondPass).isEqualTo("{{ deferred }}");
}

private TagNode fixture(String name) {
return (TagNode) fixtures(name).getFirst();
}
Expand Down
1 change: 1 addition & 0 deletions src/test/resources/tags/rawtag/deferred.jinja
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{% raw %}{{ deferred }}{% endraw %}

0 comments on commit cc5905f

Please sign in to comment.