Merge branch 'master' into extend-warnings

This commit is contained in:
Luke Page
2015-01-11 11:47:17 +00:00
54 changed files with 748 additions and 406 deletions

View File

@@ -1,3 +1,30 @@
# 2.2.0
2015-01-04
- do not apply relative paths to svg-gradient and data-uri functions data-uri output
- using import filename interpolation and import inline together now works
- deprecate the compression option (still works, but outputs a warning unless silent)
- The node version of less now has image-size, image-width, image-height which return the image dimensions of a file
- Fixed an issue that could cause the parse to occur more than once and the callback be called multiple times
- if you are outputting to the console, lessc defaults to silent so warnings do not end up in output
- isunit function supports '' to test if a dimension has no unit
- data-uri function now counts characters after base64 encoding instead of bytes before encoding to determine ie8 support
- fix bug effecting guards on pseudo class selectors
- do not cache on the browser when used with modifyVars
- detection if less does not parse last character in file
- detection of whether a file is css now requires /css, .css, ?css, &css instead of just css. You can still tell less the type of file using import options.
- remove extra new line added to sourcemap entry inline file
- support safari extension
- less.parse now exposes a way to get the AST. We do not recommend you use this unless you need to.
# 2.1.2
2014-12-20
- Fix for use with requirejs
- Fixes for data-uri function
# 2.1.1
2014-11-27

View File

@@ -5,6 +5,8 @@ module.exports = function (grunt) {
// Report the elapsed execution time of tasks.
require('time-grunt')(grunt);
var COMPRESS_FOR_TESTS = true;
// Project configuration.
grunt.initConfig({
@@ -63,7 +65,7 @@ module.exports = function (grunt) {
banner: '<%= meta.banner %>'
},
browsertest: {
src: '<%= browserify.browser.dest %>',
src: COMPRESS_FOR_TESTS ? '<%= uglify.test.dest %>' : '<%= browserify.browser.dest %>',
dest: 'test/browser/less.js'
},
dist: {
@@ -93,12 +95,19 @@ module.exports = function (grunt) {
uglify: {
options: {
banner: '<%= meta.banner %>',
mangle: true
mangle: true,
compress: {
pure_getters: true
}
},
dist: {
src: ['<%= concat.dist.dest %>'],
dest: 'dist/less.min.js'
}
},
test: {
src: '<%= browserify.browser.dest %>',
dest: 'tmp/less.min.js'
}
},
jshint: {
@@ -338,6 +347,7 @@ module.exports = function (grunt) {
// Create the browser version of less.js
grunt.registerTask('browsertest-lessjs', [
'browserify:browser',
'uglify:test',
'concat:browsertest'
]);

View File

@@ -27,8 +27,8 @@ var silent = false,
ieCompat: true,
strictMath: false,
strictUnits: false,
globalVariables: '',
modifyVariables: '',
globalVars: null,
modifyVars: null,
urlArgs: '',
plugins: plugins
};
@@ -59,9 +59,9 @@ var checkBooleanArg = function(arg) {
return Boolean(onOff[2]);
};
var parseVariableOption = function(option) {
var parseVariableOption = function(option, variables) {
var parts = option.split('=', 2);
return '@' + parts[0] + ': ' + parts[1] + ';\n';
variables[parts[0]] = parts[1];
};
var warningMessages = "";
@@ -205,12 +205,19 @@ args = args.filter(function (arg) {
break;
case "global-var":
if (checkArgFunc(arg, match[2])) {
options.globalVariables += parseVariableOption(match[2]);
if (!options.globalVars) {
options.globalVars = {};
}
parseVariableOption(match[2], options.globalVars);
}
break;
case "modify-var":
if (checkArgFunc(arg, match[2])) {
options.modifyVariables += parseVariableOption(match[2]);
if (!options.modifyVars) {
options.modifyVars = {};
}
parseVariableOption(match[2], options.modifyVars);
}
break;
case 'url-args':
@@ -348,8 +355,6 @@ var parseLessFile = function (e, data) {
return;
}
data = options.globalVariables + data + '\n' + options.modifyVariables;
options.paths = [path.dirname(input)].concat(options.paths);
options.filename = input;
@@ -369,7 +374,8 @@ var parseLessFile = function (e, data) {
}
},
warn: function(msg) {
if (!silent) {
// do not show warning if outputting css to the console or the silent option is used
if (!silent && output) {
console.warn(msg);
}
},

View File

@@ -1,6 +1,6 @@
{
"name": "less",
"version": "2.1.1",
"version": "2.2.0",
"main": "dist/less.js",
"ignore": [
"**/.*",

524
dist/less.js vendored

File diff suppressed because it is too large Load Diff

14
dist/less.min.js vendored

File diff suppressed because one or more lines are too long

View File

@@ -7,7 +7,7 @@ module.exports = function(window, options) {
addDataAttr(options, browser.currentScript(window));
if (options.isFileProtocol === undefined) {
options.isFileProtocol = /^(file|chrome(-extension)?|resource|qrc|app):/.test(window.location.protocol);
options.isFileProtocol = /^(file|(chrome|safari)(-extension)?|resource|qrc|app):/.test(window.location.protocol);
}
// Load styles asynchronously (default: false)
@@ -39,4 +39,8 @@ module.exports = function(window, options) {
options.useFileCache = true;
}
if (options.onReady === undefined) {
options.onReady = true;
}
};

View File

@@ -13,12 +13,14 @@ require("./add-default-options")(window, options);
var less = module.exports = require("./index")(window, options);
if (/!watch/.test(window.location.hash)) {
less.watch();
}
less.pageLoadFinished = less.registerStylesheets().then(
function () {
return less.refresh(less.env === 'development');
}
);
if (options.onReady) {
if (/!watch/.test(window.location.hash)) {
less.watch();
}
less.pageLoadFinished = less.registerStylesheets().then(
function () {
return less.refresh(less.env === 'development');
}
);
}

View File

@@ -16,7 +16,7 @@ module.exports = function(window, options, logger) {
cache.setItem(path + ':timestamp', lastModified);
} catch(e) {
//TODO - could do with adding more robust error handling
logger.error('failed to save');
logger.error('failed to save "' + path + '" to local storage for caching.');
}
}
},

View File

@@ -112,13 +112,14 @@ function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
if (webInfo) {
webInfo.remaining = remaining;
var css = cache.getCSS(path, webInfo);
if (!reload && css) {
browser.createCSS(window.document, css, sheet);
webInfo.local = true;
callback(null, null, data, sheet, webInfo, path);
return;
}
if (!instanceOptions.modifyVars) {
var css = cache.getCSS(path, webInfo);
if (!reload && css) {
webInfo.local = true;
callback(null, null, data, sheet, webInfo, path);
return;
}
}
}
//TODO add tests around how this behaves when reloading
@@ -130,7 +131,11 @@ function loadStyleSheet(sheet, callback, reload, remaining, modifyVars) {
e.href = path;
callback(e);
} else {
callback(null, result.css, data, sheet, webInfo, path);
result.css = postProcessCSS(result.css);
if (!instanceOptions.modifyVars) {
cache.setCSS(sheet.href, webInfo.lastModified, result.css);
}
callback(null, result.css, data, sheet, webInfo, path);
}
});
}
@@ -155,13 +160,11 @@ function initRunningMode(){
less.watchTimer = setInterval(function () {
if (less.watchMode) {
fileManager.clearFileCache();
loadStyleSheets(function (e, css, _, sheet, context) {
loadStyleSheets(function (e, css, _, sheet, webInfo) {
if (e) {
errors.add(e, e.href || sheet.href);
} else if (css) {
css = postProcessCSS(css);
browser.createCSS(window.document, css, sheet);
cache.setCSS(sheet.href, context.lastModified, css);
}
});
}
@@ -228,10 +231,8 @@ less.refresh = function (reload, modifyVars, clearFileCache) {
less.logger.info("loading " + sheet.href + " from cache.");
} else {
less.logger.info("rendered " + sheet.href + " successfully.");
css = postProcessCSS(css);
browser.createCSS(window.document, css, sheet);
cache.setCSS(sheet.href, webInfo.lastModified, css);
}
browser.createCSS(window.document, css, sheet);
less.logger.info("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms');
if (webInfo.remaining === 0) {
totalMilliseconds = new Date() - startTime;

View File

@@ -0,0 +1,34 @@
var Dimension = require("../less/tree/dimension"),
Expression = require("../less/tree/expression"),
functionRegistry = require("./../less/functions/function-registry"),
path = require("path");
function imageSize(filePathNode) {
var filePath = filePathNode.value;
var currentDirectory = filePathNode.currentFileInfo.relativeUrls ?
filePathNode.currentFileInfo.currentDirectory : filePathNode.currentFileInfo.entryPath;
var sizeOf = require('image-size');
filePath = path.join(currentDirectory, filePath);
return sizeOf(filePath);
}
var imageFunctions = {
"image-size": function(filePathNode) {
var size = imageSize(filePathNode);
return new Expression([
new Dimension(size.width, "px"),
new Dimension(size.height, "px")
]);
},
"image-width": function(filePathNode) {
var size = imageSize(filePathNode);
return new Dimension(size.width, "px");
},
"image-height": function(filePathNode) {
var size = imageSize(filePathNode);
return new Dimension(size.height, "px");
}
};
functionRegistry.addMultiple(imageFunctions);

View File

@@ -68,4 +68,7 @@ less.writeError = function (ctx, options) {
console.error(less.formatError(ctx, options));
};
// provide image-size functionality
require('./image-size');
module.exports = less;

View File

@@ -37,7 +37,6 @@ var lessc_helper = {
console.log(" --strict-imports Forces evaluation of imports.");
console.log(" --insecure Allows imports from insecure https hosts.");
console.log(" -v, --version Prints version number and exit.");
console.log(" -x, --compress Compresses output by removing some whitespaces.");
console.log(" --source-map[=FILENAME] Outputs a v3 sourcemap to the filename (or output filename.map).");
console.log(" --source-map-rootpath=X Adds this path onto the sourcemap filename and less file paths.");
console.log(" --source-map-basepath=X Sets sourcemap base path, defaults to current working directory.");
@@ -71,6 +70,8 @@ var lessc_helper = {
console.log(" media query which is compatible with the SASS");
console.log(" format, and 'all' which will do both.");
console.log(" --verbose Be verbose.");
console.log(" -x, --compress Compresses output by removing some whitespaces.");
console.log(" We recommend you use a dedicated minifer like less-plugin-clean-css");
console.log("");
console.log("Report bugs to: http://github.com/less/less.js/issues");
console.log("Home page: <http://lesscss.org/>");

View File

@@ -1,5 +1,5 @@
module.exports = function(environment) {
var Anonymous = require("../tree/anonymous"),
var Quoted = require("../tree/quoted"),
URL = require("../tree/url"),
functionRegistry = require("./function-registry"),
fallback = function(functionThis, node) {
@@ -39,9 +39,13 @@ module.exports = function(environment) {
mimetype = environment.mimeLookup(filePath);
// use base 64 unless it's an ASCII or UTF-8 format
var charset = environment.charsetLookup(mimetype);
useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
if (mimetype === "image/svg+xml") {
useBase64 = false;
} else {
// use base 64 unless it's an ASCII or UTF-8 format
var charset = environment.charsetLookup(mimetype);
useBase64 = ['US-ASCII', 'UTF-8'].indexOf(charset) < 0;
}
if (useBase64) { mimetype += ';base64'; }
}
else {
@@ -54,24 +58,26 @@ module.exports = function(environment) {
return fallback(this, filePathNode || mimetypeNode);
}
var buf = fileSync.contents;
if (useBase64 && !environment.encodeBase64) {
return fallback(this, filePathNode);
}
// IE8 cannot handle a data-uri larger than 32KB. If this is exceeded
// and the --ieCompat flag is enabled, return a normal url() instead.
var DATA_URI_MAX_KB = 32,
fileSizeInKB = parseInt((buf.length / 1024), 10);
if (fileSizeInKB >= DATA_URI_MAX_KB) {
buf = useBase64 ? environment.encodeBase64(buf) : encodeURIComponent(buf);
if (this.context.ieCompat !== false) {
logger.warn("Skipped data-uri embedding of %s because its size (%dKB) exceeds IE8-safe %dKB!", filePath, fileSizeInKB, DATA_URI_MAX_KB);
var uri = "data:" + mimetype + ',' + buf + fragment;
return fallback(this, filePathNode || mimetypeNode);
}
}
// IE8 cannot handle a data-uri larger than 32,768 characters. If this is exceeded
// and the --ieCompat flag is enabled, return a normal url() instead.
var DATA_URI_MAX = 32768;
if (uri.length >= DATA_URI_MAX) {
buf = useBase64 ? buf.toString('base64')
: encodeURIComponent(buf);
if (this.context.ieCompat !== false) {
logger.warn("Skipped data-uri embedding of " + filePath + " because its size (" + uri.length + " characters) exceeds IE8-safe " + DATA_URI_MAX + " characters!");
var uri = "\"data:" + mimetype + ',' + buf + fragment + "\"";
return new URL(new Anonymous(uri), this.index, this.currentFileInfo);
return fallback(this, filePathNode || mimetypeNode);
}
}
return new URL(new Quoted('"' + uri + '"', uri, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
});
};

View File

@@ -1,7 +1,7 @@
module.exports = function(environment) {
var Dimension = require("../tree/dimension"),
Color = require("../tree/color"),
Anonymous = require("../tree/anonymous"),
Quoted = require("../tree/quoted"),
URL = require("../tree/url"),
functionRegistry = require("./function-registry");
@@ -18,7 +18,6 @@ module.exports = function(environment) {
gradientDirectionSvg,
gradientType = "linear",
rectangleDimension = 'x="0" y="0" width="1" height="1"',
useBase64 = true,
renderEnv = {compress: false},
returner,
directionValue = direction.toCSS(renderEnv),
@@ -69,15 +68,9 @@ module.exports = function(environment) {
returner += '</' + gradientType + 'Gradient>' +
'<rect ' + rectangleDimension + ' fill="url(#gradient)" /></svg>';
if (useBase64) {
try {
returner = environment.encodeBase64(returner);
} catch(e) {
useBase64 = false;
}
}
returner = encodeURIComponent(returner);
returner = "'data:image/svg+xml" + (useBase64 ? ";base64" : "") + "," + returner + "'";
return new URL(new Anonymous(returner), this.index, this.currentFileInfo);
returner = "data:image/svg+xml," + returner;
return new URL(new Quoted("'" + returner + "'", returner, false, this.index, this.currentFileInfo), this.index, this.currentFileInfo);
});
};

View File

@@ -11,7 +11,14 @@ var isa = function (n, Type) {
return (n instanceof Type) ? Keyword.True : Keyword.False;
},
isunit = function (n, unit) {
return (n instanceof Dimension) && n.unit.is(unit.value || unit) ? Keyword.True : Keyword.False;
if (unit === undefined) {
throw { type: "Argument", message: "missing the required second argument to isunit." };
}
unit = typeof unit.value === "string" ? unit.value : unit;
if (typeof unit !== "string") {
throw { type: "Argument", message: "Second argument to isunit should be a unit or a string." };
}
return (n instanceof Dimension) && n.unit.is(unit) ? Keyword.True : Keyword.False;
};
functionRegistry.addMultiple({
iscolor: function (n) {

View File

@@ -2,7 +2,7 @@ module.exports = function(environment, fileManagers) {
var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
var less = {
version: [2, 1, 1],
version: [2, 2, 0],
data: require('./data'),
tree: require('./tree'),
Environment: (Environment = require("./environment/environment")),
@@ -17,6 +17,7 @@ module.exports = function(environment, fileManagers) {
ParseTree: (ParseTree = require('./parse-tree')(SourceMapBuilder)),
ImportManager: (ImportManager = require('./import-manager')(environment)),
render: require("./render")(environment, ParseTree, ImportManager),
parse: require("./parse")(environment, ParseTree, ImportManager),
LessError: require('./less-error'),
transformTree: require('./transform-tree'),
utils: require('./utils'),

View File

@@ -1,5 +1,6 @@
var LessError = require('./less-error'),
transformTree = require("./transform-tree");
transformTree = require("./transform-tree"),
logger = require("./logger");
module.exports = function(SourceMapBuilder) {
var ParseTree = function(root, imports) {
@@ -16,8 +17,13 @@ ParseTree.prototype.toCSS = function(options) {
}
try {
var compress = Boolean(options.compress);
if (compress) {
logger.warn("The compress option has been deprecated. We recommend you use a dedicated css minifier, for instance see less-plugin-clean-css.");
}
var toCSSOptions = {
compress: Boolean(options.compress),
compress: compress,
dumpLineNumbers: options.dumpLineNumbers,
strictUnits: Boolean(options.strictUnits),
numPrecision: 8};

61
lib/less/parse.js Normal file
View File

@@ -0,0 +1,61 @@
var PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise,
contexts = require("./contexts"),
Parser = require('./parser/parser'),
PluginManager = require('./plugin-manager');
module.exports = function(environment, ParseTree, ImportManager) {
var parse = function (input, options, callback) {
options = options || {};
if (typeof(options) === 'function') {
callback = options;
options = {};
}
if (!callback) {
var self = this;
return new PromiseConstructor(function (resolve, reject) {
parse.call(self, input, options, function(err, output) {
if (err) {
reject(err);
} else {
resolve(output);
}
});
});
} else {
var context,
rootFileInfo,
pluginManager = new PluginManager(this);
pluginManager.addPlugins(options.plugins);
options.pluginManager = pluginManager;
context = new contexts.Parse(options);
if (options.rootFileInfo) {
rootFileInfo = options.rootFileInfo;
} else {
var filename = options.filename || "input";
var entryPath = filename.replace(/[^\/\\]*$/, "");
rootFileInfo = {
filename: filename,
relativeUrls: context.relativeUrls,
rootpath: context.rootpath || "",
currentDirectory: entryPath,
entryPath: entryPath,
rootFilename: filename
};
}
var imports = new ImportManager(context, rootFileInfo);
new Parser(context, imports, rootFileInfo)
.parse(input, function (e, root) {
if (e) { return callback(e); }
callback(null, root, imports, options);
}, options);
}
};
return parse;
};

View File

@@ -16,7 +16,8 @@ module.exports = function() {
saveStack.push( { current: current, i: parserInput.i, j: j });
};
parserInput.restore = function(possibleErrorMessage) {
if (parserInput.i > furthest) {
if (parserInput.i > furthest || (parserInput.i === furthest && possibleErrorMessage && !furthestPossibleErrorMessage)) {
furthest = parserInput.i;
furthestPossibleErrorMessage = possibleErrorMessage;
}
@@ -238,7 +239,7 @@ module.exports = function() {
parserInput.end = function() {
var message,
isFinished = parserInput.i >= input.length - 1;
isFinished = parserInput.i >= input.length;
if (parserInput.i < furthest) {
message = furthestPossibleErrorMessage;

View File

@@ -1383,15 +1383,19 @@ var Parser = function Parser(context, imports, fileInfo) {
sub: function () {
var a, e;
parserInput.save();
if (parserInput.$char('(')) {
a = this.addition();
if (a) {
e = new(tree.Expression)([a]);
expectChar(')');
e.parens = true;
if (a && parserInput.$char(')')) {
parserInput.forget();
e = new(tree.Expression)([a]);
e.parens = true;
return e;
}
parserInput.restore("Expected ')'");
return;
}
parserInput.restore();
},
multiplication: function () {
var m, a, op, operation, isSpaced;

View File

@@ -1,12 +1,7 @@
var PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise,
contexts = require("./contexts"),
Parser = require('./parser/parser'),
PluginManager = require('./plugin-manager');
var PromiseConstructor = typeof Promise === 'undefined' ? require('promise') : Promise;
module.exports = function(environment, ParseTree, ImportManager) {
var render = function (input, options, callback) {
options = options || {};
if (typeof(options) === 'function') {
callback = options;
options = {};
@@ -24,44 +19,20 @@ module.exports = function(environment, ParseTree, ImportManager) {
});
});
} else {
var context,
rootFileInfo,
pluginManager = new PluginManager(this);
this.parse(input, options, function(err, root, imports, options) {
if (err) { return callback(err); }
pluginManager.addPlugins(options.plugins);
options.pluginManager = pluginManager;
context = new contexts.Parse(options);
if (options.rootFileInfo) {
rootFileInfo = options.rootFileInfo;
} else {
var filename = options.filename || "input";
var entryPath = filename.replace(/[^\/\\]*$/, "");
rootFileInfo = {
filename: filename,
relativeUrls: context.relativeUrls,
rootpath: context.rootpath || "",
currentDirectory: entryPath,
entryPath: entryPath,
rootFilename: filename
};
}
var imports = new ImportManager(context, rootFileInfo);
new Parser(context, imports, rootFileInfo)
.parse(input, function (e, root) {
if (e) { return callback(e); }
var result;
try {
var parseTree = new ParseTree(root, imports);
result = parseTree.toCSS(options);
}
catch (err) { return callback( err); }
catch (err) { return callback(err); }
callback(null, result);
}, options);
});
}
};
return render;
};

View File

@@ -38,7 +38,10 @@ Directive.prototype.genCSS = function (context, output) {
value.genCSS(context, output);
}
if (rules) {
this.outputRuleset(context, output, [rules]);
if (rules.type === "Ruleset") {
rules = [rules];
}
this.outputRuleset(context, output, rules);
} else {
output.add(';');
}

View File

@@ -28,7 +28,7 @@ var Import = function (path, features, options, index, currentFileInfo) {
this.css = !this.options.less || this.options.inline;
} else {
var pathValue = this.getPath();
if (pathValue && /css([\?;].*)?$/.test(pathValue)) {
if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) {
this.css = true;
}
}

View File

@@ -220,7 +220,8 @@ Ruleset.prototype.variables = function () {
}
// when evaluating variables in an import statement, imports have not been eval'd
// so we need to go inside import statements.
if (r.type === "Import" && r.root) {
// guard against root being a string (in the case of inlined less)
if (r.type === "Import" && r.root && r.root.variables) {
var vars = r.root.variables();
for(var name in vars) {
if (vars.hasOwnProperty(name)) {

View File

@@ -23,7 +23,10 @@ URL.prototype.eval = function (context) {
if (!this.isEvald) {
// Add the base path if the URL is relative
rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
if (rootpath && typeof val.value === "string" && context.isPathRelative(val.value)) {
if (rootpath &&
typeof val.value === "string" &&
context.isPathRelative(val.value)) {
if (!val.quote) {
rootpath = rootpath.replace(/[\(\)'"\s]/g, function(match) { return "\\"+match; });
}

View File

@@ -2,6 +2,7 @@ function ImportSequencer(onSequencerEmpty) {
this.imports = [];
this.variableImports = [];
this._onSequencerEmpty = onSequencerEmpty;
this._currentDepth = 0;
}
ImportSequencer.prototype.addImport = function(callback) {
@@ -24,23 +25,28 @@ ImportSequencer.prototype.addVariableImport = function(callback) {
};
ImportSequencer.prototype.tryRun = function() {
while(true) {
while(this.imports.length > 0) {
var importItem = this.imports[0];
if (!importItem.isReady) {
return;
}
this.imports = this.imports.slice(1);
importItem.callback.apply(null, importItem.args);
}
if (this.variableImports.length === 0) {
break;
}
var variableImport = this.variableImports[0];
this.variableImports = this.variableImports.slice(1);
variableImport();
}
if (this._onSequencerEmpty) {
this._currentDepth++;
try {
while(true) {
while(this.imports.length > 0) {
var importItem = this.imports[0];
if (!importItem.isReady) {
return;
}
this.imports = this.imports.slice(1);
importItem.callback.apply(null, importItem.args);
}
if (this.variableImports.length === 0) {
break;
}
var variableImport = this.variableImports[0];
this.variableImports = this.variableImports.slice(1);
variableImport();
}
} finally {
this._currentDepth--;
}
if (this._currentDepth === 0 && this._onSequencerEmpty) {
this._onSequencerEmpty();
}
};

View File

@@ -11,27 +11,29 @@ var ImportVisitor = function(importer, finish) {
this.importCount = 0;
this.onceFileDetectionMap = {};
this.recursionDetector = {};
this._sequencer = new ImportSequencer();
this._sequencer = new ImportSequencer(this._onSequencerEmpty.bind(this));
};
ImportVisitor.prototype = {
isReplacing: false,
run: function (root) {
var error;
try {
// process the contents
this._visitor.visit(root);
}
catch(e) {
error = e;
this.error = e;
}
this.isFinished = true;
this._sequencer.tryRun();
if (this.importCount === 0) {
this._finish(error || this.error);
}
},
_onSequencerEmpty: function() {
if (!this.isFinished) {
return;
}
this._finish(this.error);
},
visitImport: function (importNode, visitArgs) {
var inlineCSS = importNode.options.inline;
@@ -85,6 +87,9 @@ ImportVisitor.prototype = {
this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo, evaldImportNode.options, sequencedOnImported);
} else {
this.importCount--;
if (this.isFinished) {
this._sequencer.tryRun();
}
}
},
onImported: function (importNode, context, e, root, importedAtRoot, fullPath) {
@@ -134,10 +139,7 @@ ImportVisitor.prototype = {
importVisitor.importCount--;
if (importVisitor.isFinished) {
this._sequencer.tryRun();
if (importVisitor.importCount === 0) {
importVisitor._finish(importVisitor.error);
}
importVisitor._sequencer.tryRun();
}
},
visitRule: function (ruleNode, visitArgs) {

View File

@@ -1,6 +1,6 @@
{
"name": "less",
"version": "2.1.1",
"version": "2.2.0",
"description": "Leaner CSS",
"homepage": "http://lesscss.org",
"author": {
@@ -45,7 +45,8 @@
"request": "^2.48.0",
"mkdirp": "^0.5.0",
"source-map": "^0.1.x",
"promise": "^6.0.1"
"promise": "^6.0.1",
"image-size": "~0.3.5"
},
"devDependencies": {
"diff": "^1.0",

View File

@@ -6,6 +6,9 @@
.modify {
my-url: url("http://localhost:8081/test/browser/less/b.png");
}
.gray-gradient {
background: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220%22%2F%3E%3Cstop%20offset%3D%2260%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.05%22%2F%3E%3Cstop%20offset%3D%2270%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.1%22%2F%3E%3Cstop%20offset%3D%2273%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.15%22%2F%3E%3Cstop%20offset%3D%2275%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.2%22%2F%3E%3Cstop%20offset%3D%2280%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.25%22%2F%3E%3Cstop%20offset%3D%2285%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.3%22%2F%3E%3Cstop%20offset%3D%2288%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.35%22%2F%3E%3Cstop%20offset%3D%2290%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.4%22%2F%3E%3Cstop%20offset%3D%2295%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.45%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.5%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
}
@font-face {
src: url("/fonts/garamond-pro.ttf");
src: local(Futura-Medium), url(http://localhost:8081/test/browser/less/fonts.svg#MyGeometricModern) format("svg");
@@ -48,7 +51,7 @@
uri: url('http://localhost:8081/test/data/data-uri-fail.png');
}
#svg-functions {
background-image: url('data:image/svg+xml,<?xml version="1.0" ?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none"><linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#000000"/><stop offset="100%" stop-color="#ffffff"/></linearGradient><rect x="0" y="0" width="1" height="1" fill="url(#gradient)" /></svg>');
background-image: url('data:image/svg+xml,<?xml version="1.0" ?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none"><linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#000000"/><stop offset="3%" stop-color="#ffa500"/><stop offset="100%" stop-color="#ffffff"/></linearGradient><rect x="0" y="0" width="1" height="1" fill="url(#gradient)" /></svg>');
background-image: url('data:image/svg+xml,<?xml version="1.0" ?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none"><linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="1%" stop-color="#c4c4c4"/><stop offset="3%" stop-color="#ffa500"/><stop offset="5%" stop-color="#008000"/><stop offset="95%" stop-color="#ffffff"/></linearGradient><rect x="0" y="0" width="1" height="1" fill="url(#gradient)" /></svg>');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23000000%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23000000%22%2F%3E%3Cstop%20offset%3D%223%25%22%20stop-color%3D%22%23ffa500%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%221%25%22%20stop-color%3D%22%23c4c4c4%22%2F%3E%3Cstop%20offset%3D%223%25%22%20stop-color%3D%22%23ffa500%22%2F%3E%3Cstop%20offset%3D%225%25%22%20stop-color%3D%22%23008000%22%2F%3E%3Cstop%20offset%3D%2295%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
}

View File

@@ -0,0 +1,5 @@
@import "svg-gradient-mixin.less";
.gray-gradient {
.gradient-mixin(#999);
}

View File

@@ -0,0 +1,15 @@
.gradient-mixin(@color) {
background: svg-gradient(to bottom,
fade(@color, 0%) 0%,
fade(@color, 5%) 60%,
fade(@color, 10%) 70%,
fade(@color, 15%) 73%,
fade(@color, 20%) 75%,
fade(@color, 25%) 80%,
fade(@color, 30%) 85%,
fade(@color, 35%) 88%,
fade(@color, 40%) 90%,
fade(@color, 45%) 95%,
fade(@color, 50%) 100%
);
}

View File

@@ -1,5 +1,6 @@
@import "imports/urls.less";
@import "http://localhost:8081/test/browser/less/imports/urls2.less";
@import "http://localhost:8081/test/browser/less/nested-gradient-with-svg-gradient/mixin-consumer.less";
@font-face {
src: url("/fonts/garamond-pro.ttf");
src: local(Futura-Medium),

View File

@@ -147,3 +147,5 @@ body ^^ .shadow {
symbols: ;
suffix: " ";
}
@-ms-viewport {
}

View File

@@ -138,6 +138,7 @@
percent: true;
em: true;
cat: true;
no-unit-is-empty: true;
case-insensitive-1: true;
case-insensitive-2: true;
}

View File

@@ -1,6 +1,12 @@
body {
width: 100%;
}
#logo {
width: 100px;
height: 100px;
background: url('../assets/logo.png');
}
.a {
var: test;
}

View File

@@ -46,9 +46,9 @@
uri-2: url("data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A");
}
#svg-functions {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkaWVudCkiIC8+PC9zdmc+');
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjxzdG9wIG9mZnNldD0iMyUiIHN0b3AtY29sb3I9IiNmZmE1MDAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZGllbnQpIiAvPjwvc3ZnPg==');
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIxJSIgc3RvcC1jb2xvcj0iI2M0YzRjNCIvPjxzdG9wIG9mZnNldD0iMyUiIHN0b3AtY29sb3I9IiNmZmE1MDAiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDA4MDAwIi8+PHN0b3Agb2Zmc2V0PSI5NSUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZGllbnQpIiAvPjwvc3ZnPg==');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23000000%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23000000%22%2F%3E%3Cstop%20offset%3D%223%25%22%20stop-color%3D%22%23ffa500%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%221%25%22%20stop-color%3D%22%23c4c4c4%22%2F%3E%3Cstop%20offset%3D%223%25%22%20stop-color%3D%22%23ffa500%22%2F%3E%3Cstop%20offset%3D%225%25%22%20stop-color%3D%22%23008000%22%2F%3E%3Cstop%20offset%3D%2295%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
}
#data-uri-with-spaces {
background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);

View File

@@ -1,6 +1,9 @@
@import "css/background.css";
@import "import/import-test-d.css";
@import "file.css";
.gray-gradient {
background: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220%22%2F%3E%3Cstop%20offset%3D%2260%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.05%22%2F%3E%3Cstop%20offset%3D%2270%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.1%22%2F%3E%3Cstop%20offset%3D%2273%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.15%22%2F%3E%3Cstop%20offset%3D%2275%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.2%22%2F%3E%3Cstop%20offset%3D%2280%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.25%22%2F%3E%3Cstop%20offset%3D%2285%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.3%22%2F%3E%3Cstop%20offset%3D%2288%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.35%22%2F%3E%3Cstop%20offset%3D%2290%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.4%22%2F%3E%3Cstop%20offset%3D%2295%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.45%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23999999%22%20stop-opacity%3D%220.5%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
}
@font-face {
src: url("/fonts/garamond-pro.ttf");
src: local(Futura-Medium), url(fonts.svg#MyGeometricModern) format("svg");
@@ -63,13 +66,17 @@
uri-1: url("data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A");
uri-2: url("data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A");
}
#data-uri-toobig {
#file-functions {
uri: url('../data/data-uri-fail.png');
svg-not-base-64: url("data:image/svg+xml,%3Csvg%20height%3D%22100%22%20width%3D%22100%22%3E%0D%0A%20%20%3Ccircle%20cx%3D%2250%22%20cy%3D%2250%22%20r%3D%2240%22%20stroke%3D%22black%22%20stroke-width%3D%221%22%20fill%3D%22blue%22%20%2F%3E%0D%0A%3C%2Fsvg%3E");
size: 640px 430px;
width: 640px;
height: 430px;
}
#svg-functions {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkaWVudCkiIC8+PC9zdmc+');
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjxzdG9wIG9mZnNldD0iMyUiIHN0b3AtY29sb3I9IiNmZmE1MDAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZGllbnQpIiAvPjwvc3ZnPg==');
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIxJSIgc3RvcC1jb2xvcj0iI2M0YzRjNCIvPjxzdG9wIG9mZnNldD0iMyUiIHN0b3AtY29sb3I9IiNmZmE1MDAiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDA4MDAwIi8+PHN0b3Agb2Zmc2V0PSI5NSUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZGllbnQpIiAvPjwvc3ZnPg==');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23000000%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%220%25%22%20stop-color%3D%22%23000000%22%2F%3E%3Cstop%20offset%3D%223%25%22%20stop-color%3D%22%23ffa500%22%2F%3E%3Cstop%20offset%3D%22100%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
background-image: url('data:image/svg+xml,%3C%3Fxml%20version%3D%221.0%22%20%3F%3E%3Csvg%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%20version%3D%221.1%22%20width%3D%22100%25%22%20height%3D%22100%25%22%20viewBox%3D%220%200%201%201%22%20preserveAspectRatio%3D%22none%22%3E%3ClinearGradient%20id%3D%22gradient%22%20gradientUnits%3D%22userSpaceOnUse%22%20x1%3D%220%25%22%20y1%3D%220%25%22%20x2%3D%220%25%22%20y2%3D%22100%25%22%3E%3Cstop%20offset%3D%221%25%22%20stop-color%3D%22%23c4c4c4%22%2F%3E%3Cstop%20offset%3D%223%25%22%20stop-color%3D%22%23ffa500%22%2F%3E%3Cstop%20offset%3D%225%25%22%20stop-color%3D%22%23008000%22%2F%3E%3Cstop%20offset%3D%2295%25%22%20stop-color%3D%22%23ffffff%22%2F%3E%3C%2FlinearGradient%3E%3Crect%20x%3D%220%22%20y%3D%220%22%20width%3D%221%22%20height%3D%221%22%20fill%3D%22url(%23gradient)%22%20%2F%3E%3C%2Fsvg%3E');
}
@font-face {
font-family: 'MyWebFont';

3
test/data/image.svg Normal file
View File

@@ -0,0 +1,3 @@
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="1" fill="blue" />
</svg>

After

Width:  |  Height:  |  Size: 117 B

View File

@@ -46,3 +46,4 @@ lessTester.runTestSet({urlArgs: '424242'}, "url-args/");
lessTester.testSyncronous({syncImport: true}, "import");
lessTester.testSyncronous({syncImport: true}, "css");
lessTester.testNoOptions();
lessTester.finished();

View File

@@ -9,21 +9,22 @@ module.exports = function() {
var globals = Object.keys(global);
var oneTestOnly = process.argv[2];
var oneTestOnly = process.argv[2],
isFinished = false;
var isVerbose = process.env.npm_config_loglevel === 'verbose';
less.logger.addListener({
info: function(msg) {
if (isVerbose) {
console.log(msg);
process.stdout.write(msg + "\n");
}
},
warn: function(msg) {
console.warn(msg);
process.stdout.write(msg + "\n");
},
error: function(msg) {
console.error(msg);
process.stdout.write(msg + "\n");
}
});
@@ -31,27 +32,29 @@ module.exports = function() {
queueRunning = false;
function queue(func) {
if (queueRunning) {
//console.log("adding to queue");
queueList.push(func);
} else {
//console.log("first in queue - starting");
queueRunning = true;
func();
}
}
function release() {
if (queueList.length) {
//console.log("running next in queue");
var func = queueList.shift();
func();
setTimeout(func, 0);
} else {
//console.log("stopping queue");
queueRunning = false;
}
};
}
var totalTests = 0,
failedTests = 0,
passedTests = 0;
less.functions.functionRegistry.addMultiple({
add: function (a, b) {
return new(less.tree.Dimension)(a.value + b.value);
@@ -122,9 +125,12 @@ module.exports = function() {
}
function testSyncronous(options, filenameNoExtension) {
if (oneTestOnly && ("Test Sync " + filenameNoExtension) !== oneTestOnly) {
return;
}
totalTests++;
queue(function() {
var isSync = true;
totalTests++;
toCSS(options, path.join('test/less/', filenameNoExtension + ".less"), function (err, result) {
process.stdout.write("- Test Sync " + filenameNoExtension + ": ");
@@ -133,6 +139,7 @@ module.exports = function() {
} else {
fail("Not Sync");
}
release();
});
isSync = false;
});
@@ -172,11 +179,22 @@ module.exports = function() {
return JSON.parse(fs.readFileSync(getFilename(getBasename(file), 'vars'), 'utf8'));
};
var doubleCallCheck = false;
queue(function() {
toCSS(options, path.join('test/less/', foldername + file), function (err, result) {
if (doubleCallCheck) {
totalTests++;
fail("less is calling back twice");
process.stdout.write(doubleCallCheck + "\n");
process.stdout.write((new Error()).stack + "\n");
return;
}
doubleCallCheck = (new Error()).stack;
if (verifyFunction) {
return verifyFunction(name, err, result && result.css, doReplacements, result && result.map);
var verificationResult = verifyFunction(name, err, result && result.css, doReplacements, result && result.map);
release();
return verificationResult;
}
if (err) {
fail("ERROR: " + (err && err.message));
@@ -235,10 +253,16 @@ module.exports = function() {
passedTests++;
endTest();
}
function finished() {
isFinished = true;
endTest();
}
function endTest() {
var leaked = checkGlobalLeaks();
if (failedTests + passedTests === totalTests) {
if (isFinished && ((failedTests + passedTests) >= totalTests)) {
var leaked = checkGlobalLeaks();
process.stdout.write("\n");
if (failedTests > 0) {
process.stdout.write(failedTests + stylize(" Failed", "red") + ", " + passedTests + " passed\n");
@@ -251,8 +275,7 @@ module.exports = function() {
}
if (leaked.length || failedTests) {
//process.exit(1);
process.on('exit', function() { process.reallyExit(1) });
process.on('exit', function() { process.reallyExit(1); });
}
}
}
@@ -275,6 +298,9 @@ module.exports = function() {
}
function testNoOptions() {
if (oneTestOnly && "Integration" !== oneTestOnly) {
return;
}
totalTests++;
try {
process.stdout.write("- Integration - creating parser without options: ");
@@ -291,6 +317,7 @@ module.exports = function() {
testSyncronous: testSyncronous,
testErrors: testErrors,
testSourcemap: testSourcemap,
testNoOptions: testNoOptions
testNoOptions: testNoOptions,
finished: finished
};
};

View File

@@ -149,3 +149,6 @@ body ^^ .shadow {
symbols: ‣;
suffix: " ";
}
@-ms-viewport{
//width: auto !important;
}

View File

@@ -99,4 +99,5 @@
}
.errors-if-called when (@c = never) {
.mixin-doesnt-exist();
}
}
a:hover when (2 = true) {5:-}

View File

@@ -1,4 +1,4 @@
ParseError: Unrecognised input. Possibly missing opening '(' in {path}detached-ruleset-2.less on line 5, column 9:
ParseError: Expected ')' in {path}detached-ruleset-2.less on line 5, column 9:
4 .a {
5 a: @a();
6 }

View File

@@ -1,4 +1,4 @@
SyntaxError: expected ')' got '(' in {path}parens-error-1.less on line 2, column 18:
ParseError: Expected ')' in {path}parens-error-1.less on line 2, column 18:
1 .a {
2 something: (12 (13 + 5 -23) + 5);
3 }

View File

@@ -1,4 +1,4 @@
SyntaxError: expected ')' got '-' in {path}parens-error-2.less on line 2, column 28:
ParseError: Expected ')' in {path}parens-error-2.less on line 2, column 28:
1 .a {
2 something: (12 * (13 + 5 -23));
3 }

View File

@@ -1,4 +1,4 @@
SyntaxError: expected ')' got '-' in {path}parens-error-3.less on line 2, column 29:
ParseError: Expected ')' in {path}parens-error-3.less on line 2, column 29:
1 .a {
2 something: (12 + (13 + 10 -23));
3 }

View File

@@ -0,0 +1 @@
x

View File

@@ -0,0 +1,2 @@
ParseError: Unrecognised input. Possibly missing something in {path}single-character.less on line 1, column 2:
1 x

View File

@@ -148,6 +148,7 @@
percent: ispercentage(32%);
em: isem(32em);
cat: isunit(32cat, cat);
no-unit-is-empty: isunit(32, '');
case-insensitive-1: isunit(32CAT, cat);
case-insensitive-2: isunit(32px, PX);
}

View File

@@ -1 +1,2 @@
@import (inline) "imports/logo.less";
@import "import-@{in}@{terpolation}2.less";

View File

@@ -0,0 +1,5 @@
@import "svg-gradient-mixin.less";
.gray-gradient {
.gradient-mixin(#999);
}

View File

@@ -0,0 +1,15 @@
.gradient-mixin(@color) {
background: svg-gradient(to bottom,
fade(@color, 0%) 0%,
fade(@color, 5%) 60%,
fade(@color, 10%) 70%,
fade(@color, 15%) 73%,
fade(@color, 20%) 75%,
fade(@color, 25%) 80%,
fade(@color, 30%) 85%,
fade(@color, 35%) 88%,
fade(@color, 40%) 90%,
fade(@color, 45%) 95%,
fade(@color, 50%) 100%
);
}

View File

@@ -1,3 +1,5 @@
@import "nested-gradient-with-svg-gradient/mixin-consumer.less";
@font-face {
src: url("/fonts/garamond-pro.ttf");
src: local(Futura-Medium),
@@ -55,8 +57,12 @@
uri-2: data-uri('../data/page.html');
}
#data-uri-toobig {
#file-functions {
uri: data-uri('../data/data-uri-fail.png');
svg-not-base-64: data-uri('../data/image.svg');
size: image-size('../data/data-uri-fail.png');
width: image-width('../data/data-uri-fail.png');
height: image-height('../data/data-uri-fail.png');
}
.add_an_import(@file_to_import) {
@import "@{file_to_import}";