mirror of
https://github.com/less/less.js.git
synced 2026-02-09 14:35:44 -05:00
Move toCSS out to a new class (still need to remove creation of that class from parser)
This commit is contained in:
@@ -1,26 +1,32 @@
|
||||
var utils = require("./utils.js");
|
||||
|
||||
var LessError = module.exports = function LessError(parser, e, env) {
|
||||
var input = parser.getInput(e, env),
|
||||
loc = parser.getLocation(e.index, input),
|
||||
line = loc.line,
|
||||
col = loc.column,
|
||||
callLine = e.call && parser.getLocation(e.call, input).line,
|
||||
lines = input.split('\n');
|
||||
var LessError = module.exports = function LessError(e, importManager, currentFilename) {
|
||||
|
||||
this.type = e.type || 'Syntax';
|
||||
var filename = e.filename || currentFilename;
|
||||
|
||||
if (importManager && filename) {
|
||||
var input = importManager.contents[filename],
|
||||
loc = utils.getLocation(e.index, input),
|
||||
line = loc.line,
|
||||
col = loc.column,
|
||||
callLine = e.call && utils.getLocation(e.call, input).line,
|
||||
lines = input.split('\n');
|
||||
|
||||
this.type = e.type || 'Syntax';
|
||||
this.filename = filename;
|
||||
this.index = e.index;
|
||||
this.line = typeof(line) === 'number' ? line + 1 : null;
|
||||
this.callLine = callLine + 1;
|
||||
this.callExtract = lines[callLine];
|
||||
this.column = col;
|
||||
this.extract = [
|
||||
lines[line - 1],
|
||||
lines[line],
|
||||
lines[line + 1]
|
||||
];
|
||||
}
|
||||
this.message = e.message;
|
||||
this.filename = e.filename || env.currentFileInfo.filename;
|
||||
this.index = e.index;
|
||||
this.line = typeof(line) === 'number' ? line + 1 : null;
|
||||
this.callLine = callLine + 1;
|
||||
this.callExtract = lines[callLine];
|
||||
this.stack = e.stack;
|
||||
this.column = col;
|
||||
this.extract = [
|
||||
lines[line - 1],
|
||||
lines[line],
|
||||
lines[line + 1]
|
||||
];
|
||||
};
|
||||
|
||||
LessError.prototype = new Error();
|
||||
|
||||
55
lib/less/parse-tree.js
Normal file
55
lib/less/parse-tree.js
Normal file
@@ -0,0 +1,55 @@
|
||||
var LessError = require('./less-error.js'),
|
||||
transformTree = require("./transform-tree.js");
|
||||
|
||||
module.exports = function(environment)
|
||||
{
|
||||
var SourceMapOutput = require("./source-map-output")(environment);
|
||||
|
||||
var ParseTree = function(root, imports) {
|
||||
this.root = root;
|
||||
this.imports = imports;
|
||||
};
|
||||
|
||||
ParseTree.prototype.toCSS = function(options) {
|
||||
var evaldRoot;
|
||||
try {
|
||||
evaldRoot = transformTree(this.root, options);
|
||||
} catch (e) {
|
||||
throw new LessError(e, this.imports);
|
||||
}
|
||||
var css;
|
||||
try {
|
||||
if (options.sourceMap) {
|
||||
evaldRoot = new SourceMapOutput(
|
||||
{
|
||||
contentsIgnoredCharsMap: this.imports.contentsIgnoredChars,
|
||||
writeSourceMap: options.writeSourceMap,
|
||||
rootNode: evaldRoot,
|
||||
contentsMap: this.imports.contents,
|
||||
sourceMapFilename: options.sourceMapFilename,
|
||||
sourceMapURL: options.sourceMapURL,
|
||||
outputFilename: options.sourceMapOutputFilename,
|
||||
sourceMapBasepath: options.sourceMapBasepath,
|
||||
sourceMapRootpath: options.sourceMapRootpath,
|
||||
outputSourceFiles: options.outputSourceFiles,
|
||||
sourceMapGenerator: options.sourceMapGenerator
|
||||
});
|
||||
}
|
||||
|
||||
css = evaldRoot.toCSS({
|
||||
compress: Boolean(options.compress),
|
||||
dumpLineNumbers: options.dumpLineNumbers,
|
||||
strictUnits: Boolean(options.strictUnits),
|
||||
numPrecision: 8});
|
||||
} catch (e) {
|
||||
throw new LessError(e, this.imports);
|
||||
}
|
||||
|
||||
if (options.compress) {
|
||||
return css.replace(/(^(\s)+)|((\s)+$)/g, "");
|
||||
} else {
|
||||
return css;
|
||||
}
|
||||
};
|
||||
return ParseTree;
|
||||
};
|
||||
@@ -70,7 +70,7 @@ module.exports = function(environment, env, Parser) {
|
||||
} else {
|
||||
new(Parser)(newEnv).parse(contents, function (e, root) {
|
||||
fileParsedFunc(e, root, resolvedFilename);
|
||||
});
|
||||
}, null, true);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -211,27 +211,6 @@ module.exports = function() {
|
||||
return (c > CHARCODE_9 || c < CHARCODE_PLUS) || c === CHARCODE_FORWARD_SLASH || c === CHARCODE_COMMA;
|
||||
};
|
||||
|
||||
parserInput.getLocation = function(index, inputStream) {
|
||||
inputStream = inputStream == null ? input : inputStream;
|
||||
|
||||
var n = index + 1,
|
||||
line = null,
|
||||
column = -1;
|
||||
|
||||
while (--n >= 0 && inputStream.charAt(n) !== '\n') {
|
||||
column++;
|
||||
}
|
||||
|
||||
if (typeof index === 'number') {
|
||||
line = (inputStream.slice(0, index).match(/\n/g) || "").length;
|
||||
}
|
||||
|
||||
return {
|
||||
line: line,
|
||||
column: column
|
||||
};
|
||||
};
|
||||
|
||||
parserInput.start = function(str, chunkInput, parser, env) {
|
||||
input = str;
|
||||
parserInput.i = j = currentPos = furthest = 0;
|
||||
|
||||
@@ -3,10 +3,11 @@ var LessError = require('../less-error.js'),
|
||||
visitor = require("../visitor/index.js"),
|
||||
contexts = require("../contexts.js"),
|
||||
getImportManager = require("./imports.js"),
|
||||
getParserInput = require("./parser-input.js");
|
||||
getParserInput = require("./parser-input.js"),
|
||||
utils = require("../utils.js");
|
||||
|
||||
module.exports = function(environment) {
|
||||
var SourceMapOutput = require("../source-map-output")(environment);
|
||||
var ParseTree = require("../parse-tree.js")(environment);
|
||||
//
|
||||
// less.js - parser
|
||||
//
|
||||
@@ -79,20 +80,12 @@ var Parser = function Parser(env) {
|
||||
throw e;
|
||||
}
|
||||
|
||||
function getInput(e, env) {
|
||||
if (e.filename && env.currentFileInfo.filename && (e.filename !== env.currentFileInfo.filename)) {
|
||||
return parser.imports.contents[e.filename];
|
||||
} else {
|
||||
return parserInput.getInput();
|
||||
}
|
||||
}
|
||||
|
||||
function getDebugInfo(index) {
|
||||
var filename = env.currentFileInfo.filename;
|
||||
filename = environment.getAbsolutePath(env, filename);
|
||||
|
||||
return {
|
||||
lineNumber: parserInput.getLocation(index).line + 1,
|
||||
lineNumber: utils.getLocation(index, parserInput.getInput()).line + 1,
|
||||
fileName: filename
|
||||
};
|
||||
}
|
||||
@@ -109,7 +102,7 @@ var Parser = function Parser(env) {
|
||||
// @param callback call `callback` when done.
|
||||
// @param [additionalData] An optional map which can contains vars - a map (key, value) of variables to apply
|
||||
//
|
||||
parse: function (str, callback, additionalData) {
|
||||
parse: function (str, callback, additionalData, returnSubParseTree) {
|
||||
var root, error = null, globalVars, modifyVars, preText = "";
|
||||
|
||||
globalVars = (additionalData && additionalData.globalVars) ? Parser.serializeVars(additionalData.globalVars) + '\n' : '';
|
||||
@@ -136,54 +129,9 @@ var Parser = function Parser(env) {
|
||||
root.root = true;
|
||||
root.firstRoot = true;
|
||||
} catch (e) {
|
||||
return callback(new LessError(parser, e, env));
|
||||
return callback(new LessError(e, parser.imports, env.currentFileInfo.filename));
|
||||
}
|
||||
|
||||
root.toCSS = (function (evaluate) {
|
||||
return function (options) {
|
||||
var transformTree = require("../transform-tree.js"),
|
||||
evaldRoot;
|
||||
try {
|
||||
evaldRoot = transformTree(this, options);
|
||||
} catch (e) {
|
||||
throw new LessError(parser, e, env);
|
||||
}
|
||||
var css;
|
||||
try {
|
||||
if (options.sourceMap) {
|
||||
evaldRoot = new SourceMapOutput(
|
||||
{
|
||||
contentsIgnoredCharsMap: parser.imports.contentsIgnoredChars,
|
||||
writeSourceMap: options.writeSourceMap,
|
||||
rootNode: evaldRoot,
|
||||
contentsMap: parser.imports.contents,
|
||||
sourceMapFilename: options.sourceMapFilename,
|
||||
sourceMapURL: options.sourceMapURL,
|
||||
outputFilename: options.sourceMapOutputFilename,
|
||||
sourceMapBasepath: options.sourceMapBasepath,
|
||||
sourceMapRootpath: options.sourceMapRootpath,
|
||||
outputSourceFiles: options.outputSourceFiles,
|
||||
sourceMapGenerator: options.sourceMapGenerator
|
||||
});
|
||||
}
|
||||
|
||||
css = evaldRoot.toCSS({
|
||||
compress: Boolean(options.compress),
|
||||
dumpLineNumbers: env.dumpLineNumbers,
|
||||
strictUnits: Boolean(options.strictUnits),
|
||||
numPrecision: 8});
|
||||
} catch (e) {
|
||||
throw new LessError(parser, e, env);
|
||||
}
|
||||
|
||||
if (options.compress) {
|
||||
return css.replace(/(^(\s)+)|((\s)+$)/g, "");
|
||||
} else {
|
||||
return css;
|
||||
}
|
||||
};
|
||||
})(root.eval);
|
||||
|
||||
// If `i` is smaller than the `input.length - 1`,
|
||||
// it means the parser wasn't able to parse the whole
|
||||
// string, so we've got a parsing error.
|
||||
@@ -208,12 +156,12 @@ var Parser = function Parser(env) {
|
||||
}
|
||||
}
|
||||
|
||||
error = new LessError(parser, {
|
||||
error = new LessError({
|
||||
type: "Parse",
|
||||
message: message,
|
||||
index: endInfo.furthest,
|
||||
filename: env.currentFileInfo.filename
|
||||
}, env);
|
||||
}, parser.imports);
|
||||
}
|
||||
|
||||
var finish = function (e) {
|
||||
@@ -221,13 +169,14 @@ var Parser = function Parser(env) {
|
||||
|
||||
if (e) {
|
||||
if (!(e instanceof LessError)) {
|
||||
e = new LessError(parser, e, env);
|
||||
e = new LessError(e, parser.imports, env.currentFileInfo.filename);
|
||||
}
|
||||
|
||||
return callback(e);
|
||||
}
|
||||
else {
|
||||
return callback(null, root);
|
||||
return callback(null,
|
||||
returnSubParseTree ? root : new ParseTree(root, parser.imports));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -547,7 +496,7 @@ var Parser = function Parser(env) {
|
||||
|
||||
js = parserInput.$re(/^(~)?`([^`]*)`/);
|
||||
if (js) {
|
||||
return new(tree.JavaScript)(js[2], index, Boolean(js[1]));
|
||||
return new(tree.JavaScript)(js[2], Boolean(js[1]), index, env.currentFileInfo);
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -1636,9 +1585,6 @@ var Parser = function Parser(env) {
|
||||
}
|
||||
};
|
||||
|
||||
parser.getInput = getInput;
|
||||
parser.getLocation = parserInput.getLocation;
|
||||
|
||||
return parser;
|
||||
};
|
||||
Parser.serializeVars = function(vars) {
|
||||
|
||||
@@ -3,10 +3,11 @@ var JsEvalNode = require("./js-eval-node.js"),
|
||||
Quoted = require("./quoted.js"),
|
||||
Anonymous = require("./anonymous.js");
|
||||
|
||||
var JavaScript = function (string, index, escaped) {
|
||||
var JavaScript = function (string, escaped, index, currentFileInfo) {
|
||||
this.escaped = escaped;
|
||||
this.expression = string;
|
||||
this.index = index;
|
||||
this.currentFileInfo = currentFileInfo;
|
||||
};
|
||||
JavaScript.prototype = new JsEvalNode();
|
||||
JavaScript.prototype.type = "JavaScript";
|
||||
|
||||
@@ -1,28 +1,30 @@
|
||||
var Node = require("./node.js"),
|
||||
Variable = require("./variable.js");
|
||||
|
||||
var jsEvalNode = function() {
|
||||
var JsEvalNode = function() {
|
||||
};
|
||||
jsEvalNode.prototype = new Node();
|
||||
JsEvalNode.prototype = new Node();
|
||||
|
||||
jsEvalNode.prototype.evaluateJavaScript = function (expression, env) {
|
||||
JsEvalNode.prototype.evaluateJavaScript = function (expression, env) {
|
||||
var result,
|
||||
that = this,
|
||||
context = {};
|
||||
|
||||
if (env.javascriptEnabled !== undefined && !env.javascriptEnabled) {
|
||||
throw { message: "You are using JavaScript, which has been disabled." ,
|
||||
throw { message: "You are using JavaScript, which has been disabled.",
|
||||
filename: this.currentFileInfo.filename,
|
||||
index: this.index };
|
||||
}
|
||||
|
||||
expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
|
||||
return that.jsify(new(Variable)('@' + name, that.index).eval(env));
|
||||
return that.jsify(new(Variable)('@' + name, that.index, that.currentFileInfo).eval(env));
|
||||
});
|
||||
|
||||
try {
|
||||
expression = new(Function)('return (' + expression + ')');
|
||||
} catch (e) {
|
||||
throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" ,
|
||||
filename: this.currentFileInfo.filename,
|
||||
index: this.index };
|
||||
}
|
||||
|
||||
@@ -43,11 +45,12 @@ jsEvalNode.prototype.evaluateJavaScript = function (expression, env) {
|
||||
result = expression.call(context);
|
||||
} catch (e) {
|
||||
throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" ,
|
||||
filename: this.currentFileInfo.filename,
|
||||
index: this.index };
|
||||
}
|
||||
return result;
|
||||
};
|
||||
jsEvalNode.prototype.jsify = function (obj) {
|
||||
JsEvalNode.prototype.jsify = function (obj) {
|
||||
if (Array.isArray(obj.value) && (obj.value.length > 1)) {
|
||||
return '[' + obj.value.map(function (v) { return v.toCSS(); }).join(', ') + ']';
|
||||
} else {
|
||||
@@ -55,4 +58,4 @@ jsEvalNode.prototype.jsify = function (obj) {
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = jsEvalNode;
|
||||
module.exports = JsEvalNode;
|
||||
|
||||
@@ -11,13 +11,13 @@ Variable.prototype.eval = function (env) {
|
||||
var variable, name = this.name;
|
||||
|
||||
if (name.indexOf('@@') === 0) {
|
||||
name = '@' + new(Variable)(name.slice(1)).eval(env).value;
|
||||
name = '@' + new(Variable)(name.slice(1), this.index, this.currentFileInfo).eval(env).value;
|
||||
}
|
||||
|
||||
if (this.evaluating) {
|
||||
throw { type: 'Name',
|
||||
message: "Recursive variable definition for " + name,
|
||||
filename: this.currentFileInfo.file,
|
||||
filename: this.currentFileInfo.filename,
|
||||
index: this.index };
|
||||
}
|
||||
|
||||
|
||||
20
lib/less/utils.js
Normal file
20
lib/less/utils.js
Normal file
@@ -0,0 +1,20 @@
|
||||
module.exports = {
|
||||
getLocation: function(index, inputStream) {
|
||||
var n = index + 1,
|
||||
line = null,
|
||||
column = -1;
|
||||
|
||||
while (--n >= 0 && inputStream.charAt(n) !== '\n') {
|
||||
column++;
|
||||
}
|
||||
|
||||
if (typeof index === 'number') {
|
||||
line = (inputStream.slice(0, index).match(/\n/g) || "").length;
|
||||
}
|
||||
|
||||
return {
|
||||
line: line,
|
||||
column: column
|
||||
};
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user