blob: c2adcad074da3ba8bc193d5a747d0ad03f7fa118 [file] [log] [blame]
// 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.webresources.modules;
import com.github.sommeri.less4j.LessCompiler;
import com.github.sommeri.less4j.core.parser.AntlrException;
import com.google.javascript.jscomp.CompilationLevel;
import org.apache.tapestry5.MarkupWriter;
import org.apache.tapestry5.internal.webresources.*;
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;
import org.apache.tapestry5.ioc.internal.util.InternalUtils;
import org.apache.tapestry5.ioc.services.FactoryDefaults;
import org.apache.tapestry5.ioc.services.SymbolProvider;
import org.apache.tapestry5.services.ObjectRenderer;
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.webresources.WebResourcesSymbols;
import java.util.List;
/**
* Configures use of various transformers and mimimizers to support:
* <ul>
* <li>Less to CSS</li>
* <li>CoffeeScript to JavaScript</li>
* <li>CSS minimization via YUI Compressor</li>
* <li>JavaScript minimization via Google Closure</li>
* </ul>
*
* @since 5.4
*/
public class WebResourcesModule
{
public static void bind(ServiceBinder binder)
{
binder.bind(ResourceTransformerFactory.class, ResourceTransformerFactoryImpl.class);
}
@Contribute(SymbolProvider.class)
@FactoryDefaults
public static void setupDefaultCacheDirectory(MappedConfiguration<String, Object> configuration)
{
configuration.add(WebResourcesSymbols.CACHE_DIR, "${java.io.tmpdir}/tapestry-asset-cache");
configuration.add(WebResourcesSymbols.COMPILATION_LEVEL, CompilationLevel.WHITESPACE_ONLY);
}
@Contribute(StreamableResourceSource.class)
public static void provideCompilers(MappedConfiguration<String, ResourceTransformer> configuration, ResourceTransformerFactory factory,
@Autobuild CoffeeScriptCompiler coffeeScriptCompiler,
@Autobuild final TypeScriptCompiler tsCompiler)
{
// contribution ids are file extensions:
configuration.add("coffee",
factory.createCompiler("text/javascript", "CoffeeScript", "JavaScript",
coffeeScriptCompiler,
CacheMode.SINGLE_FILE));
configuration.add("less",
factory.createCompiler("text/css", "Less", "CSS", new LessResourceTransformer(),
CacheMode.MULTIPLE_FILE));
configuration.add("ts",
factory.createCompiler("text/javascript", "TS", "JavaScript", tsCompiler,
CacheMode.SINGLE_FILE));
}
@Contribute(ResourceMinimizer.class)
@Primary
public static void setupDefaultResourceMinimizers(MappedConfiguration<String, ResourceMinimizer> configuration)
{
configuration.addInstance("text/css", CSSMinimizer.class);
configuration.addInstance("text/javascript", GoogleClosureMinimizer.class);
}
/**
* Alas {@link AntlrException}s do not have a useful toString() which makes them useless in the exception report;
* here we provide an {@link ObjectRenderer} that breaks them apart into useful strings. Eventually we may be
* able to synthesize a {@link org.apache.tapestry5.ioc.Location} from them as well and show some of the source .less file.
*/
@Contribute(ObjectRenderer.class)
@Primary
public static void provideLessCompilerProblemRenderer(MappedConfiguration<Class, ObjectRenderer> configuration)
{
configuration.add(LessCompiler.Problem.class, new ObjectRenderer<LessCompiler.Problem>()
{
@Override
public void render(LessCompiler.Problem problem, MarkupWriter writer)
{
List<String> strings = CollectionFactory.newList();
if (InternalUtils.isNonBlank(problem.getMessage()))
{
strings.add(problem.getMessage());
}
// Inside WRO4J we see that the LessSource is a StringSource with no useful toString(), so
// it is omitted. We may need to create our own processors, stripping away a couple of layers of
// WRO4J to get proper exception reporting!
if (problem.getLine() > 0)
{
strings.add("line " + problem.getLine());
}
if (problem.getCharacter() > 0)
{
strings.add("position " + problem.getCharacter());
}
writer.write(InternalUtils.join(strings, " - "));
}
});
}
}