Merge https://github.com/less/less.js into misleading-error-message-2069

Conflicts:
	README.md
This commit is contained in:
jurcovicovam
2014-07-25 22:25:44 +02:00
139 changed files with 106967 additions and 787 deletions

7
.travis.yml Normal file
View File

@@ -0,0 +1,7 @@
language: node_js
node_js:
- "0.11"
- "0.10"
install:
- npm install -g grunt-cli
- npm install

View File

@@ -1,3 +1,79 @@
# 1.7.3
2014-06-22
- Include dist files, missing from 1.7.2
- Do not round the results of color functions, like lightness, hue, luma etc.
- Support cover and contain keywords in background definitions
# 1.7.2
2014-06-19
- Allow paths option to be a string (in 1.7.1 less started throwing an exception instead of incorrectly processing the string as an array of chars)
- Do not round numbers when used with javascript (introduced 1.7.0)
# 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
2014-02-27
- Add support for rulesets in variables and passed to mixins to allow wrapping
- Change luma to follow the w3c spec, luma is available as luminance. Contrast still uses luma so you may see differences if your threshold % is close to the existing calculated luma.
- Upgraded clean css which means the --selectors-merge-mode is now renamed --compatibility
- Add support for using variables with @keyframes, @namespace, @charset
- Support property merging with +_ when spaces are needed and keep + for comma separated
- Imports now always import once consistently - a race condition meant previously certain configurations would lead to a different ordering of files
- Fix support for `.mixin(@args...)` when called with no args (e.g. `.mixin();`)
- Do unit conversions with min and max functions. Don't pass through if not understood, throw an error
- Allow % to be passed on its own to the unit function e.g. `unit(10, %)`
- Fix a bug when comparing a unit value to a non-unit value if the unit-value was the multiple of another unit (e.g. cm, mm, deg etc.)
- Fix mixins with media queries in import reference files not being put into the output (they now output, they used to incorrectly not)
- Fix lint mode - now reports all errors
- Fixed a small scope issue with & {} selector rulesets incorrectly making mixins visible - regression from 1.6.2
- Browser - added log level "debug" at 3 to get less logging, The default has changed so unless you set the value to the default you won't see a difference
- Browser - logLevel takes effect regardless of the environment (production/dev)
- Browser - added postProcessor option, a function called to post-process the css before adding to the page
- Browser - use the right request for file access in IE
# 1.6.3
2014-02-08
- Fix issue with calling toCSS twice not working in some situations (like with bootstrap 2)
# 1.6.2
2014-02-02
- The Rhino release is fixed!
- ability to use uppercase colours
- Fix a nasty bug causing syntax errors when selector interpolation is preceded by a long comment (and some other cases)
- Fix a major bug with the variable scope in guards on selectors (e.g. not mixins)
- Fold in `& when () {` to the current selector rather than duplicating it
- fix another issue with array prototypes
- add a url-args option which adds a value to all urls (for cache busting)
- Round numbers to 8 decimal places - thereby stopping javascript precision errors
- some improvements to the default() function in more complex scenarios
- improved missing '{' and '(' detection
# 1.6.1
2014-01-12
@@ -92,7 +168,7 @@
- fix passing of strict maths option
# 1.4.0 Beta 4
2013-05-04
- change strictMaths to strictMath. Enable this with --strict-math=on in lessc and strictMath:true in JavaScript.
@@ -125,7 +201,7 @@
- significant bug fixes to our debug options
- other parameters can be used as defaults in mixins e.g. .a(@a, @b:@a)
- an error is shown if properties are used outside of a ruleset
- added extract function which picks a value out of a list, e.g. extract(12 13 14, 3) => 14
- added extract function which picks a value out of a list, e.g. extract(12 13 14, 3) => 14
- added luma, hsvhue, hsvsaturation, hsvvalue functions
- added pow, pi, mod, tan, sin, cos, atan, asin, acos and sqrt math functions
- added convert function, e.g. convert(1rad, deg) => value in degrees

View File

@@ -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.
@@ -47,4 +47,4 @@ _Pull requests are encouraged!_
## Developing
If you want to take an issue just add a small comment saying you are having a go at something, so we don't get duplication.
Learn more about [developing Less.js](https://github.com/less/less.js/wiki/Developing-less.js).
Learn more about [developing Less.js](http://lesscss.org/usage/#developing-less).

View File

@@ -15,17 +15,17 @@ module.exports = function(grunt) {
license: '<%= _.pluck(pkg.licenses, "type").join(", ") %>',
copyright: 'Copyright (c) 2009-<%= grunt.template.today("yyyy") %>',
banner:
'/*! \n' +
' * LESS - <%= pkg.description %> v<%= pkg.version %> \n' +
' * http://lesscss.org \n' +
' * \n' +
' * <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>> \n' +
' * Licensed under the <%= meta.license %> License. \n' +
' * \n' +
' */ \n\n' +
'/*!\n' +
' * Less - <%= pkg.description %> v<%= pkg.version %>\n' +
' * http://lesscss.org\n' +
' *\n' +
' * <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>>\n' +
' * Licensed under the <%= meta.license %> License.\n' +
' *\n' +
' */\n\n' +
' /**' +
' * @license <%= meta.license %>\n' +
' */ \n\n'
' */\n\n'
},
shell: {
@@ -64,12 +64,21 @@ module.exports = function(grunt) {
// Rhino
rhino: {
options: {
banner: '/* LESS.js v<%= pkg.version %> RHINO | <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>> */\n\n',
banner: '/* Less.js v<%= pkg.version %> RHINO | <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>> */\n\n',
footer: '' // override task-level footer
},
src: ['<%= build.rhino %>'],
dest: 'dist/less-rhino-<%= pkg.version %>.js'
},
// lessc for Rhino
rhinolessc: {
options: {
banner: '/* Less.js v<%= pkg.version %> RHINO | <%= meta.copyright %>, <%= pkg.author.name %> <<%= pkg.author.email %>> */\n\n',
footer: '' // override task-level footer
},
src: ['<%= build.rhinolessc %>'],
dest: 'dist/lessc-rhino-<%= pkg.version %>.js'
},
// Generate readme
readme: {
// override task-level banner and footer
@@ -205,6 +214,14 @@ module.exports = function(grunt) {
specs: 'test/browser/runner-global-vars-spec.js',
outfile: 'tmp/browser/test-runner-global-vars.html'
}
},
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-postProcessor.html'
}
}
},
@@ -234,9 +251,10 @@ module.exports = function(grunt) {
// Release Rhino Version
grunt.registerTask('rhino', [
'concat:rhino'
'concat:rhino',
'concat:rhinolessc'
]);
// Run all browser tests
grunt.registerTask('browsertest', [
'browser',

View File

@@ -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

View File

@@ -1,2 +1,53 @@
This branch has been merged into less.js and is not relevant anymore.
[![Build Status](https://travis-ci.org/less/less.js.png?branch=master)](https://travis-ci.org/less/less.js)
[![Dependencies](https://david-dm.org/less/less.js.png)](https://david-dm.org/less/less.js) [![devDependency Status](https://david-dm.org/less/less.js/dev-status.png)](https://david-dm.org/less/less.js#info=devDependencies) [![optionalDependency Status](https://david-dm.org/less/less.js/optional-status.png)](https://david-dm.org/less/less.js#info=optionalDependencies)
# [Less.js v1.7.3](http://lesscss.org)
> The **dynamic** stylesheet language. [http://lesscss.org](http://lesscss.org).
This is the JavaScript, official, stable version of Less.
## Getting Started
Options for adding Less.js to your project:
* Install with [NPM](https://npmjs.org/): `npm install less`
* [Download the latest release][download]
* Clone the repo: `git clone git://github.com/less/less.js.git`
## More information
For general information on the language, configuration options or usage visit [lesscss.org](http://lesscss.org).
Here are other resources for using Less.js:
* [stackoverflow.com][so] is a great place to get answers about Less.
* [Less.js Issues][issues] for reporting bugs
## Contributing
Please read [CONTRIBUTING.md](./CONTRIBUTING.md). Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
### Reporting Issues
Before opening any issue, please search for existing issues and read the [Issue Guidelines](https://github.com/necolas/issue-guidelines), written by [Nicolas Gallagher](https://github.com/necolas/). After that if you find a bug or would like to make feature request, [please open a new issue][issues].
Please report documentation issues in [the documentation project](https://github.com/less/less-docs).
### Development
Read [Developing Less](http://lesscss.org/usage/#developing-less).
## Release History
See the [changelog](CHANGELOG.md)
## [License](LICENSE)
Copyright (c) 2009-2014 [Alexis Sellier](http://cloudhead.io/) & The Core Less Team
Licensed under the [Apache License](LICENSE).
[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"

View File

@@ -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;
@@ -27,7 +27,8 @@ var options = {
strictMath: false,
strictUnits: false,
globalVariables: '',
modifyVariables: ''
modifyVariables: '',
urlArgs: ''
};
var cleancssOptions = {};
var continueProcessing = true,
@@ -78,7 +79,7 @@ args = args.filter(function (arg) {
switch (arg) {
case 'v':
case 'version':
console.log("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]");
console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]");
continueProcessing = false;
case 'verbose':
options.verbose = true;
@@ -230,18 +231,23 @@ args = args.filter(function (arg) {
case "--advanced":
cleancssOptions.noAdvanced = false;
break;
case "--selectors-merge-mode":
cleancssOptions.selectorsMergeMode = cleanOptionArgs[1];
case "--compatibility":
cleancssOptions.compatibility = cleanOptionArgs[1];
break;
default:
console.log("unrecognised clean-css option '" + cleanOptionArgs[0] + "'");
console.log("we support only arguments that make sense for less, '--keep-line-breaks', '-b'");
console.log("'--s0', '--s1', '--advanced', '--skip-advanced', '--selectors-merge-mode'");
console.log("'--s0', '--s1', '--advanced', '--skip-advanced', '--compatibility'");
continueProcessing = false;
currentErrorcode = 1;
break;
}
break;
case 'url-args':
if (checkArgFunc(arg, match[2])) {
options.urlArgs = match[2];
}
break;
default:
require('../lib/less/lessc_helper').printUsage();
continueProcessing = false;
@@ -281,7 +287,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;
}
@@ -330,7 +336,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;
@@ -346,8 +352,9 @@ var parseLessFile = function (e, data) {
sys.print(file + " ")
}
sys.print("\n");
} else if(!options.lint) {
} else {
try {
if (options.lint) { writeSourceMap = function() {} }
var css = tree.toCSS({
silent: options.silent,
verbose: options.verbose,
@@ -365,17 +372,20 @@ var parseLessFile = function (e, data) {
writeSourceMap: writeSourceMap,
maxLineLen: options.maxLineLen,
strictMath: options.strictMath,
strictUnits: options.strictUnits
strictUnits: options.strictUnits,
urlArgs: options.urlArgs
});
if (output) {
ensureDirectory(output);
fs.writeFileSync(output, css, 'utf8');
if (options.verbose) {
console.log('lessc: wrote ' + output);
}
} else {
sys.print(css);
}
if(!options.lint) {
if (output) {
ensureDirectory(output);
fs.writeFileSync(output, css, 'utf8');
if (options.verbose) {
console.log('lessc: wrote ' + output);
}
} else {
sys.print(css);
}
}
} catch (e) {
less.writeError(e, options);
currentErrorcode = 2;

View File

@@ -1,7 +1,7 @@
{
"name": "less",
"version": "1.5.0",
"main": "./dist/less-1.5.0.js",
"version": "1.7.0",
"main": "./dist/less-1.7.0.js",
"ignore": [
"**/.*",
"benchmark",

View File

@@ -36,23 +36,13 @@ project.ext {
testOut = 'out/test'
}
javascript.source {
test {
js {
srcDir '.'
include 'test/rhino/test-header.js'
include "dist/less-rhino-${packageProps.version}.js"
}
}
}
task runGruntRhino(type: GruntTask) {
gruntArgs = "rhino"
}
combineJs {
dependsOn runGruntRhino
source = javascript.source.test.js.files
source = ["dist/less-rhino-${packageProps.version}.js", "test/rhino/test-header.js","dist/lessc-rhino-${packageProps.version}.js"]
dest = file(rhinoTestSrc)
}

View File

@@ -1,8 +1,11 @@
[![Build Status](https://travis-ci.org/less/less.js.png?branch=master)](https://travis-ci.org/less/less.js)
[![Dependencies](https://david-dm.org/less/less.js.png)](https://david-dm.org/less/less.js) [![devDependency Status](https://david-dm.org/less/less.js/dev-status.png)](https://david-dm.org/less/less.js#info=devDependencies) [![optionalDependency Status](https://david-dm.org/less/less.js/optional-status.png)](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).
This is the JavaScript, and now official, stable version of LESS.
This is the JavaScript, official, stable version of Less.
## Getting Started
@@ -13,265 +16,16 @@ Options for adding Less.js to your project:
* [Download the latest release][download]
* Clone the repo: `git clone git://github.com/less/less.js.git`
## Feature Highlights
LESS extends CSS with dynamic features such as:
* [nesting](#nesting)
* [variables](#variables)
* [operations](#operations)
* [mixins](#mixins)
* [extend](#extend) (selector inheritance)
To learn about the many other features Less.js has to offer please visit [http://lesscss.org](http://lesscss.org) and [the Less.js wiki][wiki]
### Examples
#### nesting
Take advantage of nesting to make code more readable and maintainable. This:
```less
.nav > li > a {
border: 1px solid #f5f5f5;
&:hover {
border-color: #ddd;
}
}
```
renders to:
```css
.nav > li > a {
border: 1px solid #f5f5f5;
}
.nav > li > a:hover {
border-color: #ddd;
}
```
#### variables
Updated commonly used values from a single location.
```less
// Variables ("inline" comments like this can be used)
@link-color: #428bca; // appears as "sea blue"
/* Or "block comments" that span
multiple lines, like this */
a {
color: @link-color; // use the variable in styles
}
```
Variables can also be used in `@import` statements, URLs, selector names, and more.
#### operations
Continuing with the same example above, we can use our variables even easier to maintain with _operations_, which enables the use of addition, subraction, multiplication and division in your styles:
```less
// Variables
@link-color: #428bca;
@link-color-hover: darken(@link-color, 10%);
// Styles
a {
color: @link-color;
}
a:hover {
color: @link-color-hover;
}
```
renders to:
```css
a {
color: #428bca;
}
a:hover {
color: #3071a9;
}
```
#### mixins
##### "implicit" mixins
Mixins enable you to apply the styles of one selector inside another selector like this:
```less
// Variables
@link-color: #428bca;
// Any "regular" class...
.link {
color: @link-color;
}
a {
font-weight: bold;
.link; // ...can be used as an "implicit" mixin
}
```
renders to:
```css
.link {
color: #428bca;
}
a {
font-weight: bold;
color: #428bca;
}
```
So any selector can be an "implicit mixin". We'll show you a DRYer way to do this below.
##### parametric mixins
Mixins can also accept parameters:
```less
// Transition mixin
.transition(@transition) {
-webkit-transition: @transition;
-moz-transition: @transition;
-o-transition: @transition;
transition: @transition;
}
```
used like this:
```less
// Variables
@link-color: #428bca;
@link-color-hover: darken(@link-color, 10%);
//Transition mixin would be anywhere here
a {
font-weight: bold;
color: @link-color;
.transition(color .2s ease-in-out);
// Hover state
&:hover {
color: @link-color-hover;
}
}
```
renders to:
```css
a {
font-weight: bold;
color: #428bca;
-webkit-transition: color 0.2s ease-in-out;
-moz-transition: color 0.2s ease-in-out;
-o-transition: color 0.2s ease-in-out;
transition: color 0.2s ease-in-out;
}
a:hover {
color: #3071a9;
}
```
#### extend
The `extend` feature can be thought of as the _inverse_ of mixins. It accomplishes the goal of "borrowing styles", but rather than copying all the rules of _Selector A_ over to _Selector B_, `extend` copies the name of the _inheriting selector_ (_Selector B_) over to the _extending selector_ (_Selector A_). So continuing with the example used for [mixins](#mixins) above, extend works like this:
```less
// Variables
@link-color: #428bca;
.link {
color: @link-color;
}
a:extend(.link) {
font-weight: bold;
}
// Can also be written as
a {
&:extend(.link);
font-weight: bold;
}
```
renders to:
```css
.link, a {
color: #428bca;
}
a {
font-weight: bold;
}
```
## Usage
### Compiling and Parsing
Invoke the compiler from node:
```javascript
var less = require('less');
less.render('.class { width: (1 + 1) }', function (e, css) {
console.log(css);
});
```
Outputs:
```css
.class {
width: 2;
}
```
You may also manually invoke the parser and compiler:
```javascript
var parser = new(less.Parser);
parser.parse('.class { width: (1 + 1) }', function (err, tree) {
if (err) { return console.error(err) }
console.log(tree.toCSS());
});
```
### Configuration
You may also pass options to the compiler:
```javascript
var parser = new(less.Parser)({
paths: ['.', './src/less'], // Specify search paths for @import directives
filename: 'style.less' // Specify a filename, for better error messages
});
parser.parse('.class { width: (1 + 1) }', function (e, tree) {
tree.toCSS({ compress: true }); // Minify CSS output
});
```
## More information
For general information on the language, configuration options or usage visit [lesscss.org](http://lesscss.org) or [the less wiki][wiki].
For general information on the language, configuration options or usage visit [lesscss.org](http://lesscss.org).
Here are other resources for using Less.js:
* [stackoverflow.com][so] is a great place to get answers about Less.
* [node.js tools](https://github.com/less/less.js/wiki/Converting-LESS-to-CSS) for converting Less to CSS
* [GUI compilers for Less](https://github.com/less/less.js/wiki/GUI-compilers-that-use-LESS.js)
* [Less.js Issues][issues] for reporting bugs
## Contributing
Please read [CONTRIBUTING.md](./CONTRIBUTING.md). Add unit tests for any new or changed functionality. Lint and test your code using [Grunt](http://gruntjs.com/).
@@ -283,57 +37,7 @@ Please report documentation issues in [the documentation project](https://github
### Development
#### Install Less.js
Start by either [downloading this project][download] manually, or in the command line:
```shell
git clone https://github.com/less/less.js.git "less"
```
and then `cd less`.
#### Install dependencies
To install all the dependencies for less development, run:
```shell
npm install
```
If you haven't run grunt before, install grunt-cli globally so you can just run `grunt`
```shell
npm install grunt-cli -g
```
You should now be able to build Less.js, run tests, benchmarking, and other tasks listed in the Gruntfile.
## Using Less.js Grunt
Tests, benchmarking and building is done using Grunt `<%= pkg.devDependencies.grunt %>`. If you haven't used [Grunt](http://gruntjs.com/) before, be sure to check out the [Getting Started](http://gruntjs.com/getting-started) guide, as it explains how to install and use Grunt plugins, which are necessary for development with Less.js.
The Less.js [Gruntfile](Gruntfile.js) is configured with the following "convenience tasks" :
#### test - `grunt`
Runs jshint, nodeunit and headless jasmine tests using [phantomjs](http://code.google.com/p/phantomjs/). You must have phantomjs installed for the jasmine tests to run.
#### test - `grunt benchmark`
Runs the benchmark suite.
#### build for testing browser - 'grunt browser'
This builds less.js and puts it in 'test/browser/less.js'
#### build - `grunt stable | grunt beta | grunt alpha`
Builds Less.js from from the `/lib/less` source files. This is done by the developer releasing a new release, do not do this if you are creating a pull request.
#### readme - `grunt readme`
Build the README file from [a template](build/README.md) to ensure that metadata is up-to-date and (more likely to be) correct.
Please review the [Gruntfile](Gruntfile.js) to become acquainted with the other available tasks.
**Please note** that if you have any issues installing dependencies or running any of the Gruntfile commands, please make sure to uninstall any previous versions, both in the local node_modules directory, and clear your global npm cache, and then try running `npm install` again. After that if you still have issues, please let us know about it so we can help.
Read [Developing Less](http://lesscss.org/usage/#developing-less).
## Release History
See the [changelog](CHANGELOG.md)
@@ -346,5 +50,4 @@ Licensed under the [Apache License](LICENSE).
[so]: http://stackoverflow.com/questions/tagged/twitter-bootstrap+less "StackOverflow.com"
[issues]: https://github.com/less/less.js/issues "GitHub Issues for Less.js"
[wiki]: https://github.com/less/less.js/wiki "The official wiki for Less.js"
[download]: https://github.com/less/less.js/zipball/master "Download Less.js"
[download]: https://github.com/less/less.js/zipball/master "Download Less.js"

View File

@@ -102,7 +102,9 @@ rhino:
- <%= build.less.source_map_output %>
- <%= build.source_map %>
# append rhino-specific code
# <%= build.rhinolessc %>
rhinolessc:
- <%= build.append.rhino %>
@@ -125,6 +127,7 @@ tree:
- <%= build.lib %>/tree/color.js
- <%= build.lib %>/tree/comment.js
- <%= build.lib %>/tree/condition.js
- <%= build.lib %>/tree/detached-ruleset.js
- <%= build.lib %>/tree/dimension.js
- <%= build.lib %>/tree/directive.js
- <%= build.lib %>/tree/element.js
@@ -141,6 +144,7 @@ tree:
- <%= build.lib %>/tree/quoted.js
- <%= build.lib %>/tree/rule.js
- <%= build.lib %>/tree/ruleset.js
- <%= build.lib %>/tree/ruleset-call.js
- <%= build.lib %>/tree/selector.js
- <%= build.lib %>/tree/unicode-descriptor.js
- <%= build.lib %>/tree/url.js

View File

@@ -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

7624
dist/less-1.6.2.js vendored Normal file

File diff suppressed because it is too large Load Diff

16
dist/less-1.6.2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

7627
dist/less-1.6.3.js vendored Normal file

File diff suppressed because it is too large Load Diff

16
dist/less-1.6.3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

7921
dist/less-1.7.0.js vendored Normal file

File diff suppressed because it is too large Load Diff

16
dist/less-1.7.0.min.js vendored Normal file

File diff suppressed because one or more lines are too long

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

File diff suppressed because one or more lines are too long

7938
dist/less-1.7.2.js vendored Normal file

File diff suppressed because it is too large Load Diff

16
dist/less-1.7.2.min.js vendored Normal file

File diff suppressed because one or more lines are too long

7942
dist/less-1.7.3.js vendored Normal file

File diff suppressed because it is too large Load Diff

16
dist/less-1.7.3.min.js vendored Normal file

File diff suppressed because one or more lines are too long

9017
dist/less-rhino-1.6.2.js vendored Normal file

File diff suppressed because it is too large Load Diff

9020
dist/less-rhino-1.6.3.js vendored Normal file

File diff suppressed because it is too large Load Diff

9301
dist/less-rhino-1.7.0.js vendored Normal file

File diff suppressed because it is too large Load Diff

9311
dist/less-rhino-1.7.1.js vendored Normal file

File diff suppressed because it is too large Load Diff

9313
dist/less-rhino-1.7.2.js vendored Normal file

File diff suppressed because it is too large Load Diff

9317
dist/less-rhino-1.7.3.js vendored Normal file

File diff suppressed because it is too large Load Diff

449
dist/lessc-rhino-1.6.2.js vendored Normal file
View File

@@ -0,0 +1,449 @@
/* LESS.js v1.6.2 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; }
print(formatError(ctx, options));
}
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);
}
console.log("done");
}(arguments));

449
dist/lessc-rhino-1.6.3.js vendored Normal file
View File

@@ -0,0 +1,449 @@
/* LESS.js v1.6.3 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; }
print(formatError(ctx, options));
}
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);
}
console.log("done");
}(arguments));

449
dist/lessc-rhino-1.7.0.js vendored Normal file
View File

@@ -0,0 +1,449 @@
/* LESS.js v1.7.0 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; }
print(formatError(ctx, options));
}
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);
}
console.log("done");
}(arguments));

449
dist/lessc-rhino-1.7.1.js vendored Normal file
View 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));

449
dist/lessc-rhino-1.7.2.js vendored Normal file
View File

@@ -0,0 +1,449 @@
/* Less.js v1.7.2 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));

449
dist/lessc-rhino-1.7.3.js vendored Normal file
View File

@@ -0,0 +1,449 @@
/* Less.js v1.7.3 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));

View File

@@ -14,17 +14,19 @@ less.env = less.env || (location.hostname == '127.0.0.1' ||
: 'production');
var logLevel = {
debug: 3,
info: 2,
errors: 1,
none: 0
};
// The amount of logging in the javascript console.
// 3 - Debug, information and errors
// 2 - Information and errors
// 1 - Errors
// 0 - None
// Defaults to 2
less.logLevel = typeof(less.logLevel) != 'undefined' ? less.logLevel : logLevel.info;
less.logLevel = typeof(less.logLevel) != 'undefined' ? less.logLevel : (less.env === 'development' ? logLevel.debug : logLevel.errors);
// Load styles asynchronously (default: false)
//
@@ -57,7 +59,7 @@ var cache = null;
var fileCache = {};
function log(str, level) {
if (less.env == 'development' && typeof(console) !== 'undefined' && less.logLevel >= level) {
if (typeof(console) !== 'undefined' && less.logLevel >= level) {
console.log('less: ' + str);
}
}
@@ -116,13 +118,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
@@ -146,6 +142,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);
@@ -159,6 +166,13 @@ function createCSS(styles, sheet, lastModified) {
}
}
function postProcessCSS(styles) {
if (less.postProcessor && typeof less.postProcessor === 'function') {
styles = less.postProcessor.call(styles, styles) || styles;
}
return styles;
}
function errorHTML(e, rootHref) {
var id = 'less-error-message:' + extractId(rootHref || "");
var template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>';
@@ -402,12 +416,12 @@ function pathDiff(url, baseUrl) {
}
function getXMLHttpRequest() {
if (window.XMLHttpRequest) {
if (window.XMLHttpRequest && (window.location.protocol !== "file:" || !("ActiveXObject" in window))) {
return new XMLHttpRequest();
} else {
try {
/*global ActiveXObject */
return new ActiveXObject("MSXML2.XMLHTTP.3.0");
return new ActiveXObject("Microsoft.XMLHTTP");
} catch (e) {
log("browser doesn't support AJAX.", logLevel.errors);
return null;
@@ -422,7 +436,7 @@ function doXHR(url, type, callback, errback) {
if (typeof(xhr.overrideMimeType) === 'function') {
xhr.overrideMimeType('text/css');
}
log("XHR: Getting '" + url + "'", logLevel.info);
log("XHR: Getting '" + url + "'", logLevel.debug);
xhr.open('GET', url, async);
xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
xhr.send(null);
@@ -575,7 +589,9 @@ function initRunningMode(){
if (e) {
error(e, sheet.href);
} else if (root) {
createCSS(root.toCSS(less), sheet, env.lastModified);
var styles = root.toCSS(less);
styles = postProcessCSS(styles);
createCSS(styles, sheet, env.lastModified);
}
});
}
@@ -644,12 +660,14 @@ less.refresh = function (reload, modifyVars) {
if (env.local) {
log("loading " + sheet.href + " from cache.", logLevel.info);
} else {
log("parsed " + sheet.href + " successfully.", logLevel.info);
createCSS(root.toCSS(less), sheet, env.lastModified);
log("parsed " + sheet.href + " successfully.", logLevel.debug);
var styles = root.toCSS(less);
styles = postProcessCSS(styles);
createCSS(styles, sheet, env.lastModified);
}
log("css for " + sheet.href + " generated in " + (new Date() - endTime) + 'ms', logLevel.info);
if (env.remaining === 0) {
log("css generated in " + (new Date() - startTime) + 'ms', logLevel.info);
log("less has finished. css generated in " + (new Date() - startTime) + 'ms', logLevel.info);
}
endTime = new Date();
}, reload, modifyVars);

View File

@@ -36,6 +36,8 @@
if (!this.contentsIgnoredChars) { this.contentsIgnoredChars = {}; }
if (!this.files) { this.files = {}; }
if (typeof this.paths === "string") { this.paths = [this.paths]; }
if (!this.currentFileInfo) {
var filename = (options && options.filename) || "input";
var entryPath = filename.replace(/[^\/\\]*$/, "");
@@ -54,16 +56,17 @@
};
var evalCopyProperties = [
'silent', // whether to swallow errors and warnings
'verbose', // whether to log more activity
'compress', // whether to compress
'yuicompress', // whether to compress with the outside tool yui compressor
'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
'strictMath', // whether math has to be within parenthesis
'strictUnits', // whether units need to evaluate correctly
'cleancss', // whether to compress with clean-css
'sourceMap', // whether to output a source map
'importMultiple'// whether we are currently importing multiple copies
'silent', // whether to swallow errors and warnings
'verbose', // whether to log more activity
'compress', // whether to compress
'yuicompress', // whether to compress with the outside tool yui compressor
'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
'strictMath', // whether math has to be within parenthesis
'strictUnits', // whether units need to evaluate correctly
'cleancss', // whether to compress with clean-css
'sourceMap', // whether to output a source map
'importMultiple', // whether we are currently importing multiple copies
'urlArgs' // whether to add args into url tokens
];
tree.evalEnv = function(options, frames) {

10
lib/less/fs.js Normal file
View File

@@ -0,0 +1,10 @@
var fs;
try
{
fs = require("graceful-fs");
}
catch(e)
{
fs = require("fs");
}
module.exports = fs;

View File

@@ -63,22 +63,22 @@ tree.functions = {
},
hue: function (color) {
return new(tree.Dimension)(Math.round(color.toHSL().h));
return new(tree.Dimension)(color.toHSL().h);
},
saturation: function (color) {
return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%');
return new(tree.Dimension)(color.toHSL().s * 100, '%');
},
lightness: function (color) {
return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%');
return new(tree.Dimension)(color.toHSL().l * 100, '%');
},
hsvhue: function(color) {
return new(tree.Dimension)(Math.round(color.toHSV().h));
return new(tree.Dimension)(color.toHSV().h);
},
hsvsaturation: function (color) {
return new(tree.Dimension)(Math.round(color.toHSV().s * 100), '%');
return new(tree.Dimension)(color.toHSV().s * 100, '%');
},
hsvvalue: function (color) {
return new(tree.Dimension)(Math.round(color.toHSV().v * 100), '%');
return new(tree.Dimension)(color.toHSV().v * 100, '%');
},
red: function (color) {
return new(tree.Dimension)(color.rgb[0]);
@@ -93,7 +93,15 @@ tree.functions = {
return new(tree.Dimension)(color.toHSL().a);
},
luma: function (color) {
return new(tree.Dimension)(Math.round(color.luma() * color.alpha * 100), '%');
return new(tree.Dimension)(color.luma() * color.alpha * 100, '%');
},
luminance: function (color) {
var luminance =
(0.2126 * color.rgb[0] / 255)
+ (0.7152 * color.rgb[1] / 255)
+ (0.0722 * color.rgb[2] / 255);
return new(tree.Dimension)(luminance * color.alpha * 100, '%');
},
saturate: function (color, amount) {
// filter: saturate(3.2);
@@ -213,30 +221,45 @@ tree.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"));
},
'%': function (quoted /* arg, arg, ...*/) {
replace: function (string, pattern, replacement, flags) {
var result = string.value;
result = result.replace(new RegExp(pattern.value, flags ? flags.value : ''), replacement.value);
return new(tree.Quoted)(string.quote || '', result, string.escaped);
},
'%': function (string /* arg, arg, ...*/) {
var args = Array.prototype.slice.call(arguments, 1),
str = quoted.value;
result = string.value;
for (var i = 0; i < args.length; i++) {
/*jshint loopfunc:true */
str = str.replace(/%[sda]/i, function(token) {
result = result.replace(/%[sda]/i, function(token) {
var value = token.match(/s/i) ? args[i].value : args[i].toCSS();
return token.match(/[A-Z]$/) ? encodeURIComponent(value) : value;
});
}
str = str.replace(/%%/g, '%');
return new(tree.Quoted)('"' + str + '"', str);
result = result.replace(/%%/g, '%');
return new(tree.Quoted)(string.quote || '', result, string.escaped);
},
unit: function (val, unit) {
if(!(val instanceof tree.Dimension)) {
throw { type: "Argument", message: "the first argument to unit must be a number" + (val instanceof tree.Operation ? ". Have you forgotten parenthesis?" : "") };
}
return new(tree.Dimension)(val.value, unit ? unit.toCSS() : "");
if (unit) {
if (unit instanceof tree.Keyword) {
unit = unit.value;
} else {
unit = unit.toCSS();
}
} else {
unit = "";
}
return new(tree.Dimension)(val.value, unit);
},
convert: function (val, unit) {
return val.convertTo(unit.value);
@@ -264,28 +287,34 @@ tree.functions = {
_minmax: function (isMin, args) {
args = Array.prototype.slice.call(args);
switch(args.length) {
case 0: throw { type: "Argument", message: "one or more arguments required" };
case 1: return args[0];
case 0: throw { type: "Argument", message: "one or more arguments required" };
}
var i, j, current, currentUnified, referenceUnified, unit,
var i, j, current, currentUnified, referenceUnified, unit, unitStatic, unitClone,
order = [], // elems only contains original argument values.
values = {}; // key is the unit.toString() for unified tree.Dimension values,
// value is the index into the order array.
for (i = 0; i < args.length; i++) {
current = args[i];
if (!(current instanceof tree.Dimension)) {
order.push(current);
if(Array.isArray(args[i].value)) {
Array.prototype.push.apply(args, Array.prototype.slice.call(args[i].value));
}
continue;
}
currentUnified = current.unify();
unit = currentUnified.unit.toString();
j = values[unit];
currentUnified = current.unit.toString() === "" && unitClone !== undefined ? new(tree.Dimension)(current.value, unitClone).unify() : current.unify();
unit = currentUnified.unit.toString() === "" && unitStatic !== undefined ? unitStatic : currentUnified.unit.toString();
unitStatic = unit !== "" && unitStatic === undefined || unit !== "" && order[0].unify().unit.toString() === "" ? unit : unitStatic;
unitClone = unit !== "" && unitClone === undefined ? current.unit.toString() : unitClone;
j = values[""] !== undefined && unit !== "" && unit === unitStatic ? values[""] : values[unit];
if (j === undefined) {
if(unitStatic !== undefined && unit !== unitStatic) {
throw{ type: "Argument", message: "incompatible types" };
}
values[unit] = order.length;
order.push(current);
continue;
}
referenceUnified = order[j].unify();
referenceUnified = order[j].unit.toString() === "" && unitClone !== undefined ? new(tree.Dimension)(order[j].value, unitClone).unify() : order[j].unify();
if ( isMin && currentUnified.value < referenceUnified.value ||
!isMin && currentUnified.value > referenceUnified.value) {
order[j] = current;
@@ -294,8 +323,7 @@ tree.functions = {
if (order.length == 1) {
return order[0];
}
args = order.map(function (a) { return a.toCSS(this.env); })
.join(this.env.compress ? "," : ", ");
args = order.map(function (a) { return a.toCSS(this.env); }).join(this.env.compress ? "," : ", ");
return new(tree.Anonymous)((isMin ? "min" : "max") + "(" + args + ")");
},
min: function () {
@@ -304,6 +332,9 @@ tree.functions = {
max: function () {
return this._minmax(false, arguments);
},
"get-unit": function (n) {
return new(tree.Anonymous)(n.unit);
},
argb: function (color) {
return new(tree.Anonymous)(color.toARGB());
},
@@ -361,12 +392,12 @@ tree.functions = {
},
shade: function(color, amount) {
return this.mix(this.rgb(0, 0, 0), color, amount);
},
},
extract: function(values, index) {
index = index.value - 1; // (1-based index)
index = index.value - 1; // (1-based index)
// handle non-array values as an array of length 1
// return 'undefined' if index is invalid
return Array.isArray(values.value)
return Array.isArray(values.value)
? values.value[index] : Array(values)[index];
},
length: function(values) {
@@ -383,7 +414,7 @@ tree.functions = {
var mimetype = mimetypeNode.value;
var filePath = (filePathNode && filePathNode.value);
var fs = require('fs'),
var fs = require('./fs'),
path = require('path'),
useBase64 = false;
@@ -552,15 +583,15 @@ tree._mime = {
var mathFunctions = {
// name, unit
ceil: null,
floor: null,
sqrt: null,
ceil: null,
floor: null,
sqrt: null,
abs: null,
tan: "",
sin: "",
tan: "",
sin: "",
cos: "",
atan: "rad",
asin: "rad",
atan: "rad",
asin: "rad",
acos: "rad"
};
@@ -585,19 +616,19 @@ function colorBlend(mode, color1, color2) {
var ab = color1.alpha, cb, // backdrop
as = color2.alpha, cs, // source
ar, cr, r = []; // result
ar = as + ab * (1 - as);
for (var i = 0; i < 3; i++) {
cb = color1.rgb[i] / 255;
cs = color2.rgb[i] / 255;
cr = mode(cb, cs);
if (ar) {
cr = (as * cs + ab * (cb
cr = (as * cs + ab * (cb
- as * (cb + cs - cr))) / ar;
}
r[i] = cr * 255;
}
return new(tree.Color)(r, ar);
}
@@ -607,7 +638,7 @@ var colorBlendMode = {
},
screen: function(cb, cs) {
return cb + cs - cb * cs;
},
},
overlay: function(cb, cs) {
cb *= 2;
return (cb <= 1)
@@ -620,7 +651,7 @@ var colorBlendMode = {
e = 1;
d = (cb > 0.25) ? Math.sqrt(cb)
: ((16 * cb - 12) * cb + 4) * cb;
}
}
return cb - (1 - 2 * cs) * e * (d - cb);
},
hardlight: function(cb, cs) {
@@ -667,25 +698,25 @@ tree.defaultFunc = {
function initFunctions() {
var f, tf = tree.functions;
// math
for (f in mathFunctions) {
if (mathFunctions.hasOwnProperty(f)) {
tf[f] = _math.bind(null, Math[f], mathFunctions[f]);
}
}
// color blending
for (f in colorBlendMode) {
if (colorBlendMode.hasOwnProperty(f)) {
tf[f] = colorBlend.bind(null, colorBlendMode[f]);
}
}
// default
f = tree.defaultFunc;
tf["default"] = f.eval.bind(f);
} initFunctions();
function hsla(color) {
@@ -717,6 +748,12 @@ function clamp(val) {
return Math.min(1, Math.max(0, val));
}
tree.fround = function(env, 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) {
this.env = env;
this.currentFileInfo = currentFileInfo;

View File

@@ -1,10 +1,19 @@
(function (tree) {
tree.importVisitor = function(importer, finish, evalEnv) {
tree.importVisitor = function(importer, finish, evalEnv, onceFileDetectionMap, recursionDetector) {
this._visitor = new tree.visitor(this);
this._importer = importer;
this._finish = finish;
this.env = evalEnv || new tree.evalEnv();
this.importCount = 0;
this.onceFileDetectionMap = onceFileDetectionMap || {};
this.recursionDetector = {};
if (recursionDetector) {
for(var fullFilename in recursionDetector) {
if (recursionDetector.hasOwnProperty(fullFilename)) {
this.recursionDetector[fullFilename] = true;
}
}
}
};
tree.importVisitor.prototype = {
@@ -51,10 +60,22 @@
env.importMultiple = true;
}
this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, imported, fullPath) {
this._importer.push(importNode.getPath(), importNode.currentFileInfo, importNode.options, function (e, root, importedAtRoot, fullPath) {
if (e && !e.filename) { e.index = importNode.index; e.filename = importNode.currentFileInfo.filename; }
if (imported && !env.importMultiple) { importNode.skip = imported; }
if (!env.importMultiple) {
if (importedAtRoot) {
importNode.skip = true;
} else {
importNode.skip = function() {
if (fullPath in importVisitor.onceFileDetectionMap) {
return true;
}
importVisitor.onceFileDetectionMap[fullPath] = true;
return false;
};
}
}
var subFinish = function(e) {
importVisitor.importCount--;
@@ -67,8 +88,11 @@
if (root) {
importNode.root = root;
importNode.importedFilename = fullPath;
if (!inlineCSS && !importNode.skip) {
new(tree.importVisitor)(importVisitor._importer, subFinish, env)
var duplicateImport = importedAtRoot || fullPath in importVisitor.recursionDetector;
if (!inlineCSS && (env.importMultiple || !duplicateImport)) {
importVisitor.recursionDetector[fullPath] = true;
new(tree.importVisitor)(importVisitor._importer, subFinish, env, importVisitor.onceFileDetectionMap, importVisitor.recursionDetector)
.run(root);
return;
}

View File

@@ -1,10 +1,10 @@
var path = require('path'),
url = require('url'),
request,
fs = require('fs');
fs = require('./fs');
var less = {
version: [1, 6, 1],
version: [1, 7, 3],
Parser: require('./parser').Parser,
tree: require('./tree'),
render: function (input, options, callback) {
@@ -20,8 +20,13 @@ var less = {
if (callback) {
parser.parse(input, function (e, root) {
try { callback(e, root && root.toCSS && root.toCSS(options)); }
catch (err) { callback(err); }
if (e) { callback(e); return; }
var css;
try {
css = root && root.toCSS && root.toCSS(options);
}
catch (err) { callback(err); return; }
callback(null, css);
});
} else {
ee = new (require('events').EventEmitter)();
@@ -29,7 +34,7 @@ var less = {
process.nextTick(function () {
parser.parse(input, function (e, root) {
if (e) { return ee.emit('error', e); }
try { ee.emit('success', root.toCSS(options)); }
try { ee.emit('success', root.toCSS(options)); }
catch (err) { ee.emit('error', err); }
});
});
@@ -92,16 +97,36 @@ var less = {
}
};
['color', 'directive', 'operation', 'dimension',
'keyword', 'variable', 'ruleset', 'element',
'selector', 'quoted', 'expression', 'rule',
'call', 'url', 'alpha', 'import',
'mixin', 'comment', 'anonymous', 'value',
'javascript', 'assignment', 'condition', 'paren',
'media', 'unicode-descriptor', 'negative', 'extend'
].forEach(function (n) {
require('./tree/' + n);
});
require('./tree/color');
require('./tree/directive');
require('./tree/detached-ruleset');
require('./tree/operation');
require('./tree/dimension');
require('./tree/keyword');
require('./tree/variable');
require('./tree/ruleset');
require('./tree/element');
require('./tree/selector');
require('./tree/quoted');
require('./tree/expression');
require('./tree/rule');
require('./tree/call');
require('./tree/url');
require('./tree/alpha');
require('./tree/import');
require('./tree/mixin');
require('./tree/comment');
require('./tree/anonymous');
require('./tree/value');
require('./tree/javascript');
require('./tree/assignment');
require('./tree/condition');
require('./tree/paren');
require('./tree/media');
require('./tree/unicode-descriptor');
require('./tree/negative');
require('./tree/extend');
require('./tree/ruleset-call');
var isUrlRe = /^(?:https?:)?\/\//i;
@@ -118,13 +143,13 @@ less.Parser.fileLoader = function (file, currentFileInfo, callback, env) {
function handleDataAndCallCallback(data) {
var j = file.lastIndexOf('/');
// Pass on an updated rootpath if path of imported file is relative and file
// Pass on an updated rootpath if path of imported file is relative and file
// is in a (sub|sup) directory
//
// Examples:
//
// Examples:
// - If path of imported file is 'module/nav/nav.less' and rootpath is 'less/',
// then rootpath should become 'less/module/nav/'
// - If path of imported file is '../mixins.less' and rootpath is 'less/',
// - If path of imported file is '../mixins.less' and rootpath is 'less/',
// then rootpath should become 'less/../'
if(newFileInfo.relativeUrls && !/^(?:[a-z-]+:|\/)/.test(file) && j != -1) {
var relativeSubDirectory = file.slice(0, j+1);
@@ -135,7 +160,7 @@ less.Parser.fileLoader = function (file, currentFileInfo, callback, env) {
callback(null, data, pathname, newFileInfo);
}
var isUrl = isUrlRe.test( file );
if (isUrl || isUrlRe.test(currentFileInfo.currentDirectory)) {
if (request === undefined) {
@@ -150,7 +175,16 @@ less.Parser.fileLoader = function (file, currentFileInfo, callback, env) {
var urlStr = isUrl ? file : url.resolve(currentFileInfo.currentDirectory, file),
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 (error) {
callback({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n "+ error +"\n" });
return;
}
if (res.statusCode === 404) {
callback({ type: 'File', message: "resource '" + urlStr + "' was not found\n" });
return;
@@ -158,17 +192,15 @@ less.Parser.fileLoader = function (file, currentFileInfo, callback, env) {
if (!body) {
console.error( 'Warning: Empty body (HTTP '+ res.statusCode + ') returned by "' + urlStr +'"' );
}
if (error) {
callback({ type: 'File', message: "resource '" + urlStr + "' gave this Error:\n "+ error +"\n" });
}
pathname = urlStr;
dirname = urlObj.protocol +'//'+ urlObj.host + urlObj.pathname.replace(/[^\/]*$/, '');
handleDataAndCallCallback(body);
});
} else {
var paths = [currentFileInfo.currentDirectory].concat(env.paths);
paths.push('.');
var paths = [currentFileInfo.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++) {
@@ -201,8 +233,13 @@ less.Parser.fileLoader = function (file, currentFileInfo, callback, env) {
tryPathIndex(i + 1);
} else {
fs.readFile(pathname, 'utf-8', function(e, data) {
if (e) { callback(e); }
handleDataAndCallCallback(data);
if (e) { callback(e); return; }
// do processing in the next tick to allow
// file handling to dispose
process.nextTick(function() {
handleDataAndCallCallback(data);
});
});
}
});

View File

@@ -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(" -O0, -O1, -O2 Set the parser's optimization level. The lower");

View File

@@ -43,8 +43,7 @@ less.Parser = function Parser(env) {
var input, // LeSS input string
i, // current index in `input`
j, // current chunk
temp, // temporarily holds a chunk's state, for backtracking
memo, // temporarily holds `i`, when backtracking
saveStack = [], // holds state for backtracking
furthest, // furthest index the parser has gone to
chunks, // chunkified input
current, // current chunk
@@ -74,7 +73,7 @@ less.Parser = function Parser(env) {
var fileParsedFunc = function (e, root, fullPath) {
parserImports.queue.splice(parserImports.queue.indexOf(path), 1); // Remove the path from the queue
var importedPreviously = fullPath in parserImports.files || fullPath === rootFilename;
var importedPreviously = fullPath === rootFilename;
parserImports.files[fullPath] = root; // Store the root
@@ -111,8 +110,9 @@ less.Parser = function Parser(env) {
}
};
function save() { temp = current; memo = currentPos = i; }
function restore() { current = temp; currentPos = i = memo; }
function save() { currentPos = i; saveStack.push( { current: current, i: i, j: j }); }
function restore() { var state = saveStack.pop(); current = state.current; currentPos = i = state.i; j = state.j; }
function forget() { saveStack.pop(); }
function sync() {
if (i > currentPos) {
@@ -218,6 +218,8 @@ less.Parser = function Parser(env) {
if (!current.length && (j < chunks.length - 1)) {
current = chunks[++j];
skipWhitespace(0); // skip space at the beginning of a chunk
return true; // things changed
}
return oldi !== i || oldj !== j;
@@ -372,7 +374,7 @@ less.Parser = function Parser(env) {
// Split the input into chunks.
chunks = (function (input) {
var len = input.length, level = 0, parenLevel = 0,
lastOpening, lastClosing, lastMultiComment, lastMultiCommentEndBrace,
lastOpening, lastOpeningParen, lastMultiComment, lastMultiCommentEndBrace,
chunks = [], emitFrom = 0,
parserCurrentIndex, currentChunkStartIndex, cc, cc2, matched;
@@ -403,17 +405,26 @@ less.Parser = function Parser(env) {
switch (cc) {
case 40: // (
parenLevel++; continue;
parenLevel++;
lastOpeningParen = parserCurrentIndex;
continue;
case 41: // )
parenLevel--; continue;
if (--parenLevel < 0) {
return fail("missing opening `(`");
}
continue;
case 59: // ;
if (!parenLevel) { emitChunk(); }
continue;
case 123: // {
level++; lastOpening = parserCurrentIndex; continue;
level++;
lastOpening = parserCurrentIndex;
continue;
case 125: // }
level--; lastClosing = parserCurrentIndex;
if (!level) { emitChunk(); }
if (--level < 0) {
return fail("missing opening `{`");
}
if (!level && !parenLevel) { emitChunk(); }
continue;
case 92: // \
if (parserCurrentIndex < len - 1) { parserCurrentIndex++; continue; }
@@ -457,6 +468,7 @@ less.Parser = function Parser(env) {
if (parserCurrentIndex == len - 1) {
return fail("missing closing `*/`", currentChunkStartIndex);
}
parserCurrentIndex++;
}
continue;
case 42: // *, check for unmatched */
@@ -468,16 +480,13 @@ less.Parser = function Parser(env) {
}
if (level !== 0) {
if (level > 0) {
if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) {
return fail("missing closing `}` or `*/`", lastOpening);
} else {
return fail("missing closing `}`", lastOpening);
}
if ((lastMultiComment > lastOpening) && (lastMultiCommentEndBrace > lastMultiComment)) {
return fail("missing closing `}` or `*/`", lastOpening);
} else {
return fail("missing closing `}`", lastOpening);
}
return fail("missing opening `{`", lastClosing);
} else if (parenLevel !== 0) {
return fail((parenLevel > 0) ? "missing closing `)`" : "missing opening `(`");
return fail("missing closing `)`", lastOpeningParen);
}
emitChunk(true);
@@ -508,7 +517,7 @@ less.Parser = function Parser(env) {
var evaldRoot,
css,
evalEnv = new tree.evalEnv(options);
//
// Allows setting variables with a hash, so:
//
@@ -589,7 +598,8 @@ less.Parser = function Parser(env) {
css = evaldRoot.toCSS({
compress: Boolean(options.compress),
dumpLineNumbers: env.dumpLineNumbers,
strictUnits: Boolean(options.strictUnits)});
strictUnits: Boolean(options.strictUnits),
numPrecision: 8});
} catch (e) {
throw new(LessError)(e, env);
}
@@ -675,7 +685,7 @@ less.Parser = function Parser(env) {
//
// Ruleset -> Rule -> Value -> Expression -> Entity
//
// Here's some LESS code:
// Here's some Less code:
//
// .class {
// color: #fff;
@@ -719,7 +729,7 @@ less.Parser = function Parser(env) {
while (current)
{
node = this.extendRule() || mixin.definition() || this.rule() || this.ruleset() ||
mixin.call() || this.comment() || this.directive();
mixin.call() || this.comment() || this.rulesetCall() || this.directive();
if (node) {
root.push(node);
} else {
@@ -727,6 +737,9 @@ less.Parser = function Parser(env) {
break;
}
}
if (peekChar('}')) {
break;
}
}
return root;
@@ -794,7 +807,7 @@ less.Parser = function Parser(env) {
keyword: function () {
var k;
k = $re(/^[_A-Za-z-][_A-Za-z0-9-]*/);
k = $re(/^%|^[_A-Za-z-][_A-Za-z0-9-]*/);
if (k) {
var color = tree.Color.fromKeyword(k);
if (color) {
@@ -947,6 +960,11 @@ less.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]);
}
},
@@ -1017,6 +1035,19 @@ less.Parser = function Parser(env) {
if (input.charAt(i) === '@' && (name = $re(/^(@[\w-]+)\s*:/))) { return name[1]; }
},
//
// The variable part of a variable definition. Used in the `rule` parser
//
// @fink();
//
rulesetCall: function () {
var name;
if (input.charAt(i) === '@' && (name = $re(/^(@[\w-]+)\s*\(\s*\)\s*;/))) {
return new tree.RulesetCall(name[1]);
}
},
//
// extend syntax - used to extend selectors
//
@@ -1040,7 +1071,7 @@ less.Parser = function Parser(env) {
if (extendList) { extendList.push(extend); } else { extendList = [ extend ]; }
} while($char(","));
expect(/^\)/);
if (isRule) {
@@ -1056,7 +1087,7 @@ less.Parser = function Parser(env) {
extendRule: function() {
return this.extend(true);
},
//
// Mixins
//
@@ -1090,17 +1121,21 @@ less.Parser = function Parser(env) {
if (elements) { elements.push(elem); } else { elements = [ elem ]; }
c = $char('>');
}
if ($char('(')) {
args = this.args(true).args;
expectChar(')');
}
if (parsers.important()) {
important = true;
}
if (elements) {
if ($char('(')) {
args = this.args(true).args;
expectChar(')');
}
if (elements && ($char(';') || peekChar('}'))) {
return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important);
if (parsers.important()) {
important = true;
}
if (parsers.end()) {
forget();
return new(tree.mixin.Call)(elements, args, index, env.currentFileInfo, important);
}
}
restore();
@@ -1111,9 +1146,11 @@ less.Parser = function Parser(env) {
expressions = [], argsSemiColon = [], argsComma = [],
isSemiColonSeperated, expressionContainsNamed, name, nameLoop, value, arg;
save();
while (true) {
if (isCall) {
arg = parsers.expression();
arg = parsers.detachedRuleset() || parsers.expression();
} else {
parsers.comments();
if (input.charAt(i) === '.' && $re(/^\.{3}/)) {
@@ -1141,7 +1178,7 @@ less.Parser = function Parser(env) {
if (isCall) {
// Variable
if (arg.value.length == 1) {
if (arg.value && arg.value.length == 1) {
val = arg.value[0];
}
} else {
@@ -1156,7 +1193,21 @@ less.Parser = function Parser(env) {
}
expressionContainsNamed = true;
}
value = expect(parsers.expression);
// we do not support setting a ruleset as a default variable - it doesn't make sense
// However if we do want to add it, there is nothing blocking it, just don't error
// and remove isCall dependency below
value = (isCall && parsers.detachedRuleset()) || parsers.expression();
if (!value) {
if (isCall) {
error("could not understand value for named argument");
} else {
restore();
returner.args = [];
return returner;
}
}
nameLoop = (name = val.name);
} else if (!isCall && $re(/^\.{3}/)) {
returner.variadic = true;
@@ -1201,6 +1252,7 @@ less.Parser = function Parser(env) {
}
}
forget();
returner.args = isSemiColonSeperated ? argsSemiColon : argsComma;
return returner;
},
@@ -1241,12 +1293,16 @@ less.Parser = function Parser(env) {
variadic = argInfo.variadic;
// .mixincall("@{a}");
// looks a bit like a mixin definition.. so we have to be nice and restore
// looks a bit like a mixin definition..
// also
// .mixincall(@a: {rule: set;});
// so we have to be nice and restore
if (!$char(')')) {
furthest = i;
restore();
return;
}
parsers.comments();
if ($re(/^when/)) { // Guard
@@ -1256,10 +1312,13 @@ less.Parser = function Parser(env) {
ruleset = parsers.block();
if (ruleset) {
forget();
return new(tree.mixin.Definition)(name, params, ruleset, cond, variadic);
} else {
restore();
}
} else {
forget();
}
}
},
@@ -1323,10 +1382,16 @@ less.Parser = function Parser(env) {
this.entities.variableCurly();
if (! e) {
save();
if ($char('(')) {
if ((v = this.selector()) && $char(')')) {
e = new(tree.Paren)(v);
forget();
} else {
restore();
}
} else {
forget();
}
}
@@ -1344,7 +1409,7 @@ less.Parser = function Parser(env) {
//
combinator: function () {
var c = input.charAt(i);
if (c === '>' || c === '+' || c === '~' || c === '|' || c === '^') {
i++;
if (input.charAt(i) === '^') {
@@ -1429,12 +1494,28 @@ less.Parser = function Parser(env) {
}
},
blockRuleset: function() {
var block = this.block();
if (block) {
block = new tree.Ruleset(null, block);
}
return block;
},
detachedRuleset: function() {
var blockRuleset = this.blockRuleset();
if (blockRuleset) {
return new tree.DetachedRuleset(blockRuleset);
}
},
//
// div, .class, body > p {...}
//
ruleset: function () {
var selectors, s, rules, debugInfo;
save();
if (env.dumpLineNumbers) {
@@ -1459,6 +1540,7 @@ less.Parser = function Parser(env) {
}
if (selectors && (rules = this.block())) {
forget();
var ruleset = new(tree.Ruleset)(selectors, rules, env.strictImports);
if (env.dumpLineNumbers) {
ruleset.debugInfo = debugInfo;
@@ -1471,27 +1553,38 @@ less.Parser = function Parser(env) {
}
},
rule: function (tryAnonymous) {
var name, value, c = input.charAt(i), important, merge = false;
save();
var name, value, startOfRule = i, c = input.charAt(startOfRule), important, merge, isVariable;
if (c === '.' || c === '#' || c === '&') { return; }
save();
name = this.variable() || this.ruleProperty();
if (name) {
// prefer to try to parse first if its a variable or we are compressing
// but always fallback on the other one
value = !tryAnonymous && (env.compress || (name.charAt && (name.charAt(0) === '@'))) ?
(this.value() || this.anonymousValue()) :
(this.anonymousValue() || this.value());
isVariable = typeof name === "string";
important = this.important();
// a name returned by this.ruleProperty() is always an array of the form:
// ["", "string-1", ..., "string-n", ""] or ["", "string-1", ..., "string-n", "+"]
merge = name.pop && (name.pop() === "+");
if (isVariable) {
value = this.detachedRuleset();
}
if (!value) {
// prefer to try to parse first if its a variable or we are compressing
// but always fallback on the other one
value = !tryAnonymous && (env.compress || isVariable) ?
(this.value() || this.anonymousValue()) :
(this.anonymousValue() || this.value());
important = this.important();
// a name returned by this.ruleProperty() is always an array of the form:
// [string-1, ..., string-n, ""] or [string-1, ..., string-n, "+"]
// where each item is a tree.Keyword or tree.Variable
merge = !isVariable && name.pop().value;
}
if (value && this.end()) {
return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo);
forget();
return new (tree.Rule)(name, value, important, merge, startOfRule, env.currentFileInfo);
} else {
furthest = i;
restore();
@@ -1499,6 +1592,8 @@ less.Parser = function Parser(env) {
return this.rule(true);
}
}
} else {
forget();
}
},
anonymousValue: function () {
@@ -1532,6 +1627,7 @@ less.Parser = function Parser(env) {
if (dir && (path = this.entities.quoted() || this.entities.url())) {
features = this.mediaFeatures();
if ($char(';')) {
forget();
features = features && new(tree.Value)(features);
return new(tree.Import)(path, features, options, index, env.currentFileInfo);
}
@@ -1648,7 +1744,7 @@ less.Parser = function Parser(env) {
//
directive: function () {
var index = i, name, value, rules, nonVendorSpecificName,
hasBlock, hasIdentifier, hasExpression, identifier;
hasIdentifier, hasExpression, hasUnknown, hasBlock = true;
if (input.charAt(i) !== '@') { return; }
@@ -1660,7 +1756,7 @@ less.Parser = function Parser(env) {
save();
name = $re(/^@[a-z-]+/);
if (!name) { return; }
nonVendorSpecificName = name;
@@ -1669,9 +1765,8 @@ less.Parser = function Parser(env) {
}
switch(nonVendorSpecificName) {
/*
case "@font-face":
hasBlock = true;
break;
case "@viewport":
case "@top-left":
case "@top-left-corner":
@@ -1691,40 +1786,51 @@ less.Parser = function Parser(env) {
case "@right-bottom":
hasBlock = true;
break;
*/
case "@charset":
hasIdentifier = true;
hasBlock = false;
break;
case "@namespace":
hasExpression = true;
hasBlock = false;
break;
case "@keyframes":
hasIdentifier = true;
break;
case "@host":
case "@page":
case "@document":
case "@supports":
case "@keyframes":
hasBlock = true;
hasIdentifier = true;
break;
case "@namespace":
hasExpression = true;
hasUnknown = true;
break;
}
if (hasIdentifier) {
identifier = ($re(/^[^{]+/) || '').trim();
if (identifier) {
name += " " + identifier;
value = this.entity();
if (!value) {
error("expected " + name + " identifier");
}
} else if (hasExpression) {
value = this.expression();
if (!value) {
error("expected " + name + " expression");
}
} else if (hasUnknown) {
value = ($re(/^[^{;]+/) || '').trim();
if (value) {
value = new(tree.Anonymous)(value);
}
}
if (hasBlock) {
rules = this.block();
if (rules) {
return new(tree.Directive)(name, rules, index, env.currentFileInfo);
}
} else {
value = hasExpression ? this.expression() : this.entity();
if (value && $char(';')) {
var directive = new(tree.Directive)(name, value, index, env.currentFileInfo);
if (env.dumpLineNumbers) {
directive.debugInfo = getDebugInfo(i, input, env);
}
return directive;
}
rules = this.blockRuleset();
}
if (rules || (!hasBlock && value && $char(';'))) {
forget();
return new(tree.Directive)(name, value, rules, index, env.currentFileInfo,
env.dumpLineNumbers ? getDebugInfo(index, input, env) : null);
}
restore();
@@ -1780,13 +1886,17 @@ less.Parser = function Parser(env) {
if (peek(/^\/[*\/]/)) {
break;
}
save();
op = $char('/') || $char('*');
if (!op) { break; }
if (!op) { forget(); break; }
a = this.operand();
if (!a) { break; }
if (!a) { restore(); break; }
forget();
m.parensInOp = true;
a.parensInOp = true;
@@ -1810,7 +1920,7 @@ less.Parser = function Parser(env) {
if (!a) {
break;
}
m.parensInOp = true;
a.parensInOp = true;
operation = new(tree.Operation)(op, [operation || m, a], isSpaced);
@@ -1916,8 +2026,8 @@ less.Parser = function Parser(env) {
}
},
ruleProperty: function () {
var c = current, name = [], index = [], length = 0;
var c = current, name = [], index = [], length = 0, s, k;
function match(re) {
var a = re.exec(c);
if (a) {
@@ -1930,15 +2040,20 @@ less.Parser = function Parser(env) {
match(/^(\*?)/);
while (match(/^((?:[\w-]+)|(?:@\{[\w-]+\}))/)); // !
if ((name.length > 1) && match(/^\s*(\+?)\s*:/)) {
// at last, we have the complete match now. move forward,
// convert @{var}s to tree.Variable(s) and return:
if ((name.length > 1) && match(/^\s*((?:\+_|\+)?)\s*:/)) {
// at last, we have the complete match now. move forward,
// convert name particles to tree objects and return:
skipWhitespace(length);
for (var k in name) {
if (name[k].charAt(0) === '@') {
name[k] = new tree.Variable('@' + name[k].slice(2, -1),
if (name[0] === '') {
name.shift();
index.shift();
}
for (k = 0; k < name.length; k++) {
s = name[k];
name[k] = (s.charAt(0) !== '@')
? new(tree.Keyword)(s)
: new(tree.Variable)('@' + s.slice(2, -1),
index[k], env.currentFileInfo);
}
}
return name;
}
@@ -1959,4 +2074,4 @@ less.Parser.serializeVars = function(vars) {
}
return s;
};
};

View File

@@ -1,9 +1,5 @@
/*jshint rhino:true, unused: false */
/*global name:true, less, loadStyleSheet, initRhinoTest, os */
if (typeof initRhinoTest === 'function') { // definition of additional test functions (see rhino/test-header.js)
initRhinoTest();
}
/*global name:true, less, loadStyleSheet, os */
function formatError(ctx, options) {
options = options || {};
@@ -60,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) {
@@ -207,7 +204,7 @@ function writeFile(filename, content) {
switch (arg) {
case 'v':
case 'version':
console.log("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]");
console.log("lessc " + less.version.join('.') + " (Less Compiler) [JavaScript]");
continueProcessing = false;
break;
case 'verbose':
@@ -448,5 +445,4 @@ function writeFile(filename, content) {
writeError(e, options);
quit(1);
}
console.log("done");
}(arguments));

View File

@@ -127,7 +127,7 @@
if (this._writeSourceMap) {
this._writeSourceMap(sourceMapContent);
} else {
sourceMapURL = "data:application/json," + encodeURIComponent(sourceMapContent);
sourceMapURL = "data:application/json;base64," + require('./encoder.js').encodeBase64(sourceMapContent);
}
if (sourceMapURL) {

View File

@@ -18,6 +18,9 @@
},
visitMixinDefinition: function (mixinNode, visitArgs) {
// mixin definitions do not get eval'd - this means they keep state
// so we have to clear that state here so it isn't used if toCSS is called twice
mixinNode.frames = [];
return [];
},
@@ -199,14 +202,36 @@
}
Object.keys(groups).map(function (k) {
function toExpression(values) {
return new (tree.Expression)(values.map(function (p) {
return p.value;
}));
}
function toValue(values) {
return new (tree.Value)(values.map(function (p) {
return p;
}));
}
parts = groups[k];
if (parts.length > 1) {
rule = parts[0];
rule.value = new (tree.Value)(parts.map(function (p) {
return p.value;
}));
var spacedGroups = [];
var lastSpacedGroup = [];
parts.map(function (p) {
if (p.merge==="+") {
if (lastSpacedGroup.length > 0) {
spacedGroups.push(toExpression(lastSpacedGroup));
}
lastSpacedGroup = [];
}
lastSpacedGroup.push(p);
});
spacedGroups.push(toExpression(lastSpacedGroup));
rule.value = toValue(spacedGroups);
}
});
}

View File

@@ -24,7 +24,7 @@ tree.debugInfo.asComment = function(ctx) {
tree.debugInfo.asMediaQuery = function(ctx) {
return '@media -sass-debug-info{filename{font-family:' +
('file://' + ctx.debugInfo.fileName).replace(/([.:/\\])/g, function (a) {
('file://' + ctx.debugInfo.fileName).replace(/([.:\/\\])/g, function (a) {
if (a == '\\') {
a = '\/';
}
@@ -43,9 +43,9 @@ tree.find = function (obj, fun) {
tree.jsify = function (obj) {
if (Array.isArray(obj.value) && (obj.value.length > 1)) {
return '[' + obj.value.map(function (v) { return v.toCSS(false); }).join(', ') + ']';
return '[' + obj.value.map(function (v) { return v.toCSS(); }).join(', ') + ']';
} else {
return obj.toCSS(false);
return obj.toCSS();
}
};

View File

@@ -1,7 +1,7 @@
(function (tree) {
tree.Anonymous = function (string, index, currentFileInfo, mapLines) {
this.value = string.value || string;
tree.Anonymous = function (value, index, currentFileInfo, mapLines) {
this.value = value;
this.index = index;
this.mapLines = mapLines;
this.currentFileInfo = currentFileInfo;

View File

@@ -28,25 +28,36 @@ var transparentKeyword = "transparent";
tree.Color.prototype = {
type: "Color",
eval: function () { return this; },
luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); },
luma: function () {
var r = this.rgb[0] / 255,
g = this.rgb[1] / 255,
b = this.rgb[2] / 255;
r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env, doNotCompress) {
var compress = env && env.compress && !doNotCompress;
var compress = env && env.compress && !doNotCompress,
alpha = tree.fround(env, this.alpha);
// If we have some transparency, the only way to represent it
// is via `rgba`. Otherwise, we use the hex representation,
// which has better compatibility with older browsers.
// Values are capped between `0` and `255`, rounded and zero-padded.
if (this.alpha < 1) {
if (this.alpha === 0 && this.isTransparentKeyword) {
if (alpha < 1) {
if (alpha === 0 && this.isTransparentKeyword) {
return transparentKeyword;
}
return "rgba(" + this.rgb.map(function (c) {
return clamp(Math.round(c), 255);
}).concat(clamp(this.alpha, 1))
}).concat(clamp(alpha, 1))
.join(',' + (compress ? '' : ' ')) + ")";
} else {
var color = this.toRGB();
@@ -151,6 +162,8 @@ tree.Color.prototype = {
};
tree.Color.fromKeyword = function(keyword) {
keyword = keyword.toLowerCase();
if (tree.colors.hasOwnProperty(keyword)) {
// detect named color
return new(tree.Color)(tree.colors[keyword].slice(1));

View File

@@ -0,0 +1,20 @@
(function (tree) {
tree.DetachedRuleset = function (ruleset, frames) {
this.ruleset = ruleset;
this.frames = frames;
};
tree.DetachedRuleset.prototype = {
type: "DetachedRuleset",
accept: function (visitor) {
this.ruleset = visitor.visit(this.ruleset);
},
eval: function (env) {
var frames = this.frames || env.frames.slice(0);
return new tree.DetachedRuleset(this.ruleset, frames);
},
callEval: function (env) {
return this.ruleset.eval(this.frames ? new(tree.evalEnv)(env, this.frames.concat(env.frames)) : env);
}
};
})(require('../tree'));

View File

@@ -25,7 +25,7 @@ tree.Dimension.prototype = {
throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());
}
var value = this.value,
var value = tree.fround(env, this.value),
strValue = String(value);
if (value !== 0 && value < 0.000001 && value > -0.000001) {
@@ -89,17 +89,27 @@ tree.Dimension.prototype = {
compare: function (other) {
if (other instanceof tree.Dimension) {
var a = this.unify(), b = other.unify(),
aValue = a.value, bValue = b.value;
var a, b,
aValue, bValue;
if (this.unit.isEmpty() || other.unit.isEmpty()) {
a = this;
b = other;
} else {
a = this.unify();
b = other.unify();
if (a.unit.compare(b.unit) !== 0) {
return -1;
}
}
aValue = a.value;
bValue = b.value;
if (bValue > aValue) {
return -1;
} else if (bValue < aValue) {
return 1;
} else {
if (!b.unit.isEmpty() && a.unit.compare(b.unit) !== 0) {
return -1;
}
return 0;
}
} else {
@@ -108,7 +118,7 @@ tree.Dimension.prototype = {
},
unify: function () {
return this.convertTo({ length: 'm', duration: 's', angle: 'rad' });
return this.convertTo({ length: 'px', duration: 's', angle: 'rad' });
},
convertTo: function (conversions) {
@@ -161,6 +171,7 @@ tree.UnitConversions = {
'cm': 0.01,
'mm': 0.001,
'in': 0.0254,
'px': 0.0254 / 96,
'pt': 0.0254 / 72,
'pc': 0.0254 / 72 * 12
},

View File

@@ -1,58 +1,62 @@
(function (tree) {
tree.Directive = function (name, value, index, currentFileInfo) {
this.name = name;
if (Array.isArray(value)) {
this.rules = [new(tree.Ruleset)(null, value)];
this.rules[0].allowImports = true;
} else {
this.value = value;
tree.Directive = function (name, value, rules, index, currentFileInfo, debugInfo) {
this.name = name;
this.value = value;
if (rules) {
this.rules = rules;
this.rules.allowImports = true;
}
this.index = index;
this.currentFileInfo = currentFileInfo;
this.debugInfo = debugInfo;
};
tree.Directive.prototype = {
type: "Directive",
accept: function (visitor) {
if (this.rules) {
this.rules = visitor.visitArray(this.rules);
var value = this.value, rules = this.rules;
if (rules) {
rules = visitor.visit(rules);
}
if (this.value) {
this.value = visitor.visit(this.value);
if (value) {
value = visitor.visit(value);
}
},
genCSS: function (env, output) {
var value = this.value, rules = this.rules;
output.add(this.name, this.currentFileInfo, this.index);
if (this.rules) {
tree.outputRuleset(env, output, this.rules);
} else {
if (value) {
output.add(' ');
this.value.genCSS(env, output);
value.genCSS(env, output);
}
if (rules) {
tree.outputRuleset(env, output, [rules]);
} else {
output.add(';');
}
},
toCSS: tree.toCSS,
eval: function (env) {
var evaldDirective = this;
if (this.rules) {
env.frames.unshift(this);
evaldDirective = new(tree.Directive)(this.name, null, this.index, this.currentFileInfo);
evaldDirective.rules = [this.rules[0].eval(env)];
evaldDirective.rules[0].root = true;
env.frames.shift();
var value = this.value, rules = this.rules;
if (value) {
value = value.eval(env);
}
return evaldDirective;
if (rules) {
rules = rules.eval(env);
rules.root = true;
}
return new(tree.Directive)(this.name, value, rules,
this.index, this.currentFileInfo, this.debugInfo);
},
variable: function (name) { return tree.Ruleset.prototype.variable.call(this.rules[0], name); },
find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); },
rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); },
variable: function (name) { if (this.rules) return tree.Ruleset.prototype.variable.call(this.rules, name); },
find: function () { if (this.rules) return tree.Ruleset.prototype.find.apply(this.rules, arguments); },
rulesets: function () { if (this.rules) return tree.Ruleset.prototype.rulesets.apply(this.rules); },
markReferenced: function () {
var i, rules;
this.isReferenced = true;
if (this.rules) {
rules = this.rules[0].rules;
rules = this.rules.rules;
for (i = 0; i < rules.length; i++) {
if (rules[i].markReferenced) {
rules[i].markReferenced();

View File

@@ -92,7 +92,14 @@ tree.Import.prototype = {
eval: function (env) {
var ruleset, features = this.features && this.features.eval(env);
if (this.skip) { return []; }
if (this.skip) {
if (typeof this.skip === "function") {
this.skip = this.skip();
}
if (this.skip) {
return [];
}
}
if (this.options.inline) {
//todo needs to reference css file not import

View File

@@ -5,6 +5,7 @@ tree.Keyword.prototype = {
type: "Keyword",
eval: function () { return this; },
genCSS: function (env, output) {
if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; }
output.add(this.value);
},
toCSS: tree.toCSS,

View File

@@ -67,11 +67,14 @@ tree.Media.prototype = {
find: function () { return tree.Ruleset.prototype.find.apply(this.rules[0], arguments); },
rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.rules[0]); },
emptySelectors: function() {
var el = new(tree.Element)('', '&', this.index, this.currentFileInfo);
return [new(tree.Selector)([el], null, null, this.index, this.currentFileInfo)];
var el = new(tree.Element)('', '&', this.index, this.currentFileInfo),
sels = [new(tree.Selector)([el], null, null, this.index, this.currentFileInfo)];
sels[0].mediaEmpty = true;
return sels;
},
markReferenced: function () {
var i, rules = this.rules[0].rules;
this.rules[0].markReferenced();
this.isReferenced = true;
for (i = 0; i < rules.length; i++) {
if (rules[i].markReferenced) {
@@ -145,6 +148,8 @@ tree.Media.prototype = {
}
},
bubbleSelectors: function (selectors) {
if (!selectors)
return;
this.rules = [new(tree.Ruleset)(selectors.slice(0), [this.rules[0]])];
}
};

View File

@@ -19,8 +19,9 @@ tree.mixin.Call.prototype = {
}
},
eval: function (env) {
var mixins, mixin, args, rules = [], match = false, i, m, f, isRecursive, isOneFound, rule;
var candidates = [], candidate, conditionResult = [], defaultFunc = tree.defaultFunc, defaultUsed = false;
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, originalRuleset;
args = this.arguments && this.arguments.map(function (a) {
return { name: a.name, value: a.value.eval(env) };
@@ -49,7 +50,7 @@ tree.mixin.Call.prototype = {
}
if (mixin.matchArgs(args, env)) {
candidate = {mixin: mixin};
candidate = {mixin: mixin, group: defNone};
if (mixin.matchCondition) {
for (f = 0; f < 2; f++) {
@@ -58,20 +59,8 @@ tree.mixin.Call.prototype = {
}
if (conditionResult[0] || conditionResult[1]) {
if (conditionResult[0] != conditionResult[1]) {
if (defaultUsed) {
// todo: ideally, it would make sense to also print the candidate
// mixin definitions that cause the conflict (current one and the
// mixin that set defaultUsed flag). But is there any easy method
// to get their filename/line/index info here?
throw { type: 'Runtime',
message: 'Ambiguous use of `default()` found when matching for `'
+ this.format(args) + '`',
index: this.index, filename: this.currentFileInfo.filename };
}
defaultUsed = true;
candidate.matchIfDefault = true;
candidate.matchIfDefaultValue = conditionResult[1];
candidate.group = conditionResult[1] ?
defTrue : defFalse;
}
candidates.push(candidate);
@@ -86,25 +75,36 @@ tree.mixin.Call.prototype = {
}
defaultFunc.reset();
count = [0, 0, 0];
for (m = 0; m < candidates.length; m++) {
count[candidates[m].group]++;
}
if (count[defNone] > 0) {
defaultResult = defFalse;
} else {
defaultResult = defTrue;
if ((count[defTrue] + count[defFalse]) > 1) {
throw { type: 'Runtime',
message: 'Ambiguous use of `default()` found when matching for `'
+ this.format(args) + '`',
index: this.index, filename: this.currentFileInfo.filename };
}
}
for (m = 0; m < candidates.length; m++) {
candidate = candidates[m];
if (!candidate.matchIfDefault || (candidate.matchIfDefaultValue == (candidates.length == 1))) {
candidate = candidates[m].group;
if ((candidate === defNone) || (candidate === defaultResult)) {
try {
mixin = candidate.mixin;
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;
}
//if (this.important) {
// isImportant = env.isImportant;
// env.isImportant = true;
//}
Array.prototype.push.apply(
rules, mixin.eval(env, args, this.important).rules);
//if (this.important) {
// env.isImportant = isImportant;
//}
rules, mixin.evalCall(env, args, this.important).rules);
} catch (e) {
throw { message: e.message, index: this.index, filename: this.currentFileInfo.filename, stack: e.stack };
}
@@ -151,7 +151,7 @@ tree.mixin.Call.prototype = {
}
};
tree.mixin.Definition = function (name, params, rules, condition, variadic) {
tree.mixin.Definition = function (name, params, rules, condition, variadic, frames) {
this.name = name;
this.selectors = [new(tree.Selector)([new(tree.Element)(null, name, this.index, this.currentFileInfo)])];
this.params = params;
@@ -165,7 +165,7 @@ tree.mixin.Definition = function (name, params, rules, condition, variadic) {
else { return count; }
}, 0);
this.parent = tree.Ruleset.prototype;
this.frames = [];
this.frames = frames;
};
tree.mixin.Definition.prototype = {
type: "MixinDefinition",
@@ -188,14 +188,15 @@ tree.mixin.Definition.prototype = {
var frame = new(tree.Ruleset)(null, null),
varargs, arg,
params = this.params.slice(0),
i, j, val, name, isNamedFound, argIndex;
i, j, val, name, isNamedFound, argIndex, argsLength = 0;
mixinEnv = new tree.evalEnv(mixinEnv, [frame].concat(mixinEnv.frames));
if (args) {
args = args.slice(0);
argsLength = args.length;
for(i = 0; i < args.length; i++) {
for(i = 0; i < argsLength; i++) {
arg = args[i];
if (name = (arg && arg.name)) {
isNamedFound = false;
@@ -225,9 +226,9 @@ tree.mixin.Definition.prototype = {
arg = args && args[argIndex];
if (name = params[i].name) {
if (params[i].variadic && args) {
if (params[i].variadic) {
varargs = [];
for (j = argIndex; j < args.length; j++) {
for (j = argIndex; j < argsLength; j++) {
varargs.push(args[j].value.eval(env));
}
frame.prependRule(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env)));
@@ -240,7 +241,7 @@ tree.mixin.Definition.prototype = {
frame.resetCache();
} else {
throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
' (' + args.length + ' for ' + this.arity + ')' };
' (' + argsLength + ' for ' + this.arity + ')' };
}
frame.prependRule(new(tree.Rule)(name, val));
@@ -249,7 +250,7 @@ tree.mixin.Definition.prototype = {
}
if (params[i].variadic && args) {
for (j = argIndex; j < args.length; j++) {
for (j = argIndex; j < argsLength; j++) {
evaldArguments[j] = args[j].value.eval(env);
}
}
@@ -258,9 +259,12 @@ tree.mixin.Definition.prototype = {
return frame;
},
eval: function (env, args, important) {
eval: function (env) {
return new tree.mixin.Definition(this.name, this.params, this.rules, this.condition, this.variadic, this.frames || env.frames.slice(0));
},
evalCall: function (env, args, important) {
var _arguments = [],
mixinFrames = this.frames.concat(env.frames),
mixinFrames = this.frames ? this.frames.concat(env.frames) : env.frames,
frame = this.evalParams(env, new(tree.evalEnv)(env, mixinFrames), args, _arguments),
rules, ruleset;
@@ -279,7 +283,7 @@ tree.mixin.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;

View File

@@ -33,14 +33,22 @@ tree.Quoted.prototype = {
if (!x.toCSS) {
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;
}
return left < right ? -1 : 1;
}
};

View File

@@ -2,7 +2,7 @@
tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) {
this.name = name;
this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]);
this.value = (value instanceof tree.Value || value instanceof tree.Ruleset) ? value : new(tree.Value)([value]);
this.important = important ? ' ' + important.trim() : '';
this.merge = merge;
this.index = index;
@@ -30,25 +30,36 @@ tree.Rule.prototype = {
},
toCSS: tree.toCSS,
eval: function (env) {
var strictMathBypass = false;
var name = this.name.map ?
this.name.map( function(v) {
return v.eval ? v.eval(env).value : v;
}).join('') : this.name;
var strictMathBypass = false, name = this.name, evaldValue;
if (typeof name !== "string") {
// expand 'primitive' name directly to get
// things faster (~10% for benchmark.less):
name = (name.length === 1)
&& (name[0] instanceof tree.Keyword)
? name[0].value : evalName(env, name);
}
if (name === "font" && !env.strictMath) {
strictMathBypass = true;
env.strictMath = true;
}
try {
evaldValue = this.value.eval(env);
if (!this.variable && evaldValue.type === "DetachedRuleset") {
throw { message: "Rulesets cannot be evaluated on a property.",
index: this.index, filename: this.currentFileInfo.filename };
}
return new(tree.Rule)(name,
this.value.eval(env),
evaldValue,
this.important,
this.merge,
this.index, this.currentFileInfo, this.inline);
}
catch(e) {
if (e.index === undefined) {
if (typeof e.index !== 'number') {
e.index = this.index;
e.filename = this.currentFileInfo.filename;
}
throw e;
}
@@ -67,4 +78,13 @@ tree.Rule.prototype = {
}
};
function evalName(env, name) {
var value = "", i, n = name.length,
output = {add: function (s) {value += s;}};
for (i = 0; i < n; i++) {
name[i].eval(env).genCSS(env, output);
}
return value;
}
})(require('../tree'));

View File

@@ -0,0 +1,16 @@
(function (tree) {
tree.RulesetCall = function (variable) {
this.variable = variable;
};
tree.RulesetCall.prototype = {
type: "RulesetCall",
accept: function (visitor) {
},
eval: function (env) {
var detachedRuleset = new(tree.Variable)(this.variable).eval(env);
return detachedRuleset.callEval(env);
}
};
})(require('../tree'));

View File

@@ -20,7 +20,8 @@ tree.Ruleset.prototype = {
},
eval: function (env) {
var thisSelectors = this.selectors, selectors,
selCnt, i, defaultFunc = tree.defaultFunc;
selCnt, selector, i, defaultFunc = tree.defaultFunc, hasOnePassingSelector = false;
if (thisSelectors && (selCnt = thisSelectors.length)) {
selectors = [];
defaultFunc.error({
@@ -28,14 +29,20 @@ tree.Ruleset.prototype = {
message: "it is currently only allowed in parametric mixin guards,"
});
for (i = 0; i < selCnt; i++) {
selectors.push(thisSelectors[i].eval(env));
selector = thisSelectors[i].eval(env);
selectors.push(selector);
if (selector.evaldCondition) {
hasOnePassingSelector = true;
}
}
defaultFunc.reset();
} else {
hasOnePassingSelector = true;
}
var rules = this.rules ? this.rules.slice(0) : null,
ruleset = new(tree.Ruleset)(selectors, rules, this.strictImports),
rule;
rule, subRule;
ruleset.originalRuleset = this;
ruleset.root = this.root;
@@ -45,6 +52,10 @@ tree.Ruleset.prototype = {
if(this.debugInfo) {
ruleset.debugInfo = this.debugInfo;
}
if (!hasOnePassingSelector) {
rules.length = 0;
}
// push the current ruleset to the frames stack
var envFrames = env.frames;
@@ -66,8 +77,8 @@ tree.Ruleset.prototype = {
// 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] instanceof tree.mixin.Definition) {
rsRules[i].frames = envFrames.slice(0);
if (rsRules[i] instanceof tree.mixin.Definition || rsRules[i] instanceof tree.DetachedRuleset) {
rsRules[i] = rsRules[i].eval(env);
}
}
@@ -90,14 +101,46 @@ tree.Ruleset.prototype = {
rsRuleCnt += rules.length - 1;
i += rules.length-1;
ruleset.resetCache();
} else if (rsRules[i] instanceof tree.RulesetCall) {
/*jshint loopfunc:true */
rules = rsRules[i].eval(env).rules.filter(function(r) {
if ((r instanceof tree.Rule) && r.variable) {
// do not pollute the scope at all
return false;
}
return true;
});
rsRules.splice.apply(rsRules, [i, 1].concat(rules));
rsRuleCnt += rules.length - 1;
i += rules.length-1;
ruleset.resetCache();
}
}
// Evaluate everything else
for (i = 0; i < rsRuleCnt; i++) {
for (i = 0; i < rsRules.length; i++) {
rule = rsRules[i];
if (! (rule instanceof tree.mixin.Definition)) {
rsRules[i] = rule.eval ? rule.eval(env) : rule;
if (! (rule instanceof tree.mixin.Definition || rule instanceof tree.DetachedRuleset)) {
rsRules[i] = rule = rule.eval ? rule.eval(env) : rule;
}
}
// Evaluate everything else
for (i = 0; i < rsRules.length; i++) {
rule = rsRules[i];
// for rulesets, check if it is a css guard and can be removed
if (rule instanceof tree.Ruleset && rule.selectors && rule.selectors.length === 1) {
// check if it can be folded in (e.g. & where)
if (rule.selectors[0].isJustParentSelector()) {
rsRules.splice(i--, 1);
for(var j = 0; j < rule.rules.length; j++) {
subRule = rule.rules[j];
if (!(subRule instanceof tree.Rule) || !subRule.variable) {
rsRules.splice(++i, 0, subRule);
}
}
}
}
}
@@ -142,8 +185,12 @@ tree.Ruleset.prototype = {
matchArgs: function (args) {
return !args || args.length === 0;
},
// lets you call a css selector with a guard
matchCondition: function (args, env) {
var lastSelector = this.selectors[this.selectors.length-1];
if (!lastSelector.evaldCondition) {
return false;
}
if (lastSelector.condition &&
!lastSelector.condition.eval(
new(tree.evalEnv)(env,
@@ -324,6 +371,9 @@ tree.Ruleset.prototype = {
toCSS: tree.toCSS,
markReferenced: function () {
if (!this.selectors) {
return;
}
for (var s = 0; s < this.selectors.length; s++) {
this.selectors[s].markReferenced();
}
@@ -405,7 +455,7 @@ tree.Ruleset.prototype = {
// it is not lost
if (sel.length > 0) {
sel[0].elements = sel[0].elements.slice(0);
sel[0].elements.push(new(tree.Element)(el.combinator, '', 0, el.index, el.currentFileInfo));
sel[0].elements.push(new(tree.Element)(el.combinator, '', el.index, el.currentFileInfo));
}
selectorsMultiplied.push(sel);
}

View File

@@ -25,40 +25,73 @@ tree.Selector.prototype = {
},
createDerived: function(elements, extendList, evaldCondition) {
evaldCondition = (evaldCondition != null) ? evaldCondition : this.evaldCondition;
var newSelector = new(tree.Selector)(elements, extendList || this.extendList, this.condition, this.index, this.currentFileInfo, this.isReferenced);
var newSelector = new(tree.Selector)(elements, extendList || this.extendList, null, this.index, this.currentFileInfo, this.isReferenced);
newSelector.evaldCondition = evaldCondition;
newSelector.mediaEmpty = this.mediaEmpty;
return newSelector;
},
match: function (other) {
var elements = this.elements,
len = elements.length,
oelements, olen, i;
oelements = other.elements.map( function(v) {
return v.combinator.value + (v.value.value || v.value);
}).join("").match(/[,&#\.\w-]([\w-]|(\\.))*/g);
// ^ regexp could be more simple but see test/less/css-escapes.less:17, doh!
if (!oelements) {
return 0;
}
olen, i;
if (oelements[0] === "&") {
oelements.shift();
}
other.CacheElements();
olen = oelements.length;
olen = other._elements.length;
if (olen === 0 || len < olen) {
return 0;
} else {
for (i = 0; i < olen; i++) {
if (elements[i].value !== oelements[i]) {
if (elements[i].value !== other._elements[i]) {
return 0;
}
}
}
return olen; // return number of matched elements
},
CacheElements: function(){
var css = '', len, v, i;
if( !this._elements ){
len = this.elements.length;
for(i = 0; i < len; i++){
v = this.elements[i];
css += v.combinator.value;
if( !v.value.value ){
css += v.value;
continue;
}
if( typeof v.value.value !== "string" ){
css = '';
break;
}
css += v.value.value;
}
this._elements = css.match(/[,&#\.\w-]([\w-]|(\\.))*/g);
if (this._elements) {
if (this._elements[0] === "&") {
this._elements.shift();
}
} else {
this._elements = [];
}
}
},
isJustParentSelector: function() {
return !this.mediaEmpty &&
this.elements.length === 1 &&
this.elements[0].value === '&' &&
(this.elements[0].combinator.value === ' ' || this.elements[0].combinator.value === '');
},
eval: function (env) {
var evaldCondition = this.condition && this.condition.eval(env),
elements = this.elements, extendList = this.extendList;

View File

@@ -31,6 +31,19 @@ tree.URL.prototype = {
}
val.value = ctx.normalizePath(val.value);
// Add url args if enabled
if (ctx.urlArgs) {
if (!val.value.match(/^\s*data:/)) {
var delimiter = val.value.indexOf('?') === -1 ? '?' : '&';
var urlArgs = delimiter + ctx.urlArgs;
if (val.value.indexOf('#') !== -1) {
val.value = val.value.replace('#', urlArgs + '#');
} else {
val.value += urlArgs;
}
}
}
}
return new(tree.URL)(val, this.currentFileInfo, true);

View File

@@ -1,6 +1,6 @@
{
"name": "less",
"version": "1.6.1",
"version": "1.7.3",
"description": "Leaner CSS",
"homepage": "http://lesscss.org",
"author": {
@@ -31,34 +31,35 @@
"test": "./test"
},
"jam": {
"main": "./dist/less-1.5.0.js"
"main": "./dist/less-1.6.3.js"
},
"engines": {
"node": ">=0.4.2"
"node": ">=0.8.0"
},
"scripts": {
"test": "grunt test"
},
"optionalDependencies": {
"mime": "1.2.x",
"request": ">=2.12.0",
"graceful-fs": "~2.0.3",
"mime": "~1.2.11",
"request": "~2.34.0",
"mkdirp": "~0.3.5",
"clean-css": "2.0.x",
"clean-css": "2.1.x",
"source-map": "0.1.x"
},
"devDependencies": {
"diff": "~1.0",
"grunt": "~0.4.1",
"grunt": "~0.4.2",
"grunt-contrib-clean": "~0.5.0",
"grunt-contrib-concat": "~0.3.0",
"grunt-contrib-connect": "~0.3.0",
"grunt-contrib-concat": "~0.4.0",
"grunt-contrib-connect": "~0.7.0",
"grunt-contrib-jasmine": "~0.5.2",
"grunt-contrib-jshint": "~0.7.2",
"grunt-contrib-uglify": "~0.2.7",
"grunt-shell": "~0.3.1",
"http-server": "~0.5.5",
"matchdep": "~0.1.2",
"time-grunt": "~0.1.1"
"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.3.1"
},
"keywords": [
"compile less",
@@ -85,4 +86,4 @@
"variables in css",
"css less"
]
}
}

View File

@@ -0,0 +1,4 @@
hr {height:50px;}
.test {
color: #ffffff;
}

View File

@@ -0,0 +1,4 @@
@color: white;
.test {
color: @color;
}

View File

@@ -0,0 +1,4 @@
var less = {};
less.postProcessor = function(styles) {
return 'hr {height:50px;}\n' + styles;
};

View File

@@ -0,0 +1,3 @@
describe("less.js postProcessor", function() {
testLessEqualsInDocument();
});

View File

@@ -1,7 +1,7 @@
.comma-delimited {
text-shadow: -1px -1px 1px #ff0000, 6px 5px 5px #ffff00;
-moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset, 0pt 4px 6px rgba(255, 255, 255, 0.4) inset;
-webkit-transform: rotate(-0.0000000001deg);
-webkit-transform: rotate(0deg);
}
@font-face {
font-family: Headline;
@@ -127,3 +127,6 @@ h1 {
body ^^ .shadow {
display: done;
}
#issue2066 {
background: url('/images/icon-team.svg') 0 0 / contain;
}

View File

@@ -2,7 +2,7 @@
color: green;
}
.see-the {
color: orange;
color: green;
}
.hide-the {
color: green;
@@ -16,3 +16,22 @@
.inheritance:hover {
color: pink;
}
.clsWithGuard {
dispaly: none;
}
.dont-split-me-up {
width: 1px;
color: red;
height: 1px;
}
+ .dont-split-me-up {
sibling: true;
}
.scope-check {
sub-prop: 2px;
prop: 1px;
}
.scope-check-2 {
sub-prop: 2px;
prop: 1px;
}

View File

@@ -1,6 +1,6 @@
@charset "UTF-8";
/* line 3, {pathimport}test.less */
@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000033}}
/* line 1, {pathimport}test.less */
@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000031}}
/* @charset "ISO-8859-1"; */
/* line 23, {pathimport}test.less */
@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000323}}
@@ -41,3 +41,9 @@
.tst2 {
color: white;
}
/* line 27, {path}linenumbers.less */
@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\0000327}}
.test {
color: red;
width: 2;
}

View File

@@ -1,5 +1,5 @@
@charset "UTF-8";
/* line 3, {pathimport}test.less */
/* line 1, {pathimport}test.less */
/* @charset "ISO-8859-1"; */
/* line 23, {pathimport}test.less */
.tst3 {
@@ -33,3 +33,8 @@
.tst2 {
color: white;
}
/* line 27, {path}linenumbers.less */
.test {
color: red;
width: 2;
}

View File

@@ -1,5 +1,5 @@
@charset "UTF-8";
@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000033}}
@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\000031}}
/* @charset "ISO-8859-1"; */
@media -sass-debug-info{filename{font-family:file\:\/\/{pathimportesc}test\.less}line{font-family:\0000323}}
.tst3 {
@@ -33,3 +33,8 @@
.tst2 {
color: white;
}
@media -sass-debug-info{filename{font-family:file\:\/\/{pathesc}linenumbers\.less}line{font-family:\0000327}}
.test {
color: red;
width: 2;
}

View File

@@ -0,0 +1,71 @@
.wrap-selector {
color: black;
one: 1px;
four: magic-frame;
visible-one: visible;
visible-two: visible;
}
.wrap-selector {
color: red;
visible-one: visible;
visible-two: visible;
}
.wrap-selector {
color: black;
background: white;
visible-one: visible;
visible-two: visible;
}
header {
background: blue;
}
@media screen and (min-width: 1200) {
header {
background: red;
}
}
html.lt-ie9 header {
background: red;
}
.wrap-selector {
test: extra-wrap;
visible-one: visible;
visible-two: visible;
}
.wrap-selector .wrap-selector {
test: wrapped-twice;
visible-one: visible;
visible-two: visible;
}
.wrap-selector {
test-func: 90;
test-arithmetic: 18px;
visible-one: visible;
visible-two: visible;
}
.without-mixins {
b: 1;
}
@media (orientation: portrait) and tv {
.my-selector {
background-color: black;
}
}
@media (orientation: portrait) and widescreen and print and tv {
.triple-wrapped-mq {
triple: true;
}
}
@media (orientation: portrait) and widescreen and tv {
.triple-wrapped-mq {
triple: true;
}
}
@media (orientation: portrait) and tv {
.triple-wrapped-mq {
triple: true;
}
}
.a {
test: test;
}

View File

@@ -19,12 +19,17 @@
luma-white: 100%;
luma-black: 0%;
luma-black-alpha: 0%;
luma-red: 21%;
luma-green: 72%;
luma-blue: 7%;
luma-yellow: 93%;
luma-cyan: 79%;
luma-white-alpha: 50%;
luma-red: 21.26%;
luma-green: 71.52%;
luma-blue: 7.22%;
luma-yellow: 92.78%;
luma-cyan: 78.74%;
luma-differs-from-luminance: 23.89833349%;
luminance-white: 100%;
luminance-black: 0%;
luminance-black-alpha: 0%;
luminance-red: 21.26%;
luminance-differs-from-luma: 36.40541176%;
contrast-filter: contrast(30%);
saturate-filter: saturate(5%);
contrast-white: #000000;
@@ -45,13 +50,24 @@
contrast-dark-thresh-per: #eeeeee;
contrast-high-thresh-per: #eeeeee;
contrast-low-thresh-per: #111111;
replace: "Hello, World!";
replace-captured: "This is a new string.";
replace-with-flags: "2 + 2 = 4";
replace-single-quoted: 'foo-2';
replace-escaped-string: bar-2;
replace-keyword: baz-2;
format: "rgb(32, 128, 64)";
format-string: "hello world";
format-multiple: "hello earth 2";
format-url-encode: "red is %23ff0000";
format-single-quoted: 'hello single world';
format-escaped-string: hello escaped world;
eformat: rgb(32, 128, 64);
unitless: 12;
unit: 14em;
unitpercentage: 100%;
get-unit: px;
get-unit-empty: ;
hue: 98;
saturation: 12%;
lightness: 95%;
@@ -69,33 +85,36 @@
ceil: 11px;
floor: 12px;
sqrt: 5px;
pi: 3.141592653589793;
pi: 3.14159265;
mod: 2m;
abs: 4%;
tan: 0.9004040442978399;
sin: 0.17364817766693033;
cos: 0.8438539587324921;
tan: 0.90040404;
sin: 0.17364818;
cos: 0.84385396;
atan: 0.1rad;
atan: 34.00000000000001deg;
atan: 45.00000000000001deg;
atan: 34deg;
atan: 45deg;
pow: 64px;
pow: 64;
pow: 27;
min: 0;
min: min("junk", 5);
min: 3pt;
min: 5;
min: 1pt;
min: 3mm;
max: 3;
max: max(8%, 1cm);
max: 5em;
percentage: 20%;
color: #ff0011;
tint: #898989;
tint-full: #ffffff;
tint-percent: #898989;
tint-negative: #656565;
shade: #686868;
shade-full: #000000;
shade-percent: #686868;
shade-negative: #868686;
fade-out: rgba(255, 0, 0, 0.95);
fade-in: rgba(255, 0, 0, 0.9500000000000001);
fade-in: rgba(255, 0, 0, 0.95);
hsv: #4d2926;
hsva: rgba(77, 40, 38, 0.2);
mix: #ff3300;

View File

@@ -1,7 +1,17 @@
/*
The media statement above is invalid (no selector)
We should ban invalid media queries with properties and no selector?
*/
input[type="text"].class#id[attr=32]:not(1) {
color: white;
}
div#id.class[a=1][b=2].class:not(1) {
color: white;
}
@media print {
.class {
color: blue;
}
.class .sub {
width: 42;
}
}
.visible {
color: red;
}
@@ -14,9 +24,6 @@
.visible:hover {
color: green;
}
.visible {
color: green;
}
.only-with-visible + .visible,
.visible + .only-with-visible,
.visible + .visible {
@@ -37,9 +44,6 @@
.b:hover {
color: green;
}
.b {
color: green;
}
.b + .b {
color: green;
}
@@ -53,3 +57,12 @@
.visible {
extend: test;
}
.test-mediaq-import {
color: green;
test: 340px;
}
@media (max-size: 450px) {
.test-mediaq-import {
color: red;
}
}

View File

@@ -21,3 +21,8 @@
ary: "1, 2, 3";
ary1: "1, 2, 3";
}
.test-tran {
1: opacity 0.3s ease-in 0.3s, max-height 0.6s linear, margin-bottom 0.4s linear;
2: [opacity 0.3s ease-in 0.3s, max-height 0.6s linear, margin-bottom 0.4s linear];
3: opacity 0.3s ease-in 0.3s, max-height 0.6s linear, margin-bottom 0.4s linear;
}

View File

@@ -24,3 +24,11 @@
transform: t1, t2, t3;
background: b1, b2, b3;
}
.test-spaced {
transform: t1 t2 t3;
background: b1 b2, b3;
}
.test-interleaved-with-spaced {
transform: t1s, t2 t3s, t4 t5s t6s;
background: b1 b2s, b3, b4;
}

View File

@@ -112,6 +112,15 @@ guard-default-multi-4 {
always: 2;
case: 2;
}
guard-default-not-ambiguos-2 {
case: 1;
not-default: 2;
}
guard-default-not-ambiguos-3 {
case: 1;
not-default-1: 2;
not-default-2: 2;
}
guard-default-scopes-3 {
3: when default;
}

View File

@@ -67,9 +67,17 @@
content: is not #0000ff its #800080;
}
.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;
}

View File

@@ -1,5 +1,6 @@
.zero {
variadic: true;
named-variadic: true;
zero: 0;
one: 1;
two: 2;
@@ -7,6 +8,7 @@
}
.one {
variadic: true;
named-variadic: true;
one: 1;
one-req: 1;
two: 2;
@@ -14,11 +16,13 @@
}
.two {
variadic: true;
named-variadic: true;
two: 2;
three: 3;
}
.three {
variadic: true;
named-variadic: true;
three-req: 3;
three: 3;
}

View File

@@ -1,4 +1,4 @@
test {
pi-test {
border: 0;
ufo-width: 50%;
*-z-border: 1px dashed blue;
@@ -8,7 +8,13 @@ test {
border-top-red-radius-: 3pt;
global-local-mixer-property: strong;
}
test-merge {
pi-test-merge {
pre-property-ish: high, middle, low, base;
pre-property-ish+: nice try dude;
}
pi-indirect-vars {
auto: auto;
}
pi-complex-values {
3px rgba(255, 255, 0, 0.5), 3.141592653589793 /* foo */3px rgba(255, 255, 0, 0.5), 3.141592653589793 /* foo */: none;
}

View File

@@ -33,3 +33,6 @@
scope: 'top level';
sub-scope-only: 'inside';
}
#parentSelectorScope {
prop: #ffffff;
}

View File

@@ -140,3 +140,14 @@ p a span {
[3] {
attributes: yes;
}
/*
Large comment means chunk will be emitted after } which means chunk will begin with whitespace...
blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank blank
*/
.blood {
color: red;
}

View File

@@ -0,0 +1,56 @@
@font-face {
src: url("/fonts/garamond-pro.ttf?424242");
src: local(Futura-Medium), url(fonts.svg?424242#MyGeometricModern) format("svg");
}
#shorthands {
background: url("http://www.lesscss.org/spec.html?424242") no-repeat 0 4px;
background: url("img.jpg?424242") center / 100px;
background: #ffffff url(image.png?424242) center / 1px 100px repeat-x scroll content-box padding-box;
}
#misc {
background-image: url(images/image.jpg?424242);
}
#data-uri {
background: url(data:image/png;charset=utf-8;base64,
kiVBORw0KGgoAAAANSUhEUgAAABAAAAAQAQMAAAAlPW0iAAAABlBMVEUAAAD/
k//+l2Z/dAAAAM0lEQVR4nGP4/5/h/1+G/58ZDrAz3D/McH8yw83NDDeNGe4U
kg9C9zwz3gVLMDA/A6P9/AFGGFyjOXZtQAAAAAElFTkSuQmCC);
background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
background-image: url(http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700&424242);
background-image: url("http://fonts.googleapis.com/css?family=\"Rokkitt\":\(400\),700&424242");
}
#svg-data-uri {
background: transparent url('data:image/svg+xml, <svg version="1.1"><g></g></svg>');
}
.comma-delimited {
background: url(bg.jpg?424242) no-repeat, url(bg.png?424242) repeat-x top left, url(bg?424242);
}
.values {
url: url('Trebuchet?424242');
}
@font-face {
font-family: xecret;
src: url('../assets/xecret.ttf?424242');
}
#secret {
font-family: xecret, sans-serif;
}
#data-uri {
uri: url("data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==");
}
#data-uri-guess {
uri: url("data:image/jpeg;base64,bm90IGFjdHVhbGx5IGEganBlZyBmaWxlCg==");
}
#data-uri-ascii {
uri-1: url("data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A");
uri-2: url("data:text/html,%3Ch1%3EThis%20page%20is%20100%25%20Awesome.%3C%2Fh1%3E%0A");
}
#svg-functions {
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjxzdG9wIG9mZnNldD0iMTAwJSIgc3RvcC1jb2xvcj0iI2ZmZmZmZiIvPjwvbGluZWFyR3JhZGllbnQ+PHJlY3QgeD0iMCIgeT0iMCIgd2lkdGg9IjEiIGhlaWdodD0iMSIgZmlsbD0idXJsKCNncmFkaWVudCkiIC8+PC9zdmc+');
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIwJSIgc3RvcC1jb2xvcj0iIzAwMDAwMCIvPjxzdG9wIG9mZnNldD0iMyUiIHN0b3AtY29sb3I9IiNmZmE1MDAiLz48c3RvcCBvZmZzZXQ9IjEwMCUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZGllbnQpIiAvPjwvc3ZnPg==');
background-image: url('data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiA/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB2ZXJzaW9uPSIxLjEiIHdpZHRoPSIxMDAlIiBoZWlnaHQ9IjEwMCUiIHZpZXdCb3g9IjAgMCAxIDEiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjxsaW5lYXJHcmFkaWVudCBpZD0iZ3JhZGllbnQiIGdyYWRpZW50VW5pdHM9InVzZXJTcGFjZU9uVXNlIiB4MT0iMCUiIHkxPSIwJSIgeDI9IjAlIiB5Mj0iMTAwJSI+PHN0b3Agb2Zmc2V0PSIxJSIgc3RvcC1jb2xvcj0iI2M0YzRjNCIvPjxzdG9wIG9mZnNldD0iMyUiIHN0b3AtY29sb3I9IiNmZmE1MDAiLz48c3RvcCBvZmZzZXQ9IjUlIiBzdG9wLWNvbG9yPSIjMDA4MDAwIi8+PHN0b3Agb2Zmc2V0PSI5NSUiIHN0b3AtY29sb3I9IiNmZmZmZmYiLz48L2xpbmVhckdyYWRpZW50PjxyZWN0IHg9IjAiIHk9IjAiIHdpZHRoPSIxIiBoZWlnaHQ9IjEiIGZpbGw9InVybCgjZ3JhZGllbnQpIiAvPjwvc3ZnPg==');
}
#data-uri-with-spaces {
background-image: url(data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==);
background-image: url(' data:image/x-png,f9difSSFIIGFIFJD1f982FSDKAA9==');
}

View File

@@ -0,0 +1,18 @@
@charset "UTF-8";
@namespace less "http://lesscss.org";
@keyframes enlarger {
from {
font-size: 12px;
}
to {
font-size: 15px;
}
}
@-webkit-keyframes reducer {
from {
font-size: 13px;
}
to {
font-size: 10px;
}
}

View File

@@ -14,7 +14,7 @@ function getErrorPathReplacementFunction(dir) {
};
}
console.log("\n" + stylize("LESS", 'underline') + "\n");
console.log("\n" + stylize("Less", 'underline') + "\n");
lessTester.runTestSet({strictMath: true, relativeUrls: true, silent: true});
lessTester.runTestSet({strictMath: true, strictUnits: true}, "errors/",
lessTester.testErrors, null, getErrorPathReplacementFunction("errors"));
@@ -41,4 +41,5 @@ lessTester.runTestSet({globalVars: true, banner: "/**\n * Test\n */\n"}, "glob
null, null, null, function(name) { return path.join('test/less/', name) + '.json'; });
lessTester.runTestSet({modifyVars: true}, "modifyVars/",
null, null, null, function(name) { return path.join('test/less/', name) + '.json'; });
lessTester.runTestSet({urlArgs: '424242'}, "url-args/");
lessTester.testNoOptions();

View File

@@ -227,6 +227,8 @@ module.exports = function() {
} else {
try {
css = tree.toCSS(options);
var css2 = tree.toCSS(options); // integration test that 2nd call gets same output
if (css2 !== css) { throw new Error("css not equal to 2nd call"); }
callback(null, css);
} catch (e) {
callback(e);

View File

@@ -126,4 +126,8 @@ h1 { color: green; }
.shadow ^ .dom,
body ^^ .shadow {
display: done;
}
}
#issue2066 {
background: url('/images/icon-team.svg') 0 0 / contain;
}

View File

@@ -8,7 +8,7 @@
@a: #ddd;
.see-the {
@a: #444; // this mirrors what mixins do - they evaluate guards at the point of execution
@a: #444; // this mirrors what mixins do - they evaluate the guards at the point of definition
.light();
.dark();
}
@@ -61,4 +61,42 @@
.hideme {
color: red;
}
}
.mixin-with-guard-inside(@colWidth) {
// selector with guard (applies also to & when() ...)
.clsWithGuard when (@colWidth <= 0) {
dispaly: none;
}
}
.mixin-with-guard-inside(0px);
.dont-split-me-up {
width: 1px;
& when (@c = 3) {
color: red;
}
& when (@c = 3) {
height: 1px;
}
+ & when (@c = 3) { // creates invalid css but tests that we don't fold it in
sibling: true;
}
}
.scope-check when (@c = 3) {
@k: 1px;
& when (@c = 3) {
@k: 2px;
sub-prop: @k;
}
prop: @k;
}
.scope-check-2 {
.scope-check();
@k:4px;
}
.errors-if-called when (@c = never) {
.mixin-doesnt-exist();
}

View File

@@ -20,4 +20,14 @@
.mixin_import1();
.mixin_import2();
.mixin_import2();
@debug: 1;
& when (@debug = 1) {
.test {
color: red;
& when (@debug = 1) {
width: 2;
}
}
}

View File

@@ -0,0 +1,103 @@
@ruleset: {
color: black;
background: white;
};
@a: 1px;
.wrap-mixin(@ruleset) {
@a: hidden and if you see this in the output its a bug;
@b: visible;
@d: magic-frame; // same behaviour as mixin calls - falls back to this frame
.wrap-selector {
@c: visible;
@ruleset();
visible-one: @b;
visible-two: @c;
}
};
.wrap-mixin({
color: black;
one: @a;
@b: hidden and if you see this in the output its a bug;
@c: hidden and if you see this in the output its a bug;
four: @d;
});
.wrap-mixin(@ruleset: {
color: red;
});
.wrap-mixin(@ruleset);
.desktop-and-old-ie(@rules) {
@media screen and (min-width: 1200) { @rules(); }
html.lt-ie9 & { @rules(); }
}
header {
background: blue;
.desktop-and-old-ie({
background: red;
});
}
.wrap-mixin-calls-wrap(@ruleset) {
.wrap-mixin(@ruleset);
};
.wrap-mixin({
test: extra-wrap;
.wrap-mixin-calls-wrap({
test: wrapped-twice;
});
});
.wrap-mixin({
test-func: unit(90px);
test-arithmetic: unit((9+9), px);
});
// without mixins
@ruleset-2: {
b: 1;
};
.without-mixins {
@ruleset-2();
}
@my-ruleset: {
.my-selector {
@media tv {
background-color: black;
}
}
};
@media (orientation:portrait) {
@my-ruleset();
.wrap-media-mixin({
@media tv {
.triple-wrapped-mq {
triple: true;
}
}
});
}
.wrap-media-mixin(@ruleset) {
@media widescreen {
@media print {
@ruleset();
}
@ruleset();
}
@ruleset();
}
// unlocking mixins
@my-mixins: {
.mixin() {
test: test;
}
};
@my-mixins();
.a {
.mixin();
}

View File

@@ -0,0 +1,4 @@
@keyframes @name {
50% {width: 20px;}
}

View File

@@ -0,0 +1,4 @@
NameError: variable @name is undefined in {path}at-rules-undefined-var.less on line 2, column 12:
1
2 @keyframes @name {
3 50% {width: 20px;}

View File

@@ -0,0 +1,3 @@
.a {
@wrongHEXColorCode: #DCALLB;
}

View 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 }

View File

@@ -0,0 +1,3 @@
.a {
@wrongHEXColorCode: #fffblack;
}

View 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 }

View File

@@ -0,0 +1,6 @@
@a: {
b: 1;
};
.a {
a: @a;
}

View File

@@ -0,0 +1,4 @@
SyntaxError: Rulesets cannot be evaluated on a property. in {path}detached-ruleset-1.less on line 5, column 3:
4 .a {
5 a: @a;
6 }

Some files were not shown because too many files have changed in this diff Show More