Skip to content

Commit 3ea83c5

Browse files
hs-lsongclaude
andcommitted
feat(mode): Preserve set tags and include tags in PreserveUnknownExecutionMode
Enable deferredExecutionMode to preserve set tags in output while still evaluating their right-hand side expressions. This allows multi-pass rendering where: - `{% set a = 1 %}` is preserved as-is - `{% set b = a %}` becomes `{% set b = 1 %}` (RHS evaluated) - Unknown variables remain deferred: `{% set x = unknown %}` Also added tests for include tag behavior with unknown paths and unknown variables in included templates. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <[email protected]>
1 parent 4c2e582 commit 3ea83c5

File tree

2 files changed

+79
-0
lines changed

2 files changed

+79
-0
lines changed

src/main/java/com/hubspot/jinjava/mode/PreserveUnknownExecutionMode.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,5 +42,6 @@ public void prepareContext(Context context) {
4242
.forEach(maybeEagerTag -> context.registerTag(maybeEagerTag.get()));
4343

4444
context.setDynamicVariableResolver(varName -> DeferredValue.instance());
45+
context.setDeferredExecutionMode(true);
4546
}
4647
}

src/test/java/com/hubspot/jinjava/mode/PreserveUnknownExecutionModeTest.java

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@
44

55
import com.hubspot.jinjava.Jinjava;
66
import com.hubspot.jinjava.JinjavaConfig;
7+
import com.hubspot.jinjava.loader.ResourceLocator;
8+
import java.io.IOException;
9+
import java.nio.charset.Charset;
710
import java.util.HashMap;
811
import java.util.Map;
912
import org.junit.Before;
@@ -115,4 +118,79 @@ public void itPreservesComplexExpression() {
115118
String result = jinjava.render(template, new HashMap<>());
116119
assertThat(result).isEqualTo("{{ obj.property }}");
117120
}
121+
122+
@Test
123+
public void itPreservesIncludeWithUnknownPath() {
124+
String template = "{% include unknown_path %}";
125+
String result = jinjava.render(template, new HashMap<>());
126+
assertThat(result).isEqualTo("{% include unknown_path %}");
127+
}
128+
129+
@Test
130+
public void itRendersIncludeWithKnownPath() {
131+
jinjava.setResourceLocator(
132+
new ResourceLocator() {
133+
@Override
134+
public String getString(
135+
String fullName,
136+
Charset encoding,
137+
com.hubspot.jinjava.interpret.JinjavaInterpreter interpreter
138+
) throws IOException {
139+
if ("test.html".equals(fullName)) {
140+
return "included content";
141+
}
142+
throw new IOException("Template not found: " + fullName);
143+
}
144+
}
145+
);
146+
String template = "{% include 'test.html' %}";
147+
String result = jinjava.render(template, new HashMap<>());
148+
assertThat(result).isEqualTo("included content");
149+
}
150+
151+
@Test
152+
public void itPreservesUnknownVariablesInIncludedTemplate() {
153+
jinjava.setResourceLocator(
154+
new ResourceLocator() {
155+
@Override
156+
public String getString(
157+
String fullName,
158+
Charset encoding,
159+
com.hubspot.jinjava.interpret.JinjavaInterpreter interpreter
160+
) throws IOException {
161+
if ("test.html".equals(fullName)) {
162+
return "Hello {{ unknown_var }}";
163+
}
164+
throw new IOException("Template not found: " + fullName);
165+
}
166+
}
167+
);
168+
String template = "{% include 'test.html' %}";
169+
String result = jinjava.render(template, new HashMap<>());
170+
assertThat(result).isEqualTo("Hello {{ unknown_var }}");
171+
}
172+
173+
@Test
174+
public void itPreservesSetWithUnknownValue() {
175+
String template = "{% set var = unknown %}{{ var }}";
176+
String result = jinjava.render(template, new HashMap<>());
177+
assertThat(result).isEqualTo("{% set var = unknown %}{{ var }}");
178+
}
179+
180+
@Test
181+
public void itPreservesSetWithLiteralValue() {
182+
String template = "{% set a = 1 %}{{ a }}";
183+
String result = jinjava.render(template, new HashMap<>());
184+
// With deferredExecutionMode=true, set tag is preserved but {{ a }} is evaluated to 1
185+
assertThat(result).isEqualTo("{% set a = 1 %}1");
186+
}
187+
188+
@Test
189+
public void itEvaluatesSetRightSideWhenPossible() {
190+
String template = "{% set a = 1 %}{% set b = a %}{{ b }}";
191+
String result = jinjava.render(template, new HashMap<>());
192+
// Both set tags are preserved with evaluated right-hand sides
193+
// {{ b }} is evaluated because b is known (set to 1)
194+
assertThat(result).isEqualTo("{% set a = 1 %}{% set b = 1 %}1");
195+
}
118196
}

0 commit comments

Comments
 (0)