diff options
Diffstat (limited to 'theme-compiler/src/com')
4 files changed, 132 insertions, 24 deletions
diff --git a/theme-compiler/src/com/vaadin/sass/SassCompiler.java b/theme-compiler/src/com/vaadin/sass/SassCompiler.java index 840badfc25..48b2d24c46 100644 --- a/theme-compiler/src/com/vaadin/sass/SassCompiler.java +++ b/theme-compiler/src/com/vaadin/sass/SassCompiler.java @@ -17,6 +17,7 @@ package com.vaadin.sass; import java.io.File; +import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; @@ -48,6 +49,12 @@ public class SassCompiler { // ScssStylesheet.setStylesheetResolvers(new VaadinResolver()); ScssStylesheet scss = ScssStylesheet.get(input); + if(scss == null){ + System.err.println("The scss file " + input + + " could not be found."); + return; + } + scss.compile(); if (output == null) { System.out.println(scss.toString()); diff --git a/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java b/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java index 64279ad1e7..dbb3e571dc 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java +++ b/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java @@ -42,6 +42,7 @@ import com.vaadin.sass.internal.tree.MixinDefNode; import com.vaadin.sass.internal.tree.Node; import com.vaadin.sass.internal.tree.VariableNode; import com.vaadin.sass.internal.tree.controldirective.IfElseDefNode; +import com.vaadin.sass.internal.visitor.ExtendNodeHandler; import com.vaadin.sass.internal.visitor.ImportNodeHandler; public class ScssStylesheet extends Node { @@ -77,7 +78,8 @@ public class ScssStylesheet extends Node { * ScssStylesheet tree out of it. Calling compile() on it will transform * SASS into CSS. Calling toString() will print out the SCSS/CSS. * - * @param file + * @param identifier + * The file path. If null then null is returned. * @return * @throws CSSException * @throws IOException @@ -92,7 +94,8 @@ public class ScssStylesheet extends Node { * builds up a ScssStylesheet tree out of it. Calling compile() on it will * transform SASS into CSS. Calling toString() will print out the SCSS/CSS. * - * @param file + * @param identifier + * The file path. If null then null is returned. * @param encoding * @return * @throws CSSException @@ -108,6 +111,12 @@ public class ScssStylesheet extends Node { * * @charset declaration, the default one is ASCII. */ + + if (identifier == null) { + return null; + } + + // FIXME Is this actually intended? /John 1.3.2013 File file = new File(identifier); file = file.getCanonicalFile(); @@ -172,6 +181,7 @@ public class ScssStylesheet extends Node { variables.clear(); ifElseDefNodes.clear(); lastNodeAdded.clear(); + ExtendNodeHandler.clear(); importOtherFiles(this); populateDefinitions(this); traverse(this); diff --git a/theme-compiler/src/com/vaadin/sass/internal/util/StringUtil.java b/theme-compiler/src/com/vaadin/sass/internal/util/StringUtil.java index cf227fe3a3..b20e8bab61 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/util/StringUtil.java +++ b/theme-compiler/src/com/vaadin/sass/internal/util/StringUtil.java @@ -17,8 +17,10 @@ package com.vaadin.sass.internal.util; import java.util.ArrayList; +import java.util.Arrays; import java.util.Collection; import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.LinkedList; import java.util.List; import java.util.regex.Matcher; @@ -145,14 +147,7 @@ public class StringUtil { * @return true if the text contains the SCSS variable, false if not */ public static boolean containsVariable(String text, String varName) { - StringBuilder builder = new StringBuilder(); - // (?![\\w-]) means lookahead, the next one shouldn't be a word - // character nor a dash. - builder.append("\\$").append(Pattern.quote(varName)) - .append("(?![\\w-])"); - Pattern pattern = Pattern.compile(builder.toString()); - Matcher matcher = pattern.matcher(text); - return matcher.find(); + return containsSubString(text, "$" + varName); } /** @@ -162,18 +157,81 @@ public class StringUtil { * @param text * text which contains the SCSS variable * @param varName - * SCSS variable name + * SCSS variable name (Without '$' sign) * @param value * the value of the SCSS variable * @return the String after replacing */ public static String replaceVariable(String text, String varName, String value) { + return replaceSubString(text, "$" + varName, value); + } + + /** + * Check if a String contains a sub string, using whole word match. + * + * @param text + * text to be checked + * @Param sub Sub String to be checked. + * @return true if the text contains the sub string, false if not + */ + public static boolean containsSubString(String text, String sub) { StringBuilder builder = new StringBuilder(); // (?![\\w-]) means lookahead, the next one shouldn't be a word // character nor a dash. - builder.append("\\$").append(Pattern.quote(varName)) + builder.append("(?<![\\w-])").append(Pattern.quote(sub)) + .append("(?![\\w-])"); + Pattern pattern = Pattern.compile(builder.toString()); + Matcher matcher = pattern.matcher(text); + return matcher.find(); + } + + /** + * Replace the sub string in a String to a value, using whole word match. + * + * @param text + * text which contains the sub string + * @param sub + * the sub string + * @param value + * the new value + * @return the String after replacing + */ + public static String replaceSubString(String text, String sub, String value) { + StringBuilder builder = new StringBuilder(); + // (?![\\w-]) means lookahead, the next one shouldn't be a word + // character nor a dash. + builder.append("(?<![\\w-])").append(Pattern.quote(sub)) .append("(?![\\w-])"); return text.replaceAll(builder.toString(), value); } + + /** + * Remove duplicated sub string in a String given a splitter. Can be used to + * removed duplicated selectors, e.g., in ".error.error", one duplicated + * ".error" can be removed. + * + * @param motherString + * string which may contains duplicated sub strings + * @param splitter + * the splitter splits the mother string to sub strings + * @return the mother string with duplicated sub strings removed + */ + public static String removeDuplicatedSubString(String motherString, + String splitter) { + List<String> subStrings = Arrays.asList(motherString.split(Pattern + .quote(splitter))); + LinkedHashSet<String> uniqueSubStrings = new LinkedHashSet<String>( + subStrings); + StringBuilder builder = new StringBuilder(); + int count = 0; + for (String uniqueSubString : uniqueSubStrings) { + count++; + builder.append(uniqueSubString); + if (count < uniqueSubStrings.size()) { + builder.append(splitter); + } + } + return builder.toString(); + } } diff --git a/theme-compiler/src/com/vaadin/sass/internal/visitor/ExtendNodeHandler.java b/theme-compiler/src/com/vaadin/sass/internal/visitor/ExtendNodeHandler.java index f7917fff6e..e4a69ea5f3 100644 --- a/theme-compiler/src/com/vaadin/sass/internal/visitor/ExtendNodeHandler.java +++ b/theme-compiler/src/com/vaadin/sass/internal/visitor/ExtendNodeHandler.java @@ -26,6 +26,7 @@ import com.vaadin.sass.internal.ScssStylesheet; import com.vaadin.sass.internal.tree.BlockNode; import com.vaadin.sass.internal.tree.ExtendNode; import com.vaadin.sass.internal.tree.Node; +import com.vaadin.sass.internal.util.StringUtil; public class ExtendNodeHandler { private static Map<String, List<ArrayList<String>>> extendsMap = new HashMap<String, List<ArrayList<String>>>(); @@ -35,6 +36,12 @@ public class ExtendNodeHandler { modifyTree(ScssStylesheet.get()); } + public static void clear() { + if (extendsMap != null) { + extendsMap.clear(); + } + } + private static void modifyTree(Node node) throws Exception { for (Node child : node.getChildren()) { if (child instanceof BlockNode) { @@ -51,7 +58,8 @@ public class ExtendNodeHandler { } else { for (Entry<String, List<ArrayList<String>>> entry : extendsMap .entrySet()) { - if (selectorString.contains(entry.getKey())) { + if (StringUtil.containsSubString(selectorString, + entry.getKey())) { for (ArrayList<String> sList : entry.getValue()) { ArrayList<String> clone = (ArrayList<String>) sList .clone(); @@ -71,22 +79,36 @@ public class ExtendNodeHandler { if (extendsMap.get(extendedString) == null) { extendsMap.put(extendedString, new ArrayList<ArrayList<String>>()); } - extendsMap.get(extendedString).add( - ((BlockNode) node.getParentNode()).getSelectorList()); + // prevent a selector extends itself, e.g. .test{ @extend .test} + String parentSelectorString = ((BlockNode) node.getParentNode()) + .getSelectors(); + if (!parentSelectorString.equals(extendedString)) { + extendsMap.get(extendedString).add( + ((BlockNode) node.getParentNode()).getSelectorList()); + } } private static void addAdditionalSelectorListToBlockNode( - BlockNode blockNode, ArrayList<String> list, String selectorString) { - if (list != null) { - for (int i = 0; i < list.size(); i++) { - if (selectorString == null) { - blockNode.getSelectorList().add(list.get(i)); + BlockNode blockNode, ArrayList<String> extendingSelectors, + String extendedSelector) { + if (extendingSelectors != null) { + for (String extendingSelector : extendingSelectors) { + if (extendedSelector == null) { + blockNode.getSelectorList().add(extendingSelector); } else { ArrayList<String> newTags = new ArrayList<String>(); - for (final String existing : blockNode.getSelectorList()) { - if (existing.contains(selectorString)) { - newTags.add(existing.replace(selectorString, - list.get(i))); + for (final String selectorString : blockNode + .getSelectorList()) { + if (StringUtil.containsSubString(selectorString, + extendedSelector)) { + String newTag = generateExtendingSelectors( + selectorString, extendedSelector, + extendingSelector); + // prevent adding duplicated selector list + if (!blockNode.getSelectorList().contains(newTag) + && !newTags.contains(newTag)) { + newTags.add(newTag); + } } } blockNode.getSelectorList().addAll(newTags); @@ -94,4 +116,15 @@ public class ExtendNodeHandler { } } } + + private static String generateExtendingSelectors(String selectorString, + String extendedSelector, String extendingSelector) { + String result = StringUtil.replaceSubString(selectorString, + extendedSelector, extendingSelector); + // remove duplicated class selectors. + if (result.startsWith(".")) { + result = StringUtil.removeDuplicatedSubString(result, "."); + } + return result; + } } |