This is an automated email from the ASF dual-hosted git repository. radu pushed a commit to branch issue/SLING-9829 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-compiler.git
commit ec8ed4b444e5cb37c4682b2a885d9b0a2a04d12d Author: Radu Cotescu <[email protected]> AuthorDate: Wed Oct 21 20:33:58 2020 +0200 SLING-9829 - data-sly-element should correctly handle void elements * defined the set of void elements in ElementPlugin; every time the data-sly-element plugin is used, the dynamically passed tag name will be checked against the set; if the tag is a void element, no closing tag will be added --- .../compiler/expression/nodes/StringConstant.java | 18 +++++ .../compiler/expression/nodes/package-info.java | 2 +- .../impl/compiler/frontend/CompilerContext.java | 4 ++ .../impl/compiler/util/SymbolGenerator.java | 11 +++- .../sightly/impl/plugin/ElementPlugin.java | 77 +++++++++++++++++----- 5 files changed, 94 insertions(+), 18 deletions(-) diff --git a/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/StringConstant.java b/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/StringConstant.java index 2862490..4a6501f 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/StringConstant.java +++ b/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/StringConstant.java @@ -18,6 +18,8 @@ ******************************************************************************/ package org.apache.sling.scripting.sightly.compiler.expression.nodes; +import java.util.Objects; + import org.apache.sling.scripting.sightly.compiler.expression.NodeVisitor; /** @@ -63,4 +65,20 @@ public final class StringConstant implements Atom { '}'; } + @Override + public int hashCode() { + return Objects.hashCode(text); + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } + if (obj instanceof StringConstant) { + StringConstant other = (StringConstant) obj; + return Objects.equals(text, other.text); + } + return false; + } } diff --git a/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/package-info.java b/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/package-info.java index e2c21a3..efda58f 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/package-info.java +++ b/src/main/java/org/apache/sling/scripting/sightly/compiler/expression/nodes/package-info.java @@ -19,7 +19,7 @@ * The {@code org.apache.sling.scripting.sightly.compiler.expression.nodes} package exposes the various * {@link org.apache.sling.scripting.sightly.compiler.expression.ExpressionNode} types. */ -@Version("1.2.0") +@Version("1.2.1") package org.apache.sling.scripting.sightly.compiler.expression.nodes; import org.osgi.annotation.versioning.Version; diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java b/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java index 6096c20..9df6c3b 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java +++ b/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/CompilerContext.java @@ -45,6 +45,10 @@ public class CompilerContext { return symbolGenerator.next(hint); } + public String generateGlobalVariable(String hint) { + return symbolGenerator.global(hint); + } + public Expression adjustToContext(Expression expression, MarkupContext context, ExpressionContext expressionContext) { return expressionWrapper.adjustToContext(expression, context, expressionContext); } diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/util/SymbolGenerator.java b/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/util/SymbolGenerator.java index 6277b1f..39b11bf 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/util/SymbolGenerator.java +++ b/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/util/SymbolGenerator.java @@ -18,12 +18,16 @@ ******************************************************************************/ package org.apache.sling.scripting.sightly.impl.compiler.util; +import java.util.HashMap; +import java.util.Map; + public class SymbolGenerator { public static final String DEFAULT_VAR_PREFIX = "var_"; private int counter = 0; private final String prefix; + private final Map<String, String> globals = new HashMap<>(); public SymbolGenerator() { this(DEFAULT_VAR_PREFIX); @@ -34,10 +38,15 @@ public class SymbolGenerator { } public String next(String hint) { - String middle = (hint != null) ? hint.replaceAll("\\-", "_") : ""; + String middle = (hint != null) ? hint.replace("-", "_") : ""; return prefix + middle + counter++; } + public String global(String hint) { + String name = prefix + ((hint != null) ? hint.replace("-", "_") : ""); + return globals.computeIfAbsent(name, key -> name + counter++); + } + public String next() { return next(null); } diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/ElementPlugin.java b/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/ElementPlugin.java index 29439b1..9a58ef2 100644 --- a/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/ElementPlugin.java +++ b/src/main/java/org/apache/sling/scripting/sightly/impl/plugin/ElementPlugin.java @@ -18,6 +18,12 @@ ******************************************************************************/ package org.apache.sling.scripting.sightly.impl.plugin; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + import org.apache.sling.scripting.sightly.compiler.commands.Conditional; import org.apache.sling.scripting.sightly.compiler.commands.OutText; import org.apache.sling.scripting.sightly.compiler.commands.OutputVariable; @@ -25,7 +31,14 @@ import org.apache.sling.scripting.sightly.compiler.commands.VariableBinding; import org.apache.sling.scripting.sightly.compiler.expression.Expression; import org.apache.sling.scripting.sightly.compiler.expression.ExpressionNode; import org.apache.sling.scripting.sightly.compiler.expression.MarkupContext; +import org.apache.sling.scripting.sightly.compiler.expression.nodes.ArrayLiteral; +import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperation; +import org.apache.sling.scripting.sightly.compiler.expression.nodes.BinaryOperator; +import org.apache.sling.scripting.sightly.compiler.expression.nodes.Identifier; import org.apache.sling.scripting.sightly.compiler.expression.nodes.RuntimeCall; +import org.apache.sling.scripting.sightly.compiler.expression.nodes.StringConstant; +import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperation; +import org.apache.sling.scripting.sightly.compiler.expression.nodes.UnaryOperator; import org.apache.sling.scripting.sightly.impl.compiler.PushStream; import org.apache.sling.scripting.sightly.impl.compiler.frontend.CompilerContext; import org.apache.sling.scripting.sightly.impl.filter.ExpressionContext; @@ -36,27 +49,40 @@ public class ElementPlugin extends AbstractPlugin { name = "element"; } + public static final Set<ExpressionNode> VOID_ELEMENTS = + Collections.unmodifiableSet(new HashSet<>( + Arrays.asList(new StringConstant("area"), new StringConstant("base"), new StringConstant("br"), + new StringConstant("col"), new StringConstant("embed"), new StringConstant("hr"), new StringConstant("img"), + new StringConstant("input"), new StringConstant("link"), new StringConstant("meta"), + new StringConstant("param"), new StringConstant("source"), new StringConstant("track"), + new StringConstant("wbr")))); + @Override public PluginInvoke invoke(final Expression expression, final PluginCallInfo callInfo, final CompilerContext compilerContext) { return new DefaultPluginInvoke() { - private final ExpressionNode node = adjustContext(compilerContext, expression, MarkupContext.ELEMENT_NAME, ExpressionContext - .ELEMENT).getRoot(); - private String tagVar = compilerContext.generateVariable("tagVar"); + private final ExpressionNode node = adjustContext(compilerContext, expression).getRoot(); + private final String tagVar = compilerContext.generateVariable("tagVar"); + private final String tagAllowed = compilerContext.generateVariable("tagAllowed"); + private final String voidElements = compilerContext.generateGlobalVariable("elementPluginVoidElements"); + private final String selfClosingTag = compilerContext.generateVariable("selfClosingTag"); @Override public void beforeElement(PushStream stream, String tagName) { + stream.write(new VariableBinding.Global(voidElements, new ArrayLiteral(new ArrayList<>(VOID_ELEMENTS)))); stream.write(new VariableBinding.Start(tagVar, node)); + stream.write(new VariableBinding.Start(tagAllowed, new UnaryOperation(UnaryOperator.NOT, + new UnaryOperation(UnaryOperator.NOT, new Identifier(tagVar))))); } @Override public void beforeTagOpen(PushStream stream) { - stream.write(new Conditional.Start(tagVar, true)); + stream.write(new Conditional.Start(tagAllowed, true)); stream.write(new OutText("<")); stream.write(new OutputVariable(tagVar)); stream.write(Conditional.END); - stream.write(new Conditional.Start(tagVar, false)); + stream.write(new Conditional.Start(tagAllowed, false)); } @Override @@ -65,15 +91,34 @@ public class ElementPlugin extends AbstractPlugin { } @Override + public void afterAttributes(PushStream stream) { + stream.write(new Conditional.Start(tagAllowed, true)); + stream.write(new OutText(">")); + stream.write(Conditional.END); + stream.write(new Conditional.Start(tagAllowed, false)); + } + + @Override + public void afterTagOpen(PushStream stream) { + stream.write(Conditional.END); + } + + @Override public void beforeTagClose(PushStream stream, boolean isSelfClosing) { - if (!isSelfClosing) { - stream.write(new Conditional.Start(tagVar, true)); - stream.write(new OutText("</")); - stream.write(new OutputVariable(tagVar)); - stream.write(new OutText(">")); - stream.write(Conditional.END); - } - stream.write(new Conditional.Start(tagVar, false)); + stream.write(new Conditional.Start(tagAllowed, true)); + stream.write( + new VariableBinding.Start(selfClosingTag, + new BinaryOperation(BinaryOperator.IN, new Identifier(tagVar), new Identifier(voidElements)) + ) + ); + stream.write(new Conditional.Start(selfClosingTag, false)); + stream.write(new OutText("</")); + stream.write(new OutputVariable(tagVar)); + stream.write(new OutText(">")); + stream.write(Conditional.END); + stream.write(VariableBinding.END); + stream.write(Conditional.END); + stream.write(new Conditional.Start(tagAllowed, false)); } @Override @@ -84,13 +129,13 @@ public class ElementPlugin extends AbstractPlugin { @Override public void afterElement(PushStream stream) { stream.write(VariableBinding.END); + stream.write(VariableBinding.END); } }; } - private Expression adjustContext(CompilerContext compilerContext, Expression expression, MarkupContext markupContext, - ExpressionContext expressionContext) { + private Expression adjustContext(CompilerContext compilerContext, Expression expression) { ExpressionNode root = expression.getRoot(); if (root instanceof RuntimeCall) { RuntimeCall runtimeCall = (RuntimeCall) root; @@ -98,6 +143,6 @@ public class ElementPlugin extends AbstractPlugin { return expression; } } - return compilerContext.adjustToContext(expression, markupContext, expressionContext); + return compilerContext.adjustToContext(expression, MarkupContext.ELEMENT_NAME, ExpressionContext.ELEMENT); } }
