You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tapestry.apache.org by hl...@apache.org on 2013/08/25 00:36:35 UTC

[10/10] git commit: Include Bootstrap 3 source to test Less compilation Replace WRO4J CoffeeScript compiler with own implementation

Include Bootstrap 3 source to test Less compilation
Replace WRO4J CoffeeScript compiler with own implementation


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

Branch: refs/heads/master
Commit: 70889263a459919f7820b3880f92b647f843d893
Parents: 2cbe72e
Author: Howard M. Lewis Ship <hl...@apache.org>
Authored: Sat Aug 24 15:01:26 2013 -0700
Committer: Howard M. Lewis Ship <hl...@apache.org>
Committed: Sat Aug 24 15:05:13 2013 -0700

----------------------------------------------------------------------
 tapestry-wro4j/build.gradle                     |    4 +
 .../internal/wro4j/CoffeeScriptCompiler.java    |   82 +
 .../internal/wro4j/LessResourceTransformer.java |    1 -
 .../wro4j/NodeOrRhinoCoffeeScriptCompiler.java  |   63 -
 .../tapestry5/internal/wro4j/RhinoExecutor.java |   24 +
 .../internal/wro4j/RhinoExecutorPool.java       |  147 ++
 .../tapestry5/wro4j/modules/WRO4JModule.java    |    9 +-
 .../webresources/internal/coffeescript-1.6.3.js |   12 +
 .../internal/invoke-coffeescript.js             |   14 +
 .../groovy/t5/wro4j/components/Layout.groovy    |    2 +-
 .../test/groovy/t5/wro4j/tests/Wro4jSpec.groovy |    9 +-
 .../test/java/t5/wro4j/services/AppModule.java  |   14 +-
 .../src/test/resources/GebConfig.groovy         |    2 +-
 .../resources/t5/wro4j/components/Layout.tml    |   26 +-
 .../test/webapp/bootstrap/css/accordion.less    |   34 -
 .../src/test/webapp/bootstrap/css/alerts.less   |   79 -
 .../test/webapp/bootstrap/css/bootstrap.less    |   63 -
 .../test/webapp/bootstrap/css/breadcrumbs.less  |   24 -
 .../webapp/bootstrap/css/button-groups.less     |  229 --
 .../src/test/webapp/bootstrap/css/buttons.less  |  228 --
 .../src/test/webapp/bootstrap/css/carousel.less |  158 --
 .../src/test/webapp/bootstrap/css/close.less    |   32 -
 .../src/test/webapp/bootstrap/css/code.less     |   61 -
 .../bootstrap/css/component-animations.less     |   22 -
 .../test/webapp/bootstrap/css/dropdowns.less    |  248 --
 .../src/test/webapp/bootstrap/css/forms.less    |  690 ------
 .../src/test/webapp/bootstrap/css/grid.less     |   21 -
 .../test/webapp/bootstrap/css/hero-unit.less    |   25 -
 .../webapp/bootstrap/css/labels-badges.less     |   84 -
 .../src/test/webapp/bootstrap/css/layouts.less  |   16 -
 .../src/test/webapp/bootstrap/css/media.less    |   55 -
 .../src/test/webapp/bootstrap/css/mixins.less   |  702 ------
 .../src/test/webapp/bootstrap/css/modals.less   |   95 -
 .../src/test/webapp/bootstrap/css/navbar.less   |  497 ----
 .../src/test/webapp/bootstrap/css/navs.less     |  409 ----
 .../src/test/webapp/bootstrap/css/pager.less    |   43 -
 .../test/webapp/bootstrap/css/pagination.less   |  123 -
 .../src/test/webapp/bootstrap/css/popovers.less |  133 -
 .../webapp/bootstrap/css/progress-bars.less     |  122 -
 .../src/test/webapp/bootstrap/css/reset.less    |  216 --
 .../bootstrap/css/responsive-1200px-min.less    |   28 -
 .../bootstrap/css/responsive-767px-max.less     |  193 --
 .../bootstrap/css/responsive-768px-979px.less   |   19 -
 .../webapp/bootstrap/css/responsive-navbar.less |  189 --
 .../bootstrap/css/responsive-utilities.less     |   59 -
 .../test/webapp/bootstrap/css/responsive.less   |   48 -
 .../test/webapp/bootstrap/css/scaffolding.less  |   53 -
 .../src/test/webapp/bootstrap/css/sprites.less  |  197 --
 .../src/test/webapp/bootstrap/css/tables.less   |  244 --
 .../test/webapp/bootstrap/css/thumbnails.less   |   53 -
 .../src/test/webapp/bootstrap/css/tooltip.less  |   70 -
 .../src/test/webapp/bootstrap/css/type.less     |  247 --
 .../test/webapp/bootstrap/css/utilities.less    |   30 -
 .../test/webapp/bootstrap/css/variables.less    |  301 ---
 .../src/test/webapp/bootstrap/css/wells.less    |   29 -
 .../fonts/glyphicons-halflings-regular.eot      |  Bin 0 -> 14079 bytes
 .../fonts/glyphicons-halflings-regular.svg      |  228 ++
 .../fonts/glyphicons-halflings-regular.ttf      |  Bin 0 -> 29512 bytes
 .../fonts/glyphicons-halflings-regular.woff     |  Bin 0 -> 16448 bytes
 .../img/glyphicons-halflings-white.png          |  Bin 8777 -> 0 bytes
 .../bootstrap/img/glyphicons-halflings.png      |  Bin 12799 -> 0 bytes
 .../src/test/webapp/bootstrap/js/affix.js       |  126 +
 .../src/test/webapp/bootstrap/js/alert.js       |   98 +
 .../src/test/webapp/bootstrap/js/bootstrap.js   | 2280 ------------------
 .../src/test/webapp/bootstrap/js/button.js      |  109 +
 .../src/test/webapp/bootstrap/js/carousel.js    |  217 ++
 .../src/test/webapp/bootstrap/js/collapse.js    |  179 ++
 .../src/test/webapp/bootstrap/js/dropdown.js    |  154 ++
 .../src/test/webapp/bootstrap/js/modal.js       |  246 ++
 .../src/test/webapp/bootstrap/js/popover.js     |  117 +
 .../src/test/webapp/bootstrap/js/scrollspy.js   |  158 ++
 .../src/test/webapp/bootstrap/js/tab.js         |  135 ++
 .../src/test/webapp/bootstrap/js/tooltip.js     |  386 +++
 .../src/test/webapp/bootstrap/js/transition.js  |   56 +
 .../src/test/webapp/bootstrap/less/alerts.less  |   67 +
 .../src/test/webapp/bootstrap/less/badges.less  |   51 +
 .../test/webapp/bootstrap/less/bootstrap.less   |   59 +
 .../test/webapp/bootstrap/less/breadcrumbs.less |   23 +
 .../webapp/bootstrap/less/button-groups.less    |  248 ++
 .../src/test/webapp/bootstrap/less/buttons.less |  160 ++
 .../test/webapp/bootstrap/less/carousel.less    |  209 ++
 .../src/test/webapp/bootstrap/less/close.less   |   33 +
 .../src/test/webapp/bootstrap/less/code.less    |   56 +
 .../bootstrap/less/component-animations.less    |   29 +
 .../test/webapp/bootstrap/less/dropdowns.less   |  193 ++
 .../src/test/webapp/bootstrap/less/forms.less   |  353 +++
 .../test/webapp/bootstrap/less/glyphicons.less  |  232 ++
 .../src/test/webapp/bootstrap/less/grid.less    |  346 +++
 .../webapp/bootstrap/less/input-groups.less     |  127 +
 .../test/webapp/bootstrap/less/jumbotron.less   |   40 +
 .../src/test/webapp/bootstrap/less/labels.less  |   58 +
 .../test/webapp/bootstrap/less/list-group.less  |   88 +
 .../src/test/webapp/bootstrap/less/media.less   |   56 +
 .../src/test/webapp/bootstrap/less/mixins.less  |  723 ++++++
 .../src/test/webapp/bootstrap/less/modals.less  |  141 ++
 .../src/test/webapp/bootstrap/less/navbar.less  |  621 +++++
 .../src/test/webapp/bootstrap/less/navs.less    |  229 ++
 .../test/webapp/bootstrap/less/normalize.less   |  396 +++
 .../src/test/webapp/bootstrap/less/pager.less   |   55 +
 .../test/webapp/bootstrap/less/pagination.less  |   83 +
 .../src/test/webapp/bootstrap/less/panels.less  |  148 ++
 .../test/webapp/bootstrap/less/popovers.less    |  133 +
 .../src/test/webapp/bootstrap/less/print.less   |  100 +
 .../webapp/bootstrap/less/progress-bars.less    |   95 +
 .../bootstrap/less/responsive-utilities.less    |  220 ++
 .../test/webapp/bootstrap/less/scaffolding.less |  130 +
 .../src/test/webapp/bootstrap/less/tables.less  |  236 ++
 .../src/test/webapp/bootstrap/less/theme.less   |  232 ++
 .../test/webapp/bootstrap/less/thumbnails.less  |   31 +
 .../src/test/webapp/bootstrap/less/tooltip.less |   95 +
 .../src/test/webapp/bootstrap/less/type.less    |  238 ++
 .../test/webapp/bootstrap/less/utilities.less   |   42 +
 .../test/webapp/bootstrap/less/variables.less   |  620 +++++
 .../src/test/webapp/bootstrap/less/wells.less   |   29 +
 114 files changed, 9558 insertions(+), 8534 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70889263/tapestry-wro4j/build.gradle
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/build.gradle b/tapestry-wro4j/build.gradle
index cd00fbc..d4432e1 100644
--- a/tapestry-wro4j/build.gradle
+++ b/tapestry-wro4j/build.gradle
@@ -2,6 +2,10 @@ description = "Integration with WRO4J to perform runtime CoffeeScript compilatio
 
 dependencies {
     compile project(":tapestry-core")
+    compile "com.github.sommeri:less4j:1.1.1"
+    compile "com.google.javascript:closure-compiler:v20130722"
+    compile "org.mozilla:rhino:1.7R4"
+
     compile "ro.isdc.wro4j:wro4j-extensions:${versions.wro4j}", {
         exclude group: "org.codehaus.gmaven.runtime", module: "gmaven-runtime-1.7"
         exclude group: "com.github.lltyk", module: "dojo-shrinksafe"

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70889263/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/CoffeeScriptCompiler.java
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/CoffeeScriptCompiler.java b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/CoffeeScriptCompiler.java
new file mode 100644
index 0000000..452f2b3
--- /dev/null
+++ b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/CoffeeScriptCompiler.java
@@ -0,0 +1,82 @@
+package org.apache.tapestry5.internal.wro4j;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.tapestry5.annotations.Path;
+import org.apache.tapestry5.ioc.OperationTracker;
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.services.assets.ResourceDependencies;
+import org.apache.tapestry5.services.assets.ResourceTransformer;
+import org.mozilla.javascript.NativeObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+
+public class CoffeeScriptCompiler implements ResourceTransformer
+{
+    private final static Charset UTF8 = Charset.forName("utf-8");
+
+    private final RhinoExecutorPool executorPool;
+
+    public String getTransformedContentType()
+    {
+        return "text/javascript";
+    }
+
+    public CoffeeScriptCompiler(@Path("classpath:org/apache/tapestry5/webresources/internal/coffeescript-1.6.3.js")
+                                Resource mainCompiler,
+                                @Path("classpath:org/apache/tapestry5/webresources/internal/invoke-coffeescript.js")
+                                Resource shim,
+                                OperationTracker tracker)
+    {
+
+        executorPool = new RhinoExecutorPool(tracker, toList(mainCompiler, shim));
+    }
+
+    private List<Resource> toList(Resource... resources)
+    {
+        List<Resource> list = CollectionFactory.newList();
+
+        for (Resource r : resources)
+        {
+            list.add(r);
+        }
+
+        return list;
+    }
+
+
+    private String getString(NativeObject object, String key)
+    {
+        return object.get(key).toString();
+    }
+
+
+    public InputStream transform(Resource source, ResourceDependencies dependencies) throws IOException
+    {
+        String content = IOUtils.toString(source.openStream(), UTF8);
+
+        RhinoExecutor executor = executorPool.get();
+
+        try
+        {
+
+            NativeObject result = (NativeObject) executor.invokeFunction("compileCoffeeScriptSource", content, source.toString());
+
+            if (result.containsKey("exception"))
+            {
+                throw new RuntimeException(getString(result, "exception"));
+            }
+
+            return IOUtils.toInputStream(getString(result, "output"), UTF8);
+
+        } finally
+        {
+            executor.discard();
+        }
+
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70889263/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
index 1fd40d9..5b4d7a7 100644
--- 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
@@ -92,7 +92,6 @@ public class LessResourceTransformer implements ResourceTransformer
 
     public InputStream transform(Resource source, ResourceDependencies dependencies) throws IOException
     {
-
         BytestreamCache compiled = invokeLessCompiler(source, dependencies);
 
         return compiled.openStream();

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70889263/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/NodeOrRhinoCoffeeScriptCompiler.java
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/NodeOrRhinoCoffeeScriptCompiler.java b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/NodeOrRhinoCoffeeScriptCompiler.java
deleted file mode 100644
index 03e175d..0000000
--- a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/NodeOrRhinoCoffeeScriptCompiler.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// 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 org.slf4j.Logger;
-import ro.isdc.wro.extensions.processor.js.NodeCoffeeScriptProcessor;
-import ro.isdc.wro.extensions.processor.js.RhinoCoffeeScriptProcessor;
-import ro.isdc.wro.model.resource.Resource;
-import ro.isdc.wro.model.resource.processor.ResourcePreProcessor;
-
-import java.io.IOException;
-import java.io.Reader;
-import java.io.Writer;
-
-/**
- * Creates either a {@link NodeCoffeeScriptProcessor} or a {@link RhinoCoffeeScriptProcessor}
- * and delegates the process() method to it. {@link ro.isdc.wro.extensions.processor.js.CoffeeScriptProcessor} should
- * do this, but doesn't work correctly inside Tapestry due to its home-grown injection system.
- */
-public class NodeOrRhinoCoffeeScriptCompiler implements ResourcePreProcessor
-{
-    private final Logger logger;
-
-    private final ResourcePreProcessor processor;
-
-    public NodeOrRhinoCoffeeScriptCompiler(Logger logger)
-    {
-        this.logger = logger;
-        processor = create();
-    }
-
-    private ResourcePreProcessor create()
-    {
-        NodeCoffeeScriptProcessor processor = new NodeCoffeeScriptProcessor();
-
-        if (processor.isSupported())
-        {
-            logger.info("'coffee' command is available; using Node to compile CoffeeScript files.");
-            return processor;
-        }
-
-        logger.info("'coffee' command is not available, using Rhino to compile CoffeeScript files.");
-
-        return new RhinoCoffeeScriptProcessor();
-    }
-
-    public void process(Resource resource, Reader reader, Writer writer) throws IOException
-    {
-        processor.process(resource, reader, writer);
-    }
-}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70889263/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/RhinoExecutor.java
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/RhinoExecutor.java b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/RhinoExecutor.java
new file mode 100644
index 0000000..9a1faa5
--- /dev/null
+++ b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/RhinoExecutor.java
@@ -0,0 +1,24 @@
+package org.apache.tapestry5.internal.wro4j;
+
+
+import org.mozilla.javascript.ScriptableObject;
+
+public interface RhinoExecutor
+{
+    /**
+     * Invokes the named function, which must return a scriptable object (typically, a JavaScript Object).
+     *
+     * @param functionName
+     *         name of function visible to the executor's scope (e.g., loaded from the scripts associated
+     *         with the executor).
+     * @param arguments
+     *         Arguments to pass to the object which must be convertable to JavaScript types; Strings work well here.
+     * @return result of invoking the function.
+     */
+    ScriptableObject invokeFunction(String functionName, Object... arguments);
+
+    /**
+     * Discards the executor, returning it to the pool for reuse.
+     */
+    void discard();
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70889263/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/RhinoExecutorPool.java
----------------------------------------------------------------------
diff --git a/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/RhinoExecutorPool.java b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/RhinoExecutorPool.java
new file mode 100644
index 0000000..e7b72cf
--- /dev/null
+++ b/tapestry-wro4j/src/main/java/org/apache/tapestry5/internal/wro4j/RhinoExecutorPool.java
@@ -0,0 +1,147 @@
+package org.apache.tapestry5.internal.wro4j;
+
+import org.apache.tapestry5.ioc.Invokable;
+import org.apache.tapestry5.ioc.OperationTracker;
+import org.apache.tapestry5.ioc.Resource;
+import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
+import org.apache.tapestry5.ioc.internal.util.InternalUtils;
+import org.apache.tapestry5.ioc.util.ExceptionUtils;
+import org.apache.tapestry5.ioc.util.Stack;
+import org.mozilla.javascript.Context;
+import org.mozilla.javascript.ContextFactory;
+import org.mozilla.javascript.NativeFunction;
+import org.mozilla.javascript.ScriptableObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.util.List;
+
+/**
+ * Manages a pool of initialized {@link RhinoExecutor} instances.  The instances are initialized for a particular
+ */
+public class RhinoExecutorPool
+{
+    private final OperationTracker tracker;
+
+    private final List<Resource> scripts;
+
+    private final Stack<RhinoExecutor> executors = CollectionFactory.newStack();
+
+    private final ContextFactory contextFactory = new ContextFactory();
+
+    public RhinoExecutorPool(OperationTracker tracker, List<Resource> scripts)
+    {
+        this.tracker = tracker;
+        this.scripts = scripts;
+    }
+
+    /**
+     * Gets or creates an available executor. It is expected that {@link #put(RhinoExecutor)} will
+     * be invoked after the executor completes.
+     *
+     * @return executor
+     */
+    public synchronized RhinoExecutor get()
+    {
+
+        if (executors.isEmpty())
+        {
+            return createExecutor();
+        }
+
+        return executors.pop();
+    }
+
+    private synchronized void put(RhinoExecutor executor)
+    {
+        executors.push(executor);
+    }
+
+    private RhinoExecutor createExecutor()
+    {
+        return tracker.invoke(String.format("Creating Rhino executor for source(s) %s.",
+                InternalUtils.join(scripts)),
+                new Invokable<RhinoExecutor>()
+                {
+                    public RhinoExecutor invoke()
+                    {
+                        final Context context = contextFactory.enterContext();
+
+                        final ScriptableObject scope = context.initStandardObjects();
+
+                        try
+                        {
+                            context.setOptimizationLevel(-1);
+
+                            for (Resource script : scripts)
+                            {
+                                loadScript(context, scope, script);
+                            }
+
+                        } finally
+                        {
+                            Context.exit();
+                        }
+
+                        return new RhinoExecutor()
+                        {
+                            public ScriptableObject invokeFunction(String functionName, Object... arguments)
+                            {
+                                contextFactory.enterContext(context);
+
+                                try
+                                {
+                                    NativeFunction function = (NativeFunction) scope.get(functionName, scope);
+
+                                    return (ScriptableObject) function.call(context, scope, null, arguments);
+                                } finally
+                                {
+                                    Context.exit();
+                                }
+                            }
+
+                            public void discard()
+                            {
+                                put(this);
+                            }
+                        };
+                    }
+                });
+    }
+
+    private void loadScript(final Context context, final ScriptableObject scope, final Resource script)
+    {
+        tracker.run(String.format("Loading script %s.", script),
+                new Runnable()
+                {
+                    public void run()
+                    {
+                        InputStream in = null;
+                        Reader r = null;
+
+                        try
+                        {
+                            in = script.openStream();
+                            r = new InputStreamReader(in);
+
+                            context.evaluateReader(scope, r, script.toString(), 1, null);
+                        } catch (IOException ex)
+                        {
+                            throw new RuntimeException(String.format("Unable to read script %s: %s",
+                                    script,
+                                    ExceptionUtils.toMessage(ex)
+                            ), ex);
+                        } finally
+                        {
+                            InternalUtils.close(r);
+                            InternalUtils.close(in);
+                        }
+                    }
+                });
+
+    }
+
+
+}

http://git-wip-us.apache.org/repos/asf/tapestry-5/blob/70889263/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 e272448..6481d88 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
@@ -20,6 +20,7 @@ import org.apache.tapestry5.MarkupWriter;
 import org.apache.tapestry5.internal.wro4j.*;
 import org.apache.tapestry5.ioc.MappedConfiguration;
 import org.apache.tapestry5.ioc.ServiceBinder;
+import org.apache.tapestry5.ioc.annotations.Autobuild;
 import org.apache.tapestry5.ioc.annotations.Contribute;
 import org.apache.tapestry5.ioc.annotations.Primary;
 import org.apache.tapestry5.ioc.internal.util.CollectionFactory;
@@ -72,18 +73,20 @@ public class WRO4JModule
     @Contribute(ResourceProcessorSource.class)
     public static void provideDefaultProcessors(MappedConfiguration<String, ResourcePreProcessor> configuration)
     {
-        configuration.addInstance("CoffeeScriptCompiler", NodeOrRhinoCoffeeScriptCompiler.class);
         configuration.addInstance("CSSMinimizer", CssCompressorProcessor.class);
         configuration.add("JavaScriptMinimizer", new GoogleClosureCompressorProcessor());
     }
 
     @Contribute(StreamableResourceSource.class)
-    public static void provideCompilers(MappedConfiguration<String, ResourceTransformer> configuration, ResourceTransformerFactory factory)
+    public static void provideCompilers(MappedConfiguration<String, ResourceTransformer> configuration, ResourceTransformerFactory factory,
+                                        @Autobuild CoffeeScriptCompiler coffeeScriptCompiler)
     {
         // contribution ids are file extensions:
 
         configuration.add("coffee",
-                factory.createCompiler("text/javascript", "CoffeeScriptCompiler", "CoffeeScript", "JavaScript", CacheMode.SINGLE_FILE));
+                factory.createCompiler("text/javascript", "CoffeeScript", "JavaScript",
+                        coffeeScriptCompiler,
+                        CacheMode.SINGLE_FILE));
 
         configuration.add("less",
                 factory.createCompiler("text/css", "Less", "CSS", new LessResourceTransformer(),