From d912e54bd0db99a1021ecba79ec720192f46c29b Mon Sep 17 00:00:00 2001 From: Jack Smith Date: Fri, 20 Oct 2023 13:20:26 -0400 Subject: [PATCH] Add whitespace trimming functionality for notes and expressions --- .../com/hubspot/jinjava/tree/TreeParser.java | 58 +++++++------------ .../hubspot/jinjava/tree/parse/NoteToken.java | 5 ++ .../com/hubspot/jinjava/tree/parse/Token.java | 5 -- .../hubspot/jinjava/tree/TreeParserTest.java | 14 +++++ 4 files changed, 41 insertions(+), 41 deletions(-) diff --git a/src/main/java/com/hubspot/jinjava/tree/TreeParser.java b/src/main/java/com/hubspot/jinjava/tree/TreeParser.java index 07fbbb142..bc6f62557 100644 --- a/src/main/java/com/hubspot/jinjava/tree/TreeParser.java +++ b/src/main/java/com/hubspot/jinjava/tree/TreeParser.java @@ -62,12 +62,7 @@ public Node buildTree() { Node node = nextNode(); if (node != null) { - if (node instanceof TextNode && getLastSibling() instanceof TextNode) { - // merge adjacent text nodes so whitespace control properly applies - getLastSibling().getMaster().mergeImageAndContent(node.getMaster()); - } else { - parent.getChildren().add(node); - } + parent.getChildren().add(node); } } @@ -96,6 +91,12 @@ public Node buildTree() { private Node nextNode() { Token token = scanner.next(); + if (token.isLeftTrim()) { + final Node lastSibling = getLastSibling(); + if (lastSibling instanceof TextNode) { + lastSibling.getMaster().setRightTrim(true); + } + } if (token.getType() == symbols.getFixed()) { if (token instanceof UnclosedToken) { @@ -170,7 +171,7 @@ private Node text(TextToken textToken) { final Node lastSibling = getLastSibling(); // if last sibling was a tag and has rightTrimAfterEnd, strip whitespace - if (lastSibling instanceof TagNode && isRightTrim((TagNode) lastSibling)) { + if (lastSibling != null && isRightTrim(lastSibling)) { textToken.setLeftTrim(true); } @@ -186,18 +187,21 @@ private Node text(TextToken textToken) { return n; } - private boolean isRightTrim(TagNode lastSibling) { - return ( - lastSibling.getEndName() == null || - ( - lastSibling.getTag() instanceof FlexibleTag && - !((FlexibleTag) lastSibling.getTag()).hasEndTag( - (TagToken) lastSibling.getMaster() - ) + private boolean isRightTrim(Node lastSibling) { + if (lastSibling instanceof TagNode) { + return ( + ((TagNode) lastSibling).getEndName() == null || + ( + ((TagNode) lastSibling).getTag() instanceof FlexibleTag && + !((FlexibleTag) ((TagNode) lastSibling).getTag()).hasEndTag( + (TagToken) lastSibling.getMaster() + ) + ) ) - ) - ? lastSibling.getMaster().isRightTrim() - : lastSibling.getMaster().isRightTrimAfterEnd(); + ? lastSibling.getMaster().isRightTrim() + : lastSibling.getMaster().isRightTrimAfterEnd(); + } + return lastSibling.getMaster().isRightTrim(); } private Node expression(ExpressionToken expressionToken) { @@ -242,14 +246,6 @@ private Node tag(TagToken tagToken) { if (tag instanceof EndTag) { endTag(tag, tagToken); return null; - } else { - // if a tag has left trim, mark the last sibling to trim right whitespace - if (tagToken.isLeftTrim()) { - final Node lastSibling = getLastSibling(); - if (lastSibling instanceof TextNode) { - lastSibling.getMaster().setRightTrim(true); - } - } } TagNode node = new TagNode(tag, tagToken, symbols); @@ -268,16 +264,6 @@ private Node tag(TagToken tagToken) { } private void endTag(Tag tag, TagToken tagToken) { - final Node lastSibling = getLastSibling(); - - if ( - parent instanceof TagNode && - tagToken.isLeftTrim() && - lastSibling instanceof TextNode - ) { - lastSibling.getMaster().setRightTrim(true); - } - if (parent.getMaster() != null) { // root node parent.getMaster().setRightTrimAfterEnd(tagToken.isRightTrim()); } diff --git a/src/main/java/com/hubspot/jinjava/tree/parse/NoteToken.java b/src/main/java/com/hubspot/jinjava/tree/parse/NoteToken.java index fe98c4dda..c57f8e124 100644 --- a/src/main/java/com/hubspot/jinjava/tree/parse/NoteToken.java +++ b/src/main/java/com/hubspot/jinjava/tree/parse/NoteToken.java @@ -15,6 +15,8 @@ **********************************************************************/ package com.hubspot.jinjava.tree.parse; +import org.apache.commons.lang3.StringUtils; + public class NoteToken extends Token { private static final long serialVersionUID = -3859011447900311329L; @@ -37,6 +39,9 @@ public int getType() { */ @Override protected void parse() { + if (StringUtils.isNotEmpty(image)) { + handleTrim(image.substring(2, image.length() - 2)); + } content = ""; } diff --git a/src/main/java/com/hubspot/jinjava/tree/parse/Token.java b/src/main/java/com/hubspot/jinjava/tree/parse/Token.java index dda5bd63b..487987626 100644 --- a/src/main/java/com/hubspot/jinjava/tree/parse/Token.java +++ b/src/main/java/com/hubspot/jinjava/tree/parse/Token.java @@ -53,11 +53,6 @@ public String getImage() { return image; } - public void mergeImageAndContent(Token otherToken) { - this.image = image + otherToken.image; - this.content = content + otherToken.content; - } - public int getLineNumber() { return lineNumber; } diff --git a/src/test/java/com/hubspot/jinjava/tree/TreeParserTest.java b/src/test/java/com/hubspot/jinjava/tree/TreeParserTest.java index 6ba9065ca..b31e82cc3 100644 --- a/src/test/java/com/hubspot/jinjava/tree/TreeParserTest.java +++ b/src/test/java/com/hubspot/jinjava/tree/TreeParserTest.java @@ -224,6 +224,20 @@ public void itWarnsTwiceAgainstUnclosedBlockTag() { assertThat(interpreter.getErrors().get(1).getLineno()).isEqualTo(1); } + @Test + public void itTrimsNotes() { + String expression = "A\n{#- note -#}\nB"; + final Node tree = new TreeParser(interpreter, expression).buildTree(); + assertThat(interpreter.render(tree)).isEqualTo("AB"); + } + + @Test + public void itTrimsExpressions() { + String expression = "A\n{{- 'B' -}}\nC"; + final Node tree = new TreeParser(interpreter, expression).buildTree(); + assertThat(interpreter.render(tree)).isEqualTo("ABC"); + } + Node parse(String fixture) { try { return new TreeParser(