mirror of
https://github.com/less/less.js.git
synced 2026-04-09 03:00:20 -04:00
merge in latest 1.7.1 release
This commit is contained in:
@@ -2,7 +2,6 @@ language: node_js
|
||||
node_js:
|
||||
- "0.11"
|
||||
- "0.10"
|
||||
- "0.8"
|
||||
install:
|
||||
- npm install -g grunt-cli
|
||||
- npm install
|
||||
|
||||
18
CHANGELOG.md
18
CHANGELOG.md
@@ -8,6 +8,24 @@
|
||||
TODO
|
||||
- Environment Support
|
||||
- Finalised Plugin Support
|
||||
|
||||
# 1.7.1
|
||||
|
||||
2014-06-08
|
||||
|
||||
- Fix detection of recursive mixins
|
||||
- Fix the paths option for later versions of node (0.10+)
|
||||
- Fix paths joining bug
|
||||
- Fix a number precision issue on some versions of node
|
||||
- Fix an IE8 issue with importing css files
|
||||
- Fix IE11 detection for xhr requests
|
||||
- Modify var works if the last line of a less file is a comment.
|
||||
- Better detection of valid hex colour codes
|
||||
- Some stability fixes to support a low number of available file handles
|
||||
- Support comparing values with different quote types e.g. "test" now === 'test'
|
||||
- Give better error messages if accessing a url that returns a non 200 status code
|
||||
- Fix the e() function when passed empty string
|
||||
- Several minor bug fixes
|
||||
|
||||
# 1.7.0
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ We only accept issues that are bug reports or feature requests. Bugs must be iso
|
||||
1. **Search for existing issues.** We get a lot of duplicate issues, and you'd help us out a lot by first checking if someone else has reported the same issue. Moreover, the issue may have already been resolved with a fix available.
|
||||
2. **Create an isolated and reproducible test case.** Be sure the problem exists in Less.js's code with [reduced test cases](http://css-tricks.com/reduced-test-cases/) that should be included in each bug report.
|
||||
3. **Test with the latest version**. We get a lot of issues that could be resolved by updating your version of Less.js.
|
||||
3. **Include a live example.** Please use [less2css.org](http://less2css.org/) for sharing your isolated test cases.
|
||||
3. **Include an example with source.** E.g. You can use [less2css.org](http://less2css.org/) to create a short test case.
|
||||
4. **Share as much information as possible.** Include operating system and version. Describe how you use Less. If you use it in the browser, please include browser and version, and the version of Less.js you're using. Let us know if you're using the command line (`lessc`) or an external tool. And try to include steps to reproduce the bug.
|
||||
5. If you have a solution or suggestion for how to fix the bug you're reporting, please include it, or make a pull request - don't assume the maintainers know how to fix it just because you do.
|
||||
|
||||
|
||||
2
LICENSE
2
LICENSE
@@ -175,5 +175,3 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
Copyright (c) 2009-2010 Alexis Sellier
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
[](https://travis-ci.org/less/less.js)
|
||||
# [Less.js v1.7.0](http://lesscss.org)
|
||||
[](https://david-dm.org/less/less.js) [](https://david-dm.org/less/less.js#info=devDependencies) [](https://david-dm.org/less/less.js#info=optionalDependencies)
|
||||
|
||||
# [Less.js v1.7.1](http://lesscss.org)
|
||||
|
||||
> The **dynamic** stylesheet language. [http://lesscss.org](http://lesscss.org).
|
||||
|
||||
@@ -46,6 +48,6 @@ Copyright (c) 2009-2014 [Alexis Sellier](http://cloudhead.io/) & The Core Less T
|
||||
Licensed under the [Apache License](LICENSE).
|
||||
|
||||
|
||||
[so]: http://stackoverflow.com/questions/tagged/less "StackOverflow.com"
|
||||
[so]: http://stackoverflow.com/questions/tagged/twitter-bootstrap+less "StackOverflow.com"
|
||||
[issues]: https://github.com/less/less.js/issues "GitHub Issues for Less.js"
|
||||
[download]: https://github.com/less/less.js/zipball/master "Download Less.js"
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
|
||||
var path = require('path'),
|
||||
fs = require('fs'),
|
||||
fs = require('../lib/less/fs'),
|
||||
sys = require('util'),
|
||||
os = require('os'),
|
||||
mkdirp;
|
||||
@@ -286,7 +286,7 @@ if (options.sourceMap === true) {
|
||||
}
|
||||
|
||||
if (options.cleancss && options.sourceMap) {
|
||||
console.log("the sourcemap option is not compatible with sourcemap support at the moment. See Issue #1656");
|
||||
console.log("the cleancss option is not compatible with sourcemap support at the moment. See Issue #1656");
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -335,7 +335,7 @@ var parseLessFile = function (e, data) {
|
||||
return;
|
||||
}
|
||||
|
||||
data = options.globalVariables + data + options.modifyVariables;
|
||||
data = options.globalVariables + data + '\n' + options.modifyVariables;
|
||||
|
||||
options.paths = [path.dirname(input)].concat(options.paths);
|
||||
options.filename = input;
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
[](https://travis-ci.org/less/less.js)
|
||||
[](https://david-dm.org/less/less.js) [](https://david-dm.org/less/less.js#info=devDependencies) [](https://david-dm.org/less/less.js#info=optionalDependencies)
|
||||
|
||||
# [Less.js v<%= pkg.version %>](http://lesscss.org)
|
||||
|
||||
> The **dynamic** stylesheet language. [http://lesscss.org](http://lesscss.org).
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
var result = [];
|
||||
for (i in parts) {
|
||||
var part = parts[i];
|
||||
if (part === '..' && result.length > 0) {
|
||||
if (part === '..' && result.length > 0 && result[result.length-1] !== '..') {
|
||||
result.pop();
|
||||
} else if (part === '' && result.length > 0) {
|
||||
// skip
|
||||
|
||||
7936
dist/less-1.7.1.js
vendored
Normal file
7936
dist/less-1.7.1.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
16
dist/less-1.7.1.min.js
vendored
Normal file
16
dist/less-1.7.1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
9311
dist/less-rhino-1.7.1.js
vendored
Normal file
9311
dist/less-rhino-1.7.1.js
vendored
Normal file
File diff suppressed because it is too large
Load Diff
449
dist/lessc-rhino-1.7.1.js
vendored
Normal file
449
dist/lessc-rhino-1.7.1.js
vendored
Normal file
@@ -0,0 +1,449 @@
|
||||
/* Less.js v1.7.1 RHINO | Copyright (c) 2009-2014, Alexis Sellier <self@cloudhead.net> */
|
||||
|
||||
/*global name:true, less, loadStyleSheet, os */
|
||||
|
||||
function formatError(ctx, options) {
|
||||
options = options || {};
|
||||
|
||||
var message = "";
|
||||
var extract = ctx.extract;
|
||||
var error = [];
|
||||
|
||||
// var stylize = options.color ? require('./lessc_helper').stylize : function (str) { return str; };
|
||||
var 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][ctx.column], '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;
|
||||
}
|
||||
|
||||
function writeError(ctx, options) {
|
||||
options = options || {};
|
||||
if (options.silent) { return; }
|
||||
var message = formatError(ctx, options);
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
function loadStyleSheet(sheet, callback, reload, remaining) {
|
||||
var endOfPath = Math.max(name.lastIndexOf('/'), name.lastIndexOf('\\')),
|
||||
sheetName = name.slice(0, endOfPath + 1) + sheet.href,
|
||||
contents = sheet.contents || {},
|
||||
input = readFile(sheetName);
|
||||
|
||||
input = input.replace(/^\xEF\xBB\xBF/, '');
|
||||
|
||||
contents[sheetName] = input;
|
||||
|
||||
var parser = new less.Parser({
|
||||
paths: [sheet.href.replace(/[\w\.-]+$/, '')],
|
||||
contents: contents
|
||||
});
|
||||
parser.parse(input, function (e, root) {
|
||||
if (e) {
|
||||
return writeError(e);
|
||||
}
|
||||
try {
|
||||
callback(e, root, input, sheet, { local: false, lastModified: 0, remaining: remaining }, sheetName);
|
||||
} catch(e) {
|
||||
writeError(e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
less.Parser.fileLoader = function (file, currentFileInfo, callback, env) {
|
||||
|
||||
var href = file;
|
||||
if (currentFileInfo && currentFileInfo.currentDirectory && !/^\//.test(file)) {
|
||||
href = less.modules.path.join(currentFileInfo.currentDirectory, file);
|
||||
}
|
||||
|
||||
var path = less.modules.path.dirname(href);
|
||||
|
||||
var newFileInfo = {
|
||||
currentDirectory: path + '/',
|
||||
filename: href
|
||||
};
|
||||
|
||||
if (currentFileInfo) {
|
||||
newFileInfo.entryPath = currentFileInfo.entryPath;
|
||||
newFileInfo.rootpath = currentFileInfo.rootpath;
|
||||
newFileInfo.rootFilename = currentFileInfo.rootFilename;
|
||||
newFileInfo.relativeUrls = currentFileInfo.relativeUrls;
|
||||
} else {
|
||||
newFileInfo.entryPath = path;
|
||||
newFileInfo.rootpath = less.rootpath || path;
|
||||
newFileInfo.rootFilename = href;
|
||||
newFileInfo.relativeUrls = env.relativeUrls;
|
||||
}
|
||||
|
||||
var j = file.lastIndexOf('/');
|
||||
if(newFileInfo.relativeUrls && !/^(?:[a-z-]+:|\/)/.test(file) && j != -1) {
|
||||
var relativeSubDirectory = file.slice(0, j+1);
|
||||
newFileInfo.rootpath = newFileInfo.rootpath + relativeSubDirectory; // append (sub|sup) directory path of imported file
|
||||
}
|
||||
newFileInfo.currentDirectory = path;
|
||||
newFileInfo.filename = href;
|
||||
|
||||
var data = null;
|
||||
try {
|
||||
data = readFile(href);
|
||||
} catch (e) {
|
||||
callback({ type: 'File', message: "'" + less.modules.path.basename(href) + "' wasn't found" });
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
callback(null, data, href, newFileInfo, { lastModified: 0 });
|
||||
} catch (e) {
|
||||
callback(e, null, href);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
function writeFile(filename, content) {
|
||||
var fstream = new java.io.FileWriter(filename);
|
||||
var out = new java.io.BufferedWriter(fstream);
|
||||
out.write(content);
|
||||
out.close();
|
||||
}
|
||||
|
||||
// Command line integration via Rhino
|
||||
(function (args) {
|
||||
|
||||
var options = {
|
||||
depends: false,
|
||||
compress: false,
|
||||
cleancss: false,
|
||||
max_line_len: -1,
|
||||
optimization: 1,
|
||||
silent: false,
|
||||
verbose: false,
|
||||
lint: false,
|
||||
paths: [],
|
||||
color: true,
|
||||
strictImports: false,
|
||||
rootpath: '',
|
||||
relativeUrls: false,
|
||||
ieCompat: true,
|
||||
strictMath: false,
|
||||
strictUnits: false
|
||||
};
|
||||
var continueProcessing = true,
|
||||
currentErrorcode;
|
||||
|
||||
var checkArgFunc = function(arg, option) {
|
||||
if (!option) {
|
||||
print(arg + " option requires a parameter");
|
||||
continueProcessing = false;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
var checkBooleanArg = function(arg) {
|
||||
var onOff = /^((on|t|true|y|yes)|(off|f|false|n|no))$/i.exec(arg);
|
||||
if (!onOff) {
|
||||
print(" unable to parse "+arg+" as a boolean. use one of on/t/true/y/yes/off/f/false/n/no");
|
||||
continueProcessing = false;
|
||||
return false;
|
||||
}
|
||||
return Boolean(onOff[2]);
|
||||
};
|
||||
|
||||
var warningMessages = "";
|
||||
var sourceMapFileInline = false;
|
||||
|
||||
args = args.filter(function (arg) {
|
||||
var match = arg.match(/^-I(.+)$/);
|
||||
|
||||
if (match) {
|
||||
options.paths.push(match[1]);
|
||||
return false;
|
||||
}
|
||||
|
||||
match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=(.*))?$/i);
|
||||
if (match) { arg = match[1]; } // was (?:=([^\s]*)), check!
|
||||
else { return arg; }
|
||||
|
||||
switch (arg) {
|
||||
case 'v':
|
||||
case 'version':
|
||||
console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]");
|
||||
continueProcessing = false;
|
||||
break;
|
||||
case 'verbose':
|
||||
options.verbose = true;
|
||||
break;
|
||||
case 's':
|
||||
case 'silent':
|
||||
options.silent = true;
|
||||
break;
|
||||
case 'l':
|
||||
case 'lint':
|
||||
options.lint = true;
|
||||
break;
|
||||
case 'strict-imports':
|
||||
options.strictImports = true;
|
||||
break;
|
||||
case 'h':
|
||||
case 'help':
|
||||
//TODO
|
||||
// require('../lib/less/lessc_helper').printUsage();
|
||||
continueProcessing = false;
|
||||
break;
|
||||
case 'x':
|
||||
case 'compress':
|
||||
options.compress = true;
|
||||
break;
|
||||
case 'M':
|
||||
case 'depends':
|
||||
options.depends = true;
|
||||
break;
|
||||
case 'yui-compress':
|
||||
warningMessages += "yui-compress option has been removed. assuming clean-css.";
|
||||
options.cleancss = true;
|
||||
break;
|
||||
case 'clean-css':
|
||||
options.cleancss = true;
|
||||
break;
|
||||
case 'max-line-len':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.maxLineLen = parseInt(match[2], 10);
|
||||
if (options.maxLineLen <= 0) {
|
||||
options.maxLineLen = -1;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 'no-color':
|
||||
options.color = false;
|
||||
break;
|
||||
case 'no-ie-compat':
|
||||
options.ieCompat = false;
|
||||
break;
|
||||
case 'no-js':
|
||||
options.javascriptEnabled = false;
|
||||
break;
|
||||
case 'include-path':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':')
|
||||
.map(function(p) {
|
||||
if (p) {
|
||||
// return path.resolve(process.cwd(), p);
|
||||
return p;
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
case 'O0': options.optimization = 0; break;
|
||||
case 'O1': options.optimization = 1; break;
|
||||
case 'O2': options.optimization = 2; break;
|
||||
case 'line-numbers':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.dumpLineNumbers = match[2];
|
||||
}
|
||||
break;
|
||||
case 'source-map':
|
||||
if (!match[2]) {
|
||||
options.sourceMap = true;
|
||||
} else {
|
||||
options.sourceMap = match[2];
|
||||
}
|
||||
break;
|
||||
case 'source-map-rootpath':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.sourceMapRootpath = match[2];
|
||||
}
|
||||
break;
|
||||
case 'source-map-basepath':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.sourceMapBasepath = match[2];
|
||||
}
|
||||
break;
|
||||
case 'source-map-map-inline':
|
||||
sourceMapFileInline = true;
|
||||
options.sourceMap = true;
|
||||
break;
|
||||
case 'source-map-less-inline':
|
||||
options.outputSourceFiles = true;
|
||||
break;
|
||||
case 'source-map-url':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.sourceMapURL = match[2];
|
||||
}
|
||||
break;
|
||||
case 'source-map-output-map-file':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.writeSourceMap = function(sourceMapContent) {
|
||||
writeFile(match[2], sourceMapContent);
|
||||
};
|
||||
}
|
||||
break;
|
||||
case 'rp':
|
||||
case 'rootpath':
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.rootpath = match[2].replace(/\\/g, '/');
|
||||
}
|
||||
break;
|
||||
case "ru":
|
||||
case "relative-urls":
|
||||
options.relativeUrls = true;
|
||||
break;
|
||||
case "sm":
|
||||
case "strict-math":
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.strictMath = checkBooleanArg(match[2]);
|
||||
}
|
||||
break;
|
||||
case "su":
|
||||
case "strict-units":
|
||||
if (checkArgFunc(arg, match[2])) {
|
||||
options.strictUnits = checkBooleanArg(match[2]);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
console.log('invalid option ' + arg);
|
||||
continueProcessing = false;
|
||||
}
|
||||
});
|
||||
|
||||
if (!continueProcessing) {
|
||||
return;
|
||||
}
|
||||
|
||||
var name = args[0];
|
||||
if (name && name != '-') {
|
||||
// name = path.resolve(process.cwd(), name);
|
||||
}
|
||||
var output = args[1];
|
||||
var outputbase = args[1];
|
||||
if (output) {
|
||||
options.sourceMapOutputFilename = output;
|
||||
// output = path.resolve(process.cwd(), output);
|
||||
if (warningMessages) {
|
||||
console.log(warningMessages);
|
||||
}
|
||||
}
|
||||
|
||||
// options.sourceMapBasepath = process.cwd();
|
||||
// options.sourceMapBasepath = '';
|
||||
|
||||
if (options.sourceMap === true) {
|
||||
console.log("output: " + output);
|
||||
if (!output && !sourceMapFileInline) {
|
||||
console.log("the sourcemap option only has an optional filename if the css filename is given");
|
||||
return;
|
||||
}
|
||||
options.sourceMapFullFilename = options.sourceMapOutputFilename + ".map";
|
||||
options.sourceMap = less.modules.path.basename(options.sourceMapFullFilename);
|
||||
} else if (options.sourceMap) {
|
||||
options.sourceMapOutputFilename = options.sourceMap;
|
||||
}
|
||||
|
||||
|
||||
if (!name) {
|
||||
console.log("lessc: no inout files");
|
||||
console.log("");
|
||||
// TODO
|
||||
// require('../lib/less/lessc_helper').printUsage();
|
||||
currentErrorcode = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
// var ensureDirectory = function (filepath) {
|
||||
// var dir = path.dirname(filepath),
|
||||
// cmd,
|
||||
// existsSync = fs.existsSync || path.existsSync;
|
||||
// if (!existsSync(dir)) {
|
||||
// if (mkdirp === undefined) {
|
||||
// try {mkdirp = require('mkdirp');}
|
||||
// catch(e) { mkdirp = null; }
|
||||
// }
|
||||
// cmd = mkdirp && mkdirp.sync || fs.mkdirSync;
|
||||
// cmd(dir);
|
||||
// }
|
||||
// };
|
||||
|
||||
if (options.depends) {
|
||||
if (!outputbase) {
|
||||
console.log("option --depends requires an output path to be specified");
|
||||
return;
|
||||
}
|
||||
console.log(outputbase + ": ");
|
||||
}
|
||||
|
||||
if (!name) {
|
||||
console.log('No files present in the fileset');
|
||||
quit(1);
|
||||
}
|
||||
|
||||
var input = null;
|
||||
try {
|
||||
input = readFile(name, 'utf-8');
|
||||
|
||||
} catch (e) {
|
||||
console.log('lesscss: couldn\'t open file ' + name);
|
||||
quit(1);
|
||||
}
|
||||
|
||||
options.filename = name;
|
||||
var result;
|
||||
try {
|
||||
var parser = new less.Parser(options);
|
||||
parser.parse(input, function (e, root) {
|
||||
if (e) {
|
||||
writeError(e, options);
|
||||
quit(1);
|
||||
} else {
|
||||
result = root.toCSS(options);
|
||||
if (output) {
|
||||
writeFile(output, result);
|
||||
console.log("Written to " + output);
|
||||
} else {
|
||||
print(result);
|
||||
}
|
||||
quit(0);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch(e) {
|
||||
writeError(e, options);
|
||||
quit(1);
|
||||
}
|
||||
}(arguments));
|
||||
@@ -123,13 +123,7 @@ function createCSS(styles, sheet, lastModified) {
|
||||
}
|
||||
css.id = id;
|
||||
|
||||
if (css.styleSheet) { // IE
|
||||
try {
|
||||
css.styleSheet.cssText = styles;
|
||||
} catch (e) {
|
||||
throw new(Error)("Couldn't reassign styleSheet.cssText.");
|
||||
}
|
||||
} else {
|
||||
if (!css.styleSheet) {
|
||||
css.appendChild(document.createTextNode(styles));
|
||||
|
||||
// If new contents match contents of oldCss, don't replace oldCss
|
||||
@@ -153,6 +147,17 @@ function createCSS(styles, sheet, lastModified) {
|
||||
oldCss.parentNode.removeChild(oldCss);
|
||||
}
|
||||
|
||||
// For IE.
|
||||
// This needs to happen *after* the style element is added to the DOM, otherwise IE 7 and 8 may crash.
|
||||
// See http://social.msdn.microsoft.com/Forums/en-US/7e081b65-878a-4c22-8e68-c10d39c2ed32/internet-explorer-crashes-appending-style-element-to-head
|
||||
if (css.styleSheet) {
|
||||
try {
|
||||
css.styleSheet.cssText = styles;
|
||||
} catch (e) {
|
||||
throw new(Error)("Couldn't reassign styleSheet.cssText.");
|
||||
}
|
||||
}
|
||||
|
||||
// Don't update the local store if the file wasn't modified
|
||||
if (lastModified && cache) {
|
||||
log('saving ' + href + ' to cache.', logLevel.info);
|
||||
|
||||
@@ -8,7 +8,7 @@ var fileCache = {};
|
||||
// isFileProtocol is global
|
||||
|
||||
function getXMLHttpRequest() {
|
||||
if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !window.ActiveXObject)) {
|
||||
if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
|
||||
return new XMLHttpRequest();
|
||||
} else {
|
||||
try {
|
||||
@@ -203,4 +203,4 @@ return {
|
||||
}
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var path = require('path'),
|
||||
url = require('url'),
|
||||
request,
|
||||
fs = require('fs'),
|
||||
fs = require('./node/fs'),
|
||||
isUrlRe = /^(?:https?:)?\/\//i;
|
||||
|
||||
module.exports = {
|
||||
@@ -146,26 +146,33 @@ module.exports = {
|
||||
return;
|
||||
}
|
||||
|
||||
var urlStr = isUrl ? filename : url.resolve(currentDirectory, filename);
|
||||
var urlStr = isUrl ? filename : url.resolve(currentDirectory, filename),
|
||||
urlObj = url.parse(urlStr);
|
||||
|
||||
if (!urlObj.protocol) {
|
||||
urlObj.protocol = "http";
|
||||
urlStr = urlObj.format();
|
||||
}
|
||||
|
||||
request.get({uri: urlStr, strictSSL: !env.insecure }, function (error, res, body) {
|
||||
if (res.statusCode === 404) {
|
||||
if (error) {
|
||||
callback({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n "+ error +"\n" });
|
||||
}
|
||||
if (res && res.statusCode === 404) {
|
||||
callback({ type: 'File', message: "resource '" + urlStr + "' was not found\n" });
|
||||
return;
|
||||
}
|
||||
if (!body) {
|
||||
this.warn( env, 'Warning: Empty body (HTTP '+ res.statusCode + ') returned by "' + urlStr +'"');
|
||||
}
|
||||
if (error) {
|
||||
callback({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n "+ error +"\n" });
|
||||
}
|
||||
fullFilename = urlStr;
|
||||
callback(null, body, fullFilename);
|
||||
});
|
||||
} else {
|
||||
|
||||
var paths = [currentDirectory].concat(env.paths);
|
||||
paths.push('.');
|
||||
var paths = [currentDirectory];
|
||||
if (env.paths) paths.push.apply(paths, env.paths);
|
||||
if (paths.indexOf('.') === -1) paths.push('.');
|
||||
|
||||
if (env.syncImport) {
|
||||
for (var i = 0; i < paths.length; i++) {
|
||||
@@ -195,7 +202,12 @@ module.exports = {
|
||||
} else {
|
||||
fs.readFile(fullFilename, 'utf-8', function(e, data) {
|
||||
if (e) { callback(e); }
|
||||
callback(null, data, fullFilename);
|
||||
|
||||
// do processing in the next tick to allow
|
||||
// file handling to dispose
|
||||
process.nextTick(function() {
|
||||
callback(null, data, fullFilename);
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
10
lib/less/environment/node/fs.js
Normal file
10
lib/less/environment/node/fs.js
Normal file
@@ -0,0 +1,10 @@
|
||||
var fs;
|
||||
try
|
||||
{
|
||||
fs = require("graceful-fs");
|
||||
}
|
||||
catch(e)
|
||||
{
|
||||
fs = require("fs");
|
||||
}
|
||||
module.exports = fs;
|
||||
@@ -221,7 +221,7 @@ var functions = {
|
||||
}
|
||||
},
|
||||
e: function (str) {
|
||||
return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str);
|
||||
return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str.value);
|
||||
},
|
||||
escape: function (str) {
|
||||
return new(tree.Anonymous)(encodeURI(str.value).replace(/=/g, "%3D").replace(/:/g, "%3A").replace(/#/g, "%23").replace(/;/g, "%3B").replace(/\(/g, "%28").replace(/\)/g, "%29"));
|
||||
@@ -711,13 +711,9 @@ function clamp(val) {
|
||||
}
|
||||
|
||||
tree.fround = function(env, value) {
|
||||
var p;
|
||||
if (env && (env.numPrecision != null)) {
|
||||
p = Math.pow(10, env.numPrecision);
|
||||
return Math.round(value * p) / p;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
var p = env && env.numPrecision;
|
||||
//add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded...
|
||||
return (p == null) ? value : Number((value + 2e-16).toFixed(p));
|
||||
};
|
||||
|
||||
tree.functionCall = function(env, currentFileInfo, environment) {
|
||||
|
||||
@@ -59,6 +59,7 @@ var lessc_helper = {
|
||||
console.log(" --strict-units=on|off that cannot be represented.");
|
||||
console.log(" --global-var='VAR=VALUE' Defines a variable that can be referenced by the file.");
|
||||
console.log(" --modify-var='VAR=VALUE' Modifies a variable already declared in the file.");
|
||||
console.log(" --url-args='QUERYSTRING' Adds params into url tokens (e.g. 42, cb=42 or 'a=1&b=2')");
|
||||
console.log("");
|
||||
console.log("-------------------------- Deprecated ----------------");
|
||||
console.log(" --line-numbers=TYPE Outputs filename and line numbers.");
|
||||
|
||||
@@ -818,6 +818,11 @@ var Parser = function Parser(env) {
|
||||
var rgb;
|
||||
|
||||
if (input.charAt(i) === '#' && (rgb = $re(/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})/))) {
|
||||
var colorCandidateString = rgb.input.match(/^#([\w]+).*/); // strip colons, brackets, whitespaces and other characters that should not definitely be part of color string
|
||||
colorCandidateString = colorCandidateString[1];
|
||||
if (!colorCandidateString.match(/^[A-Fa-f0-9]+$/)) { // verify if candidate consists only of allowed HEX characters
|
||||
error("Invalid HEX color code");
|
||||
}
|
||||
return new(tree.Color)(rgb[1]);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -56,7 +56,8 @@ function formatError(ctx, options) {
|
||||
function writeError(ctx, options) {
|
||||
options = options || {};
|
||||
if (options.silent) { return; }
|
||||
print(formatError(ctx, options));
|
||||
var message = formatError(ctx, options);
|
||||
throw new Error(message);
|
||||
}
|
||||
|
||||
function loadStyleSheet(sheet, callback, reload, remaining) {
|
||||
@@ -440,5 +441,4 @@ function writeFile(filename, content) {
|
||||
writeError(e, options);
|
||||
quit(1);
|
||||
}
|
||||
console.log("done");
|
||||
}(arguments));
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module.exports = function (tree) {
|
||||
|
||||
var Anonymous = function (string, index, currentFileInfo, mapLines) {
|
||||
this.value = string.value || string;
|
||||
var Anonymous = function (value, index, currentFileInfo, mapLines) {
|
||||
this.value = value;
|
||||
this.index = index;
|
||||
this.mapLines = mapLines;
|
||||
this.currentFileInfo = currentFileInfo;
|
||||
|
||||
@@ -20,7 +20,7 @@ Call.prototype = {
|
||||
eval: function (env) {
|
||||
var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule,
|
||||
candidates = [], candidate, conditionResult = [], defaultFunc = tree.defaultFunc,
|
||||
defaultResult, defNone = 0, defTrue = 1, defFalse = 2, count;
|
||||
defaultResult, defNone = 0, defTrue = 1, defFalse = 2, count, originalRuleset;
|
||||
|
||||
args = this.arguments && this.arguments.map(function (a) {
|
||||
return { name: a.name, value: a.value.eval(env) };
|
||||
@@ -98,8 +98,9 @@ Call.prototype = {
|
||||
try {
|
||||
mixin = candidates[m].mixin;
|
||||
if (!(mixin instanceof tree.mixin.Definition)) {
|
||||
originalRuleset = mixin.originalRuleset || mixin;
|
||||
mixin = new tree.mixin.Definition("", [], mixin.rules, null, false);
|
||||
mixin.originalRuleset = mixins[m].originalRuleset || mixins[m];
|
||||
mixin.originalRuleset = originalRuleset;
|
||||
}
|
||||
Array.prototype.push.apply(
|
||||
rules, mixin.evalCall(env, args, this.important).rules);
|
||||
|
||||
@@ -92,7 +92,7 @@ Definition.prototype = {
|
||||
throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
|
||||
' (' + argsLength + ' for ' + this.arity + ')' };
|
||||
}
|
||||
|
||||
|
||||
frame.prependRule(new(tree.Rule)(name, val));
|
||||
evaldArguments[i] = val;
|
||||
}
|
||||
@@ -132,7 +132,7 @@ Definition.prototype = {
|
||||
matchCondition: function (args, env) {
|
||||
if (this.condition && !this.condition.eval(
|
||||
new(tree.evalEnv)(env,
|
||||
[this.evalParams(env, new(tree.evalEnv)(env, this.frames.concat(env.frames)), args, [])] // the parameter variables
|
||||
[this.evalParams(env, new(tree.evalEnv)(env, this.frames ? this.frames.concat(env.frames) : env.frames), args, [])] // the parameter variables
|
||||
.concat(this.frames) // the parent namespace/mixin frames
|
||||
.concat(env.frames)))) { // the current environment frames
|
||||
return false;
|
||||
|
||||
@@ -34,8 +34,16 @@ Quoted.prototype = {
|
||||
return -1;
|
||||
}
|
||||
|
||||
var left = this.toCSS(),
|
||||
var left, right;
|
||||
|
||||
// when comparing quoted strings allow the quote to differ
|
||||
if (x.type === "Quoted" && !this.escaped && !x.escaped) {
|
||||
left = x.value;
|
||||
right = this.value;
|
||||
} else {
|
||||
left = this.toCSS();
|
||||
right = x.toCSS();
|
||||
}
|
||||
|
||||
if (left === right) {
|
||||
return 0;
|
||||
|
||||
19
package.json
19
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "less",
|
||||
"version": "1.7.0",
|
||||
"version": "1.7.1",
|
||||
"description": "Leaner CSS",
|
||||
"homepage": "http://lesscss.org",
|
||||
"author": {
|
||||
@@ -40,8 +40,9 @@
|
||||
"test": "grunt test"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"mime": "1.2.x",
|
||||
"request": ">=2.33.0",
|
||||
"graceful-fs": "~2.0.3",
|
||||
"mime": "~1.2.11",
|
||||
"request": "~2.34.0",
|
||||
"mkdirp": "~0.3.5",
|
||||
"clean-css": "2.1.x",
|
||||
"source-map": "0.1.x",
|
||||
@@ -51,15 +52,15 @@
|
||||
"diff": "~1.0",
|
||||
"grunt": "~0.4.2",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-connect": "~0.6.0",
|
||||
"grunt-contrib-concat": "~0.4.0",
|
||||
"grunt-contrib-connect": "~0.7.0",
|
||||
"grunt-contrib-jasmine": "~0.5.2",
|
||||
"grunt-contrib-jshint": "~0.8.0",
|
||||
"grunt-contrib-uglify": "~0.3.2",
|
||||
"grunt-shell": "~0.6.4",
|
||||
"grunt-contrib-jshint": "~0.10.0",
|
||||
"grunt-contrib-uglify": "~0.4.0",
|
||||
"grunt-shell": "~0.7.0",
|
||||
"http-server": "~0.6.1",
|
||||
"matchdep": "~0.3.0",
|
||||
"time-grunt": "~0.2.9",
|
||||
"time-grunt": "~0.3.1",
|
||||
"browserify": "~3.30.2",
|
||||
"grunt-browserify": "~1.3.1"
|
||||
},
|
||||
|
||||
@@ -67,9 +67,17 @@
|
||||
content: is not blue its purple;
|
||||
}
|
||||
.stringguardtest {
|
||||
content: is theme1;
|
||||
content: is not theme2;
|
||||
content: is theme1 no quotes;
|
||||
content: "theme1" is "theme1";
|
||||
content: "theme1" is not "theme2";
|
||||
content: "theme1" is 'theme1';
|
||||
content: "theme1" is not 'theme2';
|
||||
content: 'theme1' is "theme1";
|
||||
content: 'theme1' is not "theme2";
|
||||
content: 'theme1' is 'theme1';
|
||||
content: 'theme1' is not 'theme2';
|
||||
content: theme1 is not "theme2";
|
||||
content: theme1 is not 'theme2';
|
||||
content: theme1 is theme1;
|
||||
}
|
||||
#tryNumberPx {
|
||||
catch: all;
|
||||
@@ -80,3 +88,6 @@
|
||||
a: 1;
|
||||
x: 1;
|
||||
}
|
||||
.mixin-generated-class {
|
||||
a: 1;
|
||||
}
|
||||
|
||||
3
test/less/errors/color-invalid-hex-code.less
Normal file
3
test/less/errors/color-invalid-hex-code.less
Normal file
@@ -0,0 +1,3 @@
|
||||
.a {
|
||||
@wrongHEXColorCode: #DCALLB;
|
||||
}
|
||||
4
test/less/errors/color-invalid-hex-code.txt
Normal file
4
test/less/errors/color-invalid-hex-code.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
SyntaxError: Invalid HEX color code in {path}color-invalid-hex-code.less on line 2, column 29:
|
||||
1 .a {
|
||||
2 @wrongHEXColorCode: #DCALLB;
|
||||
3 }
|
||||
3
test/less/errors/color-invalid-hex-code2.less
Normal file
3
test/less/errors/color-invalid-hex-code2.less
Normal file
@@ -0,0 +1,3 @@
|
||||
.a {
|
||||
@wrongHEXColorCode: #fffblack;
|
||||
}
|
||||
4
test/less/errors/color-invalid-hex-code2.txt
Normal file
4
test/less/errors/color-invalid-hex-code2.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
SyntaxError: Invalid HEX color code in {path}color-invalid-hex-code2.less on line 2, column 29:
|
||||
1 .a {
|
||||
2 @wrongHEXColorCode: #fffblack;
|
||||
3 }
|
||||
@@ -1,3 +1,3 @@
|
||||
.scope {
|
||||
var: `this.foo.toJS()`;
|
||||
var: `this.foo.toJS`;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
SyntaxError: JavaScript evaluation error: 'TypeError: Cannot call method 'toJS' of undefined' in {path}javascript-error.less on line 2, column 27:
|
||||
SyntaxError: JavaScript evaluation error: 'TypeError: Cannot read property 'toJS' of undefined' in {path}javascript-error.less on line 2, column 25:
|
||||
1 .scope {
|
||||
2 var: `this.foo.toJS()`;
|
||||
2 var: `this.foo.toJS`;
|
||||
3 }
|
||||
|
||||
@@ -116,13 +116,17 @@
|
||||
.colorguard(purple);
|
||||
}
|
||||
|
||||
.stringguard(@str) when (@str = "theme1") { content: is theme1; }
|
||||
.stringguard(@str) when not ("theme2" = @str) { content: is not theme2; }
|
||||
.stringguard(@str) when (~"theme1" = @str) { content: is theme1 no quotes; }
|
||||
.stringguard(@str) when (@str = "theme1") { content: @str is "theme1"; }
|
||||
.stringguard(@str) when not ("theme2" = @str) { content: @str is not "theme2"; }
|
||||
.stringguard(@str) when (@str = 'theme1') { content: @str is 'theme1'; }
|
||||
.stringguard(@str) when not ('theme2' = @str) { content: @str is not 'theme2'; }
|
||||
.stringguard(@str) when (~"theme1" = @str) { content: @str is theme1; }
|
||||
.stringguard(@str) {}
|
||||
.stringguardtest {
|
||||
.stringguard("theme1");
|
||||
.stringguard("theme2");
|
||||
.stringguard('theme1');
|
||||
.stringguard('theme2');
|
||||
.stringguard(theme1);
|
||||
}
|
||||
|
||||
@@ -157,3 +161,13 @@
|
||||
}
|
||||
}
|
||||
.bug-100cm-1m(100cm);
|
||||
|
||||
#ns {
|
||||
.mixin-for-root-usage(@a) when (@a > 0) {
|
||||
.mixin-generated-class {
|
||||
a: @a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ns > .mixin-for-root-usage(1);
|
||||
|
||||
@@ -136,6 +136,9 @@ h3 { .margin_between(15px, 5px); }
|
||||
.clearfix {
|
||||
.clearfix();
|
||||
}
|
||||
.clearfix {
|
||||
.clearfix();
|
||||
}
|
||||
.foo {
|
||||
.clearfix();
|
||||
}
|
||||
Reference in New Issue
Block a user