/* * Copyright 2010. */ package ro.isdc.wro.extensions.processor.support.coffeescript; import java.io.IOException; import java.io.InputStream; import java.util.Arrays; import org.mozilla.javascript.ScriptableObject; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import ro.isdc.wro.extensions.locator.WebjarUriLocator; import ro.isdc.wro.extensions.processor.support.linter.LinterException; import ro.isdc.wro.extensions.script.RhinoScriptBuilder; import ro.isdc.wro.util.WroUtil; /** * CoffeeScript is a little language that compiles into JavaScript. Underneath all of those embarrassing braces and * semicolons, JavaScript has always had a gorgeous object model at its heart. CoffeeScript is an attempt to expose the * good parts of JavaScript in a simple way. * <p/> * This processor loads coffee-script library from the webjar. * * @author Alex Objelean * @since 1.3.6 */ public class CoffeeScript { private static final Logger LOG = LoggerFactory.getLogger(CoffeeScript.class); private static final String DEFAULT_COFFE_SCRIPT = "coffee-script.js"; private String[] options; private ScriptableObject scope; private WebjarUriLocator webjarLocator; /** * Initialize script builder for evaluation. */ private RhinoScriptBuilder initScriptBuilder() { try { RhinoScriptBuilder builder = null; if (scope == null) { builder = RhinoScriptBuilder.newChain().evaluateChain(getCoffeeScriptAsStream(), DEFAULT_COFFE_SCRIPT); scope = builder.getScope(); } else { builder = RhinoScriptBuilder.newChain(scope); } return builder; } catch (final IOException ex) { throw new IllegalStateException("Failed reading init script", ex); } } /** * Override this method to use a different version of CoffeeScript. This method is useful for upgrading coffeeScript * processor independently of wro4j. * * @return The stream of the CoffeeScript. */ protected InputStream getCoffeeScriptAsStream() throws IOException { return getWebjarLocator().locate(WebjarUriLocator.createUri("coffee-script.min.js")); } /** * @return {@link WebjarUriLocator} instance to retrieve webjars. */ private WebjarUriLocator getWebjarLocator() { if (webjarLocator == null) { webjarLocator = new WebjarUriLocator(); } return webjarLocator; } /** * Validates a js using jsHint and throws {@link LinterException} if the js is invalid. If no exception is thrown, the * js is valid. * * @param data * js content to process. */ public String compile(final String data) { final RhinoScriptBuilder builder = initScriptBuilder(); final String compileScript = String.format("CoffeeScript.compile(%s, %s);", WroUtil.toJSMultiLineString(data), buildOptions()); return (String) builder.evaluate(compileScript, "CoffeeScript.compile"); } /** * @return A javascript representation of the options. The result is a json object. */ private String buildOptions() { final StringBuffer sb = new StringBuffer("{"); if (options != null) { for (int i = 0; i < options.length; i++) { sb.append(options[i]).append(": true"); if (i < options.length - 1) { sb.append(","); } } } sb.append("}"); return sb.toString(); } /** * @param options * the options to set */ public CoffeeScript setOptions(final String... options) { this.options = options == null ? new String[] {} : options; LOG.debug("setOptions: {}", Arrays.asList(this.options)); return this; } }