You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2014/11/14 15:05:03 UTC

svn commit: r1639641 [11/15] - in /sling/trunk/contrib/scripting/sightly: ./ engine/ engine/src/ engine/src/main/ engine/src/main/antlr4/ engine/src/main/antlr4/org/ engine/src/main/antlr4/org/apache/ engine/src/main/antlr4/org/apache/sling/ engine/src...

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateAttribute.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateAttribute.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateAttribute.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateAttribute.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,43 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.html.dom.template;
+
+public class TemplateAttribute {
+
+    private final String name;
+
+    private final String value;
+
+    public TemplateAttribute(final String name, final String value) {
+        this.name = name;
+        this.value = value;
+    }
+
+    public String getName() {
+        return this.name;
+    }
+
+    public String getValue() {
+        return this.value;
+    }
+
+    public boolean hasValue() {
+        return value != null;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateCommentNode.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateCommentNode.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateCommentNode.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateCommentNode.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.html.dom.template;
+
+public class TemplateCommentNode extends TemplateNode {
+
+    private final String text;
+
+    public TemplateCommentNode(final String t) {
+        this.text = t;
+    }
+
+    public String getText() {
+        return this.text;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateElementNode.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateElementNode.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateElementNode.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateElementNode.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,81 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.html.dom.template;
+
+import java.util.ArrayList;
+import java.util.List;
+
+public class TemplateElementNode extends TemplateNode {
+
+    private final String name;
+
+    private final boolean hasEndSlash;
+
+    private boolean hasEndElement = false;
+
+    private boolean hasStartElement = false;
+
+    private final List<TemplateAttribute> attributes;
+
+    private final List<TemplateNode> children = new ArrayList<TemplateNode>();
+
+    public TemplateElementNode(final String name,
+                               final boolean hasEndSlash,
+                               final List<TemplateAttribute> attributes) {
+        this.name = name;
+        this.hasEndSlash = hasEndSlash;
+        this.attributes = attributes;
+    }
+
+    public void setHasStartElement() {
+        this.hasStartElement = true;
+    }
+
+    public void setHasEndElement() {
+        this.hasEndElement = true;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public boolean isHasEndSlash() {
+        return hasEndSlash;
+    }
+
+    public boolean isHasStartElement() {
+        return hasStartElement;
+    }
+
+    public boolean isHasEndElement() {
+        return hasEndElement;
+    }
+
+    public List<TemplateAttribute> getAttributes() {
+        return attributes;
+    }
+
+    public void addChild(final TemplateNode node) {
+        this.children.add(node);
+    }
+
+    public List<TemplateNode> getChildren() {
+        return this.children;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateNode.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateNode.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateNode.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateNode.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,23 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.html.dom.template;
+
+public abstract class TemplateNode {
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateParser.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateParser.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateParser.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateParser.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,139 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.html.dom.template;
+
+import org.apache.sling.scripting.sightly.html.dom.AttributeList;
+import org.apache.sling.scripting.sightly.html.dom.DocumentHandler;
+import org.apache.sling.scripting.sightly.html.dom.HtmlParser;
+
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Deque;
+import java.util.ArrayDeque;
+
+/**
+ * The template parser parses an HTML document and returns a reusable tree
+ * representation.
+ */
+public class TemplateParser {
+
+    /**
+     * Parse an html document
+     * @param reader to be parsed
+     * @throws IOException in case of any parsing error
+     *
+     * @return a Template
+     */
+    public Template parse(final Reader reader) throws IOException {
+        final TemplateParserContext context = new TemplateParserContext();
+
+        HtmlParser.parse(reader, context);
+
+        return context.getTemplate();
+    }
+
+    public static final class TemplateParserContext implements DocumentHandler {
+
+        /** Used for text/character events */
+        private StringBuilder textBuilder = new StringBuilder();
+
+        /** Element stack - root is the Template */
+        private final Deque<TemplateElementNode> elementStack = new ArrayDeque<TemplateElementNode>();
+
+        /** The template. */
+        private Template template;
+
+        public Template getTemplate() {
+            return this.template;
+        }
+
+        public void onStart() throws IOException {
+            this.template = new Template();
+            this.elementStack.push(this.template);
+        }
+
+        public void onEnd() throws IOException {
+            this.checkText();
+            this.elementStack.clear();
+        }
+
+        private void checkText() {
+            if (textBuilder.length() > 0) {
+                elementStack.peek().addChild(new TemplateTextNode(textBuilder.toString()));
+                this.textBuilder = new StringBuilder();
+            }
+        }
+
+        public void onStartElement(String name, AttributeList attList, boolean endSlash) {
+            this.checkText();
+            final List<TemplateAttribute> attrs = new ArrayList<TemplateAttribute>();
+            final Iterator<String> iter = attList.attributeNames();
+            while ( iter.hasNext() ) {
+                final String aName = iter.next();
+                final TemplateAttribute attr = new TemplateAttribute(aName, attList.getValue(aName));
+                attrs.add(attr);
+            }
+            final TemplateElementNode element = new TemplateElementNode(name, endSlash, attrs);
+            element.setHasStartElement();
+            elementStack.peek().addChild(element);
+            if ( !endSlash ) {
+                elementStack.push(element);
+            }
+        }
+
+        public void onEndElement(String name) {
+            this.checkText();
+            if (contains(name)) {
+                TemplateElementNode element = this.elementStack.pop();
+                while ( !name.equals(element.getName()) ) {
+                    element = this.elementStack.pop();
+                }
+                element.setHasEndElement();
+            } else {
+                final TemplateElementNode element
+                        = new TemplateElementNode(name, false, new ArrayList<TemplateAttribute>());
+                elementStack.peek().addChild(element);
+                element.setHasEndElement();
+            }
+        }
+
+        public void onCharacters(final char[] ch, final int off, final int len) {
+            textBuilder.append(ch, off, len);
+        }
+
+        public void onComment(final String text) throws IOException {
+            this.checkText();
+            elementStack.peek().addChild(new TemplateCommentNode(text));
+        }
+
+        private boolean contains(String name) {
+            Iterator it = this.elementStack.iterator(); // ascending iterator
+            while (it.hasNext()) {
+                TemplateElementNode elem = (TemplateElementNode) it.next();
+                if (name.equals(elem.getName())) {
+                    return true;
+                }
+            }
+            return false;
+        }
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateTextNode.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateTextNode.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateTextNode.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/html/dom/template/TemplateTextNode.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,32 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.html.dom.template;
+
+public class TemplateTextNode extends TemplateNode {
+
+    private final String text;
+
+    public TemplateTextNode(final String t) {
+        this.text = t;
+    }
+
+    public String getText() {
+        return this.text;
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/AttributePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/AttributePlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/AttributePlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/AttributePlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,360 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import org.apache.sling.scripting.sightly.compiler.Syntax;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperation;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperator;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BooleanConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.PropertyAccess;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.RuntimeCall;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.StringConstant;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.MarkupContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Loop;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutText;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.html.MarkupUtils;
+
+/**
+ * Implementation for the attribute plugin
+ */
+@Component
+@Service
+@Properties({
+        @Property(name = "service.description", value = "Sightly Resource Block Plugin"),
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "attribute"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = 150)
+})
+public class AttributePlugin extends PluginComponent {
+
+    private static final Logger log = LoggerFactory.getLogger(AttributePlugin.class);
+
+    @Override
+    public PluginInvoke invoke(Expression expression, PluginCallInfo callInfo, CompilerContext compilerContext) {
+        String attributeName = decodeAttributeName(callInfo);
+        if (attributeName != null && MarkupUtils.isSensitiveAttribute(attributeName)) {
+            log.warn("Refusing to generate attribute {} for security reasons", attributeName);
+            return new DefaultPluginInvoke(); //no-op invocation
+        }
+        return (attributeName != null)
+                ? new SingleAttributeInvoke(attributeName, expression, compilerContext)
+                : new MultiAttributeInvoke(expression.getRoot(), compilerContext);
+    }
+
+    private String decodeAttributeName(PluginCallInfo info) {
+        String[] arguments = info.getArguments();
+        if (arguments.length == 0) {
+            return null;
+        }
+        return StringUtils.join(arguments, '-');
+    }
+
+    private final class SingleAttributeInvoke extends DefaultPluginInvoke {
+        private final String attributeName;
+        private final String isTrueValue;
+        private final String escapedAttrValue;
+        private final String shouldDisplayAttribute;
+
+        private boolean writeAtEnd = true;
+        private boolean beforeCall = true;
+        private final String attrValue;
+        private final ExpressionNode node;
+        private final ExpressionNode contentNode;
+
+        private SingleAttributeInvoke(String attributeName, Expression expression, CompilerContext compilerContext) {
+            this.attributeName = attributeName;
+            this.attrValue = compilerContext.generateVariable("attrValue_" + attributeName);
+            this.escapedAttrValue = compilerContext.generateVariable("attrValueEscaped_" + attributeName);
+            this.isTrueValue = compilerContext.generateVariable("isTrueValue_" + attributeName);
+            this.shouldDisplayAttribute = compilerContext.generateVariable("shouldDisplayAttr_" + attributeName);
+            this.node = expression.getRoot();
+            if (!expression.containsOption(Syntax.CONTEXT_OPTION)) {
+                this.contentNode = escapeNodeWithHint(compilerContext, new Identifier(attrValue), MarkupContext.ATTRIBUTE, new StringConstant(attributeName));
+            } else {
+                this.contentNode = new Identifier(attrValue);
+            }
+        }
+
+        @Override
+        public void beforeAttribute(PushStream stream, String attributeName) {
+            if (attributeName.equals(this.attributeName)) {
+                if (beforeCall) {
+                    emitStart(stream);
+                }
+                writeAtEnd = false;
+            }
+        }
+
+        @Override
+        public void beforeAttributeValue(PushStream stream, String attributeName, ExpressionNode attributeValue) {
+            if (attributeName.equals(this.attributeName) && beforeCall) {
+                emitWrite(stream);
+                Patterns.beginStreamIgnore(stream);
+            }
+        }
+
+        @Override
+        public void afterAttributeValue(PushStream stream, String attributeName) {
+            if (attributeName.equals(this.attributeName) && beforeCall) {
+                Patterns.endStreamIgnore(stream);
+            }
+        }
+
+        @Override
+        public void afterAttribute(PushStream stream, String attributeName) {
+            if (attributeName.equals(this.attributeName) && beforeCall) {
+                emitEnd(stream);
+            }
+        }
+
+        @Override
+        public void afterAttributes(PushStream stream) {
+            if (writeAtEnd) {
+                emitStart(stream);
+                stream.emit(new OutText(" " + this.attributeName));
+                emitWrite(stream);
+                emitEnd(stream);
+            }
+        }
+
+        @Override
+        public void onPluginCall(PushStream stream, PluginCallInfo callInfo, Expression expression) {
+            if ("attribute".equals(callInfo.getName())) {
+                String attributeName = decodeAttributeName(callInfo);
+                if (this.attributeName.equals(attributeName)) {
+                    beforeCall = false;
+                }
+            }
+        }
+
+        private void emitStart(PushStream stream) {
+            stream.emit(new VariableBinding.Start(attrValue, node));
+            stream.emit(new VariableBinding.Start(escapedAttrValue, contentNode));
+            stream.emit(
+                    new VariableBinding.Start(
+                            shouldDisplayAttribute,
+                            new BinaryOperation(
+                                    BinaryOperator.OR,
+                                    new Identifier(escapedAttrValue),
+                                    new BinaryOperation(BinaryOperator.EQ, new StringConstant("false"), new Identifier(attrValue))
+                            )
+                    )
+            );
+            stream.emit(new Conditional.Start(shouldDisplayAttribute, true));
+        }
+
+        private void emitWrite(PushStream stream) {
+            stream.emit(new VariableBinding.Start(isTrueValue,
+                    new BinaryOperation(BinaryOperator.EQ,
+                            new Identifier(attrValue),
+                            BooleanConstant.TRUE)));
+            stream.emit(new Conditional.Start(isTrueValue, false));
+            stream.emit(new OutText("=\""));
+            stream.emit(new OutVariable(escapedAttrValue));
+            stream.emit(new OutText("\""));
+            stream.emit(Conditional.END);
+            stream.emit(VariableBinding.END);
+        }
+
+        private void emitEnd(PushStream stream) {
+            stream.emit(Conditional.END);
+            stream.emit(VariableBinding.END);
+            stream.emit(VariableBinding.END);
+            stream.emit(VariableBinding.END);
+        }
+    }
+
+    private final class MultiAttributeInvoke extends DefaultPluginInvoke {
+
+        private final ExpressionNode attrMap;
+        private final String attrMapVar;
+        private final CompilerContext compilerContext;
+        private boolean beforeCall = true;
+        private final Set<String> ignored = new HashSet<String>();
+
+        private MultiAttributeInvoke(ExpressionNode attrMap, CompilerContext context) {
+            this.attrMap = attrMap;
+            this.compilerContext = context;
+            this.attrMapVar = context.generateVariable("attrMap");
+        }
+
+        @Override
+        public void beforeAttributes(PushStream stream) {
+            stream.emit(new VariableBinding.Start(attrMapVar, attrMap));
+        }
+
+        @Override
+        public void beforeAttribute(PushStream stream, String attributeName) {
+            ignored.add(attributeName);
+            if (beforeCall) {
+                String attrNameVar = compilerContext.generateVariable("attrName_" + attributeName);
+                String attrValue = compilerContext.generateVariable("mapContains_" + attributeName);
+                stream.emit(new VariableBinding.Start(attrNameVar, new StringConstant(attributeName)));
+                stream.emit(new VariableBinding.Start(attrValue, attributeValueNode(new StringConstant(attributeName))));
+                writeAttribute(stream, attrNameVar, attrValue);
+                stream.emit(new Conditional.Start(attrValue, false));
+            }
+        }
+
+        @Override
+        public void afterAttribute(PushStream stream, String attributeName) {
+            if (beforeCall) {
+                stream.emit(Conditional.END);
+                stream.emit(VariableBinding.END);
+                stream.emit(VariableBinding.END);
+            }
+        }
+
+        @Override
+        public void onPluginCall(PushStream stream, PluginCallInfo callInfo, Expression expression) {
+            if ("attribute".equals(callInfo.getName())) {
+                String attrName = decodeAttributeName(callInfo);
+                if (attrName == null) {
+                    beforeCall = false;
+                } else {
+                    if (!beforeCall) {
+                        ignored.add(attrName);
+                    }
+                }
+            }
+        }
+
+        @Override
+        public void afterAttributes(PushStream stream) {
+            HashMap<String, ExpressionNode> ignoredLiteralMap = new HashMap<String, ExpressionNode>();
+            for (String attr : ignored) {
+                ignoredLiteralMap.put(attr, new BooleanConstant(true));
+            }
+            MapLiteral ignoredLiteral = new MapLiteral(ignoredLiteralMap);
+            String ignoredVar = compilerContext.generateVariable("ignoredAttributes");
+            stream.emit(new VariableBinding.Start(ignoredVar, ignoredLiteral));
+            String attrNameVar = compilerContext.generateVariable("attrName");
+            String attrNameEscaped = compilerContext.generateVariable("attrNameEscaped");
+            String attrIndex = compilerContext.generateVariable("attrIndex");
+            stream.emit(new Loop.Start(attrMapVar, attrNameVar, attrIndex));
+            stream.emit(new VariableBinding.Start(attrNameEscaped, escapeNode(new Identifier(attrNameVar), MarkupContext.ATTRIBUTE_NAME, null)));
+            stream.emit(new Conditional.Start(attrNameEscaped, true));
+            String isIgnoredAttr = compilerContext.generateVariable("isIgnoredAttr");
+            stream.emit(new VariableBinding.Start(isIgnoredAttr, new PropertyAccess(new Identifier(ignoredVar), new Identifier(attrNameVar))));
+            stream.emit(new Conditional.Start(isIgnoredAttr, false));
+            String attrContent = compilerContext.generateVariable("attrContent");
+            stream.emit(new VariableBinding.Start(attrContent, attributeValueNode(new Identifier(attrNameVar))));
+            writeAttribute(stream, attrNameEscaped, attrContent);
+            stream.emit(VariableBinding.END); //end of attrContent
+            stream.emit(Conditional.END);
+            stream.emit(VariableBinding.END);
+            stream.emit(Conditional.END);
+            stream.emit(VariableBinding.END);
+            stream.emit(Loop.END);
+            stream.emit(VariableBinding.END);
+            stream.emit(VariableBinding.END);
+        }
+
+        private void writeAttribute(PushStream stream, String attrNameVar, String attrContentVar) {
+            String escapedContent = compilerContext.generateVariable("attrContentEscaped");
+            String shouldDisplayAttribute = compilerContext.generateVariable("shouldDisplayAttr");
+            stream.emit(new VariableBinding.Start(escapedContent, escapedExpression(new Identifier(attrContentVar), new Identifier(attrNameVar))));
+            stream.emit(
+                    new VariableBinding.Start(
+                            shouldDisplayAttribute,
+                            new BinaryOperation(
+                                    BinaryOperator.OR,
+                                    new Identifier(escapedContent),
+                                    new BinaryOperation(BinaryOperator.EQ, new StringConstant("false"), new Identifier(attrContentVar))
+                            )
+                    )
+            );
+            stream.emit(new Conditional.Start(shouldDisplayAttribute, true));
+            stream.emit(new OutText(" "));   //write("attrName");
+            writeAttributeName(stream, attrNameVar);
+            writeAttributeValue(stream, escapedContent, attrContentVar);
+            stream.emit(Conditional.END);
+            stream.emit(VariableBinding.END);
+            stream.emit(VariableBinding.END);
+        }
+
+        private void writeAttributeName(PushStream stream, String attrNameVar) {
+            stream.emit(new OutVariable(attrNameVar));
+        }
+
+        private void writeAttributeValue(PushStream stream, String escapedContent, String attrContentVar) {
+
+            String isTrueVar = compilerContext.generateVariable("isTrueAttr"); // holds the comparison (attrValue == true)
+            stream.emit(new VariableBinding.Start(isTrueVar, //isTrueAttr = (attrContent == true)
+                    new BinaryOperation(BinaryOperator.EQ, new Identifier(attrContentVar), BooleanConstant.TRUE)));
+            stream.emit(new Conditional.Start(isTrueVar, false)); //if (!isTrueAttr)
+            stream.emit(new OutText("=\""));
+
+            stream.emit(new OutVariable(escapedContent)); //write(escapedContent)
+
+            stream.emit(new OutText("\""));
+            stream.emit(Conditional.END); //end if isTrueAttr
+            stream.emit(VariableBinding.END); //end scope for isTrueAttr
+        }
+
+        private ExpressionNode attributeValueNode(ExpressionNode attributeNameNode) {
+            return new PropertyAccess(new Identifier(attrMapVar), attributeNameNode);
+        }
+
+        private ExpressionNode escapedExpression(ExpressionNode original, ExpressionNode hint) {
+            return escapeNode(original, MarkupContext.ATTRIBUTE, hint);
+        }
+
+        private ExpressionNode escapeNode(ExpressionNode node, MarkupContext markupContext, ExpressionNode hint) {
+            return escapeNodeWithHint(compilerContext, node, markupContext, hint);
+        }
+    }
+
+    private static ExpressionNode escapeNodeWithHint(CompilerContext compilerContext, ExpressionNode node, MarkupContext markupContext, ExpressionNode hint) {
+        if (hint != null) {
+            //todo: this is not the indicated way to escape via XSS. Correct after modifying the compiler context API
+            return new RuntimeCall("xss", node, new StringConstant(markupContext.getName()), hint);
+        }
+        return compilerContext.adjustToContext(new Expression(node), markupContext).getRoot();
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/CallPlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/CallPlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/CallPlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/CallPlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,87 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginException;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Procedure;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.*;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+
+/**
+ * Implementation for the {@code data-sly-call} plugin.
+ */
+@Component
+@Service(Plugin.class)
+@Properties({
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "call"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = 3)
+})
+public class CallPlugin extends PluginComponent {
+
+    @Override
+    public PluginInvoke invoke(final Expression expression,
+                               final PluginCallInfo callInfo,
+                               final CompilerContext compilerContext) {
+        if (callInfo.getArguments().length > 0) {
+            throw new PluginException(this, "Call plugin should have no arguments");
+        }
+        return new DefaultPluginInvoke() {
+
+            @Override
+            public void beforeChildren(PushStream stream) {
+                String templateVar = compilerContext.generateVariable("templateVar");
+                String argsVar = compilerContext.generateVariable("templateOptions");
+                MapLiteral args = new MapLiteral(expression.getOptions());
+                stream.emit(new VariableBinding.Start(templateVar, expression.getRoot()));
+                stream.emit(new VariableBinding.Start(argsVar, args));
+                stream.emit(new Procedure.Call(templateVar, argsVar));
+                stream.emit(VariableBinding.END);
+                stream.emit(VariableBinding.END);
+                //ignoring everything else
+                Patterns.beginStreamIgnore(stream);
+            }
+
+            @Override
+            public void afterChildren(PushStream stream) {
+                Patterns.endStreamIgnore(stream);
+            }
+
+        };
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ElementPlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ElementPlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ElementPlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ElementPlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,113 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.plugin;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.MarkupContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutText;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.MarkupContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutText;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+
+/**
+ * Implementation for the {@code data-sly-element} plugin.
+ */
+@Component
+@Service
+@Properties({
+        @Property(name = "service.description", value = "Sightly Resource Block Plugin"),
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "element"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = PluginComponent.DEFAULT_PRIORITY)
+})
+public class ElementPlugin extends PluginComponent {
+
+    @Override
+    public PluginInvoke invoke(final Expression expression, final PluginCallInfo callInfo, final CompilerContext compilerContext) {
+
+        return new DefaultPluginInvoke() {
+
+            private final ExpressionNode node = compilerContext.adjustToContext(expression, MarkupContext.ELEMENT_NAME).getRoot();
+            private String tagVar = compilerContext.generateVariable("tagVar");
+
+            @Override
+            public void beforeElement(PushStream stream, String tagName) {
+                stream.emit(new VariableBinding.Start(tagVar, node));
+            }
+
+            @Override
+            public void beforeTagOpen(PushStream stream) {
+                stream.emit(new Conditional.Start(tagVar, true));
+                stream.emit(new OutText("<"));
+                stream.emit(new OutVariable(tagVar));
+                stream.emit(Conditional.END);
+                stream.emit(new Conditional.Start(tagVar, false));
+            }
+
+            @Override
+            public void beforeAttributes(PushStream stream) {
+                stream.emit(Conditional.END);
+            }
+
+            @Override
+            public void beforeTagClose(PushStream stream, boolean isSelfClosing) {
+                if (!isSelfClosing) {
+                    stream.emit(new Conditional.Start(tagVar, true));
+                    stream.emit(new OutText("</"));
+                    stream.emit(new OutVariable(tagVar));
+                    stream.emit(new OutText(">"));
+                    stream.emit(Conditional.END);
+                }
+                stream.emit(new Conditional.Start(tagVar, false));
+            }
+
+            @Override
+            public void afterTagClose(PushStream stream, boolean isSelfClosing) {
+                stream.emit(Conditional.END);
+            }
+
+            @Override
+            public void afterElement(PushStream stream) {
+                stream.emit(VariableBinding.END);
+            }
+        };
+
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/IncludePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/IncludePlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/IncludePlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/IncludePlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+
+package org.apache.sling.scripting.sightly.plugin;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.RuntimeCall;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.RuntimeCall;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+
+/**
+ * Implementation for the include plugin
+ */
+@Component
+@Service(Plugin.class)
+@Properties({
+        @Property(name = "service.description", value = "Sightly Include Block Plugin"),
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "include"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = PluginComponent.DEFAULT_PRIORITY)
+})
+public class IncludePlugin extends PluginComponent {
+
+    public static final String FUNCTION = "include";
+
+    @Override
+    public PluginInvoke invoke(final Expression expression, final PluginCallInfo callInfo, final CompilerContext compilerContext) {
+        return new DefaultPluginInvoke() {
+
+            @Override
+            public void beforeChildren(PushStream stream) {
+                String includedContentVar = compilerContext.generateVariable("includedResult");
+                String pathVar = compilerContext.generateVariable("includePath");
+                stream.emit(new VariableBinding.Start(pathVar, expression.getRoot()));
+                stream.emit(new VariableBinding.Start(includedContentVar,
+                        new RuntimeCall(FUNCTION, new Identifier(pathVar), new MapLiteral(expression.getOptions()))));
+                stream.emit(new OutVariable(includedContentVar));
+                stream.emit(VariableBinding.END); //end includedContentVar
+                stream.emit(VariableBinding.END); //end pathVar
+                Patterns.beginStreamIgnore(stream);
+            }
+
+            @Override
+            public void afterChildren(PushStream stream) {
+                Patterns.endStreamIgnore(stream);
+            }
+        };
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ListPlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ListPlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ListPlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ListPlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,151 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import java.util.HashMap;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.Syntax;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperation;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.BinaryOperator;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.Identifier;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.NumericConstant;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.UnaryOperation;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.UnaryOperator;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Loop;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.Syntax;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.*;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Loop;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+
+/**
+ * Default implementation of the {@code data-sly-list} plugin.
+ */
+@Component()
+@Service(Plugin.class)
+@Properties({
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "list"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = 130)
+})
+public class ListPlugin extends PluginComponent {
+
+
+    private static final String INDEX = "index";
+    private static final String COUNT = "count";
+    private static final String FIRST = "first";
+    private static final String MIDDLE = "middle";
+    private static final String LAST = "last";
+    private static final String ODD = "odd";
+    private static final String EVEN = "even";
+
+    @Override
+    public PluginInvoke invoke(final Expression expression, final PluginCallInfo callInfo, final CompilerContext compilerContext) {
+        return new DefaultPluginInvoke() {
+
+            private String listVariable = compilerContext.generateVariable("collectionVar");
+            private String collectionSizeVar = compilerContext.generateVariable("size");
+
+            @Override
+            public void beforeElement(PushStream stream, String tagName) {
+                stream.emit(new VariableBinding.Start(listVariable, expression.getRoot()));
+                stream.emit(new VariableBinding.Start(collectionSizeVar,
+                        new UnaryOperation(UnaryOperator.LENGTH, new Identifier(listVariable))));
+                stream.emit(new Conditional.Start(collectionSizeVar, true));
+
+            }
+
+            @Override
+            public void beforeChildren(PushStream stream) {
+                String itemVariable = decodeItemVariable();
+                String loopStatusVar = Syntax.itemLoopStatusVariable(itemVariable);
+                String indexVariable = compilerContext.generateVariable("index");
+                stream.emit(new Loop.Start(listVariable, itemVariable, indexVariable));
+                stream.emit(new VariableBinding.Start(loopStatusVar, buildStatusObj(indexVariable, collectionSizeVar)));
+            }
+
+            @Override
+            public void afterChildren(PushStream stream) {
+                stream.emit(VariableBinding.END);
+                stream.emit(Loop.END);
+            }
+
+            @Override
+            public void afterElement(PushStream stream) {
+                stream.emit(Conditional.END);
+                stream.emit(VariableBinding.END);
+                stream.emit(VariableBinding.END);
+            }
+
+
+            private String decodeItemVariable() {
+                String[] args = callInfo.getArguments();
+                if (args.length > 0) {
+                    return args[0];
+                }
+                return Syntax.DEFAULT_LIST_ITEM_VAR_NAME;
+            }
+
+            private MapLiteral buildStatusObj(String indexVar, String sizeVar) {
+                HashMap<String, ExpressionNode> obj = new HashMap<String, ExpressionNode>();
+                Identifier indexId = new Identifier(indexVar);
+                BinaryOperation firstExpr = new BinaryOperation(BinaryOperator.EQ, indexId, NumericConstant.ZERO);
+                BinaryOperation lastExpr = new BinaryOperation(
+                        BinaryOperator.EQ,
+                        indexId,
+                        new BinaryOperation(BinaryOperator.SUB, new Identifier(sizeVar), NumericConstant.ONE));
+                obj.put(INDEX, indexId);
+                obj.put(COUNT, new BinaryOperation(BinaryOperator.ADD, indexId, NumericConstant.ONE));
+                obj.put(FIRST, firstExpr);
+                obj.put(MIDDLE, new UnaryOperation(
+                        UnaryOperator.NOT,
+                        new BinaryOperation(BinaryOperator.OR, firstExpr, lastExpr)));
+                obj.put(LAST, lastExpr);
+                obj.put(ODD, parityCheck(indexId, NumericConstant.ZERO));
+                obj.put(EVEN, parityCheck(indexId, NumericConstant.ONE));
+                return new MapLiteral(obj);
+            }
+
+            private ExpressionNode parityCheck(ExpressionNode numericExpression, NumericConstant expected) {
+                return new BinaryOperation(
+                        BinaryOperator.EQ,
+                        new BinaryOperation(BinaryOperator.REM, numericExpression, NumericConstant.TWO),
+                        expected);
+            }
+        };
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/PluginComponent.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/PluginComponent.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/PluginComponent.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/PluginComponent.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,64 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import java.util.Dictionary;
+
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.osgi.service.component.ComponentContext;
+import org.osgi.service.component.ComponentException;
+
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+
+/**
+ * Component plugin implementation
+ */
+public abstract class PluginComponent implements Plugin {
+
+    public static final int DEFAULT_PRIORITY = 100;
+
+    private int priority;
+    private String name;
+
+    @Override
+    public int priority() {
+        return priority;
+    }
+
+    @Override
+    public String name() {
+        return name;
+    }
+
+    @Override
+    public int compareTo(Plugin o) {
+        return this.priority() - o.priority();
+    }
+
+    @SuppressWarnings("UnusedDeclaration")
+    protected void activate(ComponentContext componentContext) {
+        Dictionary properties = componentContext.getProperties();
+        priority = PropertiesUtil.toInteger(properties.get(SCR_PROP_NAME_PRIORITY), DEFAULT_PRIORITY);
+        name = PropertiesUtil.toString(properties.get(SCR_PROP_NAME_BLOCK_NAME), null);
+        if (name == null) {
+            throw new ComponentException("The plugin hasn't a valid name specified");
+        }
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ResourcePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ResourcePlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ResourcePlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/ResourcePlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,90 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.MapLiteral;
+import org.apache.sling.scripting.sightly.compiler.api.expression.node.RuntimeCall;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+
+/**
+ * The resource plugin
+ */
+@Component
+@Service(Plugin.class)
+@Properties({
+        @Property(name = "service.description", value = "Sightly Resource Block Plugin"),
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "resource"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = PluginComponent.DEFAULT_PRIORITY)
+})
+public class ResourcePlugin extends PluginComponent {
+
+    public static final String FUNCTION = "includeResource";
+
+    @Override
+    public PluginInvoke invoke(final Expression expression,
+                               final PluginCallInfo callInfo,
+                               final CompilerContext compilerContext) {
+
+        return new DefaultPluginInvoke() {
+
+            private Map<String, ExpressionNode> expressionOptions = new HashMap<String, ExpressionNode>(expression.getOptions());
+
+            @Override
+            public void beforeChildren(PushStream stream) {
+                String resourceVar = compilerContext.generateVariable("resourceContent");
+                stream.emit(new VariableBinding.Start(resourceVar,
+                        new RuntimeCall(FUNCTION,
+                                expression.getRoot(), new MapLiteral(expressionOptions))));
+                stream.emit(new OutVariable(resourceVar));
+                stream.emit(VariableBinding.END);
+                Patterns.beginStreamIgnore(stream);
+            }
+
+            @Override
+            public void afterChildren(PushStream stream) {
+                Patterns.endStreamIgnore(stream);
+            }
+
+        };
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TemplatePlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TemplatePlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TemplatePlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TemplatePlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,111 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.expression.ExpressionNode;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginException;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Procedure;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+
+/**
+ * The template plugin
+ */
+@Component
+@Service
+@Properties({
+        @Property(name = "service.description", value = "Sightly Template Block Plugin"),
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "template"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = Integer.MIN_VALUE)
+})
+public class TemplatePlugin extends PluginComponent {
+    @Override
+    public PluginInvoke invoke(final Expression expressionNode,
+                               final PluginCallInfo callInfo,
+                               CompilerContext compilerContext) {
+        return new DefaultPluginInvoke() {
+
+            @Override
+            public void beforeTagOpen(PushStream stream) {
+                //ignoring template tags
+                Patterns.beginStreamIgnore(stream);
+            }
+
+            @Override
+            public void beforeElement(PushStream stream, String tagName) {
+                String name = decodeName();
+                Set<String> parameters = extractParameters();
+                stream.emit(new Procedure.Start(name, parameters));
+            }
+
+            @Override
+            public void afterElement(PushStream stream) {
+                stream.emit(Procedure.END);
+            }
+
+            @Override
+            public void afterTagOpen(PushStream stream) {
+                Patterns.endStreamIgnore(stream); //resuming normal operation
+            }
+
+            @Override
+            public void beforeTagClose(PushStream stream, boolean isSelfClosing) {
+                Patterns.beginStreamIgnore(stream); //ignoring closing tags
+            }
+
+            @Override
+            public void afterTagClose(PushStream stream, boolean isSelfClosing) {
+                Patterns.endStreamIgnore(stream);
+            }
+
+            private Set<String> extractParameters() {
+                Map<String, ExpressionNode> options = expressionNode.getOptions();
+                return options.keySet();
+            }
+
+            private String decodeName() {
+                String[] arguments = callInfo.getArguments();
+                if (arguments.length == 0) {
+                    throw new PluginException(TemplatePlugin.this, "template name was not provided");
+                }
+                return arguments[0];
+            }
+        };
+    }
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TestPlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TestPlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TestPlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TestPlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,100 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Conditional;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+
+/**
+ * Implementation for the test plugin
+ */
+@Component
+@Service(Plugin.class)
+@Properties({
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "test"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = 1)
+})
+public class TestPlugin extends PluginComponent {
+
+
+    @Override
+    public PluginInvoke invoke(final Expression expressionNode,
+                               final PluginCallInfo callInfo,
+                               final CompilerContext compilerContext) {
+
+        return new DefaultPluginInvoke() {
+
+            private boolean globalBinding;
+
+            @Override
+            public void beforeElement(PushStream stream, String tagName) {
+                String variableName = decodeVariableName();
+                globalBinding = variableName != null;
+                if (variableName == null) {
+                    variableName = compilerContext.generateVariable("testVariable");
+                }
+                if (globalBinding) {
+                    stream.emit(new VariableBinding.Global(variableName, expressionNode.getRoot()));
+                } else {
+                    stream.emit(new VariableBinding.Start(variableName, expressionNode.getRoot()));
+                }
+                stream.emit(new Conditional.Start(variableName, true));
+            }
+
+            @Override
+            public void afterElement(PushStream stream) {
+                stream.emit(Conditional.END);
+                if (!globalBinding) {
+                    stream.emit(VariableBinding.END);
+                }
+            }
+
+            private String decodeVariableName() {
+                String[] args = callInfo.getArguments();
+                if (args.length > 0) {
+                    return args[0];
+                }
+                return null;
+            }
+
+        };
+    }
+
+
+}

Added: sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TextPlugin.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TextPlugin.java?rev=1639641&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TextPlugin.java (added)
+++ sling/trunk/contrib/scripting/sightly/engine/src/main/java/org/apache/sling/scripting/sightly/plugin/TextPlugin.java Fri Nov 14 14:04:56 2014
@@ -0,0 +1,72 @@
+/*******************************************************************************
+ * 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.
+ ******************************************************************************/
+package org.apache.sling.scripting.sightly.plugin;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Service;
+
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.CompilerContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.MarkupContext;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.Plugin;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.OutVariable;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.VariableBinding;
+import org.apache.sling.scripting.sightly.compiler.common.DefaultPluginInvoke;
+import org.apache.sling.scripting.sightly.compiler.util.stream.PushStream;
+import org.apache.sling.scripting.sightly.compiler.api.expression.Expression;
+import org.apache.sling.scripting.sightly.compiler.api.plugin.PluginCallInfo;
+import org.apache.sling.scripting.sightly.compiler.api.ris.command.Patterns;
+
+/**
+ * The {@code data-sly-text} plugin.
+ */
+@Component
+@Service(Plugin.class)
+@Properties({
+        @Property(name = Plugin.SCR_PROP_NAME_BLOCK_NAME, value = "text"),
+        @Property(name = Plugin.SCR_PROP_NAME_PRIORITY, intValue = 9)
+})
+public class TextPlugin extends PluginComponent {
+
+    @Override
+    public PluginInvoke invoke(final Expression expression, PluginCallInfo callInfo, final CompilerContext compilerContext) {
+        return new DefaultPluginInvoke() {
+
+            @Override
+            public void beforeChildren(PushStream stream) {
+                String variable = compilerContext.generateVariable("textContent");
+                stream.emit(new VariableBinding.Start(variable,
+                        compilerContext.adjustToContext(expression, MarkupContext.TEXT).getRoot()));
+                stream.emit(new OutVariable(variable));
+                stream.emit(VariableBinding.END);
+                Patterns.beginStreamIgnore(stream);
+            }
+
+            @Override
+            public void afterChildren(PushStream stream) {
+                Patterns.endStreamIgnore(stream);
+            }
+        };
+    }
+}