aboutsummaryrefslogtreecommitdiffstats
path: root/theme-compiler/src/com/vaadin
diff options
context:
space:
mode:
Diffstat (limited to 'theme-compiler/src/com/vaadin')
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java104
-rw-r--r--[-rwxr-xr-x]theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java0
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/resolver/AbstractResolver.java200
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/resolver/ClassloaderResolver.java20
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/resolver/FilesystemResolver.java44
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/resolver/ScssStylesheetResolver.java7
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/resolver/VaadinResolver.java90
-rw-r--r--theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java22
8 files changed, 325 insertions, 162 deletions
diff --git a/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java b/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java
index dbb3e571dc..7213553e18 100644
--- a/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java
+++ b/theme-compiler/src/com/vaadin/sass/internal/ScssStylesheet.java
@@ -19,10 +19,10 @@ package com.vaadin.sass.internal;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
+import java.util.List;
import java.util.Map;
import java.util.logging.Logger;
@@ -35,8 +35,9 @@ import com.vaadin.sass.internal.handler.SCSSErrorHandler;
import com.vaadin.sass.internal.parser.ParseException;
import com.vaadin.sass.internal.parser.Parser;
import com.vaadin.sass.internal.parser.SCSSParseException;
+import com.vaadin.sass.internal.resolver.ClassloaderResolver;
+import com.vaadin.sass.internal.resolver.FilesystemResolver;
import com.vaadin.sass.internal.resolver.ScssStylesheetResolver;
-import com.vaadin.sass.internal.resolver.VaadinResolver;
import com.vaadin.sass.internal.tree.BlockNode;
import com.vaadin.sass.internal.tree.MixinDefNode;
import com.vaadin.sass.internal.tree.Node;
@@ -59,10 +60,12 @@ public class ScssStylesheet extends Node {
private static HashMap<Node, Node> lastNodeAdded = new HashMap<Node, Node>();
- private String fileName;
+ private File file;
private String charset;
+ private List<ScssStylesheetResolver> resolvers = new ArrayList<ScssStylesheetResolver>();
+
/**
* Read in a file SCSS and parse it into a ScssStylesheet
*
@@ -101,8 +104,8 @@ public class ScssStylesheet extends Node {
* @throws CSSException
* @throws IOException
*/
- public static ScssStylesheet get(String identifier, String encoding)
- throws CSSException, IOException {
+ public static ScssStylesheet get(String identifier,
+ ScssStylesheet parentStylesheet) throws CSSException, IOException {
/*
* The encoding to be used is passed through "encoding" parameter. the
* imported children scss node will have the same encoding as their
@@ -122,12 +125,22 @@ public class ScssStylesheet extends Node {
SCSSDocumentHandler handler = new SCSSDocumentHandlerImpl();
ScssStylesheet stylesheet = handler.getStyleSheet();
-
- InputSource source = stylesheet.resolveStylesheet(identifier);
+ if (parentStylesheet == null) {
+ // Use default resolvers
+ stylesheet.addResolver(new FilesystemResolver());
+ stylesheet.addResolver(new ClassloaderResolver());
+ } else {
+ // Use parent resolvers
+ stylesheet.setResolvers(parentStylesheet.getResolvers());
+ }
+ InputSource source = stylesheet.resolveStylesheet(identifier,
+ parentStylesheet);
if (source == null) {
return null;
}
- source.setEncoding(encoding);
+ if (parentStylesheet != null) {
+ source.setEncoding(parentStylesheet.getCharset());
+ }
Parser parser = new Parser();
parser.setErrorHandler(new SCSSErrorHandler());
@@ -145,24 +158,13 @@ public class ScssStylesheet extends Node {
return stylesheet;
}
- private static ScssStylesheetResolver[] resolvers = null;
-
- public static void setStylesheetResolvers(
- ScssStylesheetResolver... styleSheetResolvers) {
- resolvers = Arrays.copyOf(styleSheetResolvers,
- styleSheetResolvers.length);
- }
-
- public InputSource resolveStylesheet(String identifier) {
- if (resolvers == null) {
- setStylesheetResolvers(new VaadinResolver());
- }
-
- for (ScssStylesheetResolver resolver : resolvers) {
- InputSource source = resolver.resolve(identifier);
+ public InputSource resolveStylesheet(String identifier,
+ ScssStylesheet parentStylesheet) {
+ for (ScssStylesheetResolver resolver : getResolvers()) {
+ InputSource source = resolver.resolve(parentStylesheet, identifier);
if (source != null) {
File f = new File(source.getURI());
- setFileName(f.getParent());
+ setFile(f);
return source;
}
}
@@ -171,6 +173,38 @@ public class ScssStylesheet extends Node {
}
/**
+ * Retrieves a list of resolvers to use when resolving imports
+ *
+ * @since 7.2
+ * @return the resolvers used to resolving imports
+ */
+ public List<ScssStylesheetResolver> getResolvers() {
+ return Collections.unmodifiableList(resolvers);
+ }
+
+ /**
+ * Sets the list of resolvers to use when resolving imports
+ *
+ * @since 7.2
+ * @param resolvers
+ * the resolvers to set
+ */
+ public void setResolvers(List<ScssStylesheetResolver> resolvers) {
+ this.resolvers = new ArrayList<ScssStylesheetResolver>(resolvers);
+ }
+
+ /**
+ * Adds the given resolver to the resolver list
+ *
+ * @since 7.2
+ * @param resolver
+ * The resolver to add
+ */
+ public void addResolver(ScssStylesheetResolver resolver) {
+ resolvers.add(resolver);
+ }
+
+ /**
* Applies all the visitors and compiles SCSS into Css.
*
* @throws Exception
@@ -355,12 +389,28 @@ public class ScssStylesheet extends Node {
return mixinDefs.get(name);
}
- public void setFileName(String fileName) {
- this.fileName = fileName;
+ public void setFile(File file) {
+ this.file = file;
}
+ /**
+ * Returns the directory containing this style sheet
+ *
+ * @since 7.2
+ * @return The directory containing this style sheet
+ */
+ public String getDirectory() {
+ return file.getParent();
+ }
+
+ /**
+ * Returns the full file name for this style sheet
+ *
+ * @since 7.2
+ * @return The full file name for this style sheet
+ */
public String getFileName() {
- return fileName;
+ return file.getPath();
}
public static HashMap<Node, Node> getLastNodeAdded() {
diff --git a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java
index 170d8f3e54..170d8f3e54 100755..100644
--- a/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java
+++ b/theme-compiler/src/com/vaadin/sass/internal/parser/Parser.java
diff --git a/theme-compiler/src/com/vaadin/sass/internal/resolver/AbstractResolver.java b/theme-compiler/src/com/vaadin/sass/internal/resolver/AbstractResolver.java
new file mode 100644
index 0000000000..5de1f95264
--- /dev/null
+++ b/theme-compiler/src/com/vaadin/sass/internal/resolver/AbstractResolver.java
@@ -0,0 +1,200 @@
+/*
+ * Copyright 2000-2013 Vaadin Ltd.
+ *
+ * Licensed 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 com.vaadin.sass.internal.resolver;
+
+import java.io.File;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import org.w3c.css.sac.InputSource;
+
+import com.vaadin.sass.internal.ScssStylesheet;
+
+/**
+ * Base class for resolvers. Implements functionality for locating paths which
+ * an import can be relative to and helpers for extracting path information from
+ * the identifier.
+ *
+ * @since 7.2
+ * @author Vaadin Ltd
+ */
+public abstract class AbstractResolver implements ScssStylesheetResolver,
+ Serializable {
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.sass.internal.resolver.ScssStylesheetResolver#resolve(java
+ * .lang.String)
+ */
+ @Override
+ public InputSource resolve(ScssStylesheet parentStylesheet,
+ String identifier) {
+ // Remove a possible ".scss" suffix
+ identifier = identifier.replaceFirst(".scss$", "");
+
+ List<String> potentialParentPaths = getPotentialParentPaths(
+ parentStylesheet, identifier);
+
+ // remove path from identifier as it has already been added to the
+ // parent path
+ if (identifier.contains("/")) {
+ identifier = identifier.substring(identifier.lastIndexOf("/") + 1);
+ }
+
+ for (String path : potentialParentPaths) {
+ InputSource source = normalizeAndResolve(path + "/" + identifier);
+
+ if (source != null) {
+ return source;
+ }
+
+ // Try to find partial import (_identifier.scss)
+ source = normalizeAndResolve(path + "/_" + identifier);
+
+ if (source != null) {
+ return source;
+ }
+
+ }
+
+ return normalizeAndResolve(identifier);
+ }
+
+ /**
+ * Retrieves the parent paths which should be used while resolving relative
+ * identifiers. By default uses the parent stylesheet location and a
+ * possible absolute path in the identifier.
+ *
+ * @param parentStylesheet
+ * The parent stylesheet or null if there is no parent
+ * @param identifier
+ * The identifier to be resolved
+ * @return a list of paths in which to look for the relative import
+ */
+ protected List<String> getPotentialParentPaths(
+ ScssStylesheet parentStylesheet, String identifier) {
+ List<String> potentialParents = new ArrayList<String>();
+ if (parentStylesheet != null) {
+ potentialParents.add(extractFullPath(
+ parentStylesheet.getDirectory(), identifier));
+ }
+
+ // Identifier can be a full path so extract the path part also as a
+ // potential parent
+ if (identifier.contains("/")) {
+ potentialParents.add(extractFullPath("", identifier));
+ }
+
+ return potentialParents;
+
+ }
+
+ /**
+ * Extracts the full path from the path combined with the identifier
+ *
+ * @param path
+ * The base path
+ * @param identifier
+ * The identifier which may contain a path part, separated by "/"
+ * from the real identifier
+ * @return a normalized version of the path where identifier does not
+ * contain any directory information
+ */
+ protected String extractFullPath(String path, String identifier) {
+ int lastSlashPosition = identifier.lastIndexOf("/");
+ if (lastSlashPosition == -1) {
+ return path;
+ }
+ String identifierPath = identifier.substring(0, lastSlashPosition);
+ if ("".equals(path)) {
+ return identifierPath;
+ } else {
+ return path + "/" + identifierPath;
+ }
+ }
+
+ /**
+ * Resolves the normalized version of the given identifier
+ *
+ * @param identifier
+ * The identifier to resolve
+ * @return An input source if the resolver found one or null otherwise
+ */
+ protected InputSource normalizeAndResolve(String identifier) {
+ String normalized = normalize(identifier);
+ return resolveNormalized(normalized);
+ }
+
+ /**
+ * Resolves the identifier after it has been normalized using
+ * {@link #normalize(String)}.
+ *
+ * @param identifier
+ * The normalized identifier
+ * @return an InputSource if the resolver found a source or null otherwise
+ */
+ protected abstract InputSource resolveNormalized(String identifier);
+
+ /**
+ * Normalizes "." and ".." from the path string where parent path segments
+ * can be removed. Preserve leading "..". Also ensure / is used instead of \
+ * in all places.
+ *
+ * @param path
+ * A relative or absolute file path
+ * @return The normalized path
+ */
+ protected String normalize(String path) {
+
+ // Ensure only "/" is used, also in Windows
+ path = path.replace(File.separatorChar, '/');
+
+ // Split into segments
+ String[] segments = path.split("/");
+ Stack<String> result = new Stack<String>();
+
+ // Replace '.' and '..' segments
+ for (int i = 0; i < segments.length; i++) {
+ if (segments[i].equals(".")) {
+ // Segments marked '.' are ignored
+
+ } else if (segments[i].equals("..") && !result.isEmpty()
+ && !result.lastElement().equals("..")) {
+ // If segment is ".." then remove the previous iff the previous
+ // element is not a ".." and the result stack is not empty
+ result.pop();
+ } else {
+ // Other segments are just added to the stack
+ result.push(segments[i]);
+ }
+ }
+
+ // Reconstruct path
+ StringBuilder pathBuilder = new StringBuilder();
+ for (int i = 0; i < result.size(); i++) {
+ if (i > 0) {
+ pathBuilder.append("/");
+ }
+ pathBuilder.append(result.get(i));
+ }
+ return pathBuilder.toString();
+ }
+
+}
diff --git a/theme-compiler/src/com/vaadin/sass/internal/resolver/ClassloaderResolver.java b/theme-compiler/src/com/vaadin/sass/internal/resolver/ClassloaderResolver.java
index 8711a0a3e9..755073bc4c 100644
--- a/theme-compiler/src/com/vaadin/sass/internal/resolver/ClassloaderResolver.java
+++ b/theme-compiler/src/com/vaadin/sass/internal/resolver/ClassloaderResolver.java
@@ -15,31 +15,19 @@
*/
package com.vaadin.sass.internal.resolver;
-import java.io.File;
import java.io.InputStream;
import org.w3c.css.sac.InputSource;
-public class ClassloaderResolver implements ScssStylesheetResolver {
+public class ClassloaderResolver extends AbstractResolver {
@Override
- public InputSource resolve(String identifier) {
- // identifier should not have .scss, fileName should
- String ext = ".scss";
- if (identifier.endsWith(".css")) {
- ext = ".css";
- }
+ public InputSource resolveNormalized(String identifier) {
String fileName = identifier;
- if (identifier.endsWith(ext)) {
- identifier = identifier.substring(0,
- identifier.length() - ext.length());
- } else {
- fileName = fileName + ext;
+ if (!fileName.endsWith(".css")) {
+ fileName += ".scss";
}
- // Ensure only "/" is used, also in Windows
- fileName = fileName.replace(File.separatorChar, '/');
-
// Filename should be a relative path starting with VAADIN/...
int vaadinIdx = fileName.lastIndexOf("VAADIN/");
if (vaadinIdx > -1) {
diff --git a/theme-compiler/src/com/vaadin/sass/internal/resolver/FilesystemResolver.java b/theme-compiler/src/com/vaadin/sass/internal/resolver/FilesystemResolver.java
index 9bb1969ab1..786d0875da 100644
--- a/theme-compiler/src/com/vaadin/sass/internal/resolver/FilesystemResolver.java
+++ b/theme-compiler/src/com/vaadin/sass/internal/resolver/FilesystemResolver.java
@@ -18,24 +18,46 @@ package com.vaadin.sass.internal.resolver;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
+import java.util.List;
import org.w3c.css.sac.InputSource;
-public class FilesystemResolver implements ScssStylesheetResolver {
+import com.vaadin.sass.internal.ScssStylesheet;
+public class FilesystemResolver extends AbstractResolver {
+
+ private String[] customPaths = null;
+
+ public FilesystemResolver(String... customPaths) {
+ this.customPaths = customPaths;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see
+ * com.vaadin.sass.internal.resolver.AbstractResolver#getPotentialPaths(
+ * com.vaadin.sass.internal.ScssStylesheet, java.lang.String)
+ */
@Override
- public InputSource resolve(String identifier) {
- // identifier should not have .scss, fileName should
- String ext = ".scss";
- if (identifier.endsWith(".css")) {
- ext = ".css";
+ protected List<String> getPotentialParentPaths(
+ ScssStylesheet parentStyleSheet, String identifier) {
+ List<String> potentialPaths = super.getPotentialParentPaths(
+ parentStyleSheet, identifier);
+ if (customPaths != null) {
+ for (String path : customPaths) {
+ potentialPaths.add(extractFullPath(path, identifier));
+ }
}
+
+ return potentialPaths;
+ }
+
+ @Override
+ public InputSource resolveNormalized(String identifier) {
String fileName = identifier;
- if (identifier.endsWith(ext)) {
- identifier = identifier.substring(0,
- identifier.length() - ext.length());
- } else {
- fileName = fileName + ext;
+ if (!fileName.endsWith(".css")) {
+ fileName += ".scss";
}
try {
diff --git a/theme-compiler/src/com/vaadin/sass/internal/resolver/ScssStylesheetResolver.java b/theme-compiler/src/com/vaadin/sass/internal/resolver/ScssStylesheetResolver.java
index 45f10836a3..64b3d10d88 100644
--- a/theme-compiler/src/com/vaadin/sass/internal/resolver/ScssStylesheetResolver.java
+++ b/theme-compiler/src/com/vaadin/sass/internal/resolver/ScssStylesheetResolver.java
@@ -17,6 +17,8 @@ package com.vaadin.sass.internal.resolver;
import org.w3c.css.sac.InputSource;
+import com.vaadin.sass.internal.ScssStylesheet;
+
public interface ScssStylesheetResolver {
/**
* Called with the "identifier" of a stylesheet that the resolver should try
@@ -26,9 +28,12 @@ public interface ScssStylesheetResolver {
* stylesheet was found, e.g "runo.scss" might result in a URI like
* "VAADIN/themes/runo/runo.scss".
*
+ * @param parentStylesheet
+ * The parent style sheet
* @param identifier
* used fo find stylesheet
* @return InputSource for stylesheet (with URI set) or null if not found
*/
- public InputSource resolve(String identifier);
+ public InputSource resolve(ScssStylesheet parentStylesheet,
+ String identifier);
} \ No newline at end of file
diff --git a/theme-compiler/src/com/vaadin/sass/internal/resolver/VaadinResolver.java b/theme-compiler/src/com/vaadin/sass/internal/resolver/VaadinResolver.java
deleted file mode 100644
index fec16a54c8..0000000000
--- a/theme-compiler/src/com/vaadin/sass/internal/resolver/VaadinResolver.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2000-2013 Vaadin Ltd.
- *
- * Licensed 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 com.vaadin.sass.internal.resolver;
-
-import java.io.File;
-import java.util.Stack;
-
-import org.w3c.css.sac.InputSource;
-
-public class VaadinResolver implements ScssStylesheetResolver {
-
- @Override
- public InputSource resolve(String identifier) {
-
- // Remove extra "." and ".."
- identifier = normalize(identifier);
-
- InputSource source = null;
-
- // Can we find the scss from the file system?
- ScssStylesheetResolver resolver = new FilesystemResolver();
- source = resolver.resolve(identifier);
-
- if (source == null) {
- // How about the classpath?
- resolver = new ClassloaderResolver();
- source = resolver.resolve(identifier);
- }
-
- return source;
- }
-
- /**
- * Normalizes "." and ".." from the path string where parent path segments
- * can be removed. Preserve leading "..".
- *
- * @param path
- * A relative or absolute file path
- * @return The normalized path
- */
- private static String normalize(String path) {
-
- // Ensure only "/" is used, also in Windows
- path = path.replace(File.separatorChar, '/');
-
- // Split into segments
- String[] segments = path.split("/");
- Stack<String> result = new Stack<String>();
-
- // Replace '.' and '..' segments
- for (int i = 0; i < segments.length; i++) {
- if (segments[i].equals(".")) {
- // Segments marked '.' are ignored
-
- } else if (segments[i].equals("..") && !result.isEmpty()
- && !result.lastElement().equals("..")) {
- // If segment is ".." then remove the previous iff the previous
- // element is not a ".." and the result stack is not empty
- result.pop();
- } else {
- // Other segments are just added to the stack
- result.push(segments[i]);
- }
- }
-
- // Reconstruct path
- StringBuilder pathBuilder = new StringBuilder();
- for (int i = 0; i < result.size(); i++) {
- if (i > 0) {
- pathBuilder.append("/");
- }
- pathBuilder.append(result.get(i));
- }
- return pathBuilder.toString();
- }
-
-}
diff --git a/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java b/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java
index cb9896967a..e52767bb5a 100644
--- a/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java
+++ b/theme-compiler/src/com/vaadin/sass/internal/visitor/ImportNodeHandler.java
@@ -16,7 +16,6 @@
package com.vaadin.sass.internal.visitor;
-import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
@@ -57,25 +56,14 @@ public class ImportNodeHandler {
ImportNode importNode = (ImportNode) n;
if (!importNode.isPureCssImport()) {
try {
- StringBuilder filePathBuilder = new StringBuilder(
- styleSheet.getFileName());
- filePathBuilder.append(File.separatorChar).append(
- importNode.getUri());
- if (!filePathBuilder.toString().endsWith(".scss")) {
- filePathBuilder.append(".scss");
- }
-
// set parent's charset to imported node.
ScssStylesheet imported = ScssStylesheet.get(
- filePathBuilder.toString(),
- styleSheet.getCharset());
- if (imported == null) {
- imported = ScssStylesheet.get(importNode.getUri());
- }
+ importNode.getUri(), styleSheet);
if (imported == null) {
- throw new FileNotFoundException(importNode.getUri()
- + " (parent: "
- + ScssStylesheet.get().getFileName() + ")");
+ throw new FileNotFoundException("Import '"
+ + importNode.getUri() + "' in '"
+ + styleSheet.getFileName()
+ + "' could not be found");
}
traverse(imported);