Skip to content

Commit

Permalink
3.0.0 is coming out with BabelJS Built IN\!
Browse files Browse the repository at this point in the history
  • Loading branch information
davydotcom committed May 29, 2018
1 parent ef9a216 commit 8e4faeb
Show file tree
Hide file tree
Showing 18 changed files with 1,612 additions and 27 deletions.
1 change: 1 addition & 0 deletions asset-pipeline-core/build.gradle
Expand Up @@ -58,6 +58,7 @@ dependencies {
doc 'org.fusesource.jansi:jansi:1.11'
compile 'org.mozilla:rhino:1.7R4'
compile 'com.google.javascript:closure-compiler-unshaded:v20160713'
//compile 'com.google.javascript:closure-compiler-unshaded:v20180506'
// compile 'com.google.javascript:closure-compiler-unshaded:v20170124'

// compile 'com.google.javascript:closure-compiler-unshaded:v20171112'
Expand Down
Expand Up @@ -20,7 +20,8 @@ import asset.pipeline.processors.JsRequireProcessor

import java.util.regex.Pattern
import asset.pipeline.processors.JsProcessor
import asset.pipeline.processors.Es6Processor
import asset.pipeline.processors.JsNodeInjectProcessor
import asset.pipeline.processors.BabelJsProcessor
import groovy.transform.CompileStatic
/**
* An {@link AssetFile} implementation for Javascript
Expand All @@ -33,7 +34,7 @@ class JsAssetFile extends AbstractAssetFile {
static final List<String> contentType = ['application/javascript', 'application/x-javascript','text/javascript']
static List<String> extensions = ['js']
static String compiledExtension = 'js'
static processors = [JsProcessor,JsRequireProcessor,Es6Processor]
static processors = [JsProcessor,JsNodeInjectProcessor,BabelJsProcessor,JsRequireProcessor]
Pattern directivePattern = ~/(?m)^\/\/=(.*)/

}
Expand Up @@ -21,6 +21,8 @@ import asset.pipeline.processors.JsRequireProcessor

import java.util.regex.Pattern
import asset.pipeline.processors.JsProcessor
import asset.pipeline.processors.BabelJsProcessor
import asset.pipeline.processors.JsNodeInjectProcessor
import groovy.transform.CompileStatic
/**
* An {@link AssetFile} implementation for ES6 Javascript
Expand All @@ -31,9 +33,9 @@ import groovy.transform.CompileStatic
@CompileStatic
class JsEs6AssetFile extends AbstractAssetFile {
static final List<String> contentType = ['application/javascript', 'application/x-javascript','text/javascript']
static List<String> extensions = ['js.es6']
static List<String> extensions = ['js.es6','js.es7','js.es8','bjs']
static String compiledExtension = 'js'
static processors = [JsProcessor, JsRequireProcessor, Es6Processor]
static processors = [JsProcessor, JsNodeInjectProcessor,BabelJsProcessor, JsRequireProcessor]
Pattern directivePattern = ~/(?m)^\/\/=(.*)/

}
Expand Up @@ -146,7 +146,7 @@ abstract class AbstractUrlRewritingProcessor extends AbstractProcessor {
}


protected String replacementAssetPath(final AssetFile assetFile, final AssetFile currFile) {
protected String replacementAssetPath(final AssetFile assetFile, final AssetFile currFile, Boolean preferRelative=false) {

final StringBuilder replacementPathSb = new StringBuilder()
def urlConfig = AssetPipelineConfigHolder.config?.url
Expand All @@ -155,14 +155,18 @@ abstract class AbstractUrlRewritingProcessor extends AbstractProcessor {
baseUrl = urlConfig.call(null)
}

// println "Replacing Asset Path for ${currFile.path}"
if(baseUrl) {
replacementPathSb << baseUrl
} else {
replacementPathSb << '/' << (AssetPipelineConfigHolder.config?.mapping ?: 'assets') << '/'
} else if(!preferRelative){
replacementPathSb << '/' << (AssetPipelineConfigHolder.config?.mapping != null ? AssetPipelineConfigHolder.config?.mapping : 'assets')
if(AssetPipelineConfigHolder.config?.mapping?.size() > 0) {
replacementPathSb << '/'
}
}

// println "FileName Check: ${replacementPathSb}"
// file
final String fileName = nameWithoutExtension(currFile.name)
final String fileName = nameWithoutExtension(currFile.path)
if(precompiler && precompiler.options.enableDigests) {
if(currFile instanceof GenericAssetFile) {
replacementPathSb << fileName << '-' << currFile.getByteDigest() << '.' << extensionFromURI(currFile.name)
Expand All @@ -176,7 +180,7 @@ abstract class AbstractUrlRewritingProcessor extends AbstractProcessor {
}
} else {
if(currFile instanceof GenericAssetFile) {
replacementPathSb << currFile.name
replacementPathSb << currFile.path
} else {
replacementPathSb << fileName << '.' << currFile.compiledExtension
}
Expand Down
@@ -0,0 +1,137 @@
/*
* Copyright 2014 the original author or authors.
*
* 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 asset.pipeline.processors

import asset.pipeline.AssetFile
import groovy.util.logging.Commons
import jdk.nashorn.api.scripting.NashornException
import org.mozilla.javascript.Context
import org.mozilla.javascript.Scriptable
import asset.pipeline.AbstractProcessor
import asset.pipeline.AssetCompiler
import asset.pipeline.JsAssetFile
import asset.pipeline.AssetPipelineConfigHolder
import javax.script.Invocable
import javax.script.ScriptEngine
import javax.script.ScriptEngineManager
import javax.script.SimpleBindings

// CoffeeScript engine will attempt to use Node.JS coffee if it is available on
// the system path. If not, it uses Mozilla Rhino to compile the CoffeeScript
// template using the javascript in-browser compiler.
@Commons
class BabelJsProcessor extends AbstractProcessor {

static Boolean NODE_SUPPORTED
Scriptable globalScope
ClassLoader classLoader

static ScriptEngine engine
static SimpleBindings bindings
private static final $LOCK = new Object[0]
BabelJsProcessor(AssetCompiler precompiler) {
super(precompiler)

try {
classLoader = getClass().getClassLoader()
//Context cx = Context.enter()
//cx.setOptimizationLevel(-1)
//globalScope = cx.initStandardObjects()
loadBabelJs()
} catch(Exception e) {
throw new Exception("CoffeeScript Engine initialization failed.", e)
} finally {
try {
//Context.exit()
} catch(IllegalStateException e) {
}
}

}

protected void loadBabelJs() {
if(!engine) {
synchronized($LOCK) {
if(!engine) {
def babelJsResource = classLoader.getResource('asset/pipeline/babel.min.js')
engine = new ScriptEngineManager().getEngineByName("nashorn");
bindings = new SimpleBindings();
engine.eval(babelJsResource.getText('UTF-8'), bindings);
}
}
}

}


/**
* Processes an input string from a given AssetFile implementation of coffeescript and converts it to javascript
* @param input String input coffee script text to be converted to javascript
* @param AssetFile instance of the asset file from which this file came from. Not actually used currently for this implementation.
* @return String of compiled javascript
*/
String process(String input,AssetFile assetFile) {
if(!input) {
return input
}
Boolean newEcmascriptKeywordsFound = false
if(input.contains("export ") || input.contains("import ")) {
newEcmascriptKeywordsFound = true;
}
if(!newEcmascriptKeywordsFound && assetFile instanceof JsAssetFile) {
if(!AssetPipelineConfigHolder.config?.enableES6 && ! AssetPipelineConfigHolder.config?."enable-es6") {
return input
}
}
try {
def presets = "{ \"presets\": [\"es2015\",[\"stage-2\",{\"decoratorsLegacy\": true}],\"react\"], \"compact\": false }"
if(AssetPipelineConfigHolder.config?.babel?.options) {
presets = AssetPipelineConfigHolder.config?.babel?.options
}


synchronized($LOCK) {
bindings.put("input", input);
bindings.put("optionsJson", presets);
def result = engine.eval("Babel.transform(input, JSON.parse(optionsJson)).code", bindings);
return result
}
} catch(javax.script.ScriptException ex) {
if (ex.getCause() instanceof NashornException) {
String jsStackTrace = NashornException.getScriptStackString(ex.getCause());
throw new Exception("""BabelJs Engine compilation of javascript failed: ${ex.message} -- \n
${input}
""",ex)
} else {
throw new Exception("""BabelJs Engine compilation of javascript failed.
$ex
""",ex)

}

} catch(Exception e) {
throw new Exception("""BabelJs Engine compilation of javascript failed.
$e
""",e)
} finally {
// Context.exit()
}
}



}
Expand Up @@ -105,7 +105,7 @@ class ClosureCompilerProcessor {
case 'ES6':
return LanguageMode.ECMASCRIPT6
case 'ES6_STRICT':
return LanguageMode.ECMASCRIPT6
return LanguageMode.ECMASCRIPT6_STRICT
case 'ES5_SCRIPT':
return LanguageMode.ECMASCRIPT5_STRICT
case 'ES3':
Expand Down
Expand Up @@ -22,7 +22,9 @@ import asset.pipeline.AssetHelper
import asset.pipeline.AssetFile
import asset.pipeline.AssetPipelineConfigHolder
import asset.pipeline.CacheManager
import asset.pipeline.GenericAssetFile
import asset.pipeline.JsAssetFile
import sun.net.www.content.text.Generic

import java.util.regex.Pattern
import com.google.javascript.jscomp.*
Expand All @@ -47,20 +49,20 @@ class Es6Processor extends AbstractProcessor {


String process(final String inputText, final AssetFile assetFile) {

println "Checking Config: ${AssetPipelineConfigHolder.config}"
if(!inputText) {
return inputText
}
if(assetFile instanceof JsAssetFile) {
if(!AssetPipelineConfigHolder.config?.enableES6) {
if(!AssetPipelineConfigHolder.config?.enableES6 && ! AssetPipelineConfigHolder.config?."enable-es6") {
return inputText
}
}
def compiler = new Compiler()
CompilerOptions options = new CompilerOptions()
options.trustedStrings = true
CompilationLevel.WHITESPACE_ONLY.setOptionsForCompilationLevel(options);
options.setLanguageIn(LanguageMode.ECMASCRIPT6)
options.setLanguageIn(LanguageMode.ECMASCRIPT8)
options.setLanguageOut(LanguageMode.ECMASCRIPT5)
options.prettyPrint = true
options.lineBreak = true
Expand Down Expand Up @@ -101,20 +103,55 @@ class Es6Processor extends AbstractProcessor {
return "goog.require(${quote}${cachedPath}${quote})"
}
} else if(assetPath.size() > 0) {
println "looking for path: ${assetPath}"
AssetFile currFile
if(!assetPath.startsWith('/')) {
def relativeFileName = [ assetFile.parentPath, modulePath ].join( AssetHelper.DIRECTIVE_FILE_SEPARATOR )
currFile = AssetHelper.fileForUri(relativeFileName,'application/javascript')
}

if(!currFile) {
currFile = AssetHelper.fileForUri(modulePath,'application/javascript')
}

if(!currFile) {
currFile = AssetHelper.fileForUri(modulePath + '/' + modulePath,'application/javascript')
}

//Time to look for index.js
if(!currFile) {
println "module not found, checking for index.js"
if(!assetPath.startsWith('/')) {
def relativeFileName = [ assetFile.parentPath, modulePath, 'index.js' ].join( AssetHelper.DIRECTIVE_FILE_SEPARATOR )
currFile = AssetHelper.fileForUri(relativeFileName + '/index.js','application/javascript')
}
if(!currFile) {
currFile = AssetHelper.fileForUri(modulePath + '/index.js','application/javascript')
}
if(!currFile) {
currFile = AssetHelper.fileForUri(modulePath + '/' + modulePath + '/index.js','application/javascript')
}
println "Checking for currFile: ${currFile}"
}

if(!currFile) {
if(!assetPath.startsWith('/')) {
def relativeFileName = [ assetFile.parentPath, modulePath ].join( AssetHelper.DIRECTIVE_FILE_SEPARATOR )
currFile = AssetHelper.fileForUri(relativeFileName)
}
if(!currFile) {
currFile = AssetHelper.fileForUri(modulePath)
}
if(!currFile) {
currFile = AssetHelper.fileForUri(modulePath + '/' + modulePath)
}
if(currFile instanceof GenericAssetFile) {
//We have an image file we need its url or byte stream
} else {
currFile = null
}
}
if(!currFile) {
//Time to check FileLoader and see if this file exists as anything else

cachedPaths[assetPath] = null
return "goog.require(${quote}${assetPath}${quote})"
} else {
Expand Down
@@ -0,0 +1,50 @@
/*
* Copyright 2014 the original author or authors.
*
* 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 asset.pipeline.processors


import asset.pipeline.AssetCompiler
import asset.pipeline.AssetHelper
import asset.pipeline.AssetFile
import asset.pipeline.AbstractProcessor
import java.util.regex.Pattern

import static asset.pipeline.utils.net.Urls.isRelative


/**
* This Processor iterates over a js file looking for asset_path directive sand
* replaces their path with absolute paths based on the configured.
* In precompiler mode the URLs are also cache digested.
*
* @author David Estes
*/
class JsNodeInjectProcessor extends AbstractProcessor {


JsNodeInjectProcessor(final AssetCompiler precompiler) {
super(precompiler)
}


String process(final String inputText, final AssetFile assetFile) {
// if(!assetFile.baseFile) {
return "var process = process || {env: {NODE_ENV: \"development\"}};\n${inputText}"
// } else {
// return inputText
// }
}
}

0 comments on commit 8e4faeb

Please sign in to comment.