Author: radu
Date: Thu Jan 28 13:45:49 2016
New Revision: 1727349
URL: http://svn.apache.org/viewvc?rev=1727349&view=rev
Log:
SLING-5461 - Sightly quotes all markup attributes' values with double quotes
* attributes' quotes from the script are now maintained in the outputted markup
Added:
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/attributequotes/
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/attributequotes/attributequotes.html
Modified:
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/MarkupHandler.java
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateAttribute.java
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateParser.java
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json
sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java
Modified:
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java?rev=1727349&r1=1727348&r2=1727349&view=diff
==============================================================================
---
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java
(original)
+++
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/compiler/frontend/ElementContext.java
Thu Jan 28 13:45:49 2016
@@ -23,7 +23,6 @@ import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
-import java.util.Map;
import org.apache.sling.scripting.sightly.impl.compiler.expression.Expression;
import org.apache.sling.scripting.sightly.impl.html.dom.MarkupHandler;
@@ -38,7 +37,7 @@ public class ElementContext {
private final String openTagStartMarkup;
private final List<PrioritizedInvoke> invokeList = new
ArrayList<PrioritizedInvoke>();
- private final List<Map.Entry<String, Object>> attributes = new
ArrayList<Map.Entry<String, Object>>();
+ private final List<Attribute> attributes = new ArrayList<Attribute>();
private PluginInvoke aggregateInvoke;
public ElementContext(String tagName, String openTagStartMarkup) {
@@ -58,16 +57,16 @@ public class ElementContext {
invokeList.add(new PrioritizedInvoke(invoke, priority));
}
- public void addAttribute(String name, String value) {
- attributes.add(new AbstractMap.SimpleEntry<String, Object>(name,
value));
+ public void addAttribute(String name, String value, char quoteChar) {
+ attributes.add(new Attribute(name, value, quoteChar));
}
public void addPluginCall(String name, PluginCallInfo info, Expression
expression) {
- attributes.add(new AbstractMap.SimpleEntry<String, Object>(name,
- new AbstractMap.SimpleEntry<PluginCallInfo, Expression>(info,
expression)));
+ attributes.add(new Attribute(name,
+ new AbstractMap.SimpleEntry<PluginCallInfo, Expression>(info,
expression), '0'));
}
- public Iterable<Map.Entry<String, Object>> getAttributes() {
+ public Iterable<Attribute> getAttributes() {
return attributes;
}
@@ -83,6 +82,30 @@ public class ElementContext {
return aggregateInvoke;
}
+ public static class Attribute {
+ private String name;
+ private Object value;
+ private char quoteChar;
+
+ public Attribute(String name, Object value, char quoteChar) {
+ this.name = name;
+ this.value = value;
+ this.quoteChar = quoteChar;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public Object getValue() {
+ return value;
+ }
+
+ public char getQuoteChar() {
+ return quoteChar;
+ }
+ }
+
private static final class PrioritizedInvoke implements
Comparable<PrioritizedInvoke> {
@@ -110,10 +133,7 @@ public class ElementContext {
return false;
}
PrioritizedInvoke that = (PrioritizedInvoke) obj;
- if (this.priority == that.priority) {
- return true;
- }
- return false;
+ return this.priority == that.priority;
}
@Override
Modified:
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/MarkupHandler.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/MarkupHandler.java?rev=1727349&r1=1727348&r2=1727349&view=diff
==============================================================================
---
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/MarkupHandler.java
(original)
+++
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/MarkupHandler.java
Thu Jan 28 13:45:49 2016
@@ -83,12 +83,12 @@ public class MarkupHandler {
elementStack.push(context);
}
- public void onAttribute(String name, String value) {
+ public void onAttribute(String name, String value, char quoteChar) {
ElementContext context = elementStack.peek();
if (Syntax.isPluginAttribute(name)) {
handlePlugin(name, StringUtils.defaultString(value, ""), context);
} else {
- context.addAttribute(name, value);
+ context.addAttribute(name, value, quoteChar);
}
}
@@ -114,12 +114,12 @@ public class MarkupHandler {
}
private void traverseAttributes(ElementContext context, PluginInvoke
invoke) {
- for (Map.Entry<String, Object> attribute : context.getAttributes()) {
- String attrName = attribute.getKey();
+ for (ElementContext.Attribute attribute : context.getAttributes()) {
+ String attrName = attribute.getName();
Object contentObj = attribute.getValue();
if (contentObj == null || contentObj instanceof String) {
String content = (String) contentObj;
- emitAttribute(attrName, content, invoke);
+ emitAttribute(attrName, content, attribute.getQuoteChar(),
invoke);
} else if (contentObj instanceof Map.Entry) {
Map.Entry entry = (Map.Entry) contentObj;
PluginCallInfo info = (PluginCallInfo) entry.getKey();
@@ -129,30 +129,30 @@ public class MarkupHandler {
}
}
- private void emitAttribute(String name, String content, PluginInvoke
invoke) {
+ private void emitAttribute(String name, String content, char quoteChar,
PluginInvoke invoke) {
invoke.beforeAttribute(stream, name);
if (content == null) {
- emitSimpleTextAttribute(name, null, invoke);
+ emitSimpleTextAttribute(name, null, quoteChar, invoke);
} else {
Interpolation interpolation =
expressionParser.parseInterpolation(content);
String text = tryAsSimpleText(interpolation);
if (text != null) {
- emitSimpleTextAttribute(name, text, invoke);
+ emitSimpleTextAttribute(name, text, quoteChar, invoke);
} else {
- emitExpressionAttribute(name, interpolation, invoke);
+ emitExpressionAttribute(name, interpolation, quoteChar,
invoke);
}
}
invoke.afterAttribute(stream, name);
}
- private void emitSimpleTextAttribute(String name, String textValue,
PluginInvoke invoke) {
+ private void emitSimpleTextAttribute(String name, String textValue, char
quoteChar, PluginInvoke invoke) {
emitAttributeStart(name);
invoke.beforeAttributeValue(stream, name, new
StringConstant(textValue));
if (textValue != null) {
- emitAttributeValueStart();
+ emitAttributeValueStart(quoteChar);
textValue = escapeQuotes(textValue);
out(textValue);
- emitAttributeEnd();
+ emitAttributeEnd(quoteChar);
}
invoke.afterAttributeValue(stream, name);
}
@@ -161,16 +161,16 @@ public class MarkupHandler {
return textValue.replace("\"", """);
}
- private void emitExpressionAttribute(String name, Interpolation
interpolation, PluginInvoke invoke) {
+ private void emitExpressionAttribute(String name, Interpolation
interpolation, char quoteChar, PluginInvoke invoke) {
interpolation = attributeChecked(name, interpolation);
if (interpolation.size() == 1) {
- emitSingleFragment(name, interpolation, invoke);
+ emitSingleFragment(name, interpolation, quoteChar, invoke);
} else {
- emitMultipleFragment(name, interpolation, invoke);
+ emitMultipleFragment(name, interpolation, quoteChar, invoke);
}
}
- private void emitMultipleFragment(String name, Interpolation
interpolation, PluginInvoke invoke) {
+ private void emitMultipleFragment(String name, Interpolation
interpolation, char quoteChar, PluginInvoke invoke) {
// Simplified algorithm for attribute output, which works when the
interpolation is not of size 1. In this
// case we are certain that the attribute value cannot be the boolean
value true, so we can skip this test
// altogether
@@ -191,16 +191,16 @@ public class MarkupHandler {
stream.emit(new Conditional.Start(shouldDisplayAttr, true));
emitAttributeStart(name);
invoke.beforeAttributeValue(stream, name, expression.getRoot());
- emitAttributeValueStart();
+ emitAttributeValueStart(quoteChar);
stream.emit(new OutVariable(attrContent));
- emitAttributeEnd();
+ emitAttributeEnd(quoteChar);
invoke.afterAttributeValue(stream, name);
stream.emit(Conditional.END);
stream.emit(VariableBinding.END);
stream.emit(VariableBinding.END);
}
- private void emitSingleFragment(String name, Interpolation interpolation,
PluginInvoke invoke) {
+ private void emitSingleFragment(String name, Interpolation interpolation,
char quoteChar, PluginInvoke invoke) {
Expression valueExpression =
expressionWrapper.transform(interpolation, null, ExpressionContext.ATTRIBUTE);
//raw expression
String attrValue = symbolGenerator.next("attrValue"); //holds the raw
attribute value
String attrContent = symbolGenerator.next("attrContent"); //holds the
escaped attribute value
@@ -228,9 +228,9 @@ public class MarkupHandler {
stream.emit(new VariableBinding.Start(isTrueVar, //isTrueAttr =
(attrValue == true)
new BinaryOperation(BinaryOperator.EQ, new
Identifier(attrValue), BooleanConstant.TRUE)));
stream.emit(new Conditional.Start(isTrueVar, false)); //if
(!isTrueAttr)
- emitAttributeValueStart(); // write("='");
+ emitAttributeValueStart(quoteChar); // write("='");
stream.emit(new OutVariable(attrContent)); //write(attrContent)
- emitAttributeEnd(); //write("'");
+ emitAttributeEnd(quoteChar); //write("'");
stream.emit(Conditional.END); //end if isTrueAttr
stream.emit(VariableBinding.END); //end scope for isTrueAttr
invoke.afterAttributeValue(stream, name);
@@ -245,12 +245,21 @@ public class MarkupHandler {
out(" " + name);
}
- private void emitAttributeValueStart() {
- out("=\"");
+ private void emitAttributeValueStart(char quoteChar) {
+ char quote = '"';
+ if (quoteChar != 0) {
+ quote = quoteChar;
+ }
+ out("=");
+ out(String.valueOf(quote));
}
- private void emitAttributeEnd() {
- out("\"");
+ private void emitAttributeEnd(char quoteChar) {
+ char quote = '"';
+ if (quoteChar != 0) {
+ quote = quoteChar;
+ }
+ out(String.valueOf(quote));
}
Modified:
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java?rev=1727349&r1=1727348&r2=1727349&view=diff
==============================================================================
---
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java
(original)
+++
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/TreeTraverser.java
Thu Jan 28 13:45:49 2016
@@ -60,7 +60,7 @@ public class TreeTraverser {
if (elem.isHasStartElement()) {
handler.onOpenTagStart("<" + tagName, tagName);
for (TemplateAttribute attribute : elem.getAttributes()) {
- handler.onAttribute(attribute.getName(), attribute.getValue());
+ handler.onAttribute(attribute.getName(), attribute.getValue(),
attribute.getQuoteChar());
}
if (elem.isHasEndSlash()) {
handler.onOpenTagEnd("/>");
Modified:
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateAttribute.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateAttribute.java?rev=1727349&r1=1727348&r2=1727349&view=diff
==============================================================================
---
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateAttribute.java
(original)
+++
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateAttribute.java
Thu Jan 28 13:45:49 2016
@@ -24,9 +24,12 @@ public class TemplateAttribute {
private final String value;
- public TemplateAttribute(final String name, final String value) {
+ private final char quoteChar;
+
+ public TemplateAttribute(final String name, final String value, char
quoteChar) {
this.name = name;
this.value = value;
+ this.quoteChar = quoteChar;
}
public String getName() {
@@ -37,7 +40,7 @@ public class TemplateAttribute {
return this.value;
}
- public boolean hasValue() {
- return value != null;
+ public char getQuoteChar() {
+ return quoteChar;
}
}
Modified:
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateParser.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateParser.java?rev=1727349&r1=1727348&r2=1727349&view=diff
==============================================================================
---
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateParser.java
(original)
+++
sling/trunk/bundles/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/impl/html/dom/template/TemplateParser.java
Thu Jan 28 13:45:49 2016
@@ -89,7 +89,7 @@ public class TemplateParser {
final Iterator<String> iter = attList.attributeNames();
while ( iter.hasNext() ) {
final String aName = iter.next();
- final TemplateAttribute attr = new TemplateAttribute(aName,
attList.getValue(aName));
+ final TemplateAttribute attr = new TemplateAttribute(aName,
attList.getValue(aName), attList.getQuoteChar(aName));
attrs.add(attr);
}
final TemplateElementNode element = new TemplateElementNode(name,
endSlash, attrs);
@@ -126,9 +126,7 @@ public class TemplateParser {
}
private boolean contains(String name) {
- Iterator it = this.elementStack.iterator(); // ascending iterator
- while (it.hasNext()) {
- TemplateElementNode elem = (TemplateElementNode) it.next();
+ for (TemplateElementNode elem : this.elementStack) {
if (name.equals(elem.getName())) {
return true;
}
Added:
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/attributequotes/attributequotes.html
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/attributequotes/attributequotes.html?rev=1727349&view=auto
==============================================================================
---
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/attributequotes/attributequotes.html
(added)
+++
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/apps/sightly/scripts/attributequotes/attributequotes.html
Thu Jan 28 13:45:49 2016
@@ -0,0 +1,25 @@
+<!--/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ ~ Licensed to the Apache Software Foundation (ASF) under one or more
+ ~ contributor license agreements. See the NOTICE file distributed with
+ ~ this work for additional information regarding copyright ownership.
+ ~ The ASF licenses this file to You under the Apache License, Version 2.0
+ ~ (the "License"); you may not use this file except in compliance with
+ ~ the License. You may obtain a copy of the License at
+ ~
+ ~ http://www.apache.org/licenses/LICENSE-2.0
+ ~
+ ~ Unless required by applicable law or agreed to in writing, software
+ ~ distributed under the License is distributed on an "AS IS" BASIS,
+ ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ ~ See the License for the specific language governing permissions and
+ ~ limitations under the License.
+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/-->
+<div id='singleQuotes'>
+ <span data-resource='{"resource" :
"${resource.path}"}'>${resource.path}</span>
+</div>
+<div id="doubleQuotes">
+ <span data-resource="${resource.path}">${resource.path}</span>
+</div>
+<div id=noQuotes>
+ <span data-resource=${resource.path}>${resource.path}</span>
+</div>
Modified:
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json?rev=1727349&r1=1727348&r2=1727349&view=diff
==============================================================================
---
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json
(original)
+++
sling/trunk/bundles/scripting/sightly/testing-content/src/main/resources/SLING-INF/sightly.json
Thu Jan 28 13:45:49 2016
@@ -28,5 +28,9 @@
"use-sibling-dependency-resolution": {
"jcr:primaryType": "nt:unstructured",
"sling:resourceType": "/apps/sightly/scripts/siblingdeps/component"
+ },
+ "attributequotes": {
+ "jcr:primaryType": "nt:unstructured",
+ "sling:resourceType": "/apps/sightly/scripts/attributequotes"
}
}
Modified:
sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java
URL:
http://svn.apache.org/viewvc/sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java?rev=1727349&r1=1727348&r2=1727349&view=diff
==============================================================================
---
sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java
(original)
+++
sling/trunk/bundles/scripting/sightly/testing/src/test/java/org/apache/sling/scripting/sightly/it/SlingSpecificsSightlyIT.java
Thu Jan 28 13:45:49 2016
@@ -20,6 +20,8 @@ package org.apache.sling.scripting.sight
import java.io.IOException;
+import javax.swing.text.html.HTML;
+
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.ContentType;
@@ -49,6 +51,7 @@ public class SlingSpecificsSightlyIT {
private static final String SLING_USE_INHERITANCE_WITHOVERLAY =
"/sightly/useinheritance.html";
private static final String SLING_USE_INHERITANCE_WITHOUTOVERLAY =
"/sightly/useinheritance.notoverlaid.html";
private static final String SLING_JAVA_USE_POJO_UPDATE =
"/sightly/use.repopojo.html";
+ private static final String SLING_ATTRIBUTE_QUOTES =
"/sightly/attributequotes.html";
@BeforeClass
public static void init() {
@@ -176,6 +179,16 @@ public class SlingSpecificsSightlyIT {
assertEquals("nopkg", HTMLExtractor.innerHTML(url, pageContent,
"#repopojo-nopkg"));
}
+ @Test
+ public void testAttributeQuotes() {
+ String url = launchpadURL + SLING_ATTRIBUTE_QUOTES;
+ String pageContent = client.getStringContent(url, 200);
+ // need to test against the raw content
+ assertTrue(pageContent.contains("<span data-resource='{\"resource\" :
\"/sightly/attributequotes\"}'>/sightly/attributequotes</span>"));
+ assertTrue(pageContent.contains("<span
data-resource=\"/sightly/attributequotes\">/sightly/attributequotes</span>"));
+ assertTrue(pageContent.contains("<span
data-resource=\"/sightly/attributequotes\">/sightly/attributequotes</span>"));
+ }
+
private void uploadFile(String fileName, String serverFileName, String
url) throws IOException {
HttpClient httpClient = HttpClientBuilder.create().build();
HttpPost post = new HttpPost(launchpadURL + url);