You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@syncope.apache.org by il...@apache.org on 2016/07/22 10:18:23 UTC

[3/4] syncope git commit: [SYNCOPE-809] GSoC Project (Eclipse Plugin for Apache Syncope) - This closes #28

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLCompletionProcessor.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLCompletionProcessor.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLCompletionProcessor.java
new file mode 100644
index 0000000..1eefd68
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLCompletionProcessor.java
@@ -0,0 +1,331 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.List;
+import java.util.Stack;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.contentassist.CompletionProposal;
+import org.eclipse.jface.text.contentassist.ContextInformation;
+import org.eclipse.jface.text.contentassist.ContextInformationValidator;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.contentassist.IContextInformation;
+import org.eclipse.jface.text.contentassist.IContextInformationValidator;
+
+public class HTMLCompletionProcessor extends HTMLTemplateAssistProcessor {
+
+    private int offset;
+    private boolean xhtmlMode = false;
+    private char[] chars = {};
+    private boolean assistCloseTag = true;
+    protected String[] getLastWord(final String text) {
+        StringBuilder sb = new StringBuilder();
+        Stack<String> stack = new Stack<String>();
+        String word    = "";
+        String prevTag = "";
+        String lastTag = "";
+        String attr    = "";
+        String temp1   = ""; // temporary
+        String temp2   = ""; // temporary
+        for (int i = 0; i < text.length(); i++) {
+            char c = text.charAt(i);
+            // skip scriptlet
+            if (c == '<' && text.length() > i + 1 && text.charAt(i + 1) == '%') {
+                i = text.indexOf("%>", i + 2);
+                if (i == -1) {
+                    i = text.length();
+                }
+                continue;
+            }
+            // skip XML declaration
+            if (c == '<' && text.length() > i + 1 && text.charAt(i + 1) == '?') {
+                i = text.indexOf("?>", i + 2);
+                if (i == -1) {
+                    i = text.length();
+                }
+                continue;
+            }
+
+            if (isDelimiter(c)) {
+                temp1 = sb.toString();
+
+                // skip whitespaces in the attribute value
+                if (temp1.length() > 1
+                        && ((temp1.startsWith("\"") && !temp1.endsWith("\"") && c != '"')
+                        || (temp1.startsWith("'") && !temp1.endsWith("'") && c != '\''))) {
+                    sb.append(c);
+                    continue;
+                }
+                if (temp1.length() == 1 && ((temp1.equals("\"") || (temp1.equals("'"))))) {
+                    sb.append(c);
+                    continue;
+                }
+
+                if (!temp1.equals("")) {
+                    temp2 = temp1;
+                    if (temp2.endsWith("=") && !prevTag.equals("") && !temp2.equals("=")) {
+                        attr = temp2.substring(0, temp2.length() - 1);
+                    }
+                }
+                if (temp1.startsWith("<") && !temp1.startsWith("</") && !temp1.startsWith("<!")) {
+                    prevTag = temp1.substring(1);
+                    if (!temp1.endsWith("/")) {
+                        stack.push(prevTag);
+                    }
+                } else if (temp1.startsWith("</") && stack.size() != 0) {
+                    stack.pop();
+                } else if ((!temp1.startsWith("\"") && !temp1.startsWith("'"))
+                        && temp1.endsWith("/") && stack.size() != 0) {
+                    stack.pop();
+                }
+                sb.setLength(0);
+
+                if (c == '<') {
+                    sb.append(c);
+                } else if (c == '"' || c == '\'') {
+                    if (temp1.startsWith("\"") || temp1.startsWith("'")) {
+                        sb.append(temp1);
+                    }
+                    sb.append(c);
+                } else if (c == '>') {
+                    prevTag = "";
+                    attr    = "";
+                }
+            } else {
+                if (c == '=' && !prevTag.equals("")) {
+                    attr = temp2.trim();
+                }
+                temp1 = sb.toString();
+                if (temp1.length() > 1
+                    && (temp1.startsWith("\"") && temp1.endsWith("\""))
+                    || (temp1.startsWith("'") && temp1.endsWith("'"))) {
+                    sb.setLength(0);
+                }
+                sb.append(c);
+            }
+        }
+
+        if (stack.size() != 0) {
+            lastTag = (String) stack.pop();
+        }
+        // Hmm... it's not perfect...
+        if (attr.endsWith("=")) {
+            attr = attr.substring(0, attr.length() - 1);
+        }
+        word = sb.toString();
+
+        return new String[]{word, prevTag, lastTag, attr};
+    }
+
+    //Tests a character is delimiter or not delimiter.
+    protected boolean isDelimiter(final char c) {
+        return (c == ' ' || c == '(' || c == ')' || c == ',' //|| c == '.'
+                || c == ';' || c == '\n' || c == '\r' || c == '\t' || c == '+'
+                || c == '>' || c == '<' || c == '*' || c == '^' //|| c == '{'
+                //|| c == '}'
+                || c == '[' || c == ']' || c == '"' || c == '\'');
+    }
+
+    protected List<TagInfo> getTagList() {
+        return TagDefinition.getTagInfoAsList();
+    }
+
+    protected TagInfo getTagInfo(final String name) {
+        List<TagInfo> tagList = TagDefinition.getTagInfoAsList();
+        for (int i = 0; i < tagList.size(); i++) {
+            TagInfo info = (TagInfo) tagList.get(i);
+            if (info.getTagName().equals(name)) {
+                return info;
+            }
+        }
+
+        return null;
+    }
+
+    public ICompletionProposal[] computeCompletionProposals(final ITextViewer viewer,
+            final int documentOffset) {
+
+        String   text = viewer.getDocument().get().substring(0, documentOffset);
+        String[] dim  = getLastWord(text);
+        String   word = dim[0].toLowerCase();
+        String   prev = dim[1].toLowerCase();
+        String   last = dim[2];
+
+        this.offset = documentOffset;
+
+        List<ICompletionProposal> list = new ArrayList<ICompletionProposal>();
+        List<TagInfo> tagList = getTagList();
+
+        // attribute value
+        if (word.startsWith("<") && !word.equals("</")) {
+
+            TagInfo parent = getTagInfo(last);
+            //tagList = new ArrayList < TagInfo>();
+            if (parent != null) {
+                String[] childNames = parent.getChildTagNames();
+                for (int i = 0; i < childNames.length; i++) {
+                    tagList.add(getTagInfo(childNames[i]));
+                }
+
+            }
+            for (int i = 0; i < tagList.size(); i++) {
+                TagInfo tagInfo = (TagInfo) tagList.get(i);
+                if (tagInfo instanceof TextInfo) {
+                    TextInfo textInfo = (TextInfo) tagInfo;
+                    if ((textInfo.getText().toLowerCase()).indexOf(word) == 0) {
+                        list.add(new CompletionProposal(
+                                textInfo.getText(), documentOffset - word.length(),
+                                word.length(), textInfo.getPosition()));
+                    }
+                    continue;
+                }
+                String tagName = tagInfo.getTagName();
+                if (("<" + tagInfo.getTagName().toLowerCase()).indexOf(word) == 0) {
+                    String assistKeyword = tagName;
+                    int position = 0;
+                    // required attributes
+                    AttributeInfo[] requierAttrs = tagInfo.getRequiredAttributeInfo();
+                    for (int j = 0; j < requierAttrs.length; j++) {
+                        assistKeyword = assistKeyword + " " + requierAttrs[j].getAttributeName();
+                        if (requierAttrs[j].hasValue()) {
+                            assistKeyword = assistKeyword + "=\"\"";
+                            if (j == 0) {
+                                position = tagName.length() + requierAttrs[j].getAttributeName().length() + 3;
+                            }
+                        }
+                    }
+                    if (tagInfo.hasBody()) {
+                        assistKeyword = assistKeyword + ">";
+                        if (true) {
+                            if (position == 0) {
+                                position = assistKeyword.length();
+                            }
+                            assistKeyword = assistKeyword + "</" + tagName + ">";
+                        }
+                    } else {
+                        if (tagInfo.isEmptyTag() && !xhtmlMode) {
+                            assistKeyword += ">";
+                        } else {
+                            assistKeyword += "/>";
+                        }
+                    }
+                    if (position == 0) {
+                        position = assistKeyword.length();
+                    }
+                    try {
+                        list.add(new CompletionProposal(
+                                assistKeyword, documentOffset - word.length() + 1,
+                                word.length() - 1, position));
+                    } catch (Exception ex) {
+                        ex.printStackTrace();
+                    }
+                }
+            }
+            // attribute
+        } else if (!prev.equals("")) {
+            String tagName = prev;
+            TagInfo tagInfo = getTagInfo(tagName);
+            if (tagInfo != null) {
+                AttributeInfo[] attrList = tagInfo.getAttributeInfo();
+                for (int j = 0; j < attrList.length; j++) {
+                    if (attrList[j].getAttributeName().toLowerCase().indexOf(word) == 0) {
+                        String assistKeyword = null;
+                        int position = 0;
+                        if (attrList[j].hasValue()) {
+                            assistKeyword = attrList[j].getAttributeName() + "=\"\"";
+                            position = 2;
+                        } else {
+                            assistKeyword = attrList[j].getAttributeName();
+                            position = 0;
+                        }
+                        list.add(new CompletionProposal(
+                                assistKeyword, documentOffset - word.length(), word.length(),
+                                attrList[j].getAttributeName().length() + position));
+                    }
+                }
+            }
+            // close tag
+        } else if (!last.equals("")) {
+            TagInfo info = getTagInfo(last);
+            if (info == null || xhtmlMode || info.hasBody() || !info.isEmptyTag()) {
+                String assistKeyword = "</" + last + ">";
+                int length = 0;
+                if (word.equals("</")) {
+                    length = 2;
+                }
+                list.add(new CompletionProposal(
+                        assistKeyword, documentOffset - length, length,
+                        assistKeyword.length()));
+            }
+        }
+
+        sortCompilationProposal(list);
+
+        ICompletionProposal[] templates = super.computeCompletionProposals(viewer, documentOffset);
+        for (int i = 0; i < templates.length; i++) {
+            list.add(templates[i]);
+        }
+
+        ICompletionProposal[] prop = list.toArray(new ICompletionProposal[list.size()]);
+        return prop;
+    }
+
+    @Override public IContextInformation[] computeContextInformation(final ITextViewer viewer,
+            final int documentOffset) {
+        ContextInformation[] info = new ContextInformation[0];
+        return info;
+    }
+
+    @Override public char[] getCompletionProposalAutoActivationCharacters() {
+        return chars;
+    }
+
+    @Override public char[] getContextInformationAutoActivationCharacters() {
+        return chars;
+    }
+
+    @Override public IContextInformationValidator getContextInformationValidator() {
+        return new ContextInformationValidator(this);
+    }
+
+    @Override public String getErrorMessage() {
+        return "Error";
+    }
+
+    public static void sortCompilationProposal(final List<ICompletionProposal> prop) {
+        Collections.sort(prop, new Comparator<ICompletionProposal>() {
+            public int compare(final ICompletionProposal o1, final ICompletionProposal o2) {
+                return o1.getDisplayString().compareTo(o2.getDisplayString());
+            }
+        });
+    }
+
+    public void setAutoAssistChars(final char[] chars) {
+        if (chars != null) {
+            this.chars = chars;
+        }
+    }
+
+    public void setAssistCloseTag(final boolean assistCloseTag) {
+        this.assistCloseTag = assistCloseTag;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLContextType.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLContextType.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLContextType.java
new file mode 100644
index 0000000..c355623
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLContextType.java
@@ -0,0 +1,36 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.apache.syncope.ide.eclipse.plugin.Activator;
+import org.eclipse.jface.text.templates.GlobalTemplateVariables;
+import org.eclipse.jface.text.templates.TemplateContextType;
+
+public class HTMLContextType extends TemplateContextType {
+
+    public static final String CONTEXT_TYPE 
+        = Activator.PLUGIN_ID + ".templateContextType.html";
+
+    public HTMLContextType() {
+        addResolver(new GlobalTemplateVariables.Cursor());
+        addResolver(new GlobalTemplateVariables.WordSelection());
+        addResolver(new GlobalTemplateVariables.LineSelection());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLFileDocumentProvider.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLFileDocumentProvider.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLFileDocumentProvider.java
new file mode 100644
index 0000000..2256915
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLFileDocumentProvider.java
@@ -0,0 +1,50 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jface.text.IDocument;
+import org.eclipse.jface.text.IDocumentPartitioner;
+import org.eclipse.jface.text.rules.FastPartitioner;
+import org.eclipse.ui.editors.text.FileDocumentProvider;
+
+public class HTMLFileDocumentProvider extends FileDocumentProvider {
+
+    public IDocument createDocument(final Object element) throws CoreException {
+        IDocument document = super.createDocument(element);
+        if (document != null) {
+            IDocumentPartitioner partitioner =
+                new FastPartitioner(
+                        new HTMLPartitionScanner(),
+                        new String[]{
+                                HTMLPartitionScanner.HTML_TAG,
+                                HTMLPartitionScanner.HTML_COMMENT,
+                                HTMLPartitionScanner.HTML_SCRIPT,
+                                HTMLPartitionScanner.HTML_DOCTYPE,
+                                HTMLPartitionScanner.HTML_DIRECTIVE,
+                                HTMLPartitionScanner.JAVASCRIPT,
+                                HTMLPartitionScanner.HTML_CSS,
+                                HTMLPartitionScanner.SYNCOPE_TAG});
+            partitioner.connect(document);
+            document.setDocumentPartitioner(partitioner);
+        }
+        return document;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLPartitionScanner.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLPartitionScanner.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLPartitionScanner.java
new file mode 100644
index 0000000..ac52527
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLPartitionScanner.java
@@ -0,0 +1,76 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.rules.EndOfLineRule;
+import org.eclipse.jface.text.rules.IPredicateRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.RuleBasedPartitionScanner;
+import org.eclipse.jface.text.rules.Token;
+
+public class HTMLPartitionScanner extends RuleBasedPartitionScanner {
+
+    public static final String HTML_DEFAULT   = "__html_default";
+    public static final String HTML_COMMENT   = "__html_comment";
+    public static final String HTML_TAG       = "__html_tag";
+    public static final String HTML_SCRIPT    = "__html_script";
+    public static final String HTML_DOCTYPE   = "__html_doctype";
+    public static final String HTML_DIRECTIVE = "__html_directive";
+    public static final String JAVASCRIPT     = "__html_javascript";
+    public static final String HTML_CSS       = "__html_css";
+    public static final String PREFIX_TAG     = "__prefix_tag";
+    public static final String SYNCOPE_TAG    = "__syncope_tag";
+
+    public HTMLPartitionScanner() {
+
+        IToken htmlComment   = new Token(HTML_COMMENT);
+        IToken htmlTag       = new Token(HTML_TAG);
+        IToken prefixTag     = new Token(PREFIX_TAG);
+        IToken htmlScript    = new Token(HTML_SCRIPT);
+        IToken htmlDoctype   = new Token(HTML_DOCTYPE);
+        IToken htmlDirective = new Token(HTML_DIRECTIVE);
+        IToken javaScript    = new Token(JAVASCRIPT);
+        IToken htmlCss       = new Token(HTML_CSS);
+        IToken syncopeTag    = new Token(SYNCOPE_TAG);
+
+        List<IPredicateRule> rules = new ArrayList<IPredicateRule>();
+
+        rules.add(new MultiLineRule(" <!--", "-->", htmlComment));
+        rules.add(new MultiLineRule(" <%--", "--%>", htmlComment));
+        rules.add(new DocTypeRule(htmlDoctype));
+        rules.add(new MultiLineRule(" <%@", "%>", htmlDirective));
+        rules.add(new MultiLineRule(" <%", "%>", htmlScript));
+        rules.add(new MultiLineRule(" <![CDATA[", "]]>", htmlDoctype));
+        rules.add(new MultiLineRule(" <?xml", "?>", htmlDoctype));
+        rules.add(new MultiLineRule(" <script", " </script>", javaScript));
+        rules.add(new MultiLineRule(" <style", " </style>", htmlCss));
+        //rules.add(new MultiLineRule("${", "}", syncopeTag));
+        rules.add(new EndOfLineRule("$$", syncopeTag));
+        rules.add(new TagRule(prefixTag, TagRule.PREFIX));
+        rules.add(new TagRule(htmlTag, TagRule.NO_PREFIX));
+        rules.add(new SyncopeTagRule(syncopeTag, SyncopeTagRule.PREFIX));
+        rules.add(new SyncopeTagRule(syncopeTag, SyncopeTagRule.NO_PREFIX));
+   
+        setPredicateRules(rules.toArray(new IPredicateRule[rules.size()]));
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLScanner.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLScanner.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLScanner.java
new file mode 100644
index 0000000..6444ddb
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLScanner.java
@@ -0,0 +1,33 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+
+public class HTMLScanner extends RuleBasedScanner {
+
+    public HTMLScanner() {
+
+        IRule[] rules = new IRule[1];
+        rules[0] = new WhitespaceRule(new HTMLWhitespaceDetector());
+        setRules(rules);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTagDamagerRepairer.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTagDamagerRepairer.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTagDamagerRepairer.java
new file mode 100644
index 0000000..9a6f155
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTagDamagerRepairer.java
@@ -0,0 +1,61 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.ITokenScanner;
+
+public class HTMLTagDamagerRepairer extends DefaultDamagerRepairer {
+
+    public HTMLTagDamagerRepairer(final ITokenScanner scanner) {
+        super(scanner);
+    }
+
+    public IRegion getDamageRegion(final ITypedRegion partition, final DocumentEvent e,
+            final boolean documentPartitioningChanged) {
+        if (!documentPartitioningChanged) {
+            String source = fDocument.get();
+            int start = source.substring(0, e.getOffset()).lastIndexOf('<');
+            if (start == -1) {
+                start = 0;
+            }
+            int end = source.indexOf('>', e.getOffset());
+            int nextEnd = source.indexOf('>', end + 1);
+            if (nextEnd >= 0 && nextEnd > end) {
+                end = nextEnd;
+            }
+            int end2 = e.getOffset() + (e.getText() == null ? e.getLength() : e.getText().length());
+            if (end == -1) {
+                end = source.length();
+            } else if (end2 > end) {
+                end = end2;
+            } else {
+                end++;
+            }
+
+            return new Region(start, end - start);
+        }
+        return partition;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTagScanner.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTagScanner.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTagScanner.java
new file mode 100644
index 0000000..e40d35b
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTagScanner.java
@@ -0,0 +1,51 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+public class HTMLTagScanner extends RuleBasedScanner {
+
+    public HTMLTagScanner(final boolean bold) {
+        IToken string = null;
+        if (bold) {
+            RGB rgb = IHTMLColorConstants.TAGLIB_ATTR;
+            Color color = new Color(Display.getCurrent(), rgb);
+            string = new Token(new TextAttribute(color));
+        } else {
+            RGB rgb = IHTMLColorConstants.STRING;
+            Color color = new Color(Display.getCurrent(), rgb);
+            string = new Token(new TextAttribute(color));
+        }
+        IRule[] rules = new IRule[3];
+        rules[0] = new MultiLineRule("\"" , "\"" , string, '\\');
+        rules[1] = new MultiLineRule("'"  , "'"  , string, '\\');
+        rules[2] = new WhitespaceRule(new HTMLWhitespaceDetector());
+        setRules(rules);
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTemplateAssistProcessor.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTemplateAssistProcessor.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTemplateAssistProcessor.java
new file mode 100644
index 0000000..164c44c
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTemplateAssistProcessor.java
@@ -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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITextSelection;
+import org.eclipse.jface.text.ITextViewer;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.contentassist.ICompletionProposal;
+import org.eclipse.jface.text.templates.Template;
+import org.eclipse.jface.text.templates.TemplateCompletionProcessor;
+import org.eclipse.jface.text.templates.TemplateContext;
+import org.eclipse.jface.text.templates.TemplateContextType;
+import org.eclipse.jface.text.templates.TemplateException;
+import org.eclipse.swt.graphics.Image;
+
+public class HTMLTemplateAssistProcessor extends TemplateCompletionProcessor {
+
+    protected Template[] getTemplates(final String contextTypeId) {
+        HTMLTemplateManager manager = HTMLTemplateManager.getInstance();
+        return manager.getTemplateStore().getTemplates();
+    }
+
+    protected TemplateContextType getContextType(final ITextViewer viewer, final IRegion region) {
+        HTMLTemplateManager manager = HTMLTemplateManager.getInstance();
+        return manager.getContextTypeRegistry().getContextType(HTMLContextType.CONTEXT_TYPE);
+    }
+
+    public ICompletionProposal[] computeCompletionProposals(final ITextViewer viewer, final int offsetinp) {
+
+        int offset = offsetinp;
+        ITextSelection selection = (ITextSelection) viewer.getSelectionProvider().getSelection();
+
+        // adjust offset to end of normalized selection
+        if (selection.getOffset() == offset) {
+            offset = selection.getOffset() + selection.getLength();
+        }
+
+        String prefix = extractPrefix(viewer, offset);
+        Region region = new Region(offset - prefix.length(), prefix.length());
+        TemplateContext context = createContext(viewer, region);
+        if (context == null) {
+            return new ICompletionProposal[0];
+        }
+        context.setVariable("selection", selection.getText());
+        Template[] templates = getTemplates(context.getContextType().getId());
+        List<ICompletionProposal> matches = new ArrayList<ICompletionProposal>();
+        for (int i = 0; i < templates.length; i++) {
+            Template template = templates[i];
+            try {
+                context.getContextType().validate(template.getPattern());
+            } catch (final TemplateException e) {
+                continue;
+            }
+            if (template.getName().startsWith(prefix)
+                && template.matches(prefix, context.getContextType().getId())) {
+                matches.add(createProposal(template, context, (IRegion) region, getRelevance(template, prefix)));
+            }
+        }
+        return matches.toArray(new ICompletionProposal[matches.size()]);
+    }
+
+    @Override
+    protected Image getImage(final Template arg0) {
+        return null;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTemplateManager.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTemplateManager.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTemplateManager.java
new file mode 100644
index 0000000..86bcda8
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLTemplateManager.java
@@ -0,0 +1,68 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import java.io.IOException;
+
+import org.apache.syncope.ide.eclipse.plugin.Activator;
+import org.eclipse.jface.text.templates.ContextTypeRegistry;
+import org.eclipse.jface.text.templates.persistence.TemplateStore;
+import org.eclipse.ui.editors.text.templates.ContributionContextTypeRegistry;
+import org.eclipse.ui.editors.text.templates.ContributionTemplateStore;
+
+public final class HTMLTemplateManager {
+
+    private static final String CUSTOM_TEMPLATES_KEY
+        = Activator.PLUGIN_ID + ".customtemplates";
+    private static HTMLTemplateManager INSTANCE;
+    private TemplateStore fStore;
+    private ContributionContextTypeRegistry fRegistry;
+
+    private HTMLTemplateManager() {
+    }
+
+    public static HTMLTemplateManager getInstance() {
+        if (INSTANCE == null) {
+            INSTANCE = new HTMLTemplateManager();
+        }
+        return INSTANCE;
+    }
+
+    public TemplateStore getTemplateStore() {
+        if (fStore == null) {
+            fStore = new ContributionTemplateStore(getContextTypeRegistry(),
+                    Activator.getDefault().getPreferenceStore(), CUSTOM_TEMPLATES_KEY);
+            try {
+                fStore.load();
+            } catch (final IOException e) {
+                e.printStackTrace();
+            }
+        }
+        return fStore;
+    }
+
+    public ContextTypeRegistry getContextTypeRegistry() {
+        if (fRegistry == null) {
+            fRegistry = new ContributionContextTypeRegistry();
+            fRegistry.addContextType(HTMLContextType.CONTEXT_TYPE);
+        }
+        return fRegistry;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLWhitespaceDetector.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLWhitespaceDetector.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLWhitespaceDetector.java
new file mode 100644
index 0000000..ac944be
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/HTMLWhitespaceDetector.java
@@ -0,0 +1,27 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.jface.text.rules.IWhitespaceDetector;
+
+public class HTMLWhitespaceDetector implements IWhitespaceDetector {
+    public boolean isWhitespace(final char c) {
+        return (c == ' ' || c == '\t' || c == '\n' || c == '\r');
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/IHTMLColorConstants.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/IHTMLColorConstants.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/IHTMLColorConstants.java
new file mode 100644
index 0000000..4e8624a
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/IHTMLColorConstants.java
@@ -0,0 +1,42 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.swt.graphics.RGB;
+
+/** Defines initial colors used in editors. */
+public interface IHTMLColorConstants {
+    RGB HTML_COMMENT = new RGB(128, 0, 0);
+    RGB PROC_INSTR   = new RGB(128, 128, 128);
+    RGB STRING       = new RGB(0, 128, 0);
+    RGB DEFAULT      = new RGB(0, 0, 0);
+    RGB TAG          = new RGB(0, 0, 128);
+    RGB SCRIPT       = new RGB(255, 0, 0);
+    RGB CSS_PROP     = new RGB(0, 0, 255);
+    RGB CSS_COMMENT  = new RGB(128, 0, 0);
+    RGB CSS_VALUE    = new RGB(0, 128, 0);
+    RGB FOREGROUND   = new RGB(0, 0, 0);
+    RGB BACKGROUND   = new RGB(255, 255, 255);
+    RGB JAVA_COMMENT = new RGB(0, 128, 0);
+    RGB JAVA_STRING  = new RGB(0, 0, 255);
+    RGB JAVA_KEYWORD = new RGB(128, 0, 128);
+    RGB TAGLIB       = new RGB(255, 0, 0);
+    RGB TAGLIB_ATTR  = new RGB(128, 128, 0);
+    RGB JSDOC        = new RGB(128, 128, 255);
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/InnerCSSScanner.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/InnerCSSScanner.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/InnerCSSScanner.java
new file mode 100644
index 0000000..819a293
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/InnerCSSScanner.java
@@ -0,0 +1,54 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+public class InnerCSSScanner extends CSSBlockScanner {
+
+    public InnerCSSScanner() {
+        super();
+    }
+
+    @Override protected List<IRule> createRules() {
+        RGB rgb = IHTMLColorConstants.TAGLIB;
+        Color color = new Color(Display.getCurrent(), rgb);
+        IToken tag = new Token(new TextAttribute(color));
+        rgb = IHTMLColorConstants.CSS_COMMENT;
+        color = new Color(Display.getCurrent(), rgb);
+        IToken comment = new Token(new TextAttribute(color));
+        List<IRule> rules = new ArrayList<IRule>();
+        rules.add(new SingleLineRule(" <style", ">", tag));
+        rules.add(new SingleLineRule(" </style", ">", tag));
+        rules.add(new MultiLineRule("/*", "*/", comment));
+        rules.addAll(super.createRules());
+        return rules;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/InnerJavaScriptScanner.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/InnerJavaScriptScanner.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/InnerJavaScriptScanner.java
new file mode 100644
index 0000000..e681eca
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/InnerJavaScriptScanner.java
@@ -0,0 +1,54 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import java.util.List;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+
+public class InnerJavaScriptScanner extends JavaScriptScanner {
+
+    public InnerJavaScriptScanner() {
+        super();
+    }
+
+    @Override protected List<IRule> createRules() {
+        IToken tag = new Token(new TextAttribute(new Color(Display.getCurrent(),
+                IHTMLColorConstants.TAG)));
+        IToken comment = new Token(new TextAttribute(new Color(Display.getCurrent(), 
+                IHTMLColorConstants.JAVA_COMMENT)));
+        IToken jsdoc = new Token(new TextAttribute(new Color(Display.getCurrent(),
+                IHTMLColorConstants.JSDOC)));
+        List<IRule> rules = super.createRules();
+        rules.add(new SingleLineRule(" <script", ">", tag));
+        rules.add(new SingleLineRule(" </script", ">", tag));
+        rules.add(new MultiLineRule("/**", "*/", jsdoc));
+        rules.add(new MultiLineRule("/*", "*/", comment));
+        return rules;
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaScriptDamagerRepairer.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaScriptDamagerRepairer.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaScriptDamagerRepairer.java
new file mode 100644
index 0000000..99cc481
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaScriptDamagerRepairer.java
@@ -0,0 +1,57 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.jface.text.DocumentEvent;
+import org.eclipse.jface.text.IRegion;
+import org.eclipse.jface.text.ITypedRegion;
+import org.eclipse.jface.text.Region;
+import org.eclipse.jface.text.rules.DefaultDamagerRepairer;
+import org.eclipse.jface.text.rules.ITokenScanner;
+
+public class JavaScriptDamagerRepairer extends DefaultDamagerRepairer {
+
+    public JavaScriptDamagerRepairer(final ITokenScanner scanner) {
+        super(scanner);
+    }
+
+    public IRegion getDamageRegion(final ITypedRegion partition, final DocumentEvent e,
+            final boolean documentPartitioningChanged) {
+        if (!documentPartitioningChanged) {
+            String source = fDocument.get();
+            int start = source.substring(0, e.getOffset()).lastIndexOf("/*");
+            if (start == -1) {
+                start = 0;
+            }
+            int end = source.indexOf("*/", e.getOffset());
+            int end2 = e.getOffset() + (e.getText() == null ? e.getLength() : e.getText().length());
+            if (end == -1) {
+                end = source.length();
+            } else if (end2 > end) {
+                end = end2;
+            } else {
+                end++;
+            }
+
+            return new Region(start, end - start);
+        }
+        return partition;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaScriptScanner.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaScriptScanner.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaScriptScanner.java
new file mode 100644
index 0000000..921dc68
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaScriptScanner.java
@@ -0,0 +1,88 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.EndOfLineRule;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.SingleLineRule;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WordRule;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.widgets.Display;
+
+public class JavaScriptScanner extends RuleBasedScanner {
+
+    public static final String[] KEYWORDS = {
+            "abstract",
+            "boolean", "break", "byte",
+            "case", "catch", "char", "class", "const", "continue",
+            "debugger", "default", "delete", "do", "double",
+            "else", "enum", "export", "extends",
+            "false", "final", "finally", "float", "for", "function",
+            "goto", "if", "implements", "import", "in", "instanceof", "int", "interface",
+            "let", "long",
+            "native", "new", "null",
+            "package", "private", "protected", "prototype", "public",
+            "return", "short", "static", "super", "switch", "synchronized",
+            "this", "throw", "throws", "transient", "true", "try", "typeof",
+            "var", "void", "while", "with",
+            "typeof", "yield", "undefined", "Infinity", "NaN"
+    };
+
+    public JavaScriptScanner() {
+        List<IRule> rules = createRules();
+        setRules(rules.toArray(new IRule[rules.size()]));
+    }
+
+    /**
+     * Creates the list of <code>IRule < /code>.
+     * If you have to customize rules, override this method.
+     *
+     * @param colorProvider ColorProvider
+     * @return the list of <code>IRule < /code>
+     */
+    protected List<IRule> createRules() {
+        IToken normal  = new Token(new TextAttribute(new Color(Display.getCurrent(),
+                IHTMLColorConstants.FOREGROUND)));
+        IToken string  = new Token(new TextAttribute(new Color(Display.getCurrent(),
+                IHTMLColorConstants.JAVA_STRING)));
+        IToken comment = new Token(new TextAttribute(new Color(Display.getCurrent(),
+                IHTMLColorConstants.JAVA_COMMENT)));
+        IToken keyword = new Token(new TextAttribute(new Color(Display.getCurrent(),
+                IHTMLColorConstants.JAVA_KEYWORD)));
+        List<IRule> rules = new ArrayList<IRule>();
+        rules.add(new SingleLineRule("\"", "\"", string, '\\'));
+        rules.add(new SingleLineRule("'", "'", string, '\\'));
+        rules.add(new SingleLineRule("\\//", null, normal));
+        rules.add(new EndOfLineRule("//", comment));
+        WordRule wordRule = new WordRule(new JavaWordDetector(), normal);
+        for (int i = 0; i < KEYWORDS.length; i++) {
+            wordRule.addWord(KEYWORDS[i], keyword);
+        }
+        rules.add(wordRule);
+        return rules;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaWordDetector.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaWordDetector.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaWordDetector.java
new file mode 100644
index 0000000..5043925
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/JavaWordDetector.java
@@ -0,0 +1,33 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.jface.text.rules.IWordDetector;
+
+public class JavaWordDetector implements IWordDetector {
+
+    public boolean isWordStart(final char c) {
+        return Character.isJavaIdentifierStart(c);
+    }
+
+    public boolean isWordPart(final char c) {
+        return Character.isJavaIdentifierPart(c);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/SyncopeTagRule.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/SyncopeTagRule.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/SyncopeTagRule.java
new file mode 100644
index 0000000..8567ed0
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/SyncopeTagRule.java
@@ -0,0 +1,119 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.jface.text.rules.ICharacterScanner;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+
+public class SyncopeTagRule extends MultiLineRule {
+
+    public static final int PREFIX = 0;
+    public static final int NO_PREFIX = 1;
+    public static final int BOTH = 2;
+    private int prefix;
+
+    public SyncopeTagRule(final IToken token, final int prefix) {
+        super("${", "}", token);
+        this.prefix = prefix;
+    }
+
+    protected boolean sequenceDetected(final ICharacterScanner scanner,
+            final char[] sequence, final boolean eofAllowed) {
+        if (sequence[0] == '$' && sequence[1] == '{') {
+            int c = scanner.read();
+            if (c == '?' || c == '!' || c == '%') {
+                scanner.unread();
+                return false;
+            }
+            int back = 1;
+            try {
+                while (true) {
+                    c = scanner.read();
+                    back++;
+                    if (c == -1) {
+                        return false;
+                    }
+                    if (Character.isWhitespace(c) || c == '}') {
+                        if (prefix == PREFIX) {
+                            return false;
+                        }
+                        break;
+                    } else if (c == ':') {
+                        if (prefix == NO_PREFIX) {
+                            return false;
+                        }
+                        break;
+                    }
+                }
+            } finally {
+                for (int i = 0; i < back; i++) {
+                    scanner.unread();
+                }
+            }
+        } else if (sequence[0] == '}') {
+            // read previous char
+            scanner.unread();
+            scanner.unread();
+            int c = scanner.read();
+            // repair position
+            scanner.read();
+
+            if (c == '%') {
+                return false;
+            }
+        }
+        return super.sequenceDetected(scanner, sequence, eofAllowed);
+    }
+
+    protected boolean endSequenceDetected(final ICharacterScanner scanner) {
+        int c;
+        boolean doubleQuoted = false;
+        boolean singleQuoted = false;
+        char[][] delimiters = scanner.getLegalLineDelimiters();
+        boolean previousWasEscapeCharacter = false;
+        while ((c = scanner.read()) != ICharacterScanner.EOF) {
+            if (c == fEscapeCharacter) {
+                // Skip the escaped character.
+                scanner.read();
+            } else if (c == '"' && !singleQuoted) {
+                doubleQuoted = !doubleQuoted;
+            } else if (c == '\'' && !doubleQuoted) {
+                singleQuoted = !singleQuoted;
+            } else if (fEndSequence.length > 0 && c == fEndSequence[0] && !doubleQuoted
+                    && !singleQuoted && sequenceDetected(scanner, fEndSequence, true)) {
+                return true;
+            } else if (fBreaksOnEOL) {
+                // Check for end of line since it can be used to terminate the pattern.
+                for (int i = 0; i < delimiters.length; i++) {
+                    if (c == delimiters[i][0] && sequenceDetected(scanner, delimiters[i], true)
+                            && (!fEscapeContinuesLine || !previousWasEscapeCharacter)) {
+                        return true;
+                    }
+                }
+            }
+            previousWasEscapeCharacter = (c == fEscapeCharacter);
+        }
+        if (fBreaksOnEOF) {
+            return true;
+        }
+        scanner.unread();
+        return false;
+    }
+}

http://git-wip-us.apache.org/repos/asf/syncope/blob/6fee50d7/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/SyncopeTagScanner.java
----------------------------------------------------------------------
diff --git a/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/SyncopeTagScanner.java b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/SyncopeTagScanner.java
new file mode 100644
index 0000000..8d7da79
--- /dev/null
+++ b/ide/eclipse/bundles/org.apache.syncope.ide.eclipse.plugin/src/main/java/org/apache/syncope/ide/eclipse/plugin/editors/htmlhelpers/SyncopeTagScanner.java
@@ -0,0 +1,51 @@
+/*
+ * 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.syncope.ide.eclipse.plugin.editors.htmlhelpers;
+
+import org.eclipse.jface.text.TextAttribute;
+import org.eclipse.jface.text.rules.IRule;
+import org.eclipse.jface.text.rules.IToken;
+import org.eclipse.jface.text.rules.MultiLineRule;
+import org.eclipse.jface.text.rules.RuleBasedScanner;
+import org.eclipse.jface.text.rules.Token;
+import org.eclipse.jface.text.rules.WhitespaceRule;
+import org.eclipse.swt.graphics.Color;
+import org.eclipse.swt.graphics.RGB;
+import org.eclipse.swt.widgets.Display;
+
+public class SyncopeTagScanner extends RuleBasedScanner {
+
+    public SyncopeTagScanner(final boolean bold) {
+        IToken string = null;
+        if (bold) {
+            RGB rgb = IHTMLColorConstants.TAGLIB_ATTR;
+            Color color = new Color(Display.getCurrent(), rgb);
+            string = new Token(new TextAttribute(color));
+        } else {
+            RGB rgb = IHTMLColorConstants.STRING;
+            Color color = new Color(Display.getCurrent(), rgb);
+            string = new Token(new TextAttribute(color));
+        }
+        IRule[] rules = new IRule[3];
+        rules[0] = new MultiLineRule("\"" , "\"" , string, '\\');
+        rules[1] = new MultiLineRule("'"  , "'"  , string, '\\');
+        rules[2] = new WhitespaceRule(new HTMLWhitespaceDetector());
+        setRules(rules);
+    }
+}