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("\"", "&quot;");
     }
 
-    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);


Reply via email to