diff --git a/src/main/java/com/hubspot/jinjava/lib/filter/TruncateHtmlFilter.java b/src/main/java/com/hubspot/jinjava/lib/filter/TruncateHtmlFilter.java index defef913e..b2e6c25a6 100644 --- a/src/main/java/com/hubspot/jinjava/lib/filter/TruncateHtmlFilter.java +++ b/src/main/java/com/hubspot/jinjava/lib/filter/TruncateHtmlFilter.java @@ -3,6 +3,7 @@ import com.hubspot.jinjava.doc.annotations.JinjavaDoc; import com.hubspot.jinjava.doc.annotations.JinjavaParam; import com.hubspot.jinjava.doc.annotations.JinjavaSnippet; +import com.hubspot.jinjava.interpret.DeferredValueException; import com.hubspot.jinjava.interpret.InvalidArgumentException; import com.hubspot.jinjava.interpret.JinjavaInterpreter; import com.hubspot.jinjava.interpret.TemplateError; @@ -141,7 +142,21 @@ public Object filter(Object var, JinjavaInterpreter interpreter, String... args) killwords = BooleanUtils.toBoolean(args[2]); } - Document dom = Jsoup.parseBodyFragment((String) var); + int numDeferredTokensStart = interpreter.getContext().getDeferredTokens().size(); + + String val; + try ( + JinjavaInterpreter.InterpreterScopeClosable ignored = interpreter.enterScope() + ) { + val = interpreter.renderFlat((String) var); + if ( + interpreter.getContext().getDeferredTokens().size() > numDeferredTokensStart + ) { + throw new DeferredValueException("Deferred in TruncateHtmlFilter"); + } + } + + Document dom = Jsoup.parseBodyFragment(val); ContentTruncatingNodeVisitor visitor = new ContentTruncatingNodeVisitor( length, ends, @@ -171,8 +186,7 @@ private static class ContentTruncatingNodeVisitor implements NodeVisitor { @Override public void head(Node node, int depth) { - if (node instanceof TextNode) { - TextNode text = (TextNode) node; + if (node instanceof TextNode text) { String textContent = text.text(); if (textLen >= maxTextLen) { @@ -193,8 +207,7 @@ public void head(Node node, int depth) { @Override public void tail(Node node, int depth) { - if (node instanceof Element) { - Element el = (Element) node; + if (node instanceof Element el) { if (StringUtils.isBlank(el.text())) { el.addClass("__deleteme"); } diff --git a/src/test/java/com/hubspot/jinjava/lib/filter/TruncateHtmlFilterTest.java b/src/test/java/com/hubspot/jinjava/lib/filter/TruncateHtmlFilterTest.java index 963bc2e85..ff97e4562 100644 --- a/src/test/java/com/hubspot/jinjava/lib/filter/TruncateHtmlFilterTest.java +++ b/src/test/java/com/hubspot/jinjava/lib/filter/TruncateHtmlFilterTest.java @@ -1,12 +1,22 @@ package com.hubspot.jinjava.lib.filter; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; import com.google.common.collect.ImmutableMap; import com.google.common.io.Resources; import com.hubspot.jinjava.BaseInterpretingTest; +import com.hubspot.jinjava.interpret.Context; +import com.hubspot.jinjava.interpret.DeferredValueException; +import com.hubspot.jinjava.interpret.JinjavaInterpreter; +import com.hubspot.jinjava.lib.tag.eager.DeferredToken; +import com.hubspot.jinjava.tree.parse.ExpressionToken; import java.io.IOException; import java.nio.charset.StandardCharsets; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicInteger; import org.junit.Before; import org.junit.Test; @@ -54,6 +64,59 @@ public void itDoesntChopWordsWhenSpecified() { ); } + @Test + public void itExecutesJinjavaInsideTag() { + assertThat( + filter.filter("{% for i in [1, 2, 3] %}