Socket
Socket
Sign inDemoInstall

less

Package Overview
Dependencies
Maintainers
5
Versions
130
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

less - npm Package Compare versions

Comparing version 2.7.1 to 3.0.0-alpha.1

.eslintrc.json

255

Gruntfile.js

@@ -9,3 +9,143 @@ 'use strict';

var COMPRESS_FOR_TESTS = true;
var git = require('git-rev');
// Sauce Labs browser
var browsers = [
// Desktop browsers
{
browserName: "chrome",
version: 'latest',
platform: 'Windows 7'
},
{
browserName: "firefox",
version: 'latest',
platform: 'Linux'
},
{
browserName: 'safari',
version: '9',
platform: 'OS X 10.11'
},
{
browserName: "internet explorer",
version: '8',
platform: 'Windows XP'
},
{
browserName: "internet explorer",
version: '11',
platform: 'Windows 8.1'
},
{
browserName: "edge",
version: '13',
platform: 'Windows 10'
},
// Mobile browsers
{
browserName: 'ipad',
deviceName: 'iPad Air Simulator',
deviceOrientation: 'portrait',
version: '8.4',
platform: 'OS X 10.9'
},
{
browserName: 'iphone',
deviceName: 'iPhone 5 Simulator',
deviceOrientation: 'portrait',
version: '9.3',
platform: 'OS X 10.11'
},
{
browserName: 'android',
deviceName: 'Google Nexus 7 HD Emulator',
deviceOrientation: 'portrait',
version: '4.4',
platform: 'Linux'
}
];
var sauceJobs = {};
var browserTests = [ "filemanager-plugin",
"visitor-plugin",
"global-vars",
"modify-vars",
"production",
"rootpath-relative",
"rootpath",
"relative-urls",
"browser",
"no-js-errors",
"legacy"
];
function makeJob(testName) {
sauceJobs[testName] = {
options: {
urls: testName === 'all' ?
browserTests.map(function(name) {
return "http://localhost:8081/tmp/browser/test-runner-" + name + ".html";
}) :
["http://localhost:8081/tmp/browser/test-runner-" + testName + ".html"],
testname: testName === 'all' ? 'Unit Tests for Less.js' : testName,
browsers: browsers,
public: 'public',
recordVideo: false,
videoUploadOnPass: false,
recordScreenshots: process.env.TRAVIS_BRANCH !== "master",
build: process.env.TRAVIS_BRANCH === "master" ? process.env.TRAVIS_JOB_ID : undefined,
tags: [process.env.TRAVIS_BUILD_NUMBER, process.env.TRAVIS_PULL_REQUEST, process.env.TRAVIS_BRANCH],
statusCheckAttempts: -1,
sauceConfig: {
'idle-timeout': 100
},
throttled: 5,
onTestComplete: function(result, callback) {
// Called after a unit test is done, per page, per browser
// 'result' param is the object returned by the test framework's reporter
// 'callback' is a Node.js style callback function. You must invoke it after you
// finish your work.
// Pass a non-null value as the callback's first parameter if you want to throw an
// exception. If your function is synchronous you can also throw exceptions
// directly.
// Passing true or false as the callback's second parameter passes or fails the
// test. Passing undefined does not alter the test result. Please note that this
// only affects the grunt task's result. You have to explicitly update the Sauce
// Labs job's status via its REST API, if you want so.
// This should be the encrypted value in Travis
var user = process.env.SAUCE_USERNAME;
var pass = process.env.SAUCE_ACCESS_KEY;
git.short(function(hash) {
require('request').put({
url: ['https://saucelabs.com/rest/v1', user, 'jobs', result.job_id].join('/'),
auth: { user: user, pass: pass },
json: {
passed: result.passed,
build: 'build-' + hash
}
}, function (error, response, body) {
if (error) {
console.log(error);
callback(error);
} else if (response.statusCode !== 200) {
console.log(response);
callback(new Error('Unexpected response status'));
} else {
callback(null, result.passed);
}
});
});
}
}
};
}
// Make the SauceLabs jobs
(['all'].concat(browserTests)).map(makeJob);
// Project configuration.

@@ -35,3 +175,3 @@ grunt.initConfig({

test: {
command: 'node test'
command: 'node test/index.js'
},

@@ -112,20 +252,12 @@ benchmark: {

jshint: {
options: {jshintrc: '.jshintrc'},
files: {
src: [
'Gruntfile.js',
'lib/less/**/*.js',
'lib/less-node/**/*.js',
'lib/less-browser/**/*.js',
'lib/less-rhino/**/*.js',
'bin/lessc'
]
}
},
jscs: {
src: ["test/**/*.js", "lib/less*/**/*.js", "bin/lessc"],
eslint: {
target: ["Gruntfile.js",
"test/**/*.js",
"lib/less*/**/*.js",
"bin/lessc",
"!test/browser/jasmine-jsreporter.js",
"!test/less/errors/plugin/plugin-error.js"
],
options: {
config: ".jscsrc"
configFile: ".eslintrc.json"
}

@@ -192,3 +324,3 @@ },

browser: {
src: ['test/browser/less/*.less'],
src: ['test/browser/less/*.less', 'test/browser/less/plugin/*.less'],
options: {

@@ -248,10 +380,2 @@ helpers: 'test/browser/runner-browser-options.js',

},
postProcessor: {
src: ['test/browser/less/postProcessor/*.less'],
options: {
helpers: 'test/browser/runner-postProcessor-options.js',
specs: 'test/browser/runner-postProcessor.js',
outfile: 'tmp/browser/test-runner-post-processor.html'
}
},
postProcessorPlugin: {

@@ -291,59 +415,5 @@ src: ['test/less/postProcessorPlugin/*.less'],

'saucelabs-jasmine': {
all: {
options: {
urls: ["filemanager-plugin","visitor-plugin","pre-processor-plugin","post-processor-plugin","post-processor", "global-vars", "modify-vars", "production", "rootpath-relative",
"rootpath", "relative-urls", "browser", "no-js-errors", "legacy", "strict-units"
].map(function(testName) {
return "http://localhost:8081/tmp/browser/test-runner-" + testName + ".html";
}),
testname: 'Sauce Unit Test for less.js',
browsers: [{
browserName: "chrome",
version: '',
platform: 'Windows 8'
},
{
browserName: "firefox",
version: '33',
platform: 'Linux'
},
{
browserName: "iPad",
version: '8.0',
platform: 'OS X 10.9',
'device-orientation': 'portrait'
},
{
browserName: "internet explorer",
version: '8',
platform: 'Windows XP'
},
{
browserName: "internet explorer",
version: '9',
platform: 'Windows 7'
},
{
browserName: "internet explorer",
version: '10',
platform: 'Windows 7'
},
{
browserName: "internet explorer",
version: '11',
platform: 'Windows 8.1'
}],
sauceConfig: {
'record-video': process.env.TRAVIS_BRANCH !== "master",
'record-screenshots': process.env.TRAVIS_BRANCH !== "master",
'idle-timeout': 100, 'max-duration': 120,
build: process.env.TRAVIS_BRANCH === "master" ? process.env.TRAVIS_JOB_ID : undefined,
tags: [process.env.TRAVIS_BUILD_NUMBER, process.env.TRAVIS_PULL_REQUEST, process.env.TRAVIS_BRANCH]
},
throttled: 3
}
}
},
'saucelabs-jasmine': sauceJobs,
// Clean the version of less built for the tests

@@ -358,2 +428,4 @@ clean: {

// Load these plugins to provide the necessary tasks
grunt.loadNpmTasks('grunt-saucelabs');
require('jit-grunt')(grunt);

@@ -425,5 +497,9 @@

// setup a web server to run the browser tests in a browser rather than phantom
// var sauceTests = [];
// browserTests.map(function(testName) {
// sauceTests.push('saucelabs-jasmine:' + testName);
// });
grunt.registerTask('sauce-after-setup', [
'saucelabs-jasmine',
'saucelabs-jasmine:all',
'clean:sauce_log'

@@ -434,4 +510,3 @@ ]);

'clean',
'jshint',
'jscs',
'eslint',
'shell:test',

@@ -442,4 +517,4 @@ 'browsertest'

if (isNaN(Number(process.env.TRAVIS_PULL_REQUEST, 10)) &&
Number(process.env.TRAVIS_NODE_VERSION) === 0.11 &&
(process.env.TRAVIS_BRANCH === "master" || process.env.TRAVIS_BRANCH === "sauce")) {
Number(process.env.TRAVIS_NODE_VERSION) === 4 &&
(process.env.TRAVIS_BRANCH === "master" || process.env.TRAVIS_BRANCH === "3.x")) {
testTasks.push("force:on");

@@ -454,3 +529,3 @@ testTasks.push("sauce-after-setup");

// Run all tests
grunt.registerTask('quicktest', testTasks.slice(0, testTasks.length -1));
grunt.registerTask('quicktest', testTasks.slice(0, testTasks.length - 1));

@@ -457,0 +532,0 @@ // generate a good test environment for testing sourcemaps

@@ -46,2 +46,4 @@ var addDataAttr = require("./utils").addDataAttr,

options.javascriptEnabled = (options.javascriptEnabled || options.inlineJavaScript) ? true : false;
};

@@ -8,4 +8,5 @@ /**

// shim Promise if required
require('promise/polyfill.js');
// TODO - consider switching this out for a recommendation for this polyfill:
// <script src="https://cdn.polyfill.io/v2/polyfill.min.js"></script>
require("promise/polyfill");

@@ -12,0 +13,0 @@ var options = window.less || {};

@@ -20,3 +20,3 @@ // Cache system is a bit outdated and could do with work

}
} catch(e) {
} catch (e) {
//TODO - could do with adding more robust error handling

@@ -23,0 +23,0 @@ logger.error('failed to save "' + path + '" to local storage for caching.');

@@ -27,3 +27,3 @@ var utils = require("./utils"),

if (e.extract) {
if (e.line) {
errorline(e, 0, '');

@@ -134,3 +134,3 @@ errorline(e, 1, 'line');

var content = (e.type || "Syntax") + "Error: " + (e.message || 'There is an error in your .less file') +
" in " + filename + " ";
" in " + filename;

@@ -145,7 +145,7 @@ var errorline = function (e, i, classname) {

if (e.extract) {
if (e.line) {
errorline(e, 0, '');
errorline(e, 1, 'line');
errorline(e, 2, '');
content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
content += ' on line ' + e.line + ', column ' + (e.column + 1) + ':\n' +
errors.join('\n');

@@ -152,0 +152,0 @@ }

@@ -10,17 +10,2 @@ /*global window, XMLHttpRequest */

//TODOS - move log somewhere. pathDiff and doing something similar in node. use pathDiff in the other browser file for the initial load
function getXMLHttpRequest() {
if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
return new XMLHttpRequest();
} else {
try {
/*global ActiveXObject */
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
logger.error("browser doesn't support AJAX.");
return null;
}
}
}
var FileManager = function() {

@@ -42,3 +27,3 @@ };

var xhr = getXMLHttpRequest();
var xhr = new XMLHttpRequest();
var async = options.isFileProtocol ? options.fileAsync : true;

@@ -45,0 +30,0 @@

@@ -11,4 +11,3 @@ //

var less = require('../less')();
//module.exports = less;
less.options = options;

@@ -20,2 +19,3 @@ var environment = less.environment,

less.FileManager = FileManager;
less.PluginLoader = require("./plugin-loader");

@@ -27,3 +27,3 @@ require("./log-listener")(less, options);

//Setup user functions
//Setup user functions - Deprecate?
if (options.functions) {

@@ -35,9 +35,2 @@ less.functions.functionRegistry.addMultiple(options.functions);

function postProcessCSS(styles) { // deprecated, use a plugin for postprocesstasks
if (options.postProcessor && typeof options.postProcessor === 'function') {
styles = options.postProcessor.call(styles, styles) || styles;
}
return styles;
}
function clone(obj) {

@@ -139,3 +132,2 @@ var cloned = {};

} else {
result.css = postProcessCSS(result.css);
cache.setCSS(sheet.href, webInfo.lastModified, instanceOptions.modifyVars, result.css);

@@ -142,0 +134,0 @@ callback(null, result.css, data, sheet, webInfo, path);

@@ -19,3 +19,3 @@ module.exports = {

}
catch(_) {}
catch (_) {}
}

@@ -22,0 +22,0 @@ }

@@ -8,3 +8,3 @@ var path = require('path'),

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

@@ -11,0 +11,0 @@

@@ -6,3 +6,3 @@ var fs;

}
catch(e)
catch (e)
{

@@ -9,0 +9,0 @@ fs = require("fs");

module.exports = function(environment) {
var Dimension = require("../less/tree/dimension"),
Expression = require("../less/tree/expression"),
functionRegistry = require("./../less/functions/function-registry");
Expression = require("../less/tree/expression"),
functionRegistry = require("./../less/functions/function-registry");

@@ -6,0 +6,0 @@ function imageSize(functionContext, filePathNode) {

@@ -15,58 +15,4 @@ var environment = require("./environment"),

less.UrlFileManager = UrlFileManager;
less.formatError = function(ctx, options) {
options = options || {};
less.options = less.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

@@ -73,0 +19,0 @@ require('./image-size')(less.environment);

@@ -18,4 +18,4 @@ // lessc_helper.js

};
return '\033[' + styles[style][0] + 'm' + str +
'\033[' + styles[style][1] + 'm';
return '\x1b[' + styles[style][0] + 'm' + str +
'\x1b[' + styles[style][1] + 'm';
},

@@ -35,3 +35,3 @@

console.log(" --no-ie-compat Disables IE compatibility checks.");
console.log(" --no-js Disables JavaScript in less files");
console.log(" --js Enables inline JavaScript in less files");
console.log(" -l, --lint Syntax check only (lint).");

@@ -38,0 +38,0 @@ console.log(" -s, --silent Suppresses output of error messages.");

@@ -1,2 +0,4 @@

var path = require("path");
var path = require("path"),
AbstractPluginLoader = require("../less/environment/abstract-plugin-loader.js");
/**

@@ -7,86 +9,109 @@ * Node Plugin Loader

this.less = less;
};
PluginLoader.prototype.tryLoadPlugin = function(name, argument) {
var plugin = this.tryRequirePlugin(name);
if (plugin) {
// support plugins being a function
// so that the plugin can be more usable programmatically
if (typeof plugin === "function") {
plugin = new plugin();
}
if (plugin.minVersion) {
if (this.compareVersion(plugin.minVersion, this.less.version) < 0) {
console.log("plugin " + name + " requires version " + this.versionToString(plugin.minVersion));
return null;
this.require = require;
this.requireRelative = function(prefix) {
prefix = path.dirname(prefix);
return function(id) {
var str = id.substr(0, 2);
if (str === '..' || str === './') {
return require(path.join(prefix, id));
}
}
if (argument) {
if (!plugin.setOptions) {
console.log("options have been provided but the plugin " + name + "does not support any options");
return null;
else {
return require(id);
}
try {
plugin.setOptions(argument);
};
};
};
PluginLoader.prototype = new AbstractPluginLoader();
PluginLoader.prototype.tryLoadPlugin = function(name, basePath, callback) {
var self = this;
var prefix = name.slice(0, 1);
var explicit = prefix === "." || prefix === "/" || name.slice(-3).toLowerCase() === ".js";
if (explicit) {
this.tryLoadFromEnvironment(name, basePath, explicit, callback);
}
else {
this.tryLoadFromEnvironment('less-plugin-' + name, basePath, explicit, function(err, data) {
if (!err) {
callback(null, data);
}
catch(e) {
console.log("Error setting options on plugin " + name);
console.log(e.message);
return null;
else {
self.tryLoadFromEnvironment(name, basePath, explicit, callback);
}
}
return plugin;
});
}
return null;
};
PluginLoader.prototype.compareVersion = function(aVersion, bVersion) {
for (var i = 0; i < aVersion.length; i++) {
if (aVersion[i] !== bVersion[i]) {
return parseInt(aVersion[i]) > parseInt(bVersion[i]) ? -1 : 1;
PluginLoader.prototype.tryLoadFromEnvironment = function(name, basePath, explicit, callback) {
var filename = name;
var self = this;
function getFile(filename) {
var fileManager = new self.less.FileManager();
filename = fileManager.tryAppendExtension(filename, '.js');
fileManager.loadFile(filename).then(
function(data) {
try {
self.require = self.requireRelative(filename);
}
catch (e) {
callback(e);
}
callback(null, data);
},
function(err) {
callback(err);
}
);
}
if (explicit) {
if (basePath) {
filename = path.join(basePath, name);
}
getFile(filename);
}
return 0;
};
PluginLoader.prototype.versionToString = function(version) {
var versionString = "";
for (var i = 0; i < version.length; i++) {
versionString += (versionString ? "." : "") + version[i];
}
return versionString;
};
PluginLoader.prototype.tryRequirePlugin = function(name) {
// is at the same level as the less.js module
try {
return require("../../../" + name);
}
catch(e) {
}
// is installed as a sub dependency of the current folder
try {
return require(path.join(process.cwd(), "node_modules", name));
}
catch(e) {
}
// is referenced relative to the current directory
try {
return require(path.join(process.cwd(), name));
}
catch(e) {
}
// unlikely - would have to be a dependency of where this code was running (less.js)...
if (name[0] !== '.') {
else {
// Search node_modules for a possible plugin name match
try {
return require(name);
filename = require.resolve(path.join("../../../", name));
}
catch(e) {
catch (e) {
}
}
};
PluginLoader.prototype.printUsage = function(plugins) {
for (var i = 0; i < plugins.length; i++) {
var plugin = plugins[i];
if (plugin.printUsage) {
plugin.printUsage();
// is installed as a sub dependency of the current folder
try {
filename = require.resolve(path.join(process.cwd(), "node_modules", name));
}
catch (e) {
}
// is referenced relative to the current directory
try {
filename = require.resolve(path.join(process.cwd(), name));
}
catch (e) {
}
// unlikely - would have to be a dependency of where this code was running (less.js)...
if (name[0] !== '.') {
try {
filename = require.resolve(name);
}
catch (e) {
}
}
if (basePath) {
filename = path.join(basePath, name);
}
if (filename) {
getFile(filename);
}
else {
callback({ message: 'Plugin could not be found.'});
}
}
};
module.exports = PluginLoader;

@@ -24,3 +24,3 @@ var isUrlRe = /^(?:https?:)?\/\//i,

try { request = require('request'); }
catch(e) { request = null; }
catch (e) { request = null; }
}

@@ -27,0 +27,0 @@ if (!request) {

@@ -84,3 +84,3 @@ /* jshint rhino:true, unused: false */

callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName);
} catch(e) {
} catch (e) {
writeError(e);

@@ -168,3 +168,3 @@ }

var continueProcessing = true,
currentErrorcode;
currentErrorcode;

@@ -448,3 +448,3 @@ var checkArgFunc = function(arg, option) {

}
catch(e) {
catch (e) {
writeError(e, options);

@@ -451,0 +451,0 @@ quit(1);

@@ -51,6 +51,6 @@ var contexts = {};

'urlArgs', // whether to add args into url tokens
'javascriptEnabled',// option - whether JavaScript is enabled. if undefined, defaults to true
'javascriptEnabled',// option - whether Inline JavaScript is enabled. if undefined, defaults to false
'pluginManager', // Used as the plugin manager for the session
'importantScope' // used to bubble up !important statements
];
];

@@ -87,4 +87,4 @@ contexts.Eval = function(options, frames) {

var
segments = path.split("/").reverse(),
segment;
segments = path.split("/").reverse(),
segment;

@@ -94,3 +94,3 @@ path = [];

segment = segments.pop();
switch( segment ) {
switch ( segment ) {
case ".":

@@ -97,0 +97,0 @@ break;

@@ -38,3 +38,3 @@ var abstractFileManager = function() {

};
// TODO: pull out / replace?
abstractFileManager.prototype.join = function(basePath, laterPath) {

@@ -46,2 +46,3 @@ if (!basePath) {

};
abstractFileManager.prototype.pathDiff = function pathDiff(url, baseUrl) {

@@ -120,2 +121,3 @@ // diff between two paths to create a relative path

returner.path = (urlParts[1] || "") + directories.join("/");
returner.filename = urlParts[4];
returner.fileUrl = returner.path + (urlParts[4] || "");

@@ -122,0 +124,0 @@ returner.url = returner.fileUrl + (urlParts[5] || "");

@@ -14,4 +14,4 @@ var Expression = require("../tree/expression");

};
functionCaller.prototype.call = function(args) {
// This code is terrible and should be replaced as per this issue...

@@ -18,0 +18,0 @@ // https://github.com/less/less.js/issues/2477

@@ -23,4 +23,10 @@ function makeRegistry( base ) {

},
inherit : function() {
getLocalFunctions: function() {
return this._data;
},
inherit: function() {
return makeRegistry( this );
},
create: function(base) {
return makeRegistry(base);
}

@@ -27,0 +33,0 @@ };

@@ -8,3 +8,3 @@ var Dimension = require("../tree/dimension"),

args = Array.prototype.slice.call(args);
switch(args.length) {
switch (args.length) {
case 0: throw { type: "Argument", message: "one or more arguments required" };

@@ -31,3 +31,3 @@ }

if (unitStatic !== undefined && unit !== unitStatic) {
throw{ type: "Argument", message: "incompatible types" };
throw { type: "Argument", message: "incompatible types" };
}

@@ -34,0 +34,0 @@ values[unit] = order.length;

@@ -18,8 +18,8 @@ module.exports = function(environment) {

directionValue = direction.toCSS(renderEnv),
i, color, position, positionValue, alpha;
i, color, position, positionValue, alpha;
function throwArgumentDescriptor() {
throw { type: "Argument",
message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
" end_color [end_position] or direction, color list" };
message: "svg-gradient expects direction, start_color [start_position], [color position,]...," +
" end_color [end_position] or direction, color list" };
}

@@ -65,3 +65,3 @@

for (i = 0; i < stops.length; i+= 1) {
for (i = 0; i < stops.length; i += 1) {
if (stops[i] instanceof Expression) {

@@ -68,0 +68,0 @@ color = stops[i].value[0];

var contexts = require("./contexts"),
Parser = require('./parser/parser'),
FunctionImporter = require('./plugins/function-importer');
LessError = require('./less-error');

@@ -16,3 +16,4 @@ module.exports = function(environment) {

var ImportManager = function(context, rootFileInfo) {
var ImportManager = function(less, context, rootFileInfo) {
this.less = less;
this.rootFilename = rootFileInfo.filename;

@@ -32,3 +33,3 @@ this.paths = context.paths || []; // Search paths, when importing

* @param path - the raw path
* @param tryAppendLessExtension - whether to try appending the less extension (if the path has no extension)
* @param tryAppendExtension - whether to try appending a file extension (.less or .js if the path has no extension)
* @param currentFileInfo - the current file info (used for instance to work out relative paths)

@@ -38,4 +39,6 @@ * @param importOptions - import options

*/
ImportManager.prototype.push = function (path, tryAppendLessExtension, currentFileInfo, importOptions, callback) {
var importManager = this;
ImportManager.prototype.push = function (path, tryAppendExtension, currentFileInfo, importOptions, callback) {
var importManager = this,
pluginLoader = this.context.pluginManager.Loader;
this.queue.push(path);

@@ -71,8 +74,9 @@

if (tryAppendLessExtension) {
path = fileManager.tryAppendExtension(path, importOptions.plugin ? ".js" : ".less");
if (tryAppendExtension) {
path = importOptions.isPlugin ? path : fileManager.tryAppendExtension(path, ".less");
}
var loadFileCallback = function(loadedFile) {
var resolvedFilename = loadedFile.filename,
var plugin,
resolvedFilename = loadedFile.filename,
contents = loadedFile.contents.replace(/^\uFEFF/, '');

@@ -109,6 +113,10 @@

if (importOptions.plugin) {
new FunctionImporter(newEnv, newFileInfo).eval(contents, function (e, root) {
fileParsedFunc(e, root, resolvedFilename);
});
if (importOptions.isPlugin) {
plugin = pluginLoader.evalPlugin(contents, newEnv, importManager, importOptions.pluginArgs, newFileInfo);
if (plugin instanceof LessError) {
fileParsedFunc(plugin, null, resolvedFilename);
}
else {
fileParsedFunc(null, plugin, resolvedFilename);
}
} else if (importOptions.inline) {

@@ -122,5 +130,4 @@ fileParsedFunc(null, contents, resolvedFilename);

};
var promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment,
function(err, loadedFile) {
var promise;
var done = function(err, loadedFile) {
if (err) {

@@ -131,8 +138,20 @@ fileParsedFunc(err);

}
});
if (promise) {
promise.then(loadFileCallback, fileParsedFunc);
};
if (importOptions.isPlugin) {
try {
pluginLoader.tryLoadPlugin(path, currentFileInfo.currentDirectory, done);
}
catch (e) {
callback(e);
}
}
else {
promise = fileManager.loadFile(path, currentFileInfo.currentDirectory, this.context, environment, done);
if (promise) {
promise.then(loadFileCallback, fileParsedFunc);
}
}
};
return ImportManager;
};
module.exports = function(environment, fileManagers) {
var SourceMapOutput, SourceMapBuilder, ParseTree, ImportManager, Environment;
var less = {
version: [2, 7, 1],
var initial = {
version: [3, 0, 0],
data: require('./data'),

@@ -10,2 +10,3 @@ tree: require('./tree'),

AbstractFileManager: require("./environment/abstract-file-manager"),
AbstractPluginLoader: require("./environment/abstract-plugin-loader"),
environment: (environment = new Environment(environment, fileManagers)),

@@ -29,3 +30,28 @@ visitors: require('./visitors'),

return less;
// Create a public API
var ctor = function(t) {
return function() {
var obj = Object.create(t.prototype);
t.apply(obj, Array.prototype.slice.call(arguments, 0));
return obj;
};
};
var t, api = Object.create(initial);
for (var n in initial.tree) {
/*eslint guard-for-in: 0 */
t = initial.tree[n];
if (typeof t === "function") {
api[n] = ctor(t);
}
else {
api[n] = Object.create(null);
for (var o in t) {
/*eslint guard-for-in: 0 */
api[n][o] = ctor(t[o]);
}
}
}
return api;
};

@@ -1,5 +0,25 @@

var utils = require("./utils");
var utils = require('./utils');
/**
* This is a centralized class of any error that could be thrown internally (mostly by the parser).
* Besides standard .message it keeps some additional data like a path to the file where the error
* occurred along with line and column numbers.
*
* @class
* @extends Error
* @type {module.LessError}
*
* @prop {string} type
* @prop {string} filename
* @prop {number} index
* @prop {number} line
* @prop {number} column
* @prop {number} callLine
* @prop {number} callExtract
* @prop {string[]} extract
*
* @param {Object} e - An error object to wrap around or just a descriptive object
* @param {Object} importManager - An instance of ImportManager (see import-manager.js)
* @param {string} [currentFilename]
*/
var LessError = module.exports = function LessError(e, importManager, currentFilename) {
Error.call(this);

@@ -9,2 +29,5 @@

this.message = e.message;
this.stack = e.stack;
if (importManager && filename) {

@@ -22,13 +45,28 @@ var input = importManager.contents[filename],

this.line = typeof line === 'number' ? line + 1 : null;
this.column = col;
if (!this.line && this.stack) {
var found = this.stack.match(/(<anonymous>|Function):(\d+):(\d+)/);
if (found) {
if (found[2]) {
this.line = parseInt(found[2]) - 2;
}
if (found[3]) {
this.column = parseInt(found[3]);
}
}
}
this.callLine = callLine + 1;
this.callExtract = lines[callLine];
this.column = col;
this.extract = [
lines[line - 1],
lines[line],
lines[line + 1]
lines[this.line - 2],
lines[this.line - 1],
lines[this.line]
];
}
this.message = e.message;
this.stack = e.stack;
};

@@ -45,1 +83,62 @@

LessError.prototype.constructor = LessError;
/**
* An overridden version of the default Object.prototype.toString
* which uses additional information to create a helpful message.
*
* @param {Object} options
* @returns {string}
*/
LessError.prototype.toString = function(options) {
options = options || {};
var message = '';
var extract = this.extract || [];
var error = [];
var stylize = function (str) { return str; };
if (options.stylize) {
var type = typeof options.stylize;
if (type !== 'function') {
throw Error('options.stylize should be a function, got a ' + type + '!');
}
stylize = options.stylize;
}
if (this.line !== null) {
if (typeof extract[0] === 'string') {
error.push(stylize((this.line - 1) + ' ' + extract[0], 'grey'));
}
if (typeof extract[1] === 'string') {
var errorTxt = this.line + ' ';
if (extract[1]) {
errorTxt += extract[1].slice(0, this.column) +
stylize(stylize(stylize(extract[1].substr(this.column, 1), 'bold') +
extract[1].slice(this.column + 1), 'red'), 'inverse');
}
error.push(errorTxt);
}
if (typeof extract[2] === 'string') {
error.push(stylize((this.line + 1) + ' ' + extract[2], 'grey'));
}
error = error.join('\n') + stylize('', 'reset') + '\n';
}
message += stylize(this.type + 'Error: ' + this.message, 'red');
if (this.filename) {
message += stylize(' in ', 'red') + this.filename;
}
if (this.line) {
message += stylize(' on line ' + this.line + ', column ' + (this.column + 1) + ':', 'grey');
}
message += '\n' + error;
if (this.callLine) {
message += stylize('from ', 'red') + (this.filename || '') + '/n';
message += stylize(this.callLine, 'grey') + ' ' + this.callExtract + '/n';
}
return message;
};
var PromiseConstructor,
contexts = require("./contexts"),
Parser = require('./parser/parser'),
PluginManager = require('./plugin-manager');
PluginManager = require('./plugin-manager'),
LessError = require('./less-error');

@@ -32,5 +33,4 @@ module.exports = function(environment, ParseTree, ImportManager) {

rootFileInfo,
pluginManager = new PluginManager(this);
pluginManager = new PluginManager(this, true);
pluginManager.addPlugins(options.plugins);
options.pluginManager = pluginManager;

@@ -59,9 +59,26 @@

var imports = new ImportManager(context, rootFileInfo);
var imports = new ImportManager(this, context, rootFileInfo);
this.importManager = imports;
if (options.plugins) {
options.plugins.forEach(function(plugin) {
var evalResult, contents;
if (plugin.fileContent) {
contents = plugin.fileContent.replace(/^\uFEFF/, '');
evalResult = pluginManager.Loader.evalPlugin(contents, context, imports, plugin.options, plugin.filename);
if (evalResult instanceof LessError) {
return callback(evalResult);
}
}
else {
pluginManager.addPlugin(plugin);
}
});
}
new Parser(context, imports, rootFileInfo)
.parse(input, function (e, root) {
if (e) { return callback(e); }
callback(null, root, imports, options);
}, options);
if (e) { return callback(e); }
callback(null, root, imports, options);
}, options);
}

@@ -68,0 +85,0 @@ };

@@ -159,3 +159,3 @@ var chunker = require('./chunker');

var nextChar = input.charAt(i + currentPosition);
switch(nextChar) {
switch (nextChar) {
case "\\":

@@ -162,0 +162,0 @@ i++;

@@ -0,1 +1,2 @@

var utils = require('./utils');
/**

@@ -11,3 +12,14 @@ * Plugin Manager

this.fileManagers = [];
this.iterator = -1;
this.pluginCache = {};
this.Loader = new less.PluginLoader(less);
};
var pm, PluginManagerFactory = function(less, newFactory) {
if (newFactory || !pm) {
pm = new PluginManager(less);
}
return pm;
};
/**

@@ -27,8 +39,34 @@ * Adds all the plugins in the array

* @param plugin
* @param {String} filename
*/
PluginManager.prototype.addPlugin = function(plugin) {
PluginManager.prototype.addPlugin = function(plugin, filename, functionRegistry) {
this.installedPlugins.push(plugin);
plugin.install(this.less, this);
if (filename) {
this.pluginCache[filename] = plugin;
}
if (plugin.install) {
plugin.install(this.less, this, functionRegistry || this.less.functions.functionRegistry);
}
};
/**
*
* @param filename
*/
PluginManager.prototype.get = function(filename) {
return this.pluginCache[filename];
};
/**
* Deprecate eventually
*/
function upgradeVisitors(visitor, oldType, newType) {
if (visitor['visit' + oldType] && !visitor['visit' + newType]) {
visitor['visit' + newType] = visitor['visit' + oldType];
}
if (visitor['visit' + oldType + 'Out'] && !visitor['visit' + newType + 'Out']) {
visitor['visit' + newType + 'Out'] = visitor['visit' + oldType + 'Out'];
}
}
/**
* Adds a visitor. The visitor object has options on itself to determine

@@ -39,2 +77,11 @@ * when it should run.

PluginManager.prototype.addVisitor = function(visitor) {
var proto;
// 2.x to 3.x visitor compatibility
try {
proto = utils.getPrototype(visitor);
upgradeVisitors(proto, 'Directive', 'AtRule');
upgradeVisitors(proto, 'Rule', 'Declaration');
}
catch (e) {}
this.visitors.push(visitor);

@@ -109,2 +156,16 @@ };

};
PluginManager.prototype.visitor = function() {
var self = this;
return {
first: function() {
self.iterator = -1;
return self.visitors[self.iterator];
},
get: function() {
self.iterator += 1;
return self.visitors[self.iterator];
}
};
};
/**

@@ -118,2 +179,4 @@ *

};
module.exports = PluginManager;
//
module.exports = PluginManagerFactory;

@@ -29,2 +29,5 @@ module.exports = function (SourceMapOutput, environment) {

}
if (this.options.sourceMapBasepath !== undefined && this.sourceMapURL !== undefined) {
this.sourceMapURL = sourceMapOutput.removeBasepath(this.sourceMapURL);
}
return css + this.getCSSAppendage();

@@ -31,0 +34,0 @@ };

@@ -31,11 +31,16 @@ module.exports = function (environment) {

SourceMapOutput.prototype.removeBasepath = function(path) {
if (this._sourceMapBasepath && path.indexOf(this._sourceMapBasepath) === 0) {
path = path.substring(this._sourceMapBasepath.length);
if (path.charAt(0) === '\\' || path.charAt(0) === '/') {
path = path.substring(1);
}
}
return path;
};
SourceMapOutput.prototype.normalizeFilename = function(filename) {
filename = filename.replace(/\\/g, '/');
if (this._sourceMapBasepath && filename.indexOf(this._sourceMapBasepath) === 0) {
filename = filename.substring(this._sourceMapBasepath.length);
if (filename.charAt(0) === '\\' || filename.charAt(0) === '/') {
filename = filename.substring(1);
}
}
filename = this.removeBasepath(filename);
return (this._sourceMapRootpath || "") + filename;

@@ -42,0 +47,0 @@ };

@@ -16,3 +16,3 @@ var contexts = require("./contexts"),

//
// new tree.Rule('@color',
// new tree.Declaration('@color',
// new tree.Value([

@@ -29,4 +29,4 @@ // new tree.Expression([

if (! (value instanceof tree.Value)) {
if (! (value instanceof tree.Expression)) {
if (!(value instanceof tree.Value)) {
if (!(value instanceof tree.Expression)) {
value = new tree.Expression([value]);

@@ -36,3 +36,3 @@ }

}
return new tree.Rule('@' + k, value, false, null, 0);
return new tree.Declaration('@' + k, value, false, null, 0);
});

@@ -42,4 +42,3 @@ evalEnv.frames = [new tree.Ruleset(null, variables)];

var preEvalVisitors = [],
visitors = [
var visitors = [
new visitor.JoinSelectorVisitor(),

@@ -49,16 +48,11 @@ new visitor.MarkVisibleSelectorsVisitor(true),

new visitor.ToCSSVisitor({compress: Boolean(options.compress)})
], i;
], v, visitorIterator;
// first() / get() allows visitors to be added while visiting
if (options.pluginManager) {
var pluginVisitors = options.pluginManager.getVisitors();
for (i = 0; i < pluginVisitors.length; i++) {
var pluginVisitor = pluginVisitors[i];
if (pluginVisitor.isPreEvalVisitor) {
preEvalVisitors.push(pluginVisitor);
} else {
if (pluginVisitor.isPreVisitor) {
visitors.splice(0, 0, pluginVisitor);
} else {
visitors.push(pluginVisitor);
}
visitorIterator = options.pluginManager.visitor();
visitorIterator.first();
while ((v = visitorIterator.get())) {
if (v.isPreEvalVisitor) {
v.run(root);
}

@@ -68,13 +62,18 @@ }

for (i = 0; i < preEvalVisitors.length; i++) {
preEvalVisitors[i].run(root);
}
evaldRoot = root.eval(evalEnv);
for (i = 0; i < visitors.length; i++) {
for (var i = 0; i < visitors.length; i++) {
visitors[i].run(evaldRoot);
}
if (options.pluginManager) {
visitorIterator.first();
while ((v = visitorIterator.get())) {
if (!v.isPreEvalVisitor) {
v.run(evaldRoot);
}
}
}
return evaldRoot;
};

@@ -5,5 +5,5 @@ var Node = require("./node");

this.value = value;
this.index = index;
this._index = index;
this._fileInfo = currentFileInfo;
this.mapLines = mapLines;
this.currentFileInfo = currentFileInfo;
this.rulesetLike = (typeof rulesetLike === 'undefined') ? false : rulesetLike;

@@ -16,3 +16,3 @@ this.allowRoot = true;

Anonymous.prototype.eval = function () {
return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo());
return new Anonymous(this.value, this._index, this._fileInfo, this.mapLines, this.rulesetLike, this.visibilityInfo());
};

@@ -26,4 +26,7 @@ Anonymous.prototype.compare = function (other) {

Anonymous.prototype.genCSS = function (context, output) {
output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
this.nodeVisible = Boolean(this.value);
if (this.nodeVisible) {
output.add(this.value, this._fileInfo, this._index, this.mapLines);
}
};
module.exports = Anonymous;
var Node = require("./node"),
Anonymous = require("./anonymous"),
FunctionCaller = require("../functions/function-caller");

@@ -9,4 +10,4 @@ //

this.args = args;
this.index = index;
this.currentFileInfo = currentFileInfo;
this._index = index;
this._fileInfo = currentFileInfo;
};

@@ -33,4 +34,4 @@ Call.prototype = new Node();

var args = this.args.map(function (a) { return a.eval(context); }),
result, funcCaller = new FunctionCaller(this.name, context, this.index, this.currentFileInfo);
result, funcCaller = new FunctionCaller(this.name, context, this.getIndex(), this.fileInfo());
if (funcCaller.isValid()) {

@@ -40,19 +41,30 @@ try {

} catch (e) {
throw { type: e.type || "Runtime",
message: "error evaluating function `" + this.name + "`" +
(e.message ? ': ' + e.message : ''),
index: this.index, filename: this.currentFileInfo.filename };
throw {
type: e.type || "Runtime",
message: "error evaluating function `" + this.name + "`" +
(e.message ? ': ' + e.message : ''),
index: this.getIndex(),
filename: this.fileInfo().filename,
line: e.lineNumber,
column: e.columnNumber
};
}
if (result != null) {
result.index = this.index;
result.currentFileInfo = this.currentFileInfo;
if (result !== null && result !== undefined) {
// All returned results must be Nodes,
// so anything other than a Node is a null Node
if (!(result instanceof Node)) {
result = new Anonymous(null);
}
result._index = this._index;
result._fileInfo = this._fileInfo;
return result;
}
}
return new Call(this.name, args, this.index, this.currentFileInfo);
return new Call(this.name, args, this.getIndex(), this.fileInfo());
};
Call.prototype.genCSS = function (context, output) {
output.add(this.name + "(", this.currentFileInfo, this.index);
output.add(this.name + "(", this.fileInfo(), this.getIndex());

@@ -59,0 +71,0 @@ for (var i = 0; i < this.args.length; i++) {

@@ -102,3 +102,3 @@ var Node = require("./node"),

Color.prototype.operate = function (context, op, other) {
var rgb = [];
var rgb = new Array(3);
var alpha = this.alpha * (1 - other.alpha) + other.alpha;

@@ -156,3 +156,3 @@ for (var c = 0; c < 3; c++) {

} else {
switch(max) {
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;

@@ -159,0 +159,0 @@ case g: h = (b - r) / d + 2; break;

@@ -7,3 +7,4 @@ var Node = require("./node"),

this.isLineComment = isLineComment;
this.currentFileInfo = currentFileInfo;
this._index = index;
this._fileInfo = currentFileInfo;
this.allowRoot = true;

@@ -15,3 +16,3 @@ };

if (this.debugInfo) {
output.add(getDebugInfo(context, this), this.currentFileInfo, this.index);
output.add(getDebugInfo(context, this), this.fileInfo(), this.getIndex());
}

@@ -18,0 +19,0 @@ output.add(this.value);

@@ -7,3 +7,3 @@ var Node = require("./node");

this.rvalue = r;
this.index = i;
this._index = i;
this.negate = negate;

@@ -10,0 +10,0 @@ };

var debugInfo = function(context, ctx, lineSeparator) {
var result = "";
if (context.dumpLineNumbers && !context.compress) {
switch(context.dumpLineNumbers) {
switch (context.dumpLineNumbers) {
case 'comments':

@@ -6,0 +6,0 @@ result = debugInfo.asComment(ctx);

var Node = require("./node"),
contexts = require("../contexts");
contexts = require("../contexts"),
utils = require("../utils");

@@ -7,2 +8,3 @@ var DetachedRuleset = function (ruleset, frames) {

this.frames = frames;
this.setParent(this.ruleset, this);
};

@@ -16,3 +18,3 @@ DetachedRuleset.prototype = new Node();

DetachedRuleset.prototype.eval = function (context) {
var frames = this.frames || context.frames.slice(0);
var frames = this.frames || utils.copyArray(context.frames);
return new DetachedRuleset(this.ruleset, frames);

@@ -19,0 +21,0 @@ };

@@ -13,2 +13,3 @@ var Node = require("./node"),

new Unit(unit ? [unit] : undefined);
this.setParent(this.unit, this);
};

@@ -15,0 +16,0 @@

@@ -1,134 +0,12 @@

var Node = require("./node"),
Selector = require("./selector"),
Ruleset = require("./ruleset");
// Backwards compatibility shim for Directive (AtRule)
var AtRule = require("./atrule");
var Directive = function (name, value, rules, index, currentFileInfo, debugInfo, isRooted, visibilityInfo) {
var i;
this.name = name;
this.value = value;
if (rules) {
if (Array.isArray(rules)) {
this.rules = rules;
} else {
this.rules = [rules];
this.rules[0].selectors = (new Selector([], null, null, this.index, currentFileInfo)).createEmptySelectors();
}
for (i = 0; i < this.rules.length; i++) {
this.rules[i].allowImports = true;
}
}
this.index = index;
this.currentFileInfo = currentFileInfo;
this.debugInfo = debugInfo;
this.isRooted = isRooted || false;
this.copyVisibilityInfo(visibilityInfo);
this.allowRoot = true;
var Directive = function () {
var args = Array.prototype.slice.call(arguments);
AtRule.apply(this, args);
};
Directive.prototype = new Node();
Directive.prototype.type = "Directive";
Directive.prototype.accept = function (visitor) {
var value = this.value, rules = this.rules;
if (rules) {
this.rules = visitor.visitArray(rules);
}
if (value) {
this.value = visitor.visit(value);
}
};
Directive.prototype.isRulesetLike = function() {
return this.rules || !this.isCharset();
};
Directive.prototype.isCharset = function() {
return "@charset" === this.name;
};
Directive.prototype.genCSS = function (context, output) {
var value = this.value, rules = this.rules;
output.add(this.name, this.currentFileInfo, this.index);
if (value) {
output.add(' ');
value.genCSS(context, output);
}
if (rules) {
this.outputRuleset(context, output, rules);
} else {
output.add(';');
}
};
Directive.prototype.eval = function (context) {
var mediaPathBackup, mediaBlocksBackup, value = this.value, rules = this.rules;
Directive.prototype = Object.create(AtRule.prototype);
Directive.prototype.constructor = Directive;
//media stored inside other directive should not bubble over it
//backpup media bubbling information
mediaPathBackup = context.mediaPath;
mediaBlocksBackup = context.mediaBlocks;
//deleted media bubbling information
context.mediaPath = [];
context.mediaBlocks = [];
if (value) {
value = value.eval(context);
}
if (rules) {
// assuming that there is only one rule at this point - that is how parser constructs the rule
rules = [rules[0].eval(context)];
rules[0].root = true;
}
//restore media bubbling information
context.mediaPath = mediaPathBackup;
context.mediaBlocks = mediaBlocksBackup;
return new Directive(this.name, value, rules,
this.index, this.currentFileInfo, this.debugInfo, this.isRooted, this.visibilityInfo());
};
Directive.prototype.variable = function (name) {
if (this.rules) {
// assuming that there is only one rule at this point - that is how parser constructs the rule
return Ruleset.prototype.variable.call(this.rules[0], name);
}
};
Directive.prototype.find = function () {
if (this.rules) {
// assuming that there is only one rule at this point - that is how parser constructs the rule
return Ruleset.prototype.find.apply(this.rules[0], arguments);
}
};
Directive.prototype.rulesets = function () {
if (this.rules) {
// assuming that there is only one rule at this point - that is how parser constructs the rule
return Ruleset.prototype.rulesets.apply(this.rules[0]);
}
};
Directive.prototype.outputRuleset = function (context, output, rules) {
var ruleCnt = rules.length, i;
context.tabLevel = (context.tabLevel | 0) + 1;
// Compressed
if (context.compress) {
output.add('{');
for (i = 0; i < ruleCnt; i++) {
rules[i].genCSS(context, output);
}
output.add('}');
context.tabLevel--;
return;
}
// Non-compressed
var tabSetStr = '\n' + Array(context.tabLevel).join(" "), tabRuleStr = tabSetStr + " ";
if (!ruleCnt) {
output.add(" {" + tabSetStr + '}');
} else {
output.add(" {" + tabRuleStr);
rules[0].genCSS(context, output);
for (i = 1; i < ruleCnt; i++) {
output.add(tabRuleStr);
rules[i].genCSS(context, output);
}
output.add(tabSetStr + '}');
}
context.tabLevel--;
};
module.exports = Directive;
module.exports = Directive;

@@ -5,3 +5,3 @@ var Node = require("./node"),

var Element = function (combinator, value, index, currentFileInfo, info) {
var Element = function (combinator, value, index, currentFileInfo, visibilityInfo) {
this.combinator = combinator instanceof Combinator ?

@@ -17,5 +17,6 @@ combinator : new Combinator(combinator);

}
this.index = index;
this.currentFileInfo = currentFileInfo;
this.copyVisibilityInfo(info);
this._index = index;
this._fileInfo = currentFileInfo;
this.copyVisibilityInfo(visibilityInfo);
this.setParent(this.combinator, this);
};

@@ -34,4 +35,4 @@ Element.prototype = new Node();

this.value.eval ? this.value.eval(context) : this.value,
this.index,
this.currentFileInfo, this.visibilityInfo());
this.getIndex(),
this.fileInfo(), this.visibilityInfo());
};

@@ -41,7 +42,7 @@ Element.prototype.clone = function () {

this.value,
this.index,
this.currentFileInfo, this.visibilityInfo());
this.getIndex(),
this.fileInfo(), this.visibilityInfo());
};
Element.prototype.genCSS = function (context, output) {
output.add(this.toCSS(context), this.currentFileInfo, this.index);
output.add(this.toCSS(context), this.fileInfo(), this.getIndex());
};

@@ -48,0 +49,0 @@ Element.prototype.toCSS = function (context) {

@@ -7,10 +7,10 @@ var Node = require("./node"),

this.option = option;
this.index = index;
this.object_id = Extend.next_id++;
this.parent_ids = [this.object_id];
this.currentFileInfo = currentFileInfo || {};
this._index = index;
this._fileInfo = currentFileInfo;
this.copyVisibilityInfo(visibilityInfo);
this.allowRoot = true;
switch(option) {
switch (option) {
case "all":

@@ -25,2 +25,3 @@ this.allowBefore = true;

}
this.setParent(this.selector, this);
};

@@ -35,6 +36,6 @@ Extend.next_id = 0;

Extend.prototype.eval = function (context) {
return new Extend(this.selector.eval(context), this.option, this.index, this.currentFileInfo, this.visibilityInfo());
return new Extend(this.selector.eval(context), this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo());
};
Extend.prototype.clone = function (context) {
return new Extend(this.selector, this.option, this.index, this.currentFileInfo, this.visibilityInfo());
return new Extend(this.selector, this.option, this.getIndex(), this.fileInfo(), this.visibilityInfo());
};

@@ -41,0 +42,0 @@ //it concatenates (joins) all selectors in selector array

@@ -6,3 +6,5 @@ var Node = require("./node"),

Ruleset = require("./ruleset"),
Anonymous = require("./anonymous");
Anonymous = require("./anonymous"),
utils = require("../utils"),
LessError = require("../less-error");

@@ -23,6 +25,6 @@ //

this.options = options;
this.index = index;
this._index = index;
this._fileInfo = currentFileInfo;
this.path = path;
this.features = features;
this.currentFileInfo = currentFileInfo;
this.allowRoot = true;

@@ -34,3 +36,3 @@

var pathValue = this.getPath();
if (pathValue && /[#\.\&\?\/]css([\?;].*)?$/.test(pathValue)) {
if (pathValue && /[#\.\&\?]css([\?;].*)?$/.test(pathValue)) {
this.css = true;

@@ -40,2 +42,4 @@ }

this.copyVisibilityInfo(visibilityInfo);
this.setParent(this.features, this);
this.setParent(this.path, this);
};

@@ -59,3 +63,3 @@

this.path = visitor.visit(this.path);
if (!this.options.plugin && !this.options.inline && this.root) {
if (!this.options.isPlugin && !this.options.inline && this.root) {
this.root = visitor.visit(this.root);

@@ -65,4 +69,4 @@ }

Import.prototype.genCSS = function (context, output) {
if (this.css && this.path.currentFileInfo.reference === undefined) {
output.add("@import ", this.currentFileInfo, this.index);
if (this.css && this.path._fileInfo.reference === undefined) {
output.add("@import ", this._fileInfo, this._index);
this.path.genCSS(context, output);

@@ -98,7 +102,7 @@ if (this.features) {

return new Import(path.eval(context), this.features, this.options, this.index, this.currentFileInfo, this.visibilityInfo());
return new Import(path.eval(context), this.features, this.options, this._index, this._fileInfo, this.visibilityInfo());
};
Import.prototype.evalPath = function (context) {
var path = this.path.eval(context);
var rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
var rootpath = this._fileInfo && this._fileInfo.rootpath;

@@ -123,4 +127,4 @@ if (!(path instanceof URL)) {

result.forEach(function (node) {
node.addVisibilityBlock();
}
node.addVisibilityBlock();
}
);

@@ -137,3 +141,12 @@ } else {

if (this.options.plugin) {
if (this.options.isPlugin) {
if (this.root && this.root.eval) {
try {
this.root.eval(context);
}
catch (e) {
e.message = "Plugin error during evaluation";
throw new LessError(e, this.root.imports, this.root.filename);
}
}
registry = context.frames[0] && context.frames[0].functionRegistry;

@@ -143,2 +156,3 @@ if ( registry && this.root && this.root.functions ) {

}
return [];

@@ -157,10 +171,10 @@ }

var contents = new Anonymous(this.root, 0,
{
filename: this.importedFilename,
reference: this.path.currentFileInfo && this.path.currentFileInfo.reference
}, true, true);
{
filename: this.importedFilename,
reference: this.path._fileInfo && this.path._fileInfo.reference
}, true, true);
return this.features ? new Media([contents], this.features.value) : [contents];
} else if (this.css) {
var newImport = new Import(this.evalPath(context), features, this.options, this.index);
var newImport = new Import(this.evalPath(context), features, this.options, this._index);
if (!newImport.css && this.error) {

@@ -171,3 +185,3 @@ throw this.error;

} else {
ruleset = new Ruleset(null, this.root.rules.slice(0));
ruleset = new Ruleset(null, utils.copyArray(this.root.rules));
ruleset.evalImports(context);

@@ -174,0 +188,0 @@

@@ -1,2 +0,2 @@

var tree = {};
var tree = Object.create(null);

@@ -6,2 +6,4 @@ tree.Node = require('./node');

tree.Color = require('./color');
tree.AtRule = require('./atrule');
// Backwards compatibility
tree.Directive = require('./directive');

@@ -14,2 +16,3 @@ tree.DetachedRuleset = require('./detached-ruleset');

tree.Variable = require('./variable');
tree.Property = require('./property');
tree.Ruleset = require('./ruleset');

@@ -22,2 +25,4 @@ tree.Element = require('./element');

tree.Expression = require('./expression');
tree.Declaration = require('./declaration');
// Backwards compatibility
tree.Rule = require('./rule');

@@ -24,0 +29,0 @@ tree.Call = require('./call');

@@ -9,4 +9,4 @@ var JsEvalNode = require("./js-eval-node"),

this.expression = string;
this.index = index;
this.currentFileInfo = currentFileInfo;
this._index = index;
this._fileInfo = currentFileInfo;
};

@@ -21,3 +21,3 @@ JavaScript.prototype = new JsEvalNode();

} else if (typeof result === 'string') {
return new Quoted('"' + result + '"', result, this.escaped, this.index);
return new Quoted('"' + result + '"', result, this.escaped, this._index);
} else if (Array.isArray(result)) {

@@ -24,0 +24,0 @@ return new Anonymous(result.join(', '));

@@ -13,10 +13,10 @@ var Node = require("./node"),

if (context.javascriptEnabled !== undefined && !context.javascriptEnabled) {
throw { message: "You are using JavaScript, which has been disabled.",
filename: this.currentFileInfo.filename,
index: this.index };
if (!context.javascriptEnabled) {
throw { message: "Inline JavaScript is not enabled. Is it set in your options?",
filename: this.fileInfo().filename,
index: this.getIndex() };
}
expression = expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
return that.jsify(new Variable('@' + name, that.index, that.currentFileInfo).eval(context));
return that.jsify(new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context));
});

@@ -28,4 +28,4 @@

throw { message: "JavaScript evaluation error: " + e.message + " from `" + expression + "`" ,
filename: this.currentFileInfo.filename,
index: this.index };
filename: this.fileInfo().filename,
index: this.getIndex() };
}

@@ -50,4 +50,4 @@

throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message.replace(/["]/g, "'") + "'" ,
filename: this.currentFileInfo.filename,
index: this.index };
filename: this.fileInfo().filename,
index: this.getIndex() };
}

@@ -54,0 +54,0 @@ return result;

@@ -6,9 +6,10 @@ var Ruleset = require("./ruleset"),

Expression = require("./expression"),
Directive = require("./directive");
AtRule = require("./atrule"),
utils = require("../utils");
var Media = function (value, features, index, currentFileInfo, visibilityInfo) {
this.index = index;
this.currentFileInfo = currentFileInfo;
this._index = index;
this._fileInfo = currentFileInfo;
var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors();
var selectors = (new Selector([], null, null, this._index, this._fileInfo)).createEmptySelectors();

@@ -20,6 +21,9 @@ this.features = new Value(features);

this.allowRoot = true;
this.setParent(selectors, this);
this.setParent(this.features, this);
this.setParent(this.rules, this);
};
Media.prototype = new Directive();
Media.prototype = new AtRule();
Media.prototype.type = "Media";
Media.prototype.isRulesetLike = true;
Media.prototype.isRulesetLike = function() { return true; };
Media.prototype.accept = function (visitor) {

@@ -34,3 +38,3 @@ if (this.features) {

Media.prototype.genCSS = function (context, output) {
output.add('@media ', this.currentFileInfo, this.index);
output.add('@media ', this._fileInfo, this._index);
this.features.genCSS(context, output);

@@ -45,3 +49,3 @@ this.outputRuleset(context, output, this.rules);

var media = new Media(null, [], this.index, this.currentFileInfo, this.visibilityInfo());
var media = new Media(null, [], this._index, this._fileInfo, this.visibilityInfo());
if (this.debugInfo) {

@@ -83,6 +87,7 @@ this.rules[0].debugInfo = this.debugInfo;

if (context.mediaBlocks.length > 1) {
var selectors = (new Selector([], null, null, this.index, this.currentFileInfo)).createEmptySelectors();
var selectors = (new Selector([], null, null, this.getIndex(), this.fileInfo())).createEmptySelectors();
result = new Ruleset(selectors, context.mediaBlocks);
result.multiMedia = true;
result.copyVisibilityInfo(this.visibilityInfo());
this.setParent(result, this);
}

@@ -124,2 +129,3 @@

}));
this.setParent(this.features, this);

@@ -149,4 +155,5 @@ // Fake a tree-node that doesn't output anything.

}
this.rules = [new Ruleset(selectors.slice(0), [this.rules[0]])];
this.rules = [new Ruleset(utils.copyArray(selectors), [this.rules[0]])];
this.setParent(this.rules, this);
};
module.exports = Media;

@@ -9,6 +9,7 @@ var Node = require("./node"),

this.arguments = args || [];
this.index = index;
this.currentFileInfo = currentFileInfo;
this._index = index;
this._fileInfo = currentFileInfo;
this.important = important;
this.allowRoot = true;
this.setParent(this.selector, this);
};

@@ -121,3 +122,3 @@ MixinCall.prototype = new Node();

message: 'Ambiguous use of `default()` found when matching for `' + this.format(args) + '`',
index: this.index, filename: this.currentFileInfo.filename };
index: this.getIndex(), filename: this.fileInfo().filename };
}

@@ -140,3 +141,3 @@ }

} catch (e) {
throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
throw { message: e.message, index: this.getIndex(), filename: this.fileInfo().filename, stack: e.stack };
}

@@ -154,7 +155,7 @@ }

message: 'No matching definition was found for `' + this.format(args) + '`',
index: this.index, filename: this.currentFileInfo.filename };
index: this.getIndex(), filename: this.fileInfo().filename };
} else {
throw { type: 'Name',
message: this.selector.toCSS().trim() + " is undefined",
index: this.index, filename: this.currentFileInfo.filename };
index: this.getIndex(), filename: this.fileInfo().filename };
}

@@ -161,0 +162,0 @@ };

var Selector = require("./selector"),
Element = require("./element"),
Ruleset = require("./ruleset"),
Rule = require("./rule"),
Declaration = require("./declaration"),
Expression = require("./expression"),
contexts = require("../contexts");
contexts = require("../contexts"),
utils = require("../utils");
var Definition = function (name, params, rules, condition, variadic, frames, visibilityInfo) {
this.name = name;
this.selectors = [new Selector([new Element(null, name, this.index, this.currentFileInfo)])];
this.selectors = [new Selector([new Element(null, name, this._index, this._fileInfo)])];
this.params = params;

@@ -48,3 +49,3 @@ this.condition = condition;

varargs, arg,
params = this.params.slice(0),
params = utils.copyArray(this.params),
i, j, val, name, isNamedFound, argIndex, argsLength = 0;

@@ -58,3 +59,3 @@

if (args) {
args = args.slice(0);
args = utils.copyArray(args);
argsLength = args.length;

@@ -69,3 +70,3 @@

evaldArguments[j] = arg.value.eval(context);
frame.prependRule(new Rule(name, arg.value.eval(context)));
frame.prependRule(new Declaration(name, arg.value.eval(context)));
isNamedFound = true;

@@ -98,3 +99,3 @@ break;

}
frame.prependRule(new Rule(name, new Expression(varargs).eval(context)));
frame.prependRule(new Declaration(name, new Expression(varargs).eval(context)));
} else {

@@ -112,3 +113,3 @@ val = arg && arg.value;

frame.prependRule(new Rule(name, val));
frame.prependRule(new Declaration(name, val));
evaldArguments[i] = val;

@@ -140,3 +141,3 @@ }

Definition.prototype.eval = function (context) {
return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || context.frames.slice(0));
return new Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || utils.copyArray(context.frames));
};

@@ -149,5 +150,5 @@ Definition.prototype.evalCall = function (context, args, important) {

frame.prependRule(new Rule('@arguments', new Expression(_arguments).eval(context)));
frame.prependRule(new Declaration('@arguments', new Expression(_arguments).eval(context)));
rules = this.rules.slice(0);
rules = utils.copyArray(this.rules);

@@ -183,3 +184,3 @@ ruleset = new Ruleset(null, rules);

if (! this.variadic) {
if (!this.variadic) {
if (requiredArgsCnt < this.required) {

@@ -186,0 +187,0 @@ return false;

var Node = function() {
this.parent = null;
this.visibilityBlocks = undefined;
this.nodeVisible = undefined;
this.rootNode = null;
this.parsed = null;
var self = this;
Object.defineProperty(this, "currentFileInfo", {
get: function() { return self.fileInfo(); }
});
Object.defineProperty(this, "index", {
get: function() { return self.getIndex(); }
});
};
Node.prototype.setParent = function(nodes, parent) {
function set(node) {
if (node && node instanceof Node) {
node.parent = parent;
}
}
if (Array.isArray(nodes)) {
nodes.forEach(set);
}
else {
set(nodes);
}
};
Node.prototype.getIndex = function() {
return this._index || (this.parent && this.parent.getIndex()) || 0;
};
Node.prototype.fileInfo = function() {
return this._fileInfo || (this.parent && this.parent.fileInfo()) || {};
};
Node.prototype.isRulesetLike = function() { return false; };
Node.prototype.toCSS = function (context) {

@@ -4,0 +38,0 @@ var strs = [];

@@ -28,3 +28,3 @@ var Node = require("./node"),

throw { type: "Operation",
message: "Operation on an invalid type" };
message: "Operation on an invalid type" };
}

@@ -31,0 +31,0 @@

var Node = require("./node"),
JsEvalNode = require("./js-eval-node"),
Variable = require("./variable");
Variable = require("./variable"),
Property = require("./property");

@@ -9,4 +10,4 @@ var Quoted = function (str, content, escaped, index, currentFileInfo) {

this.quote = str.charAt(0);
this.index = index;
this.currentFileInfo = currentFileInfo;
this._index = index;
this._fileInfo = currentFileInfo;
};

@@ -17,3 +18,3 @@ Quoted.prototype = new JsEvalNode();

if (!this.escaped) {
output.add(this.quote, this.currentFileInfo, this.index);
output.add(this.quote, this.fileInfo(), this.getIndex());
}

@@ -33,6 +34,10 @@ output.add(this.value);

};
var interpolationReplacement = function (_, name) {
var v = new Variable('@' + name, that.index, that.currentFileInfo).eval(context, true);
var variableReplacement = function (_, name) {
var v = new Variable('@' + name, that.getIndex(), that.fileInfo()).eval(context, true);
return (v instanceof Quoted) ? v.value : v.toCSS();
};
var propertyReplacement = function (_, name) {
var v = new Property('$' + name, that.getIndex(), that.fileInfo()).eval(context, true);
return (v instanceof Quoted) ? v.value : v.toCSS();
};
function iterativeReplace(value, regexp, replacementFnc) {

@@ -47,4 +52,5 @@ var evaluatedValue = value;

value = iterativeReplace(value, /`([^`]+)`/g, javascriptReplacement);
value = iterativeReplace(value, /@\{([\w-]+)\}/g, interpolationReplacement);
return new Quoted(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo);
value = iterativeReplace(value, /@\{([\w-]+)\}/g, variableReplacement);
value = iterativeReplace(value, /\$\{([\w-]+)\}/g, propertyReplacement);
return new Quoted(this.quote + value + this.quote, value, this.escaped, this.getIndex(), this.fileInfo());
};

@@ -51,0 +57,0 @@ Quoted.prototype.compare = function (other) {

@@ -1,96 +0,12 @@

var Node = require("./node"),
Value = require("./value"),
Keyword = require("./keyword");
// Backwards compatibility shim for Rule (Declaration)
var Declaration = require("./declaration");
var Rule = function (name, value, important, merge, index, currentFileInfo, inline, variable) {
this.name = name;
this.value = (value instanceof Node) ? value : new Value([value]); //value instanceof tree.Value || value instanceof tree.Ruleset ??
this.important = important ? ' ' + important.trim() : '';
this.merge = merge;
this.index = index;
this.currentFileInfo = currentFileInfo;
this.inline = inline || false;
this.variable = (variable !== undefined) ? variable
: (name.charAt && (name.charAt(0) === '@'));
this.allowRoot = true;
var Rule = function () {
var args = Array.prototype.slice.call(arguments);
Declaration.apply(this, args);
};
function evalName(context, name) {
var value = "", i, n = name.length,
output = {add: function (s) {value += s;}};
for (i = 0; i < n; i++) {
name[i].eval(context).genCSS(context, output);
}
return value;
}
Rule.prototype = Object.create(Declaration.prototype);
Rule.prototype.constructor = Rule;
Rule.prototype = new Node();
Rule.prototype.type = "Rule";
Rule.prototype.genCSS = function (context, output) {
output.add(this.name + (context.compress ? ':' : ': '), this.currentFileInfo, this.index);
try {
this.value.genCSS(context, output);
}
catch(e) {
e.index = this.index;
e.filename = this.currentFileInfo.filename;
throw e;
}
output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? "" : ";"), this.currentFileInfo, this.index);
};
Rule.prototype.eval = function (context) {
var strictMathBypass = false, name = this.name, evaldValue, variable = this.variable;
if (typeof name !== "string") {
// expand 'primitive' name directly to get
// things faster (~10% for benchmark.less):
name = (name.length === 1) && (name[0] instanceof Keyword) ?
name[0].value : evalName(context, name);
variable = false; // never treat expanded interpolation as new variable name
}
if (name === "font" && !context.strictMath) {
strictMathBypass = true;
context.strictMath = true;
}
try {
context.importantScope.push({});
evaldValue = this.value.eval(context);
if (!this.variable && evaldValue.type === "DetachedRuleset") {
throw { message: "Rulesets cannot be evaluated on a property.",
index: this.index, filename: this.currentFileInfo.filename };
}
var important = this.important,
importantResult = context.importantScope.pop();
if (!important && importantResult.important) {
important = importantResult.important;
}
return new Rule(name,
evaldValue,
important,
this.merge,
this.index, this.currentFileInfo, this.inline,
variable);
}
catch(e) {
if (typeof e.index !== 'number') {
e.index = this.index;
e.filename = this.currentFileInfo.filename;
}
throw e;
}
finally {
if (strictMathBypass) {
context.strictMath = false;
}
}
};
Rule.prototype.makeImportant = function () {
return new Rule(this.name,
this.value,
"!important",
this.merge,
this.index, this.currentFileInfo, this.inline);
};
module.exports = Rule;
var Node = require("./node"),
Rule = require("./rule"),
Declaration = require("./declaration"),
Keyword = require("./keyword"),
Comment = require("./comment"),
Paren = require("./paren"),
Selector = require("./selector"),
Element = require("./element"),
Paren = require("./paren"),
Anonymous = require("./anonymous"),
contexts = require("../contexts"),
globalFunctionRegistry = require("../functions/function-registry"),
defaultFunc = require("../functions/default"),
getDebugInfo = require("./debug-info");
getDebugInfo = require("./debug-info"),
utils = require("../utils");

@@ -15,5 +19,11 @@ var Ruleset = function (selectors, rules, strictImports, visibilityInfo) {

this._lookups = {};
this._variables = null;
this._properties = null;
this.strictImports = strictImports;
this.copyVisibilityInfo(visibilityInfo);
this.allowRoot = true;
this.setParent(this.selectors, this);
this.setParent(this.rules, this);
};

@@ -23,3 +33,3 @@ Ruleset.prototype = new Node();

Ruleset.prototype.isRuleset = true;
Ruleset.prototype.isRulesetLike = true;
Ruleset.prototype.isRulesetLike = function() { return true; };
Ruleset.prototype.accept = function (visitor) {

@@ -40,3 +50,3 @@ if (this.paths) {

if (thisSelectors && (selCnt = thisSelectors.length)) {
selectors = [];
selectors = new Array(selCnt);
defaultFunc.error({

@@ -48,3 +58,3 @@ type: "Syntax",

selector = thisSelectors[i].eval(context);
selectors.push(selector);
selectors[i] = selector;
if (selector.evaldCondition) {

@@ -59,3 +69,3 @@ hasOnePassingSelector = true;

var rules = this.rules ? this.rules.slice(0) : null,
var rules = this.rules ? utils.copyArray(this.rules) : null,
ruleset = new Ruleset(selectors, rules, this.strictImports, this.visibilityInfo()),

@@ -108,6 +118,6 @@ rule, subRule;

// so they can be evaluated like closures when the time comes.
var rsRules = ruleset.rules, rsRuleCnt = rsRules ? rsRules.length : 0;
for (i = 0; i < rsRuleCnt; i++) {
if (rsRules[i].evalFirst) {
rsRules[i] = rsRules[i].eval(context);
var rsRules = ruleset.rules;
for (i = 0; (rule = rsRules[i]); i++) {
if (rule.evalFirst) {
rsRules[i] = rule.eval(context);
}

@@ -119,7 +129,7 @@ }

// Evaluate mixin calls.
for (i = 0; i < rsRuleCnt; i++) {
if (rsRules[i].type === "MixinCall") {
for (i = 0; (rule = rsRules[i]); i++) {
if (rule.type === "MixinCall") {
/*jshint loopfunc:true */
rules = rsRules[i].eval(context).filter(function(r) {
if ((r instanceof Rule) && r.variable) {
rules = rule.eval(context).filter(function(r) {
if ((r instanceof Declaration) && r.variable) {
// do not pollute the scope if the variable is

@@ -133,9 +143,8 @@ // already there. consider returning false here

rsRules.splice.apply(rsRules, [i, 1].concat(rules));
rsRuleCnt += rules.length - 1;
i += rules.length - 1;
ruleset.resetCache();
} else if (rsRules[i].type === "RulesetCall") {
} else if (rule.type === "RulesetCall") {
/*jshint loopfunc:true */
rules = rsRules[i].eval(context).rules.filter(function(r) {
if ((r instanceof Rule) && r.variable) {
rules = rule.eval(context).rules.filter(function(r) {
if ((r instanceof Declaration) && r.variable) {
// do not pollute the scope at all

@@ -147,3 +156,2 @@ return false;

rsRules.splice.apply(rsRules, [i, 1].concat(rules));
rsRuleCnt += rules.length - 1;
i += rules.length - 1;

@@ -155,4 +163,3 @@ ruleset.resetCache();

// Evaluate everything else
for (i = 0; i < rsRules.length; i++) {
rule = rsRules[i];
for (i = 0; (rule = rsRules[i]); i++) {
if (!rule.evalFirst) {

@@ -164,4 +171,3 @@ rsRules[i] = rule = rule.eval ? rule.eval(context) : rule;

// Evaluate everything else
for (i = 0; i < rsRules.length; i++) {
rule = rsRules[i];
for (i = 0; (rule = rsRules[i]); i++) {
// for rulesets, check if it is a css guard and can be removed

@@ -173,7 +179,8 @@ if (rule instanceof Ruleset && rule.selectors && rule.selectors.length === 1) {

for (var j = 0; j < rule.rules.length; j++) {
subRule = rule.rules[j];
subRule.copyVisibilityInfo(rule.visibilityInfo());
if (!(subRule instanceof Rule) || !subRule.variable) {
rsRules.splice(++i, 0, subRule);
for (var j = 0; (subRule = rule.rules[j]); j++) {
if (subRule instanceof Node) {
subRule.copyVisibilityInfo(rule.visibilityInfo());
if (!(subRule instanceof Declaration) || !subRule.variable) {
rsRules.splice(++i, 0, subRule);
}
}

@@ -206,3 +213,3 @@ }

rules.splice.apply(rules, [i, 1].concat(importRules));
i+= importRules.length - 1;
i += importRules.length - 1;
} else {

@@ -246,2 +253,3 @@ rules.splice(i, 1, importRules);

this._variables = null;
this._properties = null;
this._lookups = {};

@@ -252,3 +260,3 @@ };

this._variables = !this.rules ? {} : this.rules.reduce(function (hash, r) {
if (r instanceof Rule && r.variable === true) {
if (r instanceof Declaration && r.variable === true) {
hash[r.name] = r;

@@ -272,13 +280,77 @@ }

};
Ruleset.prototype.properties = function () {
if (!this._properties) {
this._properties = !this.rules ? {} : this.rules.reduce(function (hash, r) {
if (r instanceof Declaration && r.variable !== true) {
var name = (r.name.length === 1) && (r.name[0] instanceof Keyword) ?
r.name[0].value : r.name;
// Properties don't overwrite as they can merge
if (!hash['$' + name]) {
hash['$' + name] = [ r ];
}
else {
hash['$' + name].push(r);
}
}
return hash;
}, {});
}
return this._properties;
};
Ruleset.prototype.variable = function (name) {
return this.variables()[name];
var decl = this.variables()[name];
if (decl) {
return this.parseValue(decl);
}
};
Ruleset.prototype.property = function (name) {
var decl = this.properties()[name];
if (decl) {
return this.parseValue(decl);
}
};
Ruleset.prototype.parseValue = function(toParse) {
var self = this;
function transformDeclaration(decl) {
if (decl.value instanceof Anonymous && !decl.parsed) {
this.parse.parseNode(
decl.value.value,
["value", "important"],
decl.value.getIndex(),
decl.fileInfo(),
function(err, result) {
if (err) {
decl.parsed = true;
}
if (result) {
decl.value = result[0];
decl.important = result[1] || '';
decl.parsed = true;
}
});
return decl;
}
else {
return decl;
}
}
if (!Array.isArray(toParse)) {
return transformDeclaration.call(self, toParse);
}
else {
var nodes = [];
toParse.forEach(function(n) {
nodes.push(transformDeclaration.call(self, n));
});
return nodes;
}
};
Ruleset.prototype.rulesets = function () {
if (!this.rules) { return []; }
var filtRules = [], rules = this.rules, cnt = rules.length,
var filtRules = [], rules = this.rules,
i, rule;
for (i = 0; i < cnt; i++) {
rule = rules[i];
for (i = 0; (rule = rules[i]); i++) {
if (rule.isRuleset) {

@@ -298,2 +370,3 @@ filtRules.push(rule);

}
this.setParent(rule, this);
};

@@ -349,21 +422,6 @@ Ruleset.prototype.find = function (selector, self, filter) {

function isRulesetLikeNode(rule) {
// if it has nested rules, then it should be treated like a ruleset
// medias and comments do not have nested rules, but should be treated like rulesets anyway
// some directives and anonymous nodes are ruleset like, others are not
if (typeof rule.isRulesetLike === "boolean") {
return rule.isRulesetLike;
} else if (typeof rule.isRulesetLike === "function") {
return rule.isRulesetLike();
}
//anything else is assumed to be a rule
return false;
}
var charsetNodeIndex = 0;
var importNodeIndex = 0;
for (i = 0; i < this.rules.length; i++) {
rule = this.rules[i];
if (rule.type === "Comment") {
for (i = 0; (rule = this.rules[i]); i++) {
if (rule instanceof Comment) {
if (importNodeIndex === i) {

@@ -419,4 +477,3 @@ importNodeIndex++;

// Compile rules and rulesets
for (i = 0; i < ruleNodes.length; i++) {
rule = ruleNodes[i];
for (i = 0; (rule = ruleNodes[i]); i++) {

@@ -428,3 +485,3 @@ if (i + 1 === ruleNodes.length) {

var currentLastRule = context.lastRule;
if (isRulesetLikeNode(rule)) {
if (rule.isRulesetLike(rule)) {
context.lastRule = false;

@@ -441,3 +498,3 @@ }

if (!context.lastRule) {
if (!context.lastRule && rule.isVisible()) {
output.add(context.compress ? '' : ('\n' + tabRuleStr));

@@ -472,5 +529,5 @@ } else {

} else {
var insideParent = [];
var insideParent = new Array(elementsToPak.length);
for (j = 0; j < elementsToPak.length; j++) {
insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo));
insideParent[j] = new Element(null, elementsToPak[j], originalElement._index, originalElement._fileInfo);
}

@@ -484,3 +541,3 @@ replacementParen = new Paren(new Selector(insideParent));

var element, selector;
element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo);
element = new Element(null, containedElement, originalElement._index, originalElement._fileInfo);
selector = new Selector([element]);

@@ -501,5 +558,5 @@ return selector;

if (beginningPath.length > 0) {
newSelectorPath = beginningPath.slice(0);
newSelectorPath = utils.copyArray(beginningPath);
lastSelector = newSelectorPath.pop();
newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
newJoinedSelector = originalSelector.createDerived(utils.copyArray(lastSelector.elements));
}

@@ -520,3 +577,3 @@ else {

// join the elements so far with the first part of the parent
newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement.index, replacedElement.currentFileInfo));
newJoinedSelector.elements.push(new Element(combinator, parentEl.value, replacedElement._index, replacedElement._fileInfo));
newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));

@@ -564,5 +621,3 @@ }

for (i = 0; i < selectors.length; i++) {
sel = selectors[i];
for (i = 0; (sel = selectors[i]); i++) {
// if the previous thing in sel is a parent this needs to join on to it

@@ -595,3 +650,3 @@ if (sel.length > 0) {

var maybeSelector;
if (element.value.type !== 'Paren') {
if (!(element.value instanceof Paren)) {
return null;

@@ -601,3 +656,3 @@ }

maybeSelector = element.value.value;
if (maybeSelector.type !== 'Selector') {
if (!(maybeSelector instanceof Selector)) {
return null;

@@ -618,4 +673,3 @@ }

for (i = 0; i < inSelector.elements.length; i++) {
el = inSelector.elements[i];
for (i = 0; (el = inSelector.elements[i]); i++) {
// non parent reference elements just get added

@@ -662,3 +716,3 @@ if (el.value !== "&") {

if (sel.length > 0) {
sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
sel[0].elements.push(new Element(el.combinator, '', el._index, el._fileInfo));
}

@@ -695,3 +749,2 @@ selectorsMultiplied.push(sel);

newSelectors[i][length - 1] = lastSelector.createDerived(lastSelector.elements, inSelector.extendList);
//newSelectors[i][length - 1].copyVisibilityInfo(inSelector.visibilityInfo());
}

@@ -719,8 +772,3 @@ }

for (i = 0; i < context.length; i++) {
//var concatenated = [];
//context[i].forEach(function(entry) {
// var newEntry = entry.createDerived(entry.elements, entry.extendList, entry.evaldCondition);
// newEntry.copyVisibilityInfo(selector.visibilityInfo());
// concatenated.push(newEntry);
//}, this);
var concatenated = context[i].map(deriveSelector.bind(this, selector.visibilityInfo()));

@@ -727,0 +775,0 @@

var Node = require("./node"),
Element = require("./element");
Element = require("./element"),
LessError = require("../less-error");
var Selector = function (elements, extendList, condition, index, currentFileInfo, visibilityInfo) {
this.elements = elements;
this.extendList = extendList;
this.condition = condition;
this.currentFileInfo = currentFileInfo || {};
this._index = index;
this._fileInfo = currentFileInfo;
this.elements = this.getElements(elements);
if (!condition) {

@@ -13,2 +15,3 @@ this.evaldCondition = true;

this.copyVisibilityInfo(visibilityInfo);
this.setParent(this.elements, this);
};

@@ -29,5 +32,6 @@ Selector.prototype = new Node();

Selector.prototype.createDerived = function(elements, extendList, evaldCondition) {
elements = this.getElements(elements);
var info = this.visibilityInfo();
evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
var newSelector = new Selector(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, info);
var newSelector = new Selector(elements, extendList || this.extendList, null, this.getIndex(), this.fileInfo(), info);
newSelector.evaldCondition = evaldCondition;

@@ -37,5 +41,24 @@ newSelector.mediaEmpty = this.mediaEmpty;

};
Selector.prototype.getElements = function(els) {
if (typeof els === "string") {
this.parse.parseNode(
els,
["selector"],
this._index,
this._fileInfo,
function(err, result) {
if (err) {
throw new LessError({
index: err.index,
message: err.message
}, this.parse.imports, this._fileInfo.filename);
}
els = result[0].elements;
});
}
return els;
};
Selector.prototype.createEmptySelectors = function() {
var el = new Element('', '&', this.index, this.currentFileInfo),
sels = [new Selector([el], null, null, this.index, this.currentFileInfo)];
var el = new Element('', '&', this._index, this._fileInfo),
sels = [new Selector([el], null, null, this._index, this._fileInfo)];
sels[0].mediaEmpty = true;

@@ -49,3 +72,3 @@ return sels;

other.CacheElements();
other.cacheElements();

@@ -65,3 +88,3 @@ olen = other._elements.length;

};
Selector.prototype.CacheElements = function() {
Selector.prototype.cacheElements = function() {
if (this._elements) {

@@ -103,3 +126,3 @@ return;

if ((!context || !context.firstSelector) && this.elements[0].combinator.value === "") {
output.add(' ', this.currentFileInfo, this.index);
output.add(' ', this.fileInfo(), this.getIndex());
}

@@ -106,0 +129,0 @@ if (!this._css) {

var Node = require("./node"),
unitConversions = require("../data/unit-conversions");
unitConversions = require("../data/unit-conversions"),
utils = require("../utils");
var Unit = function (numerator, denominator, backupUnit) {
this.numerator = numerator ? numerator.slice(0).sort() : [];
this.denominator = denominator ? denominator.slice(0).sort() : [];
this.numerator = numerator ? utils.copyArray(numerator).sort() : [];
this.denominator = denominator ? utils.copyArray(denominator).sort() : [];
if (backupUnit) {

@@ -17,3 +18,3 @@ this.backupUnit = backupUnit;

Unit.prototype.clone = function () {
return new Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
return new Unit(utils.copyArray(this.numerator), utils.copyArray(this.denominator), this.backupUnit);
};

@@ -20,0 +21,0 @@ Unit.prototype.genCSS = function (context, output) {

@@ -5,4 +5,4 @@ var Node = require("./node");

this.value = val;
this.currentFileInfo = currentFileInfo;
this.index = index;
this._index = index;
this._fileInfo = currentFileInfo;
this.isEvald = isEvald;

@@ -26,3 +26,3 @@ };

// Add the base path if the URL is relative
rootpath = this.currentFileInfo && this.currentFileInfo.rootpath;
rootpath = this.fileInfo() && this.fileInfo().rootpath;
if (rootpath &&

@@ -54,4 +54,4 @@ typeof val.value === "string" &&

return new URL(val, this.index, this.currentFileInfo, true);
return new URL(val, this.getIndex(), this.fileInfo(), true);
};
module.exports = URL;
var Node = require("./node");
var Value = function (value) {
this.value = value;
if (!value) {
throw new Error("Value requires an array argument");
}
if (!Array.isArray(value)) {
this.value = [ value ];
}
else {
this.value = value;
}
};

@@ -9,0 +14,0 @@ Value.prototype = new Node();

@@ -5,4 +5,4 @@ var Node = require("./node");

this.name = name;
this.index = index;
this.currentFileInfo = currentFileInfo || {};
this._index = index;
this._fileInfo = currentFileInfo;
};

@@ -15,3 +15,3 @@ Variable.prototype = new Node();

if (name.indexOf('@@') === 0) {
name = '@' + new Variable(name.slice(1), this.index, this.currentFileInfo).eval(context).value;
name = '@' + new Variable(name.slice(1), this.getIndex(), this.fileInfo()).eval(context).value;
}

@@ -21,5 +21,5 @@

throw { type: 'Name',
message: "Recursive variable definition for " + name,
filename: this.currentFileInfo.filename,
index: this.index };
message: "Recursive variable definition for " + name,
filename: this.fileInfo().filename,
index: this.getIndex() };
}

@@ -44,5 +44,5 @@

throw { type: 'Name',
message: "variable " + name + " is undefined",
filename: this.currentFileInfo.filename,
index: this.index };
message: "variable " + name + " is undefined",
filename: this.fileInfo().filename,
index: this.getIndex() };
}

@@ -49,0 +49,0 @@ };

@@ -0,1 +1,2 @@

/* jshint proto: true */
module.exports = {

@@ -19,3 +20,25 @@ getLocation: function(index, inputStream) {

};
},
copyArray: function(arr) {
var i, length = arr.length,
copy = new Array(length);
for (i = 0; i < length; i++) {
copy[i] = arr[i];
}
return copy;
},
getPrototype: function(obj) {
if (Object.getPrototypeOf) {
return Object.getPrototypeOf(obj);
}
else {
if ("".__proto__ === String.prototype) {
return obj.__proto__;
}
else if (obj.constructor) {
return obj.constructor.prototype;
}
}
}
};
var tree = require("../tree"),
Visitor = require("./visitor"),
logger = require("../logger");
logger = require("../logger"),
utils = require("../utils");

@@ -19,3 +20,3 @@ /*jshint loopfunc:true */

},
visitRule: function (ruleNode, visitArgs) {
visitDeclaration: function (declNode, visitArgs) {
visitArgs.visitDeeper = false;

@@ -50,3 +51,3 @@ },

extendList = selExtendList ? selExtendList.slice(0).concat(allSelectorsExtendList)
extendList = selExtendList ? utils.copyArray(selExtendList).concat(allSelectorsExtendList)
: allSelectorsExtendList;

@@ -84,7 +85,7 @@

},
visitDirective: function (directiveNode, visitArgs) {
directiveNode.allExtends = [];
this.allExtendsStack.push(directiveNode.allExtends);
visitAtRule: function (atRuleNode, visitArgs) {
atRuleNode.allExtends = [];
this.allExtendsStack.push(atRuleNode.allExtends);
},
visitDirectiveOut: function (directiveNode) {
visitAtRuleOut: function (atRuleNode) {
this.allExtendsStack.length = this.allExtendsStack.length - 1;

@@ -115,13 +116,13 @@ }

}).forEach(function(extend) {
var selector = "_unknown_";
try {
selector = extend.selector.toCSS({});
}
catch(_) {}
var selector = "_unknown_";
try {
selector = extend.selector.toCSS({});
}
catch (_) {}
if (!indices[extend.index + ' ' + selector]) {
indices[extend.index + ' ' + selector] = true;
logger.warn("extend '" + selector + "' has no matches");
}
});
if (!indices[extend.index + ' ' + selector]) {
indices[extend.index + ' ' + selector] = true;
logger.warn("extend '" + selector + "' has no matches");
}
});
},

@@ -173,3 +174,3 @@ doExtendChaining: function (extendsList, extendsListTarget, iterationCount) {

// but now we create a new extend from it
newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.currentFileInfo, info);
newExtend = new(tree.Extend)(targetExtend.selector, targetExtend.option, 0, targetExtend.fileInfo(), info);
newExtend.selfSelectors = newSelector;

@@ -210,3 +211,3 @@

}
catch(e) {}
catch (e) {}
throw { message: "extend circular reference detected. One of the circular extends is currently:" +

@@ -223,3 +224,3 @@ selectorOne + ":extend(" + selectorTwo + ")"};

},
visitRule: function (ruleNode, visitArgs) {
visitDeclaration: function (ruleNode, visitArgs) {
visitArgs.visitDeeper = false;

@@ -394,4 +395,4 @@ },

replacementSelector.elements[0].value,
replacementSelector.elements[0].index,
replacementSelector.elements[0].currentFileInfo
replacementSelector.elements[0].getIndex(),
replacementSelector.elements[0].fileInfo()
);

@@ -457,8 +458,8 @@

},
visitDirective: function (directiveNode, visitArgs) {
var newAllExtends = directiveNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, directiveNode.allExtends));
visitAtRule: function (atRuleNode, visitArgs) {
var newAllExtends = atRuleNode.allExtends.concat(this.allExtendsStack[this.allExtendsStack.length - 1]);
newAllExtends = newAllExtends.concat(this.doExtendChaining(newAllExtends, atRuleNode.allExtends));
this.allExtendsStack.push(newAllExtends);
},
visitDirectiveOut: function (directiveNode) {
visitAtRuleOut: function (atRuleNode) {
var lastIndex = this.allExtendsStack.length - 1;

@@ -465,0 +466,0 @@ this.allExtendsStack.length = lastIndex;

var contexts = require("../contexts"),
Visitor = require("./visitor"),
ImportSequencer = require("./import-sequencer");
ImportSequencer = require("./import-sequencer"),
utils = require("../utils");

@@ -24,3 +25,3 @@ var ImportVisitor = function(importer, finish) {

}
catch(e) {
catch (e) {
this.error = e;

@@ -43,3 +44,3 @@ }

var context = new contexts.Eval(this.context, this.context.frames.slice(0));
var context = new contexts.Eval(this.context, utils.copyArray(this.context.frames));
var importParent = context.frames[0];

@@ -62,4 +63,4 @@

evaldImportNode = importNode.evalForImport(context);
} catch(e) {
if (!e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
} catch (e) {
if (!e.filename) { e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename; }
// attempt to eval properly and treat as css

@@ -90,3 +91,3 @@ importNode.css = true;

this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.currentFileInfo,
this._importer.push(evaldImportNode.getPath(), tryAppendLessExtension, evaldImportNode.fileInfo(),
evaldImportNode.options, sequencedOnImported);

@@ -103,3 +104,3 @@ } else {

if (!e.filename) {
e.index = importNode.index; e.filename = importNode.currentFileInfo.filename;
e.index = importNode.getIndex(); e.filename = importNode.fileInfo().filename;
}

@@ -111,3 +112,3 @@ this.error = e;

inlineCSS = importNode.options.inline,
isPlugin = importNode.options.plugin,
isPlugin = importNode.options.isPlugin,
isOptional = importNode.options.optional,

@@ -158,5 +159,5 @@ duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;

},
visitRule: function (ruleNode, visitArgs) {
if (ruleNode.value.type === "DetachedRuleset") {
this.context.frames.unshift(ruleNode);
visitDeclaration: function (declNode, visitArgs) {
if (declNode.value.type === "DetachedRuleset") {
this.context.frames.unshift(declNode);
} else {

@@ -166,11 +167,11 @@ visitArgs.visitDeeper = false;

},
visitRuleOut : function(ruleNode) {
if (ruleNode.value.type === "DetachedRuleset") {
visitDeclarationOut: function(declNode) {
if (declNode.value.type === "DetachedRuleset") {
this.context.frames.shift();
}
},
visitDirective: function (directiveNode, visitArgs) {
this.context.frames.unshift(directiveNode);
visitAtRule: function (atRuleNode, visitArgs) {
this.context.frames.unshift(atRuleNode);
},
visitDirectiveOut: function (directiveNode) {
visitAtRuleOut: function (atRuleNode) {
this.context.frames.shift();

@@ -177,0 +178,0 @@ },

@@ -12,3 +12,3 @@ var Visitor = require("./visitor");

},
visitRule: function (ruleNode, visitArgs) {
visitDeclaration: function (declNode, visitArgs) {
visitArgs.visitDeeper = false;

@@ -26,3 +26,3 @@ },

if (! rulesetNode.root) {
if (!rulesetNode.root) {
selectors = rulesetNode.selectors;

@@ -45,6 +45,6 @@ if (selectors) {

},
visitDirective: function (directiveNode, visitArgs) {
visitAtRule: function (atRuleNode, visitArgs) {
var context = this.contexts[this.contexts.length - 1];
if (directiveNode.rules && directiveNode.rules.length) {
directiveNode.rules[0].root = (directiveNode.isRooted || context.length === 0 || null);
if (atRuleNode.rules && atRuleNode.rules.length) {
atRuleNode.rules[0].root = (atRuleNode.isRooted || context.length === 0 || null);
}

@@ -51,0 +51,0 @@ }

@@ -18,3 +18,3 @@ var tree = require("../tree"),

if (rule.isSilent && rule.isSilent(this._context) && !rule.blocksVisibility()) {
//the directive contains something that was referenced (likely by extend)
//the atrule contains something that was referenced (likely by extend)
//therefore it needs to be shown in output too

@@ -33,4 +33,4 @@ return true;

owner.rules = owner.rules.filter(function(thing) {
return thing.isVisible();
}
return thing.isVisible();
}
);

@@ -105,7 +105,7 @@ },

visitRule: function (ruleNode, visitArgs) {
if (ruleNode.blocksVisibility() || ruleNode.variable) {
visitDeclaration: function (declNode, visitArgs) {
if (declNode.blocksVisibility() || declNode.variable) {
return;
}
return ruleNode;
return declNode;
},

@@ -144,20 +144,20 @@

visitDirective: function(directiveNode, visitArgs) {
if (directiveNode.rules && directiveNode.rules.length) {
return this.visitDirectiveWithBody(directiveNode, visitArgs);
visitAtRule: function(atRuleNode, visitArgs) {
if (atRuleNode.rules && atRuleNode.rules.length) {
return this.visitAtRuleWithBody(atRuleNode, visitArgs);
} else {
return this.visitDirectiveWithoutBody(directiveNode, visitArgs);
return this.visitAtRuleWithoutBody(atRuleNode, visitArgs);
}
},
visitDirectiveWithBody: function(directiveNode, visitArgs) {
visitAtRuleWithBody: function(atRuleNode, visitArgs) {
//if there is only one nested ruleset and that one has no path, then it is
//just fake ruleset
function hasFakeRuleset(directiveNode) {
var bodyRules = directiveNode.rules;
function hasFakeRuleset(atRuleNode) {
var bodyRules = atRuleNode.rules;
return bodyRules.length === 1 && (!bodyRules[0].paths || bodyRules[0].paths.length === 0);
}
function getBodyRules(directiveNode) {
var nodeRules = directiveNode.rules;
if (hasFakeRuleset(directiveNode)) {
function getBodyRules(atRuleNode) {
var nodeRules = atRuleNode.rules;
if (hasFakeRuleset(atRuleNode)) {
return nodeRules[0].rules;

@@ -171,26 +171,26 @@ }

//process childs
var originalRules = getBodyRules(directiveNode);
directiveNode.accept(this._visitor);
var originalRules = getBodyRules(atRuleNode);
atRuleNode.accept(this._visitor);
visitArgs.visitDeeper = false;
if (!this.utils.isEmpty(directiveNode)) {
this._mergeRules(directiveNode.rules[0].rules);
if (!this.utils.isEmpty(atRuleNode)) {
this._mergeRules(atRuleNode.rules[0].rules);
}
return this.utils.resolveVisibility(directiveNode, originalRules);
return this.utils.resolveVisibility(atRuleNode, originalRules);
},
visitDirectiveWithoutBody: function(directiveNode, visitArgs) {
if (directiveNode.blocksVisibility()) {
visitAtRuleWithoutBody: function(atRuleNode, visitArgs) {
if (atRuleNode.blocksVisibility()) {
return;
}
if (directiveNode.name === "@charset") {
if (atRuleNode.name === "@charset") {
// Only output the debug info together with subsequent @charset definitions
// a comment (or @media statement) before the actual @charset directive would
// a comment (or @media statement) before the actual @charset atrule would
// be considered illegal css as it has to be on the first line
if (this.charset) {
if (directiveNode.debugInfo) {
var comment = new tree.Comment("/* " + directiveNode.toCSS(this._context).replace(/\n/g, "") + " */\n");
comment.debugInfo = directiveNode.debugInfo;
if (atRuleNode.debugInfo) {
var comment = new tree.Comment("/* " + atRuleNode.toCSS(this._context).replace(/\n/g, "") + " */\n");
comment.debugInfo = atRuleNode.debugInfo;
return this._visitor.visit(comment);

@@ -203,3 +203,3 @@ }

return directiveNode;
return atRuleNode;
},

@@ -214,13 +214,13 @@

var ruleNode = rules[i];
if (isRoot && ruleNode instanceof tree.Rule && !ruleNode.variable) {
if (isRoot && ruleNode instanceof tree.Declaration && !ruleNode.variable) {
throw { message: "Properties must be inside selector blocks. They cannot be in the root",
index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename};
}
if (ruleNode instanceof tree.Call) {
throw { message: "Function '" + ruleNode.name + "' is undefined",
index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename};
}
if (ruleNode.type && !ruleNode.allowRoot) {
throw { message: ruleNode.type + " node returned by a function is not valid here",
index: ruleNode.index, filename: ruleNode.currentFileInfo && ruleNode.currentFileInfo.filename};
index: ruleNode.getIndex(), filename: ruleNode.fileInfo() && ruleNode.fileInfo().filename};
}

@@ -236,3 +236,3 @@ }

if (! rulesetNode.root) {
if (!rulesetNode.root) {
//remove invisible paths

@@ -313,3 +313,3 @@ this._compileRulesetPaths(rulesetNode);

rule = rules[i];
if (rule instanceof tree.Rule) {
if (rule instanceof tree.Declaration) {
if (!ruleCache[rule.name]) {

@@ -319,3 +319,3 @@ ruleCache[rule.name] = rule;

ruleList = ruleCache[rule.name];
if (ruleList instanceof tree.Rule) {
if (ruleList instanceof tree.Declaration) {
ruleList = ruleCache[rule.name] = [ruleCache[rule.name].toCSS(this._context)];

@@ -345,3 +345,3 @@ }

if ((rule instanceof tree.Rule) && rule.merge) {
if ((rule instanceof tree.Declaration) && rule.merge) {
key = [rule.name,

@@ -348,0 +348,0 @@ rule.important ? "!" : ""].join(",");

@@ -13,17 +13,17 @@ var tree = require("../tree");

var key, child;
for (key in parent) {
if (parent.hasOwnProperty(key)) {
child = parent[key];
switch (typeof child) {
case "function":
// ignore bound functions directly on tree which do not have a prototype
// or aren't nodes
if (child.prototype && child.prototype.type) {
child.prototype.typeIndex = ticker++;
}
break;
case "object":
ticker = indexNodeTypes(child, ticker);
break;
}
for (key in parent) {
/*eslint guard-for-in: 0 */
child = parent[key];
switch (typeof child) {
case "function":
// ignore bound functions directly on tree which do not have a prototype
// or aren't nodes
if (child.prototype && child.prototype.type) {
child.prototype.typeIndex = ticker++;
}
break;
case "object":
ticker = indexNodeTypes(child, ticker);
break;
}

@@ -30,0 +30,0 @@ }

{
"name": "less",
"version": "2.7.1",
"version": "3.0.0-alpha.1",
"description": "Leaner CSS",

@@ -52,4 +52,5 @@ "homepage": "http://lesscss.org",

"devDependencies": {
"diff": "^2.2.2",
"grunt": "^1.0.1",
"diff": "^3.2.0",
"git-rev": "^0.2.1",
"grunt": "~0.4.5",
"grunt-browserify": "^5.0.0",

@@ -60,8 +61,11 @@ "grunt-contrib-clean": "^1.0.0",

"grunt-contrib-jasmine": "^1.0.3",
"grunt-contrib-jshint": "^1.0.0",
"grunt-contrib-uglify": "^1.0.1",
"grunt-jscs": "^2.8.0",
"grunt-saucelabs": "^8.6.2",
"grunt-eslint": "^19.0.0",
"grunt-saucelabs": "^9.0.0",
"grunt-shell": "^1.3.0",
"jit-grunt": "^0.10.0",
"performance-now": "^0.2.0",
"phantomjs-prebuilt": "^2.1.7",
"promise": "^7.1.1",
"request": "^2.73.0",
"time-grunt": "^1.3.0"

@@ -95,3 +99,4 @@ },

"rawcurrent": "https://raw.github.com/less/less.js/v",
"sourcearchive": "https://github.com/less/less.js/archive/v"
"sourcearchive": "https://github.com/less/less.js/archive/v",
"dependencies": {}
}
[![npm version](https://badge.fury.io/js/less.svg)](http://badge.fury.io/js/less) [![Build Status](https://travis-ci.org/less/less.js.svg?branch=master)](https://travis-ci.org/less/less.js)
[![Dependencies](https://david-dm.org/less/less.js.svg)](https://david-dm.org/less/less.js) [![devDependency Status](https://david-dm.org/less/less.js/dev-status.svg)](https://david-dm.org/less/less.js#info=devDependencies) [![optionalDependency Status](https://david-dm.org/less/less.js/optional-status.svg)](https://david-dm.org/less/less.js#info=optionalDependencies)
[![Sauce Test Status](https://saucelabs.com/browser-matrix/less.svg)](https://saucelabs.com/u/less) [![Build status](https://ci.appveyor.com/api/projects/status/bx2qspy3qbuxpl9q/branch/master?svg=true)](https://ci.appveyor.com/project/lukeapage/less-js/branch/master)
[![Sauce Test Status](https://saucelabs.com/browser-matrix/less.svg)](https://saucelabs.com/u/less) [![Build status](https://ci.appveyor.com/api/projects/status/bx2qspy3qbuxpl9q/branch/3.x?svg=true)](https://ci.appveyor.com/project/lukeapage/less-js/branch/3.x)

@@ -5,0 +5,0 @@ # [Less.js](http://lesscss.org)

/* Add js reporter for sauce */
jasmine.getEnv().addReporter(new jasmine.JSReporter2());
jasmine.getEnv().defaultTimeoutInterval = 3000;
// From https://github.com/axemclion/grunt-saucelabs/issues/109#issuecomment-166767282
// (function () {
// var oldJSReport = window.jasmine.getJSReport;
// window.jasmine.getJSReport = function () {
// var results = oldJSReport();
// if (results) {
// return {
// durationSec: results.durationSec,
// suites: removePassingTests(results.suites),
// passed: results.passed
// };
// } else {
// return null;
// }
// };
// function removePassingTests (suites) {
// return suites.filter(specFailed)
// .map(mapSuite);
// }
// function mapSuite (suite) {
// var result = {};
// for (var s in suite) {
// result[s] = suite[s];
// }
// result.specs = suite.specs.filter(specFailed);
// result.suites = removePassingTests(suite.suites);
// return result;
// }
// function specFailed (item) {
// return !item.passed;
// }
// })();
/* record log messages for testing */

@@ -47,11 +83,11 @@

var testLessEqualsInDocument = function () {
testLessEqualsInDocument = function () {
testLessInDocument(testSheet);
};
var testLessErrorsInDocument = function (isConsole) {
testLessErrorsInDocument = function (isConsole) {
testLessInDocument(isConsole ? testErrorSheetConsole : testErrorSheet);
};
var testLessInDocument = function (testFunc) {
testLessInDocument = function (testFunc) {
var links = document.getElementsByTagName('link'),

@@ -68,3 +104,3 @@ typePattern = /^text\/(x-)?less$/;

var ieFormat = function(text) {
ieFormat = function(text) {
var styleNode = document.createElement('style');

@@ -88,3 +124,3 @@ styleNode.setAttribute('type', 'text/css');

var testSheet = function (sheet) {
testSheet = function (sheet) {
it(sheet.id + " should match the expected output", function (done) {

@@ -128,3 +164,3 @@ var lessOutputId = sheet.id.replace("original-", ""),

var waitFor = function (waitFunc) {
waitFor = function (waitFunc) {
return new Promise(function (resolve) {

@@ -140,3 +176,3 @@ var timeoutId = setInterval(function () {

var testErrorSheet = function (sheet) {
testErrorSheet = function (sheet) {
it(sheet.id + " should match an error", function (done) {

@@ -155,3 +191,3 @@ var lessHref = sheet.href,

}).then(function () {
var innerText = (actualErrorElement.innerHTML
var innerText = (actualErrorElement.innerHTML
.replace(/<h3>|<\/?p>|<a href="[^"]*">|<\/a>|<ul>|<\/?pre( class="?[^">]*"?)?>|<\/li>|<\/?label>/ig, "")

@@ -164,3 +200,3 @@ .replace(/<\/h3>/ig, " ")

.replace(/\. \nin/, ". in");
actualErrorMsg = innerText
actualErrorMsg = innerText
.replace(/\n\d+/g, function (lineNo) {

@@ -172,4 +208,5 @@ return lineNo + " ";

.replace(/\nStack Trace\n[\s\S]*/i, "")
.replace(/\n$/, "");
errorFile
.replace(/\n$/, "")
.trim();
errorFile
.then(function (errorTxt) {

@@ -181,4 +218,5 @@ errorTxt = errorTxt

.replace(/\{404status\}/g, " (404)")
.replace(/\{node\}.*\{\/node\}/g, "")
.replace(/\n$/, "");
.replace(/\{node\}[\s\S]*\{\/node\}/g, "")
.replace(/\n$/, "")
.trim();
expect(actualErrorMsg).toEqual(errorTxt);

@@ -190,7 +228,7 @@ if (errorTxt == actualErrorMsg) {

});
});
});
});
};
var testErrorSheetConsole = function (sheet) {
testErrorSheetConsole = function (sheet) {
it(sheet.id + " should match an error", function (done) {

@@ -224,3 +262,3 @@ var lessHref = sheet.href,

var loadFile = function (href) {
loadFile = function (href) {
return new Promise(function (resolve, reject) {

@@ -227,0 +265,0 @@ var request = new XMLHttpRequest();

@@ -45,3 +45,3 @@ /*

* @return Elapsed time in Seconds */
function elapsedSec (startMs, finishMs) {
function elapsedSec(startMs, finishMs) {
return (finishMs - startMs) / 1000;

@@ -56,3 +56,3 @@ }

* @return Rounded amount */
function round (amount, numOfDecDigits) {
function round(amount, numOfDecDigits) {
numOfDecDigits = numOfDecDigits || 2;

@@ -66,3 +66,3 @@ return Math.round(amount * Math.pow(10, numOfDecDigits)) / Math.pow(10, numOfDecDigits);

* @returns {Array} of failed items */
function failures (items) {
function failures(items) {
var fs = [], i, v;

@@ -82,3 +82,3 @@ for (i = 0; i < items.length; i += 1) {

*/
function getSuiteData (suite) {
function getSuiteData(suite) {
var suiteData = {

@@ -85,0 +85,0 @@ description : suite.description,

@@ -1,2 +0,2 @@

var less = {logLevel: 4, errorReporting: "console"};
var less = {logLevel: 4, errorReporting: "console", javascriptEnabled: true};

@@ -3,0 +3,0 @@ // There originally run inside describe method. However, since they have not

var less = {
strictUnits: true,
strictMath: true,
logLevel: 4 };
logLevel: 4,
javascriptEnabled: true
};

@@ -1,4 +0,5 @@

var less = {logLevel: 4,
var less = {
logLevel: 4,
errorReporting: "console",
plugins: [AddFilePlugin]
};
};

@@ -20,4 +20,4 @@ var alreadyRun = false;

}).then(function () {
done();
});
done();
});
});

@@ -24,0 +24,0 @@ });

@@ -6,52 +6,48 @@ var lessTest = require("./less-test"),

function getErrorPathReplacementFunction(dir) {
return function(input, baseDir) {
return input.replace(/\{path\}/g, path.join(process.cwd(), baseDir, dir + "/"))
.replace(/\{node\}/g, "")
.replace(/\{\/node\}/g, "")
.replace(/\{pathrel\}/g, path.join(baseDir, dir + "/"))
.replace(/\{pathhref\}/g, "")
.replace(/\{404status\}/g, "")
.replace(/\r\n/g, '\n');
};
}
console.log("\n" + stylize("Less", 'underline') + "\n");
console.log("\n" + stylize("Less", 'underline') + "\n");
lessTester.prepBomTest();
lessTester.runTestSet({strictMath: true, relativeUrls: true, silent: true});
lessTester.runTestSet({strictMath: true, strictUnits: true}, "errors/",
lessTester.testErrors, null, getErrorPathReplacementFunction("errors"));
lessTester.runTestSet({strictMath: true, strictUnits: true, javascriptEnabled: false}, "no-js-errors/",
lessTester.testErrors, null, getErrorPathReplacementFunction("no-js-errors"));
lessTester.runTestSet({strictMath: true, dumpLineNumbers: 'comments'}, "debug/", null,
function(name) { return name + '-comments'; });
lessTester.runTestSet({strictMath: true, dumpLineNumbers: 'mediaquery'}, "debug/", null,
function(name) { return name + '-mediaquery'; });
lessTester.runTestSet({strictMath: true, dumpLineNumbers: 'all'}, "debug/", null,
function(name) { return name + '-all'; });
lessTester.runTestSet({strictMath: true, relativeUrls: false, rootpath: "folder (1)/"}, "static-urls/");
lessTester.runTestSet({strictMath: true, compress: true}, "compression/");
lessTester.runTestSet({strictMath: true, strictUnits: true}, "strict-units/");
lessTester.runTestSet({}, "legacy/");
lessTester.runTestSet({strictMath: true, strictUnits: true, sourceMap: true, globalVars: true }, "sourcemaps/",
lessTester.testSourcemap, null, null,
function(filename, type, baseFolder) {
if (type === "vars") {
return path.join(baseFolder, filename) + '.json';
}
return path.join('test/sourcemaps', filename) + '.json';
});
lessTester.runTestSet({strictMath: true, strictUnits: true, sourceMap: {sourceMapFileInline: true}}, "sourcemaps-empty/", lessTester.testEmptySourcemap);
lessTester.runTestSet({globalVars: true, banner: "/**\n * Test\n */\n"}, "globalVars/",
null, null, null, function(name, type, baseFolder) { return path.join(baseFolder, name) + '.json'; });
lessTester.runTestSet({modifyVars: true}, "modifyVars/",
null, null, null, function(name, type, baseFolder) { return path.join(baseFolder, name) + '.json'; });
lessTester.runTestSet({urlArgs: '424242'}, "url-args/");
lessTester.runTestSet({paths: ['test/data/', 'test/less/import/']}, "include-path/");
lessTester.runTestSet({paths: 'test/data/'}, "include-path-string/");
lessTester.runTestSet({plugin: 'test/plugins/postprocess/'}, "postProcessorPlugin/");
lessTester.runTestSet({plugin: 'test/plugins/preprocess/'}, "preProcessorPlugin/");
lessTester.runTestSet({plugin: 'test/plugins/visitor/'}, "visitorPlugin/");
lessTester.runTestSet({plugin: 'test/plugins/filemanager/'}, "filemanagerPlugin/");
lessTester.runTestSet({}, "no-strict-math/");
var testMap = [
[{strictMath: true, relativeUrls: true, silent: true, javascriptEnabled: true}],
[{strictMath: true, strictUnits: true, javascriptEnabled: true}, "errors/",
lessTester.testErrors, null],
[{strictMath: true, strictUnits: true, javascriptEnabled: false}, "no-js-errors/",
lessTester.testErrors, null],
[{strictMath: true, dumpLineNumbers: 'comments'}, "debug/", null,
function(name) { return name + '-comments'; }],
[{strictMath: true, dumpLineNumbers: 'mediaquery'}, "debug/", null,
function(name) { return name + '-mediaquery'; }],
[{strictMath: true, dumpLineNumbers: 'all'}, "debug/", null,
function(name) { return name + '-all'; }],
[{strictMath: true, relativeUrls: false, rootpath: "folder (1)/"}, "static-urls/"],
[{strictMath: true, compress: true}, "compression/"],
[{strictMath: true, strictUnits: true}, "strict-units/"],
[{}, "legacy/"],
[{strictMath: true, strictUnits: true, sourceMap: true, globalVars: true }, "sourcemaps/",
lessTester.testSourcemap, null, null,
function(filename, type, baseFolder) {
if (type === "vars") {
return path.join(baseFolder, filename) + '.json';
}
return path.join('test/sourcemaps', filename) + '.json';
}],
[{strictMath: true, strictUnits: true, sourceMap: {sourceMapFileInline: true}},
"sourcemaps-empty/", lessTester.testEmptySourcemap],
[{globalVars: true, banner: "/**\n * Test\n */\n"}, "globalVars/",
null, null, null, function(name, type, baseFolder) { return path.join(baseFolder, name) + '.json'; }],
[{modifyVars: true}, "modifyVars/",
null, null, null, function(name, type, baseFolder) { return path.join(baseFolder, name) + '.json'; }],
[{urlArgs: '424242'}, "url-args/"],
[{paths: ['test/data/', 'test/less/import/']}, "include-path/"],
[{paths: 'test/data/'}, "include-path-string/"],
[{plugin: 'test/plugins/postprocess/'}, "postProcessorPlugin/"],
[{plugin: 'test/plugins/preprocess/'}, "preProcessorPlugin/"],
[{plugin: 'test/plugins/visitor/'}, "visitorPlugin/"],
[{plugin: 'test/plugins/filemanager/'}, "filemanagerPlugin/"],
[{}, "no-strict-math/"]
];
testMap.forEach(function(args) {
lessTester.runTestSet.apply(lessTester, args)
});
lessTester.testSyncronous({syncImport: true}, "import");

@@ -58,0 +54,0 @@ lessTester.testSyncronous({syncImport: true}, "css");

SyntaxError: Invalid HEX color code in {path}color-invalid-hex-code.less on line 2, column 29:
1 .a {
2 @wrongHEXColorCode: #DCALLB;
3 }
3 color: @wrongHEXColorCode;
SyntaxError: Invalid HEX color code in {path}color-invalid-hex-code2.less on line 2, column 29:
1 .a {
2 @wrongHEXColorCode: #fffblack;
3 }
3 color: @wrongHEXColorCode;

@@ -1,4 +0,4 @@

SyntaxError: You are using JavaScript, which has been disabled. in {path}no-js-errors.less on line 2, column 6:
SyntaxError: Inline JavaScript is not enabled. Is it set in your options? in {path}no-js-errors.less on line 2, column 6:
1 .a {
2 a: `1 + 1`;
3 }

@@ -9,1 +9,7 @@ functions.addMultiple({

});
registerPlugin({
setOptions: function(raw) {
// do nothing
}
});
functions.addMultiple({
"test-transitive" : function() {
return new tree.Anonymous( "transitive" );
var anon = new tree.Anonymous( "transitive" );
return anon;
}
});
functions.addMultiple({
"test-comment": function() {
return new tree.Combinator(' ');
return less.Combinator(' ');
},
"test-directive": function(arg1, arg2) {
return new tree.Directive(arg1.value, new tree.Anonymous(arg2.value));
"test-atrule": function(arg1, arg2) {
return less.AtRule(arg1.value, arg2.value);
},

@@ -25,57 +25,62 @@ "test-extend": function() {

"test-ruleset-call": function() {
return new tree.Combinator(' ');
return less.Combinator(' ');
},
// Functions must return something. Must 'return true' if they produce no output.
"test-undefined": function() { },
// Functions must return something, even if it's false/true
"test-undefined": function() {
return;
},
"test-collapse": function() {
return true;
},
// These cause root errors
"test-alpha": function() {
return new tree.Alpha(30);
return less.Alpha(30);
},
"test-assignment": function() {
return new tree.Assignment("bird", "robin");
return less.Assignment("bird", "robin");
},
"test-attribute": function() {
return new tree.Attribute("foo", "=", "bar");
return less.Attribute("foo", "=", "bar");
},
"test-call": function() {
return new tree.Call("foo");
return less.Call("foo");
},
"test-color": function() {
return new tree.Color([50, 50, 50]);
return less.Color([50, 50, 50]);
},
"test-condition": function() {
return new tree.Condition('<', new tree.Value([0]), new tree.Value([1]));
return less.Condition('<', less.Value([0]), less.Value([1]));
},
"test-detached-ruleset" : function() {
var rule = new tree.Rule('prop', new tree.Anonymous('value'));
return new tree.DetachedRuleset(new tree.Ruleset("", [ rule ]));
var decl = less.Declaration('prop', 'value');
return less.DetachedRuleset(less.Ruleset("", [ decl ]));
},
"test-dimension": function() {
return new tree.Dimension(1, 'px');
return less.Dimension(1, 'px');
},
"test-element": function() {
return new tree.Element('+', 'a');
return less.Element('+', 'a');
},
"test-expression": function() {
return new tree.Expression([1, 2, 3]);
return less.Expression([1, 2, 3]);
},
"test-keyword": function() {
return new tree.Keyword('foo');
return less.Keyword('foo');
},
"test-operation": function() {
return new tree.Operation('+', [1, 2]);
return less.Operation('+', [1, 2]);
},
"test-quoted": function() {
return new tree.Quoted('"', 'foo');
return less.Quoted('"', 'foo');
},
"test-selector": function() {
return new tree.Selector([new tree.Element('a')]);
var sel = less.Selector('.a.b');
return sel;
},
"test-url": function() {
return new tree.URL('http://google.com');
return less.URL('http://google.com');
},
"test-value": function() {
return new tree.Value([1]);
return less.Value([1]);
}
});

@@ -22,2 +22,10 @@ /*jshint latedef: nofunc */

// Define String.prototype.endsWith if it doesn't exist (in older versions of node)
// This is required by the testSourceMap function below
if (typeof String.prototype.endsWith !== 'function') {
String.prototype.endsWith = function (str) {
return this.slice(-str.length) === str;
}
}
less.logger.addListener({

@@ -62,3 +70,4 @@ info: function(msg) {

failedTests = 0,
passedTests = 0;
passedTests = 0,
finishTimer = setInterval(endTest, 500);

@@ -78,2 +87,21 @@ less.functions.functionRegistry.addMultiple({

function testSourcemap(name, err, compiledLess, doReplacements, sourcemap, baseFolder) {
// Check the sourceMappingURL at the bottom of the file
var expectedSourceMapURL = name + ".css.map",
sourceMappingPrefix = "/*# sourceMappingURL=",
sourceMappingSuffix = " */",
expectedCSSAppendage = sourceMappingPrefix + expectedSourceMapURL + sourceMappingSuffix;
if (!compiledLess.endsWith(expectedCSSAppendage)) {
// To display a better error message, we need to figure out what the actual sourceMappingURL value was, if it was even present
var indexOfSourceMappingPrefix = compiledLess.indexOf(sourceMappingPrefix);
if (indexOfSourceMappingPrefix === -1) {
fail("ERROR: sourceMappingURL was not found in " + baseFolder + "/" + name + ".css.");
return;
}
var startOfSourceMappingValue = indexOfSourceMappingPrefix + sourceMappingPrefix.length,
indexOfNextSpace = compiledLess.indexOf(" ", startOfSourceMappingValue),
actualSourceMapURL = compiledLess.substring(startOfSourceMappingValue, indexOfNextSpace === -1 ? compiledLess.length : indexOfNextSpace);
fail("ERROR: sourceMappingURL should be \"" + expectedSourceMapURL + "\" but is \"" + actualSourceMapURL + "\".");
}
fs.readFile(path.join('test/', name) + '.json', 'utf8', function (e, expectedSourcemap) {

@@ -114,16 +142,16 @@ process.stdout.write("- " + path.join(baseFolder, name) + ": ");

fs.readFile(path.join(baseFolder, name) + '.txt', 'utf8', function (e, expectedErr) {
process.stdout.write("- " + path.join(baseFolder, name) + ": ");
expectedErr = doReplacements(expectedErr, baseFolder);
process.stdout.write('- ' + path.join(baseFolder, name) + ": ");
expectedErr = doReplacements(expectedErr, baseFolder, err && err.filename);
if (!err) {
if (compiledLess) {
fail("No Error", 'red');
fail('No Error', 'red');
} else {
fail("No Error, No Output");
fail('No Error, No Output');
}
} else {
var errMessage = less.formatError(err);
var errMessage = err.toString();
if (errMessage === expectedErr) {
ok('OK');
} else {
difference("FAIL", expectedErr, errMessage);
difference('FAIL', expectedErr, errMessage);
}

@@ -134,4 +162,5 @@ }

function globalReplacements(input, directory) {
var p = path.join(process.cwd(), directory),
function globalReplacements(input, directory, filename) {
var path = require('path');
var p = filename ? path.join(path.dirname(filename), '/') : path.join(process.cwd(), directory),
pathimport = path.join(process.cwd(), directory + "import/"),

@@ -142,2 +171,7 @@ pathesc = p.replace(/[.:/\\]/g, function(a) { return '\\' + (a == '\\' ? '\/' : a); }),

return input.replace(/\{path\}/g, p)
.replace(/\{node\}/g, "")
.replace(/\{\/node\}/g, "")
.replace(/\{pathhref\}/g, "")
.replace(/\{404status\}/g, "")
.replace(/\{pathrel\}/g, path.join(path.relative(process.cwd(), p), '/'))
.replace(/\{pathesc\}/g, pathesc)

@@ -205,3 +239,3 @@ .replace(/\{pathimport\}/g, pathimport)

fs.readdirSync(path.join(baseFolder, foldername)).forEach(function (file) {
if (! /\.less/.test(file)) { return; }
if (!/\.less/.test(file)) { return; }

@@ -222,2 +256,7 @@ var name = getBasename(file);

options.sourceMap = options;
// This options is normally set by the bin/lessc script. Setting it causes the sourceMappingURL comment to be appended to the CSS
// output. The value is designed to allow the sourceMapBasepath option to be tested, as it should be removed by less before
// setting the sourceMappingURL value, leaving just the sourceMapOutputFilename and .map extension.
options.sourceMapFilename = options.sourceMapBasepath + "/" + options.sourceMapOutputFilename + ".map";
}

@@ -232,44 +271,45 @@

toCSS(options, path.join(baseFolder, 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) {
var verificationResult = verifyFunction(name, err, result && result.css, doReplacements, result && result.map, baseFolder);
release();
return verificationResult;
}
if (err) {
fail("ERROR: " + (err && err.message));
if (isVerbose) {
process.stdout.write("\n");
if (err.stack) {
process.stdout.write(err.stack + "\n");
} else {
//this sometimes happen - show the whole error object
console.log(err);
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) {
var verificationResult = verifyFunction(name, err, result && result.css, doReplacements, result && result.map, baseFolder);
release();
return verificationResult;
}
if (err) {
fail("ERROR: " + (err && err.message));
if (isVerbose) {
process.stdout.write("\n");
if (err.stack) {
process.stdout.write(err.stack + "\n");
} else {
//this sometimes happen - show the whole error object
console.log(err);
}
}
release();
return;
}
release();
return;
}
var css_name = name;
if (nameModifier) { css_name = nameModifier(name); }
fs.readFile(path.join('test/css', css_name) + '.css', 'utf8', function (e, css) {
process.stdout.write("- " + path.join(baseFolder, css_name) + ": ");
var css_name = name;
if (nameModifier) { css_name = nameModifier(name); }
fs.readFile(path.join('test/css', css_name) + '.css', 'utf8', function (e, css) {
process.stdout.write("- " + path.join(baseFolder, css_name) + ": ");
css = css && doReplacements(css, path.join(baseFolder, foldername));
if (result.css === css) { ok('OK'); }
else {
difference("FAIL", css, result.css);
}
release();
css = css && doReplacements(css, path.join(baseFolder, foldername));
if (result.css === css) { ok('OK'); }
else {
difference("FAIL", css, result.css);
}
release();
});
});
});
});
});

@@ -317,4 +357,4 @@ }

if (isFinished && ((failedTests + passedTests) >= totalTests)) {
clearInterval(finishTimer);
var leaked = checkGlobalLeaks();
process.stdout.write("\n");

@@ -378,3 +418,3 @@ if (failedTests > 0) {

less.render("");
} catch(e) {
} catch (e) {
fail(stylize("FAIL\n", "red"));

@@ -381,0 +421,0 @@ return;

SyntaxError: Invalid HEX color code in {path}color-invalid-hex-code.less on line 2, column 29:
1 .a {
2 @wrongHEXColorCode: #DCALLB;
3 }
3 color: @wrongHEXColorCode;
SyntaxError: Invalid HEX color code in {path}color-invalid-hex-code2.less on line 2, column 29:
1 .a {
2 @wrongHEXColorCode: #fffblack;
3 }
3 color: @wrongHEXColorCode;

@@ -1,4 +0,4 @@

SyntaxError: You are using JavaScript, which has been disabled. in {path}no-js-errors.less on line 2, column 6:
SyntaxError: Inline JavaScript is not enabled. Is it set in your options? in {path}no-js-errors.less on line 2, column 6:
1 .a {
2 a: `1 + 1`;
3 }

@@ -9,1 +9,7 @@ functions.addMultiple({

});
registerPlugin({
setOptions: function(raw) {
// do nothing
}
});
functions.addMultiple({
"test-transitive" : function() {
return new tree.Anonymous( "transitive" );
var anon = new tree.Anonymous( "transitive" );
return anon;
}
});
functions.addMultiple({
"test-comment": function() {
return new tree.Combinator(' ');
return less.Combinator(' ');
},
"test-directive": function(arg1, arg2) {
return new tree.Directive(arg1.value, new tree.Anonymous(arg2.value));
"test-atrule": function(arg1, arg2) {
return less.AtRule(arg1.value, arg2.value);
},

@@ -25,57 +25,62 @@ "test-extend": function() {

"test-ruleset-call": function() {
return new tree.Combinator(' ');
return less.Combinator(' ');
},
// Functions must return something. Must 'return true' if they produce no output.
"test-undefined": function() { },
// Functions must return something, even if it's false/true
"test-undefined": function() {
return;
},
"test-collapse": function() {
return true;
},
// These cause root errors
"test-alpha": function() {
return new tree.Alpha(30);
return less.Alpha(30);
},
"test-assignment": function() {
return new tree.Assignment("bird", "robin");
return less.Assignment("bird", "robin");
},
"test-attribute": function() {
return new tree.Attribute("foo", "=", "bar");
return less.Attribute("foo", "=", "bar");
},
"test-call": function() {
return new tree.Call("foo");
return less.Call("foo");
},
"test-color": function() {
return new tree.Color([50, 50, 50]);
return less.Color([50, 50, 50]);
},
"test-condition": function() {
return new tree.Condition('<', new tree.Value([0]), new tree.Value([1]));
return less.Condition('<', less.Value([0]), less.Value([1]));
},
"test-detached-ruleset" : function() {
var rule = new tree.Rule('prop', new tree.Anonymous('value'));
return new tree.DetachedRuleset(new tree.Ruleset("", [ rule ]));
var decl = less.Declaration('prop', 'value');
return less.DetachedRuleset(less.Ruleset("", [ decl ]));
},
"test-dimension": function() {
return new tree.Dimension(1, 'px');
return less.Dimension(1, 'px');
},
"test-element": function() {
return new tree.Element('+', 'a');
return less.Element('+', 'a');
},
"test-expression": function() {
return new tree.Expression([1, 2, 3]);
return less.Expression([1, 2, 3]);
},
"test-keyword": function() {
return new tree.Keyword('foo');
return less.Keyword('foo');
},
"test-operation": function() {
return new tree.Operation('+', [1, 2]);
return less.Operation('+', [1, 2]);
},
"test-quoted": function() {
return new tree.Quoted('"', 'foo');
return less.Quoted('"', 'foo');
},
"test-selector": function() {
return new tree.Selector([new tree.Element('a')]);
var sel = less.Selector('.a.b');
return sel;
},
"test-url": function() {
return new tree.URL('http://google.com');
return less.URL('http://google.com');
},
"test-value": function() {
return new tree.Value([1]);
return less.Value([1]);
}
});
var less = require('../lib/less'),
fs = require('fs');
fs = require('fs');

@@ -4,0 +4,0 @@ var input = fs.readFileSync("./test/less/modifyVars/extended.less", 'utf8');

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc