Skip to content

Commit 535c9d4

Browse files
authored
Merge pull request #619 from HubSpot/raw-override
[Eager Execution] Add temporary override for preserveRawTags
2 parents 6b61dbf + ddabd70 commit 535c9d4

File tree

12 files changed

+99
-15
lines changed

12 files changed

+99
-15
lines changed

src/main/java/com/hubspot/jinjava/interpret/Context.java

Lines changed: 32 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
import java.util.Optional;
4646
import java.util.Set;
4747
import java.util.Stack;
48+
import java.util.function.Consumer;
4849
import java.util.stream.Collectors;
4950

5051
public class Context extends ScopeMap<String, Object> {
@@ -104,6 +105,7 @@ public enum Library {
104105
private boolean deferredExecutionMode = false;
105106
private boolean throwInterpreterErrors = false;
106107
private boolean partialMacroEvaluation = false;
108+
private boolean unwrapRawOverride = false;
107109

108110
public Context() {
109111
this(null, null, null, true);
@@ -196,6 +198,7 @@ public Context(
196198
if (parent != null) {
197199
this.expressionStrategy = parent.expressionStrategy;
198200
this.partialMacroEvaluation = parent.partialMacroEvaluation;
201+
this.unwrapRawOverride = parent.unwrapRawOverride;
199202
}
200203
}
201204

@@ -638,24 +641,44 @@ public void setPartialMacroEvaluation(boolean partialMacroEvaluation) {
638641
this.partialMacroEvaluation = partialMacroEvaluation;
639642
}
640643

641-
public PartialMacroEvaluationClosable withPartialMacroEvaluation() {
642-
PartialMacroEvaluationClosable partialMacroEvaluationClosable = new PartialMacroEvaluationClosable(
643-
this.partialMacroEvaluation
644+
public TemporaryValueClosable<Boolean> withPartialMacroEvaluation() {
645+
TemporaryValueClosable<Boolean> temporaryValueClosable = new TemporaryValueClosable<>(
646+
this.partialMacroEvaluation,
647+
this::setPartialMacroEvaluation
644648
);
645649
this.partialMacroEvaluation = true;
646-
return partialMacroEvaluationClosable;
650+
return temporaryValueClosable;
647651
}
648652

649-
public class PartialMacroEvaluationClosable implements AutoCloseable {
650-
private final boolean previousPartialMacroEvaluation;
653+
public boolean isUnwrapRawOverride() {
654+
return unwrapRawOverride;
655+
}
656+
657+
public void setUnwrapRawOverride(boolean unwrapRawOverride) {
658+
this.unwrapRawOverride = unwrapRawOverride;
659+
}
660+
661+
public TemporaryValueClosable<Boolean> withUnwrapRawOverride() {
662+
TemporaryValueClosable<Boolean> temporaryValueClosable = new TemporaryValueClosable<>(
663+
this.unwrapRawOverride,
664+
this::setUnwrapRawOverride
665+
);
666+
this.unwrapRawOverride = true;
667+
return temporaryValueClosable;
668+
}
669+
670+
public static class TemporaryValueClosable<T> implements AutoCloseable {
671+
private final T previousValue;
672+
private final Consumer<T> resetValueConsumer;
651673

652-
private PartialMacroEvaluationClosable(boolean previousPartialMacroEvaluation) {
653-
this.previousPartialMacroEvaluation = previousPartialMacroEvaluation;
674+
private TemporaryValueClosable(T previousValue, Consumer<T> resetValueConsumer) {
675+
this.previousValue = previousValue;
676+
this.resetValueConsumer = resetValueConsumer;
654677
}
655678

656679
@Override
657680
public void close() {
658-
setPartialMacroEvaluation(previousPartialMacroEvaluation);
681+
resetValueConsumer.accept(previousValue);
659682
}
660683
}
661684
}

src/main/java/com/hubspot/jinjava/interpret/JinjavaInterpreter.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import com.hubspot.jinjava.Jinjava;
2828
import com.hubspot.jinjava.JinjavaConfig;
2929
import com.hubspot.jinjava.el.ExpressionResolver;
30+
import com.hubspot.jinjava.interpret.Context.TemporaryValueClosable;
3031
import com.hubspot.jinjava.interpret.TemplateError.ErrorItem;
3132
import com.hubspot.jinjava.interpret.TemplateError.ErrorReason;
3233
import com.hubspot.jinjava.interpret.TemplateError.ErrorType;
@@ -203,7 +204,9 @@ public String renderFlat(String template) {
203204
return template;
204205
} else {
205206
context.setRenderDepth(depth + 1);
206-
return render(parse(template), false);
207+
try (TemporaryValueClosable<Boolean> c = context.withUnwrapRawOverride()) {
208+
return render(parse(template), false);
209+
}
207210
}
208211
} finally {
209212
context.setRenderDepth(depth);

src/main/java/com/hubspot/jinjava/lib/expression/EagerExpressionStrategy.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,7 @@ private static String wrapInRawOrExpressionIfNeeded(
114114
JinjavaConfig config = interpreter.getConfig();
115115
if (
116116
config.getExecutionMode().isPreserveRawTags() &&
117+
!interpreter.getContext().isUnwrapRawOverride() &&
117118
(
118119
output.contains(config.getTokenScannerSymbols().getExpressionStart()) ||
119120
output.contains(config.getTokenScannerSymbols().getExpressionStartWithTag())

src/main/java/com/hubspot/jinjava/lib/fn/MacroFunction.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,9 @@ public String getEvaluationResult(
143143
for (Node node : content) {
144144
result.append(node.render(interpreter));
145145
}
146+
if (interpreter.getConfig().getExecutionMode().isPreserveRawTags()) {
147+
return interpreter.renderFlat(result.toString());
148+
}
146149
return result.toString();
147150
}
148151

src/main/java/com/hubspot/jinjava/lib/tag/RawTag.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,10 @@ public String getName() {
3030

3131
@Override
3232
public String interpret(TagNode tagNode, JinjavaInterpreter interpreter) {
33-
if (interpreter.getConfig().getExecutionMode().isPreserveRawTags()) {
33+
if (
34+
interpreter.getConfig().getExecutionMode().isPreserveRawTags() &&
35+
!interpreter.getContext().isUnwrapRawOverride()
36+
) {
3437
return renderNodeRaw(tagNode);
3538
}
3639

src/main/java/com/hubspot/jinjava/lib/tag/eager/EagerTagDecorator.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -484,7 +484,10 @@ public static String reconstructEnd(TagNode tagNode) {
484484
}
485485

486486
public static String wrapInRawIfNeeded(String output, JinjavaInterpreter interpreter) {
487-
if (interpreter.getConfig().getExecutionMode().isPreserveRawTags()) {
487+
if (
488+
interpreter.getConfig().getExecutionMode().isPreserveRawTags() &&
489+
!interpreter.getContext().isUnwrapRawOverride()
490+
) {
488491
if (
489492
output.contains(
490493
interpreter.getConfig().getTokenScannerSymbols().getExpressionStart()

src/test/java/com/hubspot/jinjava/EagerTest.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,4 +813,9 @@ public void itHandlesUnknownFunctionErrors() {
813813
public void itKeepsMaxMacroRecursionDepth() {
814814
expectedTemplateInterpreter.assertExpectedOutput("keeps-max-macro-recursion-depth");
815815
}
816+
817+
@Test
818+
public void itHandlesComplexRaw() {
819+
expectedTemplateInterpreter.assertExpectedOutput("handles-complex-raw");
820+
}
816821
}

src/test/java/com/hubspot/jinjava/ExpectedTemplateInterpreter.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ public String assertExpectedNonEagerOutput(String name) {
4646
JinjavaInterpreter.pushCurrent(preserveInterpreter);
4747

4848
preserveInterpreter.getContext().putAll(interpreter.getContext());
49-
return assertExpectedOutput(name);
49+
String template = getFixtureTemplate(name);
50+
String output = JinjavaInterpreter.getCurrent().render(template);
51+
assertThat(output.trim()).isEqualTo(expected(name).trim());
52+
return output;
5053
} finally {
5154
JinjavaInterpreter.popCurrent();
5255
}

src/test/java/com/hubspot/jinjava/lib/fn/eager/EagerMacroFunctionTest.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import static org.assertj.core.api.Assertions.assertThatThrownBy;
55

66
import com.hubspot.jinjava.BaseInterpretingTest;
7-
import com.hubspot.jinjava.interpret.Context.PartialMacroEvaluationClosable;
7+
import com.hubspot.jinjava.interpret.Context.TemporaryValueClosable;
88
import com.hubspot.jinjava.interpret.DeferredValue;
99
import com.hubspot.jinjava.interpret.DeferredValueException;
1010
import com.hubspot.jinjava.lib.fn.MacroFunction;
@@ -81,7 +81,7 @@ public void itPartiallyEvaluatesMacroFunction() {
8181
);
8282
assertThatThrownBy(() -> macroFunction.evaluate("Bar"))
8383
.isInstanceOf(DeferredValueException.class);
84-
try (PartialMacroEvaluationClosable ignored = context.withPartialMacroEvaluation()) {
84+
try (TemporaryValueClosable<Boolean> ignored = context.withPartialMacroEvaluation()) {
8585
assertThat(macroFunction.evaluate("Bar")).isEqualTo("It's: Bar, {{ deferred }}");
8686
}
8787
}

src/test/java/com/hubspot/jinjava/lib/tag/RawTagTest.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import com.google.common.io.Resources;
66
import com.hubspot.jinjava.BaseInterpretingTest;
77
import com.hubspot.jinjava.JinjavaConfig;
8+
import com.hubspot.jinjava.interpret.Context.TemporaryValueClosable;
89
import com.hubspot.jinjava.interpret.DeferredValue;
910
import com.hubspot.jinjava.interpret.JinjavaInterpreter;
1011
import com.hubspot.jinjava.mode.PreserveRawExecutionMode;
@@ -117,6 +118,31 @@ public void itPreservesRawTags() {
117118
}
118119
}
119120

121+
@Test
122+
public void itOverridesRawTagPreservation() {
123+
TagNode tagNode = fixture("hubl");
124+
JinjavaInterpreter preserveInterpreter = new JinjavaInterpreter(
125+
jinjava,
126+
jinjava.getGlobalContextCopy(),
127+
JinjavaConfig
128+
.newBuilder()
129+
.withExecutionMode(PreserveRawExecutionMode.instance())
130+
.build()
131+
);
132+
String result;
133+
try (
134+
TemporaryValueClosable<Boolean> c = preserveInterpreter
135+
.getContext()
136+
.withUnwrapRawOverride()
137+
) {
138+
result = tag.interpret(tagNode, preserveInterpreter);
139+
}
140+
assertThat(StringUtils.normalizeSpace(result))
141+
.isEqualTo(
142+
"<h1>Blog Posts</h1> <ul> {% for content in contents %} <li>{{ content.name|title }}</li> {% endfor %} </ul>"
143+
);
144+
}
145+
120146
@Test
121147
public void itPreservesDeferredWhilePreservingRawTags() {
122148
TagNode tagNode = fixture("deferred");

0 commit comments

Comments
 (0)