You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ra...@apache.org on 2018/06/08 19:22:15 UTC
[sling-org-apache-sling-scripting-sightly-compiler] branch master
updated: SLING-7549 - tag is not being treated as "self closing"
when used in conjunction with HTL block statements
This is an automated email from the ASF dual-hosted git repository.
radu pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-sightly-compiler.git
The following commit(s) were added to refs/heads/master by this push:
new c470800 SLING-7549 - <link> tag is not being treated as "self closing" when used in conjunction with HTL block statements
c470800 is described below
commit c4708006176521fcd92723541b1f8af361c80ebf
Author: Radu Cotescu <ra...@apache.org>
AuthorDate: Fri Jun 8 21:22:04 2018 +0200
SLING-7549 - <link> tag is not being treated as "self closing" when used in conjunction with HTL block statements
* corrected HTML's parser behaviour for HTML5 void elements by not requiring that such a tag is
explicitly closed
---
.../sightly/impl/html/dom/HtmlParser.java | 12 +-
.../sightly/impl/html/dom/TreeTraverser.java | 4 +-
.../html/dom/template/TemplateElementNode.java | 4 +-
.../sightly/impl/html/dom/HtmlParserTest.java | 142 ++++++++++++++++++++-
4 files changed, 150 insertions(+), 12 deletions(-)
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/HtmlParser.java b/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/HtmlParser.java
index 877e8c4..6fce2b3 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/HtmlParser.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/HtmlParser.java
@@ -21,6 +21,10 @@ package org.apache.sling.scripting.sightly.impl.html.dom;
import java.io.CharArrayWriter;
import java.io.IOException;
import java.io.Reader;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
/**
* HTML parser. Invokes a <code>DocumentHandler</code> whenever an event occurs.
@@ -68,6 +72,9 @@ public final class HtmlParser {
/** Expression state constant */
private final static int EXPR_MAYBE = 1;
+ final static Set<String> VOID_ELEMENTS = Collections.unmodifiableSet(new HashSet<>(
+ Arrays.asList("area", "base", "br", "col", "embed", "hr", "img", "input", "link", "meta", "param", "source", "track", "wbr")));
+
/** Parse state */
private PARSE_STATE parseState = PARSE_STATE.OUTSIDE;
@@ -479,9 +486,8 @@ public final class HtmlParser {
tokenizer.tokenize(snippet, 0, snippet.length);
if (!tokenizer.endTag()) {
- documentHandler.onStartElement(tokenizer.tagName(), tokenizer
- .attributes(), tokenizer
- .endSlash());
+ documentHandler.onStartElement(tokenizer.tagName(), tokenizer.attributes(),
+ tokenizer.endSlash() || VOID_ELEMENTS.contains(tokenizer.tagName().toLowerCase()));
} else {
documentHandler.onEndElement(tokenizer.tagName());
}
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java b/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java
index 30e2701..43611d7 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java
@@ -57,12 +57,12 @@ public class TreeTraverser {
}
String tagName = elem.getName();
- if (elem.isHasStartElement()) {
+ if (elem.isStartElement()) {
handler.onOpenTagStart("<" + tagName, tagName);
for (TemplateAttribute attribute : elem.getAttributes()) {
handler.onAttribute(attribute.getName(), attribute.getValue(), attribute.getQuoteChar());
}
- if (elem.isHasEndSlash()) {
+ if (elem.hasEndSlash()) {
handler.onOpenTagEnd("/>");
} else {
handler.onOpenTagEnd(">");
diff --git a/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateElementNode.java b/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateElementNode.java
index 266a748..d6b04be 100644
--- a/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateElementNode.java
+++ b/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateElementNode.java
@@ -55,11 +55,11 @@ public class TemplateElementNode extends TemplateNode {
return name;
}
- public boolean isHasEndSlash() {
+ public boolean hasEndSlash() {
return hasEndSlash;
}
- public boolean isHasStartElement() {
+ public boolean isStartElement() {
return hasStartElement;
}
diff --git a/src/test/java/org/apache/sling/scripting/sightly/impl/html/dom/HtmlParserTest.java b/src/test/java/org/apache/sling/scripting/sightly/impl/html/dom/HtmlParserTest.java
index c849cf7..c1ea70b 100644
--- a/src/test/java/org/apache/sling/scripting/sightly/impl/html/dom/HtmlParserTest.java
+++ b/src/test/java/org/apache/sling/scripting/sightly/impl/html/dom/HtmlParserTest.java
@@ -18,20 +18,33 @@
******************************************************************************/
package org.apache.sling.scripting.sightly.impl.html.dom;
+import java.io.IOException;
import java.io.StringReader;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashSet;
import java.util.List;
+import java.util.Set;
import org.apache.commons.lang3.StringUtils;
-import org.apache.sling.scripting.sightly.impl.html.dom.template.*;
-
+import org.apache.sling.scripting.sightly.impl.html.dom.template.Template;
+import org.apache.sling.scripting.sightly.impl.html.dom.template.TemplateCommentNode;
+import org.apache.sling.scripting.sightly.impl.html.dom.template.TemplateElementNode;
+import org.apache.sling.scripting.sightly.impl.html.dom.template.TemplateNode;
+import org.apache.sling.scripting.sightly.impl.html.dom.template.TemplateParser;
+import org.apache.sling.scripting.sightly.impl.html.dom.template.TemplateTextNode;
import org.junit.Test;
import org.powermock.reflect.Whitebox;
import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
public class HtmlParserTest {
+ private static final String DATA_TEST_ATTRIBUTE = "data-test-attribute";
+
/**
* Pretty print a template nodes structure for debugging of failed tests
*
@@ -79,7 +92,7 @@ public class HtmlParserTest {
*/
private static void assertSameStructure(TemplateNode reference, TemplateNode parsed) {
if (parsed == null || reference == null) {
- assertTrue("Expecting both null", parsed == reference);
+ assertSame("Expecting both null", parsed, reference);
return;
}
assertEquals("Expecting same class", reference.getClass(), parsed.getClass());
@@ -113,7 +126,7 @@ public class HtmlParserTest {
}
if (parsedChildren == null || referenceChildren == null) {
- assertTrue("Expecting both children null", parsedChildren == referenceChildren);
+ assertSame("Expecting both children null", parsedChildren, referenceChildren);
return;
}
@@ -130,7 +143,7 @@ public class HtmlParserTest {
* Create a basic template nodes structure containing one text nodes and one comment nodes
*
* @param textAndComment - String containing text (optional) and comment
- * @return
+ * @return a reference template
*/
private Template createReference(String textAndComment) {
int commentIx = textAndComment.indexOf("<!");
@@ -185,4 +198,123 @@ public class HtmlParserTest {
throw e;
}
}
+
+ @Test
+ public void testVoidElements() throws IOException {
+ VoidAndSelfClosingElementsDocumentHandler voidAndSelfClosingElementsDocumentHandler = new VoidAndSelfClosingElementsDocumentHandler();
+ for (String tag : HtmlParser.VOID_ELEMENTS) {
+ StringReader stringReader = new StringReader("<" + tag + " " + DATA_TEST_ATTRIBUTE + ">");
+ HtmlParser.parse(stringReader, voidAndSelfClosingElementsDocumentHandler);
+ assertEquals("Parsed tag is not what was expected.", tag, voidAndSelfClosingElementsDocumentHandler.getLastProcessedTag());
+ }
+ assertEquals("Expected 0 invocations for 'onEndElement'", 0, voidAndSelfClosingElementsDocumentHandler.onEndElementInvocations);
+ assertEquals("Expected as many invocations for 'onStartElement' as many void elements.", HtmlParser.VOID_ELEMENTS.size(),
+ voidAndSelfClosingElementsDocumentHandler.onStartElementInvocations);
+
+ HtmlParser.parse(new StringReader("<img " + DATA_TEST_ATTRIBUTE + "/>"), voidAndSelfClosingElementsDocumentHandler);
+ assertEquals("Expected 0 invocations for 'onEndElement'", 0, voidAndSelfClosingElementsDocumentHandler.onEndElementInvocations);
+ assertEquals("Expected as many invocations for 'onStartElement' as many void elements + 1.", HtmlParser.VOID_ELEMENTS.size() + 1,
+ voidAndSelfClosingElementsDocumentHandler.onStartElementInvocations);
+ }
+
+ @Test
+ public void testExplicitlyClosedElements() throws IOException {
+ TestDocumentHandler handler = new TestDocumentHandler();
+ Set<String> tags = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("a", "p", "div")));
+ for (String tag : tags) {
+ StringReader stringReader = new StringReader("<" + tag + " " + DATA_TEST_ATTRIBUTE + "></" + tag + ">");
+ HtmlParser.parse(stringReader, handler);
+ assertEquals("Parsed tag is not what was expected.", tag, handler.getLastProcessedTag());
+ }
+ assertEquals("Expected as many invocations for 'onEndElement' as many test elements.", tags.size(),
+ handler.onEndElementInvocations);
+ assertEquals("Expected as many invocations for 'onStartElement' as many test elements.", tags.size(),
+ handler.onStartElementInvocations);
+ }
+
+ abstract class AbstractDocumentHandler implements DocumentHandler {
+
+ private String lastProcessedTag;
+
+ @Override
+ public void onCharacters(char[] ch, int off, int len) {
+
+ }
+
+ @Override
+ public void onComment(String characters) {
+
+ }
+
+ @Override
+ public void onStartElement(String name, AttributeList attList, boolean endSlash) {
+ lastProcessedTag = name;
+ }
+
+ @Override
+ public void onEndElement(String name) {
+
+ }
+
+ @Override
+ public void onStart() {
+
+ }
+
+ @Override
+ public void onEnd() {
+
+ }
+
+ String getLastProcessedTag() {
+ return lastProcessedTag;
+ }
+ }
+
+ class VoidAndSelfClosingElementsDocumentHandler extends AbstractDocumentHandler {
+
+ int onEndElementInvocations = 0;
+ int onStartElementInvocations = 0;
+
+ @Override
+ public void onStartElement(String name, AttributeList attList, boolean endSlash) {
+ super.onStartElement(name, attList, endSlash);
+ assertTrue("Expected a " + DATA_TEST_ATTRIBUTE + ".",
+ attList.attributeCount() == 1 && attList.containsAttribute(DATA_TEST_ATTRIBUTE) &&
+ attList.getValue(DATA_TEST_ATTRIBUTE) == null);
+ assertTrue("Expected a self-closing attribute.", endSlash);
+ onStartElementInvocations++;
+ }
+
+ @Override
+ public void onEndElement(String name) {
+ super.onEndElement(name);
+ onEndElementInvocations++;
+ }
+ }
+
+ class TestDocumentHandler extends AbstractDocumentHandler {
+ int onEndElementInvocations = 0;
+ int onStartElementInvocations = 0;
+
+ @Override
+ public void onStartElement(String name, AttributeList attList, boolean endSlash) {
+ super.onStartElement(name, attList, endSlash);
+ assertTrue("Expected a " + DATA_TEST_ATTRIBUTE + ".",
+ attList.attributeCount() == 1 && attList.containsAttribute(DATA_TEST_ATTRIBUTE) &&
+ attList.getValue(DATA_TEST_ATTRIBUTE) == null);
+ assertFalse("Did not expect a self-closing attribute.", endSlash);
+ onStartElementInvocations++;
+ }
+
+ @Override
+ public void onEndElement(String name) {
+ super.onEndElement(name);
+ onEndElementInvocations++;
+ }
+ }
+
+
+
+
}
--
To stop receiving notification emails like this one, please contact
radu@apache.org.