summaryrefslogtreecommitdiffstats
path: root/client-compiler
diff options
context:
space:
mode:
authorMarc Englund <marc@vaadin.com>2012-12-14 12:08:26 +0200
committerMarc Englund <marc@vaadin.com>2012-12-14 13:50:36 +0200
commitaefc9fe8f210296e647fe12f48c5baf81229fee4 (patch)
treeacbd1e52d424f058dbe4dfe833d5c4b4e6e0bd71 /client-compiler
parent4abad6d44b062709a20406d603cdee567f67ebae (diff)
downloadvaadin-framework-aefc9fe8f210296e647fe12f48c5baf81229fee4.tar.gz
vaadin-framework-aefc9fe8f210296e647fe12f48c5baf81229fee4.zip
SassLinker for (public folder) Sass support in plain GWT, fixes #10202
Originally by Michael Vogt (+ added log message, moved) Change-Id: I565207b4fa5223f470e1e5bbdc196d4c343a8142
Diffstat (limited to 'client-compiler')
-rw-r--r--client-compiler/ivy.xml2
-rw-r--r--client-compiler/src/com/vaadin/sass/linker/SassLinker.java195
2 files changed, 197 insertions, 0 deletions
diff --git a/client-compiler/ivy.xml b/client-compiler/ivy.xml
index 1340ab2c5b..ee36e4e261 100644
--- a/client-compiler/ivy.xml
+++ b/client-compiler/ivy.xml
@@ -25,6 +25,8 @@
rev="${vaadin.version}" conf="build" />
<dependency org="com.vaadin" name="vaadin-client"
rev="${vaadin.version}" conf="build" />
+ <dependency org="com.vaadin" name="vaadin-theme-compiler"
+ rev="${vaadin.version}" conf="build" />
<dependency org="commons-collections" name="commons-collections"
rev="3.1" conf="build,ide -> default" />
diff --git a/client-compiler/src/com/vaadin/sass/linker/SassLinker.java b/client-compiler/src/com/vaadin/sass/linker/SassLinker.java
new file mode 100644
index 0000000000..82a228a166
--- /dev/null
+++ b/client-compiler/src/com/vaadin/sass/linker/SassLinker.java
@@ -0,0 +1,195 @@
+package com.vaadin.sass.linker;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.w3c.css.sac.CSSException;
+
+import com.google.gwt.core.ext.LinkerContext;
+import com.google.gwt.core.ext.TreeLogger;
+import com.google.gwt.core.ext.UnableToCompleteException;
+import com.google.gwt.core.ext.linker.AbstractLinker;
+import com.google.gwt.core.ext.linker.ArtifactSet;
+import com.google.gwt.core.ext.linker.EmittedArtifact;
+import com.google.gwt.core.ext.linker.LinkerOrder;
+import com.google.gwt.core.ext.linker.LinkerOrder.Order;
+import com.google.gwt.core.ext.linker.Shardable;
+import com.vaadin.sass.internal.ScssStylesheet;
+
+/**
+ * Pre-linker that checks for the existence of SASS files in public folders,
+ * compiles them to CSS files with the SassCompiler from Vaadin and adds the CSS
+ * back into the artifact.
+ *
+ */
+@LinkerOrder(Order.PRE)
+@Shardable
+public class SassLinker extends AbstractLinker {
+
+ @Override
+ public String getDescription() {
+ return "Compiling SASS files in public folders to standard CSS";
+ }
+
+ @Override
+ public ArtifactSet link(TreeLogger logger, LinkerContext context,
+ ArtifactSet artifacts, boolean onePermutation)
+ throws UnableToCompleteException {
+
+ if (!onePermutation) {
+ // The artifact to return
+ ArtifactSet toReturn = new ArtifactSet(artifacts);
+
+ // The temporary sass files provided from the artefacts
+ List<FileInfo> sassFiles = new ArrayList<FileInfo>();
+
+ // The public files are provided as inputstream, but the compiler
+ // needs real files, as they can contain references to other
+ // files. They will be stored here, with their relative paths intact
+ String tempFolderName = new Date().getTime() + File.separator;
+ File tempFolder = createTempDir(tempFolderName);
+
+ // Create the temporary files
+ for (EmittedArtifact resource : artifacts
+ .find(EmittedArtifact.class)) {
+
+ String partialPath = resource.getPartialPath();
+ if (partialPath.endsWith(".scss")) {
+
+ String fileName = partialPath;
+ File path = tempFolder;
+
+ int separatorIndex = fileName.lastIndexOf(File.separator);
+ if (-1 != separatorIndex) {
+ fileName = fileName.substring(separatorIndex + 1);
+
+ String filePath = partialPath.substring(0,
+ separatorIndex);
+ path = createTempDir(tempFolderName + filePath);
+ }
+
+ File tempfile = new File(path, fileName);
+ try {
+ boolean fileCreated = tempfile.createNewFile();
+ if (fileCreated) {
+
+ // write the received inputstream to the temp file
+ writeFromInputStream(resource.getContents(logger),
+ tempfile);
+
+ // Store the file info for the compilation
+ sassFiles.add(new FileInfo(tempfile, partialPath));
+
+ // In my oppinion, the SASS file does not need to be
+ // output to the web content, as they can't be used
+ // there
+ toReturn.remove(resource);
+ }
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+ }
+
+ // Compile the files and store them in the artifact
+ logger.log(TreeLogger.INFO, "Processing " + sassFiles.size()
+ + " Sass file(s)");
+ for (FileInfo fileInfo : sassFiles) {
+ logger.log(TreeLogger.INFO, " " + fileInfo.originalScssPath
+ + " -> " + fileInfo.getOriginalCssPath());
+
+ ScssStylesheet scss;
+
+ try {
+ scss = ScssStylesheet.get(fileInfo.getAbsolutePath());
+ scss.compile();
+ InputStream is = new ByteArrayInputStream(scss.toString()
+ .getBytes());
+
+ toReturn.add(this.emitInputStream(logger, is,
+ fileInfo.getOriginalCssPath()));
+ } catch (CSSException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+ }
+
+ return toReturn;
+ }
+
+ return artifacts;
+ }
+
+ private void writeFromInputStream(InputStream contents, File tempfile)
+ throws IOException {
+ // write the inputStream to a FileOutputStream
+ OutputStream out = new FileOutputStream(tempfile);
+
+ int read = 0;
+ byte[] bytes = new byte[1024];
+
+ while ((read = contents.read(bytes)) != -1) {
+ out.write(bytes, 0, read);
+ }
+
+ contents.close();
+ out.flush();
+ out.close();
+ }
+
+ /**
+ * Create folder in temporary space on disk.
+ *
+ * @param partialPath
+ * @return
+ */
+ private File createTempDir(String partialPath) {
+ String baseTempPath = System.getProperty("java.io.tmpdir");
+
+ File tempDir = new File(baseTempPath + File.separator + partialPath);
+ if (!tempDir.exists()) {
+ tempDir.mkdir();
+ }
+
+ tempDir.deleteOnExit();
+ return tempDir;
+ }
+
+ /**
+ * Temporal storage for file info from Artifact
+ *
+ */
+ private class FileInfo {
+ private String originalScssPath;
+ private File file;
+
+ public FileInfo(File file, String originalScssPath) {
+ this.file = file;
+ this.originalScssPath = originalScssPath;
+ }
+
+ public String getAbsolutePath() {
+ return file.getAbsolutePath();
+ }
+
+ public String getOriginalCssPath() {
+ return originalScssPath.substring(0, originalScssPath.length() - 5)
+ + ".css";
+ }
+ }
+
+}