summaryrefslogtreecommitdiffstats
path: root/theme-compiler/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'theme-compiler/src/com')
-rw-r--r--theme-compiler/src/com/vaadin/sass/SassCompiler.java7
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java14
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/util/StringUtil.java78
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/visitor/ExtendNodeHandler.java57
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;
+ }
}