You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tapestry.apache.org by hl...@apache.org on 2013/06/01 03:20:04 UTC

[7/7] git commit: Improve Less support; including ability to reference other Less files via @import

Improve Less support; including ability to reference other Less files via @import


Project: http://git-wip-us.apache.org/repos/asf/tapestry-5/repo
Commit: http://git-wip-us.apache.org/repos/asf/tapestry-5/commit/512ee316
Tree: http://git-wip-us.apache.org/repos/asf/tapestry-5/tree/512ee316
Diff: http://git-wip-us.apache.org/repos/asf/tapestry-5/diff/512ee316

Branch: refs/heads/master
Commit: 512ee3168890efd00ffbb04efd277e35745ecb83
Parents: 1539066
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Fri May 31 18:19:41 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Fri May 31 18:19:41 2013 -0700

----------------------------------------------------------------------
 .../internal/wro4j/LessResourceTransformer.java    |  147 +++++++++++++++
 .../internal/wro4j/ResourceTransformUtils.java     |   28 +++
 .../wro4j/ResourceTransformerFactoryImpl.java      |    4 +-
 .../tapestry5/wro4j/modules/WRO4JModule.java       |    7 +-
 .../src/test/resources/META-INF/assets/colors.less |    4 +-
 5 files changed, 180 insertions(+), 10 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/512ee316/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/LessResourceTransformer.java
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/LessResourceTransformer.java b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/LessResourceTransformer.java
new file mode 100644
index 0000000..1b655f9
--- /dev/null
+++ b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/LessResourceTransformer.java
@@ -0,0 +1,147 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.internal.wro4j;
+
+import com.github.sommeri.less4j.Less4jException;
+import com.github.sommeri.less4j.LessCompiler;
+import com.github.sommeri.less4j.LessSource;
+import com.github.sommeri.less4j.core.DefaultLessCompiler;
+import org.apache.commons.io.IOUtils;
+import org.apache.tapestry5.internal.services.assets.BytestreamCache;
+import org.apache.tapestry5.ioc.IOOperation;
+import org.apache.tapestry5.ioc.OperationTracker;
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.services.assets.ResourceDependencies;
+import org.apache.tapestry5.services.assets.ResourceTransformer;
+import org.slf4j.Logger;
+
+import java.io.*;
+
+/**
+ * Direct wrapper around the LessCompiler, so that Less source files may use {@code @import}, which isn't
+ * supported by the normal WRO4J processor.
+ */
+public class LessResourceTransformer implements ResourceTransformer
+{
+    private final LessCompiler compiler = new DefaultLessCompiler();
+
+    private final OperationTracker tracker;
+
+    private final Logger logger;
+
+    public LessResourceTransformer(OperationTracker tracker, Logger logger)
+    {
+        this.tracker = tracker;
+        this.logger = logger;
+    }
+
+    public String getTransformedContentType()
+    {
+        return "text/css";
+    }
+
+    class ResourceLessSource extends LessSource
+    {
+        private final Resource resource;
+
+        private final ResourceDependencies dependencies;
+
+
+        ResourceLessSource(Resource resource, ResourceDependencies dependencies)
+        {
+            this.resource = resource;
+            this.dependencies = dependencies;
+        }
+
+        @Override
+        public LessSource relativeSource(String filename) throws FileNotFound, CannotReadFile, StringSourceException
+        {
+            Resource relative = resource.forFile(filename);
+
+            if (!relative.exists())
+            {
+                throw new FileNotFound();
+            }
+
+            dependencies.addDependency(relative);
+
+            return new ResourceLessSource(relative, dependencies);
+        }
+
+        @Override
+        public String getContent() throws FileNotFound, CannotReadFile
+        {
+            // Adapted from Less's URLSource
+            try
+            {
+                Reader input = new InputStreamReader(resource.openStream());
+                String content = IOUtils.toString(input).replace("\r\n", "\n");
+
+                input.close();
+
+                return content;
+            } catch (FileNotFoundException ex)
+            {
+                throw new FileNotFound();
+            } catch (IOException ex)
+            {
+                throw new CannotReadFile();
+            }
+        }
+    }
+
+
+    public InputStream transform(final Resource source, final ResourceDependencies dependencies) throws IOException
+    {
+        return tracker.perform(String.format("Compiling %s from Less to CSS", source), new IOOperation<InputStream>()
+        {
+            public InputStream perform() throws IOException
+            {
+                long start = System.nanoTime();
+
+                InputStream result = compile(source, dependencies);
+
+                long complete = System.nanoTime();
+
+                logger.info(String.format("Compiled %s to Less in %.2f ms",
+                        source, ResourceTransformUtils.nanosToMillis(complete - start)));
+
+                return result;
+            }
+        });
+    }
+
+    private InputStream compile(Resource source, ResourceDependencies dependencies) throws IOException
+    {
+        try
+        {
+            LessSource lessSource = new ResourceLessSource(source, dependencies);
+
+            LessCompiler.CompilationResult result = compiler.compile(lessSource);
+
+            // Currently, ignoring any warnings.
+
+            BytestreamCache cache = new BytestreamCache(result.getCss().getBytes("utf-8"));
+
+            return cache.openStream();
+        } catch (Less4jException ex)
+        {
+            throw new IOException(ex);
+        } catch (UnsupportedEncodingException ex)
+        {
+            throw new IOException(ex);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/512ee316/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformUtils.java
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformUtils.java b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformUtils.java
new file mode 100644
index 0000000..eed495f
--- /dev/null
+++ b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformUtils.java
@@ -0,0 +1,28 @@
+// Copyright 2013 The Apache Software Foundation
+//
+// 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 org.apache.tapestry5.internal.wro4j;
+
+/**
+ * @since 5.4
+ */
+public class ResourceTransformUtils
+{
+    private static final double NANOS_TO_MILLIS = 1.0d / 1000000.0d;
+
+    public static double nanosToMillis(long nanos)
+    {
+        return ((double) nanos) * NANOS_TO_MILLIS;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/512ee316/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformerFactoryImpl.java
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformerFactoryImpl.java b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformerFactoryImpl.java
index 64e67a7..99d438f 100644
--- a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformerFactoryImpl.java
+++ b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/ResourceTransformerFactoryImpl.java
@@ -34,8 +34,6 @@ import java.util.zip.Adler32;
 
 public class ResourceTransformerFactoryImpl implements ResourceTransformerFactory
 {
-    private static final double NANOS_TO_MILLIS = 1.0d / 1000000.0d;
-
     private final Logger logger;
 
     private final ResourceProcessorSource source;
@@ -150,7 +148,7 @@ public class ResourceTransformerFactoryImpl implements ResourceTransformerFactor
 
                         logger.info(String.format("Compiled %s to %s in %.2f ms",
                                 source, targetName,
-                                ((double) elapsedTime) * NANOS_TO_MILLIS));
+                                ResourceTransformUtils.nanosToMillis(elapsedTime)));
 
                         return result;
                     }

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/512ee316/tapestry-wro4j/src/main/java/org/apache/tapestry5/wro4j/modules/WRO4JModule.java
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/main/java/org/apache/tapestry5/wro4j/modules/WRO4JModule.java b/tapestry-wro4j/src/main/java/org/apache/tapestry5/wro4j/modules/WRO4JModule.java
index ac02015..05b39a7 100644
--- a/tapestry-wro4j/src/main/java/org/apache/tapestry5/wro4j/modules/WRO4JModule.java
+++ b/tapestry-wro4j/src/main/java/org/apache/tapestry5/wro4j/modules/WRO4JModule.java
@@ -31,7 +31,6 @@ import org.apache.tapestry5.services.assets.ResourceMinimizer;
 import org.apache.tapestry5.services.assets.ResourceTransformer;
 import org.apache.tapestry5.services.assets.StreamableResourceSource;
 import org.apache.tapestry5.wro4j.services.ResourceProcessorSource;
-import ro.isdc.wro.extensions.processor.css.Less4jProcessor;
 import ro.isdc.wro.extensions.processor.js.GoogleClosureCompressorProcessor;
 import ro.isdc.wro.extensions.processor.js.RhinoCoffeeScriptProcessor;
 import ro.isdc.wro.extensions.processor.support.coffeescript.CoffeeScript;
@@ -61,7 +60,6 @@ public class WRO4JModule
      * <dt>JavaScriptMinimizer</dt>
      * <dd>{@link GoogleClosureCompressorProcessor} configured for simple optimizations. Advanced optimizations assume that all code is loaded
      * in a single bundle, not a given for Tapestry.</dd>
-     * <dt>LessCompiler</dt> <dd>Compiles Less source files into CSS.</dd>
      * </dl>
      */
     @Contribute(ResourceProcessorSource.class)
@@ -81,7 +79,6 @@ public class WRO4JModule
 
         configuration.addInstance("CSSMinimizer", CssCompressorProcessor.class);
         configuration.add("JavaScriptMinimizer", new GoogleClosureCompressorProcessor());
-        configuration.addInstance("LessCompiler", Less4jProcessor.class);
     }
 
     @Contribute(StreamableResourceSource.class)
@@ -92,8 +89,8 @@ public class WRO4JModule
         configuration.add("coffee",
                 factory.createCompiler("text/javascript", "CoffeeScriptCompiler", "CoffeeScript", "JavaScript", !productionMode));
 
-        // We'll have to see how imports work in a Less file before we can get into whether we can enable development-mode caching.
-        configuration.add("less", factory.createCompiler("text/css", "LessCompiler", "Less", "CSS", false));
+        // Had to create our own wrapper around Less4J to handle @imports correctly.
+        configuration.addInstance("less", LessResourceTransformer.class);
     }
 
     @Contribute(ResourceMinimizer.class)

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/512ee316/tapestry-wro4j/src/test/resources/META-INF/assets/colors.less
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/test/resources/META-INF/assets/colors.less b/tapestry-wro4j/src/test/resources/META-INF/assets/colors.less
index ebac95e..923c7c5 100644
--- a/tapestry-wro4j/src/test/resources/META-INF/assets/colors.less
+++ b/tapestry-wro4j/src/test/resources/META-INF/assets/colors.less
@@ -1,2 +1,2 @@
-@primary = "blue";
-@secondary = lighten(@primary, 25%);
\ No newline at end of file
+@primary: blue;
+@secondary: lighten(@primary, 25%);
\ No newline at end of file