Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature - Nashorn support (Java 8) #2985

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
528 changes: 528 additions & 0 deletions bin/lessjjsc

Large diffs are not rendered by default.

19 changes: 19 additions & 0 deletions lib/less-nashorn/console.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
if (typeof console === 'undefined') {
console = {
log: function(msg) {
print(msg);
},
info: function(msg) {
print('INFO: ' + msg);
},
warn: function(msg) {
print('WARN: ' + msg);
},
error: function(msg) {
java.lang.System.err.println('ERROR: ' + msg);
},
dir: function(msg) {
print('DIR: ' + JSON.stringify(msg));
},
};
}
1,015 changes: 1,015 additions & 0 deletions lib/less-nashorn/environment.js

Large diffs are not rendered by default.

87 changes: 87 additions & 0 deletions lib/less-nashorn/file-manager.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
var Paths = Java.type('java.nio.file.Paths'),
Files = Java.type('java.nio.file.Files'),
PromiseConstructor,
AbstractFileManager = require("../less/environment/abstract-file-manager.js");

try {
PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
} catch(e) {
}

var FileManager = function() {
};

FileManager.prototype = new AbstractFileManager();

FileManager.prototype.supports = function(filename, currentDirectory, options, environment) {
return true;
};
FileManager.prototype.supportsSync = function(filename, currentDirectory, options, environment) {
return true;
};

FileManager.prototype.loadFile = function(filename, currentDirectory, options, environment, callback) {
var data;

options = options || {};

data = this.loadFileSync(filename, currentDirectory, options, environment, 'utf-8');
callback(data.error, data);
};

FileManager.prototype.loadFileSync = function(filename, currentDirectory, options, environment, encoding) {
var fullFilename, paths, filenamesTried = [], isAbsoluteFilename = this.isPathAbsolute(filename) , data;
options = options || {};

paths = isAbsoluteFilename ? [""] : [currentDirectory];
if (options.paths) {
paths.push.apply(paths, options.paths);
}
if (!isAbsoluteFilename && paths.indexOf('.') === -1) {
paths.push('.');
}

var err, result;
for (var i = 0; i < paths.length; i++) {
try {
fullFilename = filename;
if (paths[i]) {
fullFilename = Paths.get(paths[i], fullFilename).normalize().toString();
}
filenamesTried.push(fullFilename);
if (Files.isRegularFile(Paths.get(fullFilename)) === false)
throw "File does not exist";
break;
} catch (e) {
fullFilename = null;
}
}

if (!fullFilename) {
err = { type: 'File', message: "'" + filename + "' wasn't found. Tried - " + filenamesTried.join(",") };
result = { error: err };
} else {
try {
if (!encoding) {
// data-uri.js doesn't pass useBase64 or the encoding type so look it up again
var mimetype = environment.mimeLookup(fullFilename);
// use base 64 unless it's an ASCII or UTF-8 format
encoding = environment.charsetLookup(mimetype);
}
if (encoding) {
data = new java.lang.String(Files.readAllBytes(Paths.get(fullFilename)), encoding);
}
else
data = Files.readAllBytes(Paths.get(fullFilename));
result = {contents: data, filename: fullFilename};
}
catch (e) {
err = { type: 'File', message: "'" + fullFilename + "' failed reading - " + e.message};
result = { error: err };
}
}

return result;
};

module.exports = FileManager;
92 changes: 92 additions & 0 deletions lib/less-nashorn/fs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
var Paths = java.nio.file.Paths;
var Files = java.nio.file.Files;
var FileSystem = function() {
};
FileSystem.prototype.mkdirSync = function(path) {
if (!path)
return;
Files.createDirectories(Paths.get(path));
};
FileSystem.prototype.existsSync = function(path) {
if (!path)
return false;
return Files.isRegularFile(Paths.get(path));
};
FileSystem.prototype.writeFile = function(path, data, options, callback) {
if (arguments.length == 3) {
callback = options;
options = null;
}
try {
if (typeof data === 'string') {
if (!options || !options.encoding) {
options = 'UTF-8';
}
var encoding = typeof options === 'string' ? options : options.encoding;
Files.write(Paths.get(path), data.getBytes(encoding));
}
else {
Files.write(Paths.get(path), data);
}
callback(null);
}
catch (e) {
var error = new Error(e.toString());
callback(error);
}
};
FileSystem.prototype.writeFileSync = function(path, data, options) {
if (typeof data === 'string') {
if (arguments.length == 2 || !options || !options.encoding) {
options = 'UTF-8';
}
var encoding = typeof options === 'string' ? options : options.encoding;
Files.write(Paths.get(path), data.getBytes(encoding));
}
else {
Files.write(Paths.get(path), data);
}
};
FileSystem.prototype.readFile = function(path, options, callback) {
if (arguments.length == 2) {
callback = options;
options = null;
}
try {
var encoding = typeof options === 'string' ? options:(options ? options.encoding : null);
var bytes = Files.readAllBytes(Paths.get(path));
callback(null, encoding ? new java.lang.String(bytes, encoding) : bytes);
}
catch (e) {
var error = new Error(e.toString());
callback(error, null);
}
};
FileSystem.prototype.readFileSync = function(path, options) {
var encoding = typeof options === 'string' ? options:(options ? options.encoding : null);
var bytes = Files.readAllBytes(Paths.get(path));
return encoding ? new java.lang.String(bytes, encoding) : bytes;
};
FileSystem.prototype.readdirSync = function(path, options) {
var dir = Paths.get(path);
var list = Files.list(dir).collect(java.util.stream.Collectors.toList());
var ret = []
for(var i = 0; i < list.length; i++) {
ret[i] = dir.relativize(list[i]).toString();
}
return ret;
};
FileSystem.prototype.lstatSync = function(path) {
return {
isFile: isFile,
isDirectory: isDirectory
};
function isFile() {
return Files.isRegularFile(Paths.get(path));
}
function isDirectory() {
return Files.isDirectory(Paths.get(path));
}
};

module.exports = new FileSystem();
65 changes: 65 additions & 0 deletions lib/less-nashorn/image-size.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
module.exports = function(environment) {
var Dimension = require("../less/tree/dimension"),
Expression = require("../less/tree/expression"),
functionRegistry = require("./../less/functions/function-registry");

function imageSize(functionContext, filePathNode) {
var filePath = filePathNode.value;
var currentFileInfo = functionContext.currentFileInfo;
var currentDirectory = currentFileInfo.relativeUrls ?
currentFileInfo.currentDirectory : currentFileInfo.entryPath;

var fragmentStart = filePath.indexOf('#');
var fragment = '';
if (fragmentStart !== -1) {
fragment = filePath.slice(fragmentStart);
filePath = filePath.slice(0, fragmentStart);
}

var fileManager = environment.getFileManager(filePath, currentDirectory, functionContext.context, environment, true);

if (!fileManager) {
throw {
type: "File",
message: "Can not set up FileManager for " + filePathNode
};
}

var fileSync = fileManager.loadFileSync(filePath, currentDirectory, functionContext.context, environment);

if (fileSync.error) {
throw fileSync.error;
}

var inputByteStream = new java.io.ByteArrayInputStream((fileSync.contents instanceof java.lang.String) ? fileSync.contents.getBytes() : fileSync.contents);
if (/\.svg$/i.test(filePath))
{
var xml = javax.xml.parsers.DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputByteStream);
if (xml.getDocumentElement().getAttribute('width') && xml.getDocumentElement().getAttribute('height'))
return { width : xml.getDocumentElement().getAttribute('width'), height : xml.getDocumentElement().getAttribute('height')};
}

var bimg = javax.imageio.ImageIO.read(inputByteStream);
return { width: bimg.getWidth(), height: bimg.getHeight() };
}

var imageFunctions = {
"image-size": function(filePathNode) {
var size = imageSize(this, filePathNode);
return new Expression([
new Dimension(size.width, "px"),
new Dimension(size.height, "px")
]);
},
"image-width": function(filePathNode) {
var size = imageSize(this, filePathNode);
return new Dimension(size.width, "px");
},
"image-height": function(filePathNode) {
var size = imageSize(this, filePathNode);
return new Dimension(size.height, "px");
}
};

functionRegistry.addMultiple(imageFunctions);
};
74 changes: 74 additions & 0 deletions lib/less-nashorn/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
var environment = require("./environment"),
FileManager = require("./file-manager"),
UrlFileManager = require("./url-file-manager"),
createFromEnvironment = require("../less"),
less = createFromEnvironment(environment, [new FileManager(), new UrlFileManager()]),
lesscHelper = require('./lessjjsc-helper');

// allow people to create less with their own environment
less.createFromEnvironment = createFromEnvironment;
less.lesscHelper = lesscHelper;
less.PluginLoader = require("./plugin-loader");
less.fs = require("./fs");
less.FileManager = FileManager;
less.UrlFileManager = UrlFileManager;
less.formatError = function(ctx, options) {
options = options || {};

var message = "";
var extract = ctx.extract;
var error = [];
var stylize = /*options.color ? lesscHelper.stylize :*/ function (str) { return str; };

// only output a stack if it isn't a less error
if (ctx.stack && !ctx.type) { return stylize(ctx.stack, 'red'); }

if (!ctx.hasOwnProperty('index') || !extract) {
return ctx.stack || ctx.message;
}

if (typeof extract[0] === 'string') {
error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey'));
}

if (typeof extract[1] === 'string') {
var errorTxt = ctx.line + ' ';
if (extract[1]) {
errorTxt += extract[1].slice(0, ctx.column) +
stylize(stylize(stylize(extract[1].substr(ctx.column, 1), 'bold') +
extract[1].slice(ctx.column + 1), 'red'), 'inverse');
}
error.push(errorTxt);
}

if (typeof extract[2] === 'string') {
error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
}
error = error.join('\n') + stylize('', 'reset') + '\n';

message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
if (ctx.filename) {
message += stylize(' in ', 'red') + ctx.filename +
stylize(' on line ' + ctx.line + ', column ' + (ctx.column + 1) + ':', 'grey');
}

message += '\n' + error;

if (ctx.callLine) {
message += stylize('from ', 'red') + (ctx.filename || '') + '/n';
message += stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract + '/n';
}

return message;
};

less.writeError = function (ctx, options) {
options = options || {};
if (options.silent) { return; }
console.error(less.formatError(ctx, options));
};

// provide image-size functionality
require('./image-size')(less.environment);

module.exports = less;
Loading