Skip to content

Commit 6b57d7d

Browse files
committed
Adds Nashorn support. Fixes #55
1 parent b2f9de9 commit 6b57d7d

File tree

4 files changed

+146
-2
lines changed

4 files changed

+146
-2
lines changed

src/main/java/com/asual/lesscss/LessEngine.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
import org.apache.commons.logging.LogFactory;
2626

2727
import com.asual.lesscss.compiler.LessCompiler;
28+
import com.asual.lesscss.compiler.NashornCompiler;
2829
import com.asual.lesscss.compiler.RhinoCompiler;
2930
import com.asual.lesscss.loader.ChainedResourceLoader;
3031
import com.asual.lesscss.loader.ClasspathResourceLoader;
@@ -80,7 +81,13 @@ public LessEngine(LessOptions options, ResourceLoader loader) {
8081
URL engine = classLoader.getResource("META-INF/engine.js");
8182
URL cssmin = classLoader.getResource("META-INF/cssmin.js");
8283
URL sourceMap = classLoader.getResource("META-INF/source-map.js");
83-
compiler = new RhinoCompiler(options, loader, less, env, engine, cssmin, sourceMap);
84+
double version = Double.parseDouble(Runtime.class.getPackage()
85+
.getImplementationVersion().replaceFirst("^(\\d\\.\\d).*", "$1"));
86+
if (version < 1.8) {
87+
compiler = new RhinoCompiler(options, loader, less, env, engine, cssmin, sourceMap);
88+
} else {
89+
compiler = new NashornCompiler(options, loader, less, env, engine, cssmin, sourceMap);
90+
}
8491
} catch (Exception e) {
8592
logger.error("LESS Engine intialization failed.", e);
8693
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
/*
2+
* Licensed under the Apache License, Version 2.0 (the "License");
3+
* you may not use this file except in compliance with the License.
4+
* You may obtain a copy of the License at
5+
*
6+
* http://www.apache.org/licenses/LICENSE-2.0
7+
*
8+
* Unless required by applicable law or agreed to in writing, software
9+
* distributed under the License is distributed on an "AS IS" BASIS,
10+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11+
* See the License for the specific language governing permissions and
12+
* limitations under the License.
13+
*/
14+
15+
package com.asual.lesscss.compiler;
16+
17+
import com.asual.lesscss.LessException;
18+
import com.asual.lesscss.LessOptions;
19+
import com.asual.lesscss.loader.ResourceLoader;
20+
import org.apache.commons.logging.Log;
21+
import org.apache.commons.logging.LogFactory;
22+
23+
import java.io.IOException;
24+
import java.io.InputStreamReader;
25+
import java.net.URL;
26+
import java.util.ArrayList;
27+
import java.util.List;
28+
29+
import javax.script.ScriptEngine;
30+
import javax.script.ScriptEngineManager;
31+
import javax.script.ScriptException;
32+
import jdk.nashorn.api.scripting.ScriptObjectMirror;
33+
import jdk.nashorn.internal.objects.NativeArray;
34+
import jdk.nashorn.internal.runtime.ScriptObject;
35+
import jdk.nashorn.internal.runtime.ECMAException;
36+
37+
@SuppressWarnings("restriction")
38+
public class NashornCompiler implements LessCompiler {
39+
40+
private final Log logger = LogFactory.getLog(getClass());
41+
private ScriptObjectMirror compile;
42+
43+
public NashornCompiler(LessOptions options, ResourceLoader loader, URL less, URL env, URL engine, URL cssmin, URL sourceMap) throws IOException {
44+
ScriptEngineManager factory = new ScriptEngineManager();
45+
ScriptEngine scriptEngine = factory.getEngineByName("nashorn");
46+
try {
47+
scriptEngine.eval(new InputStreamReader(sourceMap
48+
.openConnection().getInputStream()));
49+
scriptEngine.eval(new InputStreamReader(env.openConnection()
50+
.getInputStream()));
51+
ScriptObjectMirror lessenv = (ScriptObjectMirror) scriptEngine.get("lessenv");
52+
lessenv.put("charset", options.getCharset());
53+
lessenv.put("css", options.isCss());
54+
lessenv.put("lineNumbers", options.getLineNumbers());
55+
lessenv.put("optimization", options.getOptimization());
56+
lessenv.put("sourceMap", options.isSourceMap());
57+
lessenv.put("sourceMapRootpath", options.getSourceMapRootpath());
58+
lessenv.put("sourceMapBasepath", options.getSourceMapBasepath());
59+
lessenv.put("sourceMapURL", options.getSourceMapUrl());
60+
lessenv.put("loader", loader);
61+
lessenv.put("paths", options.getPaths());
62+
scriptEngine.eval(new InputStreamReader(less
63+
.openConnection().getInputStream()));
64+
scriptEngine.eval(new InputStreamReader(cssmin.openConnection()
65+
.getInputStream()));
66+
scriptEngine.eval(new InputStreamReader(engine.openConnection()
67+
.getInputStream()));
68+
compile = (ScriptObjectMirror) scriptEngine.get("compile");
69+
} catch (ScriptException e) {
70+
logger.error(e.getMessage(), e);
71+
}
72+
}
73+
74+
@Override
75+
public String compile(String input, String location, boolean compress) throws LessException {
76+
try {
77+
return (String) compile.call(null, input, location, compress);
78+
} catch (Exception e) {
79+
throw new LessException(parseLessException(e));
80+
}
81+
}
82+
83+
private Exception parseLessException(Exception root) {
84+
logger.debug("Parsing LESS Exception", root);
85+
if (root instanceof ECMAException) {
86+
ECMAException e = (ECMAException) root;
87+
Object thrown = e.getThrown();
88+
String type = null;
89+
String message = null;
90+
String filename = null;
91+
int line = -1;
92+
int column = -1;
93+
List<String> extractList = new ArrayList<String>();
94+
if (thrown instanceof ScriptObject) {
95+
ScriptObject so = (ScriptObject) e.getThrown();
96+
type = so.get("type").toString() + " Error";
97+
message = so.get("message").toString();
98+
filename = "";
99+
if (so.has("filename")) {
100+
filename = so.get("filename").toString();
101+
}
102+
if (so.has("line")) {
103+
line = ((Long) so.get("line")).intValue();
104+
}
105+
if (so.has("column")) {
106+
column = ((Double) so.get("column")).intValue();
107+
}
108+
if (so.has("extract")) {
109+
NativeArray extract = (NativeArray) so.get("extract");
110+
for (int i = 0; i < extract.size(); i++) {
111+
if (extract.get(i) instanceof String) {
112+
extractList.add(((String) extract.get(i))
113+
.replace("\t", " "));
114+
}
115+
}
116+
}
117+
} else {
118+
type = thrown.getClass().getSimpleName() + " Error";
119+
message = e.getMessage().replaceFirst("[^:]+: ", "");
120+
}
121+
return new LessException(message, type, filename, line, column,
122+
extractList);
123+
}
124+
return root;
125+
}
126+
127+
}

src/main/resources/META-INF/engine.js

+1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
print = lessenv.print;
22
quit = lessenv.quit;
33
readFile = lessenv.readFile;
4+
readUrl = lessenv.readUrl;
45
delete arguments;
56

67
var basePath = function(path) {

src/main/resources/META-INF/env.js

+10-1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,12 @@
1+
if (typeof readFile === "undefined") {
2+
var readFile = function(path) {
3+
return new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(path)));
4+
};
5+
var readUrl = function(url) {
6+
return new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get(new java.net.URL(url).getAbsoluteFile())));
7+
};
8+
}
9+
110
var lessenv = {
211
print : print,
312
quit : quit,
@@ -20,7 +29,7 @@ var lessenv = {
2029
return javax.xml.bind.DatatypeConverter.printBase64Binary(
2130
new java.lang.String(str).getBytes());
2231
}
23-
},location = {
32+
}, location = {
2433
port : 0
2534
}, document = {
2635
getElementsByTagName : function(name) {

0 commit comments

Comments
 (0)