mirror of
https://github.com/less/less.js.git
synced 2026-04-09 03:00:20 -04:00
Merge branch 'grunt-wip'
This commit is contained in:
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,10 +1,20 @@
|
||||
node_modules
|
||||
# OS and IDE
|
||||
.emacs*
|
||||
*.flymake
|
||||
*~
|
||||
.#*
|
||||
.idea
|
||||
*.sublime-*
|
||||
|
||||
# npm
|
||||
node_modules
|
||||
npm-debug.log
|
||||
|
||||
# project-specific
|
||||
tmp
|
||||
test/browser/less.js
|
||||
test/browser/test-runner-*.htm
|
||||
test/sourcemaps/*.map
|
||||
test/sourcemaps/*.css
|
||||
|
||||
# grunt
|
||||
.grunt
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
benchmark/
|
||||
build/
|
||||
dist/
|
||||
node_modules/
|
||||
test/browser/
|
||||
@@ -3,7 +3,7 @@
|
||||
> We welcome feature requests and bug reports. Please read these guidelines before submitting one.
|
||||
|
||||
|
||||
<span class="warning">**Words that begin with the at sign (`@`) must be wrapped in backticks!** </span>. as a courtesy to avoid sending notifications to any user that might have the `@username` being referenced. Remember, usernames start with the at sign.
|
||||
<span class="warning">**Words that begin with the at sign (`@`) must be wrapped in backticks!** </span>. As a courtesy to avoid sending notifications to any user that might have the `@username` being referenced, please remember that GitHub usernames also start with the at sign. If you don't wrap them in backticks, users will get unintended notifications from you.
|
||||
|
||||
GitHub has other great markdown features as well, [go here to learn more about them](https://help.github.com/articles/github-flavored-markdown).
|
||||
|
||||
|
||||
293
Gruntfile.js
Normal file
293
Gruntfile.js
Normal file
@@ -0,0 +1,293 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
// Report the elapsed execution time of tasks.
|
||||
require('time-grunt')(grunt);
|
||||
|
||||
// Project configuration.
|
||||
grunt.initConfig({
|
||||
|
||||
// Metadata required for build.
|
||||
build: grunt.file.readYAML('build/build.yml'),
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
meta: {
|
||||
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' +
|
||||
' * @licence \n' +
|
||||
' */ \n\n'
|
||||
},
|
||||
|
||||
shell: {
|
||||
options: {stdout: true, failOnError: true},
|
||||
test: {
|
||||
command: 'node test/less-test.js'
|
||||
},
|
||||
benchmark: {
|
||||
command: 'node benchmark/less-benchmark.js'
|
||||
},
|
||||
"browsertest-server": {
|
||||
command: 'node node_modules/http-server/bin/http-server . -p 8088'
|
||||
},
|
||||
"sourcemap-test": {
|
||||
command: [
|
||||
'node bin/lessc --source-map --source-map-inline test/less/import.less test/sourcemaps/import.css',
|
||||
'node bin/lessc --source-map --source-map-inline test/less/sourcemaps/basic.less test/sourcemaps/basic.css',
|
||||
'node node_modules/http-server/bin/http-server test/sourcemaps -p 8084'].join('&&')
|
||||
}
|
||||
},
|
||||
concat: {
|
||||
options: {
|
||||
stripBanners: 'all',
|
||||
banner: '<%= meta.banner %>\n\n(function (window, undefined) {',
|
||||
footer: '\n})(window);'
|
||||
},
|
||||
// Browser versions
|
||||
browsertest: {
|
||||
src: ['<%= build.browser %>'],
|
||||
dest: 'test/browser/less.js'
|
||||
},
|
||||
alpha: {
|
||||
src: ['<%= build.browser %>'],
|
||||
dest: 'dist/less-<%= pkg.version %>-alpha.js'
|
||||
},
|
||||
beta: {
|
||||
src: ['<%= build.browser %>'],
|
||||
dest: 'dist/less-<%= pkg.version %>-beta.js'
|
||||
},
|
||||
stable: {
|
||||
src: ['<%= build.browser %>'],
|
||||
dest: 'dist/less-<%= pkg.version %>.js'
|
||||
},
|
||||
// Rhino
|
||||
rhino: {
|
||||
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.rhino %>'],
|
||||
dest: 'dist/less-rhino-<%= pkg.version %>.js'
|
||||
},
|
||||
// Generate readme
|
||||
readme: {
|
||||
// override task-level banner and footer
|
||||
options: {process: true, banner: '', footer: ''},
|
||||
src: ['build/README.md'],
|
||||
dest: 'README.md'
|
||||
}
|
||||
},
|
||||
|
||||
uglify: {
|
||||
options: {
|
||||
banner: '<%= meta.banner %>',
|
||||
mangle: true
|
||||
},
|
||||
alpha: {
|
||||
src: ['<%= concat.alpha.src %>'],
|
||||
dest: 'dist/less-<%= pkg.version %>-alpha.min.js'
|
||||
},
|
||||
beta: {
|
||||
src: ['<%= concat.beta.src %>'],
|
||||
dest: 'dist/less-<%= pkg.version %>-beta.min.js'
|
||||
},
|
||||
stable: {
|
||||
src: ['<%= concat.browser.src %>'],
|
||||
dest: 'dist/less-<%= pkg.version %>.min.js'
|
||||
}
|
||||
},
|
||||
|
||||
jshint: {
|
||||
options: {jshintrc: '.jshintrc'},
|
||||
files: {
|
||||
src: [
|
||||
'Gruntfile.js',
|
||||
'lib/**/*.js'
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
connect: {
|
||||
server: {
|
||||
options: {
|
||||
port: 8081
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
jasmine: {
|
||||
options: {
|
||||
// version: '2.0.0-rc2',
|
||||
keepRunner: true,
|
||||
host: 'http://localhost:8081/',
|
||||
vendor: ['test/browser/common.js', 'test/browser/less.js'],
|
||||
template: 'test/browser/test-runner-template.tmpl'
|
||||
},
|
||||
main: {
|
||||
// src is used to build list of less files to compile
|
||||
src: ['test/less/*.less', '!test/less/javascript.less', '!test/less/urls.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-main-options.js',
|
||||
specs: 'test/browser/runner-main-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-main.html'
|
||||
}
|
||||
},
|
||||
legacy: {
|
||||
src: ['test/less/legacy/*.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-legacy-options.js',
|
||||
specs: 'test/browser/runner-legacy-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-legacy.html'
|
||||
}
|
||||
},
|
||||
errors: {
|
||||
src: ['test/less/errors/*.less', '!test/less/errors/javascript-error.less'],
|
||||
options: {
|
||||
timeout: 20000,
|
||||
helpers: 'test/browser/runner-errors-options.js',
|
||||
specs: 'test/browser/runner-errors-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-errors.html'
|
||||
}
|
||||
},
|
||||
noJsErrors: {
|
||||
src: ['test/less/no-js-errors/*.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-no-js-errors-options.js',
|
||||
specs: 'test/browser/runner-no-js-errors-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-no-js-errors.html'
|
||||
}
|
||||
},
|
||||
browser: {
|
||||
src: ['test/browser/less/*.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-browser-options.js',
|
||||
specs: 'test/browser/runner-browser-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-browser.html'
|
||||
}
|
||||
},
|
||||
relativeUrls: {
|
||||
src: ['test/browser/less/relative-urls/*.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-relative-urls-options.js',
|
||||
specs: 'test/browser/runner-relative-urls-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-relative-urls.html'
|
||||
}
|
||||
},
|
||||
rootpath: {
|
||||
src: ['test/browser/less/rootpath/*.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-rootpath-options.js',
|
||||
specs: 'test/browser/runner-rootpath-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-rootpath.html'
|
||||
}
|
||||
},
|
||||
rootpathRelative: {
|
||||
src: ['test/browser/less/rootpath-relative/*.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-rootpath-relative-options.js',
|
||||
specs: 'test/browser/runner-rootpath-relative-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-rootpath-relative.html'
|
||||
}
|
||||
},
|
||||
production: {
|
||||
src: ['test/browser/less/production/*.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-production-options.js',
|
||||
specs: 'test/browser/runner-production-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-production.html'
|
||||
}
|
||||
},
|
||||
modifyVars: {
|
||||
src: ['test/browser/less/modify-vars/*.less'],
|
||||
options: {
|
||||
helpers: 'test/browser/runner-modify-vars-options.js',
|
||||
specs: 'test/browser/runner-modify-vars-spec.js',
|
||||
outfile: 'tmp/browser/test-runner-modify-vars.html'
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
// Clean the version of less built for the tests
|
||||
clean: {
|
||||
test: ['test/browser/less.js', 'tmp'],
|
||||
"sourcemap-test": ['test/sourcemaps/*.css', 'test/sourcemaps/*.map']
|
||||
}
|
||||
});
|
||||
|
||||
// Load these plugins to provide the necessary tasks
|
||||
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
|
||||
|
||||
// Actually load this plugin's task(s).
|
||||
grunt.loadTasks('build/tasks');
|
||||
|
||||
// by default, run tests
|
||||
grunt.registerTask('default', [
|
||||
'test'
|
||||
]);
|
||||
|
||||
// Alpha
|
||||
grunt.registerTask('alpha', [
|
||||
'concat:alpha',
|
||||
'uglify:alpha'
|
||||
]);
|
||||
|
||||
// Beta
|
||||
grunt.registerTask('beta', [
|
||||
'concat:beta',
|
||||
'uglify:beta'
|
||||
]);
|
||||
|
||||
// Beta
|
||||
grunt.registerTask('stable', [
|
||||
'concat:stable',
|
||||
'uglify:stable'
|
||||
]);
|
||||
|
||||
// Run all browser tests
|
||||
grunt.registerTask('browsertest', [
|
||||
'browser',
|
||||
'connect',
|
||||
'jasmine'
|
||||
]);
|
||||
|
||||
// setup a web server to run the browser tests in a browser rather than phantom
|
||||
grunt.registerTask('browsertest-server', [
|
||||
'shell:browsertest-server'
|
||||
]);
|
||||
|
||||
// Create the browser version of less.js
|
||||
grunt.registerTask('browser', [
|
||||
'concat:browsertest'
|
||||
]);
|
||||
|
||||
// Run all tests
|
||||
grunt.registerTask('test', [
|
||||
'clean',
|
||||
'jshint',
|
||||
'shell:test',
|
||||
'browsertest'
|
||||
]);
|
||||
|
||||
// generate a good test environment for testing sourcemaps
|
||||
grunt.registerTask('sourcemap-test', [
|
||||
'clean:sourcemap-test',
|
||||
'shell:sourcemap-test'
|
||||
]);
|
||||
|
||||
// Run benchmark
|
||||
grunt.registerTask('benchmark', [
|
||||
'shell:benchmark'
|
||||
]);
|
||||
|
||||
// Readme.
|
||||
grunt.registerTask('readme', [
|
||||
'concat:readme'
|
||||
]);
|
||||
};
|
||||
114
Makefile
114
Makefile
@@ -1,114 +0,0 @@
|
||||
#
|
||||
# Run all tests
|
||||
#
|
||||
test:
|
||||
node test/less-test.js
|
||||
|
||||
#
|
||||
# Run benchmark
|
||||
#
|
||||
benchmark:
|
||||
node benchmark/less-benchmark.js
|
||||
|
||||
#
|
||||
# Build less.js
|
||||
#
|
||||
SRC = lib/less
|
||||
HEADER = build/header.js
|
||||
VERSION = `cat package.json | grep version \
|
||||
| grep -o '[0-9]\.[0-9]\.[0-9]\+'`
|
||||
DIST = dist/less-${VERSION}.js
|
||||
RHINO = dist/less-rhino-${VERSION}.js
|
||||
DIST_MIN = dist/less-${VERSION}.min.js
|
||||
|
||||
browser-prepare: DIST := test/browser/less.js
|
||||
|
||||
alpha: DIST := dist/less-${VERSION}-alpha.js
|
||||
alpha: DIST_MIN := dist/less-${VERSION}-alpha.min.js
|
||||
|
||||
beta: DIST := dist/less-${VERSION}-beta.js
|
||||
beta: DIST_MIN := dist/less-${VERSION}-beta.min.js
|
||||
|
||||
less:
|
||||
@@mkdir -p dist
|
||||
@@touch ${DIST}
|
||||
@@cat ${HEADER} | sed s/@VERSION/${VERSION}/ > ${DIST}
|
||||
@@echo "(function (window, undefined) {" >> ${DIST}
|
||||
@@cat build/require.js\
|
||||
build/browser-header.js\
|
||||
${SRC}/parser.js\
|
||||
${SRC}/functions.js\
|
||||
${SRC}/colors.js\
|
||||
${SRC}/tree.js\
|
||||
${SRC}/tree/*.js\
|
||||
${SRC}/env.js\
|
||||
${SRC}/visitor.js\
|
||||
${SRC}/import-visitor.js\
|
||||
${SRC}/join-selector-visitor.js\
|
||||
${SRC}/to-css-visitor.js\
|
||||
${SRC}/extend-visitor.js\
|
||||
${SRC}/browser.js\
|
||||
build/amd.js >> ${DIST}
|
||||
@@echo "})(window);" >> ${DIST}
|
||||
@@echo ${DIST} built.
|
||||
|
||||
browser-prepare: less
|
||||
node test/browser-test-prepare.js
|
||||
|
||||
browser-test: browser-prepare
|
||||
phantomjs test/browser/phantom-runner.js
|
||||
|
||||
browser-test-server: browser-prepare
|
||||
phantomjs test/browser/phantom-runner.js --no-tests
|
||||
|
||||
jshint:
|
||||
node_modules/.bin/jshint --config ./.jshintrc .
|
||||
|
||||
test-sourcemaps:
|
||||
node bin/lessc --source-map --source-map-inline test/less/import.less test/sourcemaps/import.css
|
||||
node bin/lessc --source-map --source-map-inline test/less/sourcemaps/basic.less test/sourcemaps/basic.css
|
||||
node node_modules/http-server/bin/http-server test/sourcemaps -p 8083
|
||||
|
||||
rhino:
|
||||
@@mkdir -p dist
|
||||
@@touch ${RHINO}
|
||||
@@cat build/require-rhino.js\
|
||||
build/rhino-header.js\
|
||||
${SRC}/parser.js\
|
||||
${SRC}/env.js\
|
||||
${SRC}/visitor.js\
|
||||
${SRC}/import-visitor.js\
|
||||
${SRC}/join-selector-visitor.js\
|
||||
${SRC}/to-css-visitor.js\
|
||||
${SRC}/extend-visitor.js\
|
||||
${SRC}/functions.js\
|
||||
${SRC}/colors.js\
|
||||
${SRC}/tree/*.js\
|
||||
${SRC}/tree.js\
|
||||
${SRC}/rhino.js > ${RHINO}
|
||||
@@echo ${RHINO} built.
|
||||
|
||||
min: less
|
||||
@@echo minifying...
|
||||
@@uglifyjs ${DIST} > ${DIST_MIN}
|
||||
@@echo ${DIST_MIN} built.
|
||||
|
||||
alpha: min
|
||||
|
||||
beta: min
|
||||
|
||||
alpha-release: alpha
|
||||
git add dist/*.js
|
||||
git commit -m "Update alpha ${VERSION}"
|
||||
|
||||
dist: min rhino
|
||||
git add dist/*
|
||||
git commit -a -m "(dist) build ${VERSION}"
|
||||
git archive master --prefix=less/ -o less-${VERSION}.tar.gz
|
||||
npm publish less-${VERSION}.tar.gz
|
||||
|
||||
stable:
|
||||
npm tag less@${VERSION} stable
|
||||
|
||||
|
||||
.PHONY: test benchmark
|
||||
341
README.md
341
README.md
@@ -1,20 +1,335 @@
|
||||
less.js
|
||||
=======
|
||||
# [Less.js v1.5.0-b1](http://lesscss.org)
|
||||
|
||||
The **dynamic** stylesheet language.
|
||||
|
||||
<http://lesscss.org>
|
||||
|
||||
about
|
||||
-----
|
||||
> The **dynamic** stylesheet language. [http://lesscss.org](http://lesscss.org).
|
||||
|
||||
This is the JavaScript, and now official, stable version of LESS.
|
||||
|
||||
For more information on the language and usage visit [lesscss.org](http://lesscss.org). More information also available [in our wiki](https://github.com/less/less.js/wiki)
|
||||
|
||||
license
|
||||
-------
|
||||
## Getting Started
|
||||
|
||||
See `LICENSE` file.
|
||||
Options for adding Less.js to your project:
|
||||
|
||||
> Copyright (c) 2009-2013 Alexis Sellier & The Core Less Team
|
||||
* 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`
|
||||
|
||||
|
||||
|
||||
## 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
|
||||
// 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
|
||||
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
|
||||
.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;
|
||||
}
|
||||
```
|
||||
|
||||
## 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].
|
||||
|
||||
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/).
|
||||
|
||||
### 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].
|
||||
|
||||
|
||||
|
||||
### 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 `~0.4.1`. 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.
|
||||
|
||||
|
||||
## Release History
|
||||
See the [changelog](CHANGELOG)
|
||||
|
||||
## [License](LICENSE)
|
||||
|
||||
Copyright (c) 2009-2013 [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"
|
||||
[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"
|
||||
@@ -16,18 +16,17 @@ fs.readFile(file, 'utf8', function (e, data) {
|
||||
start = new(Date);
|
||||
|
||||
new(less.Parser)({ optimization: 2 }).parse(data, function (err, tree) {
|
||||
end = new(Date);
|
||||
end = new Date();
|
||||
|
||||
total = end - start;
|
||||
|
||||
sys.puts("Parsing: " +
|
||||
total + " ms (" +
|
||||
parseInt(1000 / total *
|
||||
data.length / 1024) + " KB\/s)");
|
||||
Number(1000 / total * data.length / 1024) + " KB\/s)");
|
||||
|
||||
start = new(Date);
|
||||
start = new Date();
|
||||
css = tree.toCSS();
|
||||
end = new(Date);
|
||||
end = new Date();
|
||||
|
||||
sys.puts("Generation: " + (end - start) + " ms (" +
|
||||
parseInt(1000 / (end - start) *
|
||||
@@ -36,7 +35,7 @@ fs.readFile(file, 'utf8', function (e, data) {
|
||||
total += end - start;
|
||||
|
||||
sys.puts("Total: " + total + "ms (" +
|
||||
parseInt(1000 / total * data.length / 1024) + " KB/s)");
|
||||
Number(1000 / total * data.length / 1024) + " KB/s)");
|
||||
|
||||
if (err) {
|
||||
less.writeError(err);
|
||||
|
||||
335
build/README.md
Normal file
335
build/README.md
Normal file
@@ -0,0 +1,335 @@
|
||||
# [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.
|
||||
|
||||
|
||||
## 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`
|
||||
|
||||
|
||||
|
||||
## 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
|
||||
// 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
|
||||
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
|
||||
.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;
|
||||
}
|
||||
```
|
||||
|
||||
## 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].
|
||||
|
||||
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/).
|
||||
|
||||
### 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].
|
||||
|
||||
|
||||
|
||||
### 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.
|
||||
|
||||
|
||||
## Release History
|
||||
See the [changelog](CHANGELOG)
|
||||
|
||||
## [License](LICENSE)
|
||||
|
||||
Copyright (c) 2009-<%= grunt.template.today("yyyy") %> [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"
|
||||
[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"
|
||||
147
build/build.yml
Normal file
147
build/build.yml
Normal file
@@ -0,0 +1,147 @@
|
||||
###
|
||||
# NOTICE:
|
||||
# this file is specifically for controlling
|
||||
# paths for Less.js source files, as well as
|
||||
# the order in which source files are
|
||||
# concatenated.
|
||||
#
|
||||
# Please do not add paths for anything else
|
||||
# to this file. All other paths for testing,
|
||||
# benchmarking and so on should be controlled
|
||||
# in the Gruntfile.
|
||||
###
|
||||
|
||||
# Less.js Lib
|
||||
lib: lib/less
|
||||
|
||||
|
||||
# =================================
|
||||
# General
|
||||
# =================================
|
||||
prepend:
|
||||
browser: ['build/require.js', 'build/browser-header.js']
|
||||
rhino: build/require-rhino.js
|
||||
|
||||
append:
|
||||
amd: build/amd.js
|
||||
browser: <%= build.lib %>/browser.js
|
||||
rhino: <%= build.lib %>/rhino.js
|
||||
|
||||
|
||||
# =================================
|
||||
# Core less files
|
||||
# =================================
|
||||
|
||||
# <%= build.less.* %>
|
||||
less:
|
||||
parser : <%= build.lib %>/parser.js
|
||||
functions : <%= build.lib %>/functions.js
|
||||
colors : <%= build.lib %>/colors.js
|
||||
tree : <%= build.lib %>/tree.js
|
||||
treedir : <%= build.lib %>/tree/*.js # glob all files in ./lib/less/tree directory
|
||||
env : <%= build.lib %>/env.js
|
||||
visitor : <%= build.lib %>/visitor.js
|
||||
import_visitor : <%= build.lib %>/import-visitor.js
|
||||
join : <%= build.lib %>/join-selector-visitor.js
|
||||
to_css_visitor : <%= build.lib %>/to-css-visitor.js
|
||||
extend_visitor : <%= build.lib %>/extend-visitor.js
|
||||
browser : <%= build.lib %>/browser.js
|
||||
source_map_output: <%= build.lib %>/source-map-output.js
|
||||
|
||||
|
||||
# =================================
|
||||
# Browser build
|
||||
# =================================
|
||||
|
||||
# <%= build.browser %>
|
||||
browser:
|
||||
|
||||
# prepend utils
|
||||
- <%= build.prepend.browser %>
|
||||
|
||||
# core
|
||||
- <%= build.less.parser %>
|
||||
- <%= build.less.functions %>
|
||||
- <%= build.less.colors %>
|
||||
- <%= build.less.tree %>
|
||||
- <%= build.less.treedir %> # glob all files
|
||||
- <%= build.less.env %>
|
||||
- <%= build.less.visitor %>
|
||||
- <%= build.less.import_visitor %>
|
||||
- <%= build.less.join %>
|
||||
- <%= build.less.to_css_visitor %>
|
||||
- <%= build.less.extend_visitor %>
|
||||
- <%= build.less.source_map_output %>
|
||||
|
||||
# append browser-specific code
|
||||
- <%= build.append.browser %>
|
||||
- <%= build.append.amd %>
|
||||
|
||||
|
||||
# =================================
|
||||
# Rhino build
|
||||
# =================================
|
||||
|
||||
# <%= build.rhino %>
|
||||
rhino:
|
||||
# prepend utils
|
||||
- <%= build.prepend.rhino %>
|
||||
|
||||
# core
|
||||
- <%= build.less.parser %>
|
||||
- <%= build.less.env %>
|
||||
- <%= build.less.visitor %>
|
||||
- <%= build.less.import_visitor %>
|
||||
- <%= build.less.join %>
|
||||
- <%= build.less.to_css_visitor %>
|
||||
- <%= build.less.extend_visitor %>
|
||||
- <%= build.less.functions %>
|
||||
- <%= build.less.colors %>
|
||||
- <%= build.less.tree %>
|
||||
- <%= build.less.treedir %> # glob all files
|
||||
- <%= build.less.source_map_output %>
|
||||
|
||||
# append rhino-specific code
|
||||
- <%= build.append.rhino %>
|
||||
|
||||
|
||||
# =================================
|
||||
# Tree files
|
||||
# =================================
|
||||
|
||||
# <%= build.tree %>
|
||||
# Technically listing the array out this way isn't
|
||||
# necessary since we can glob the files in alphabetical
|
||||
# order anyway. But this gives you control over the order
|
||||
# the files are used, and allows targeting of individual
|
||||
# files directly in the Gruntfile. But be we can just
|
||||
# remove this if files can be concatenated in any order.
|
||||
tree:
|
||||
- <%= build.lib %>/tree/alpha.js
|
||||
- <%= build.lib %>/tree/anonymous.js
|
||||
- <%= build.lib %>/tree/assignment.js
|
||||
- <%= build.lib %>/tree/call.js
|
||||
- <%= build.lib %>/tree/color.js
|
||||
- <%= build.lib %>/tree/comment.js
|
||||
- <%= build.lib %>/tree/condition.js
|
||||
- <%= build.lib %>/tree/dimension.js
|
||||
- <%= build.lib %>/tree/directive.js
|
||||
- <%= build.lib %>/tree/element.js
|
||||
- <%= build.lib %>/tree/expression.js
|
||||
- <%= build.lib %>/tree/extend.js
|
||||
- <%= build.lib %>/tree/import.js
|
||||
- <%= build.lib %>/tree/javascript.js
|
||||
- <%= build.lib %>/tree/keyword.js
|
||||
- <%= build.lib %>/tree/media.js
|
||||
- <%= build.lib %>/tree/mixin.js
|
||||
- <%= build.lib %>/tree/negative.js
|
||||
- <%= build.lib %>/tree/operation.js
|
||||
- <%= build.lib %>/tree/paren.js
|
||||
- <%= build.lib %>/tree/quoted.js
|
||||
- <%= build.lib %>/tree/rule.js
|
||||
- <%= build.lib %>/tree/ruleset.js
|
||||
- <%= build.lib %>/tree/selector.js
|
||||
- <%= build.lib %>/tree/unicode-descriptor.js
|
||||
- <%= build.lib %>/tree/url.js
|
||||
- <%= build.lib %>/tree/value.js
|
||||
- <%= build.lib %>/tree/variable.js
|
||||
@@ -1,9 +0,0 @@
|
||||
/*
|
||||
* LESS - Leaner CSS v@VERSION
|
||||
* http://lesscss.org
|
||||
*
|
||||
* Copyright (c) 2009-2013, Alexis Sellier
|
||||
* Licensed under the Apache 2.0 License.
|
||||
*
|
||||
* @licence
|
||||
*/
|
||||
1
build/tasks/.gitkeep
Normal file
1
build/tasks/.gitkeep
Normal file
@@ -0,0 +1 @@
|
||||
# Reserved for specialized Less.js tasks.
|
||||
37
package.json
37
package.json
@@ -3,7 +3,10 @@
|
||||
"version": "1.5.0-b1",
|
||||
"description": "Leaner CSS",
|
||||
"homepage": "http://lesscss.org",
|
||||
"author": "Alexis Sellier <self@cloudhead.net>",
|
||||
"author": {
|
||||
"name": "Alexis Sellier",
|
||||
"email": "self@cloudhead.net"
|
||||
},
|
||||
"contributors": [
|
||||
"The Core Less Team"
|
||||
],
|
||||
@@ -14,6 +17,12 @@
|
||||
"type": "git",
|
||||
"url": "https://github.com/less/less.js.git"
|
||||
},
|
||||
"licenses": [
|
||||
{
|
||||
"type": "Apache v2",
|
||||
"url": "https://github.com/less/less.js/blob/master/LICENSE"
|
||||
}
|
||||
],
|
||||
"bin": {
|
||||
"lessc": "./bin/lessc"
|
||||
},
|
||||
@@ -28,8 +37,7 @@
|
||||
"node": ">=0.4.2"
|
||||
},
|
||||
"scripts": {
|
||||
"pretest": "make jshint",
|
||||
"test": "make test"
|
||||
"test": "grunt test"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"mime": "1.2.x",
|
||||
@@ -40,9 +48,18 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"diff": "~1.0",
|
||||
"jshint": "~2.1.4",
|
||||
"http-server": "~0.5.5"
|
||||
},
|
||||
"grunt": "~0.4.1",
|
||||
"grunt-contrib-clean": "~0.5.0",
|
||||
"grunt-contrib-concat": "~0.3.0",
|
||||
"grunt-contrib-connect": "~0.3.0",
|
||||
"grunt-contrib-jasmine": "~0.5.1",
|
||||
"grunt-contrib-jshint": "~0.6.0",
|
||||
"grunt-contrib-uglify": "~0.2.2",
|
||||
"grunt-shell": "~0.3.1",
|
||||
"http-server": "~0.5.5",
|
||||
"matchdep": "~0.1.2",
|
||||
"time-grunt": "~0.1.1"
|
||||
},
|
||||
"keywords": [
|
||||
"compile less",
|
||||
"css nesting",
|
||||
@@ -67,11 +84,5 @@
|
||||
"stylesheet",
|
||||
"variables in css",
|
||||
"css less"
|
||||
],
|
||||
"licenses": [
|
||||
{
|
||||
"type": "Apache v2",
|
||||
"url": "https://github.com/less/less.js/blob/master/LICENSE"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
var path = require('path'),
|
||||
fs = require('fs');
|
||||
|
||||
var readDirFilesSync = function(dir, regex, callback) {
|
||||
fs.readdirSync(dir).forEach(function (file) {
|
||||
if (! regex.test(file)) { return; }
|
||||
callback(file);
|
||||
});
|
||||
};
|
||||
|
||||
var createTestRunnerPage = function(dir, exclude, testSuiteName, dir2) {
|
||||
var output = '<html><head>\n';
|
||||
|
||||
readDirFilesSync(path.join("test", dir, 'less', dir2 || ""), /\.less$/, function (file) {
|
||||
var name = path.basename(file, '.less'),
|
||||
id = (dir ? dir + '-' : "") + 'less-' + (dir2 ? dir2 + "-" : "") + name;
|
||||
|
||||
if (exclude && name.match(exclude)) { return; }
|
||||
|
||||
output += '<link id="original-less:' + id + '" rel="stylesheet/less" type="text/css" href="/' + path.join(dir, 'less', dir2 || "", name).replace("\\", "/") + '.less' +'" />\n';
|
||||
output += '<link id="expected-less:' + id + '" rel="stylesheet" type="text/css" href="/' + path.join(dir, 'css', dir2 || "", name).replace("\\", "/") + '.css' + '" />\n';
|
||||
});
|
||||
|
||||
output += String(fs.readFileSync(path.join('test/browser', 'template.htm'))).replace("{runner-name}", testSuiteName);
|
||||
|
||||
fs.writeFileSync(path.join('test/browser', 'test-runner-'+testSuiteName+'.htm'), output);
|
||||
};
|
||||
|
||||
var removeFiles = function(dir, regex) {
|
||||
readDirFilesSync(dir, regex, function(file) {
|
||||
fs.unlinkSync(path.join(dir, file), function() {
|
||||
console.log("Failed to delete " + file);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
removeFiles("test/browser", /test-runner-[a-zA-Z-]*\.htm$/);
|
||||
createTestRunnerPage("", /javascript|urls/, "main");
|
||||
createTestRunnerPage("", null, "legacy", "legacy");
|
||||
createTestRunnerPage("", /javascript/, "errors", "errors");
|
||||
createTestRunnerPage("", null, "no-js-errors", "no-js-errors");
|
||||
createTestRunnerPage("browser", null, "console-errors", "console-errors");
|
||||
createTestRunnerPage("browser", null, "browser");
|
||||
createTestRunnerPage("browser", null, "relative-urls", "relative-urls");
|
||||
createTestRunnerPage("browser", null, "rootpath", "rootpath");
|
||||
createTestRunnerPage("browser", null, "rootpath-relative", "rootpath-relative");
|
||||
createTestRunnerPage("browser", null, "production");
|
||||
createTestRunnerPage("browser", null, "modify-vars", "modify-vars");
|
||||
@@ -1,16 +1,24 @@
|
||||
/*if not async then phantomjs fails to run the webserver and the test concurrently*/
|
||||
var less = { async: true, strictMath: true };
|
||||
|
||||
/* record log messages for testing */
|
||||
// var logAllIds = function() {
|
||||
// var allTags = document.head.getElementsByTagName('style');
|
||||
// var ids = [];
|
||||
// for (var tg = 0; tg < allTags.length; tg++) {
|
||||
// var tag = allTags[tg];
|
||||
// if (tag.id) {
|
||||
// console.log(tag.id);
|
||||
// }
|
||||
// }
|
||||
// };
|
||||
|
||||
var logMessages = [],
|
||||
realConsoleLog = console.log;
|
||||
realConsoleLog = console.log;
|
||||
console.log = function(msg) {
|
||||
logMessages.push(msg);
|
||||
realConsoleLog.call(console, msg);
|
||||
logMessages.push(msg);
|
||||
realConsoleLog.call(console, msg);
|
||||
};
|
||||
|
||||
var testLessEqualsInDocument = function() {
|
||||
testLessInDocument(testSheet);
|
||||
testLessInDocument(testSheet);
|
||||
};
|
||||
|
||||
var testLessErrorsInDocument = function(isConsole) {
|
||||
@@ -18,68 +26,97 @@ var testLessErrorsInDocument = function(isConsole) {
|
||||
};
|
||||
|
||||
var testLessInDocument = function(testFunc) {
|
||||
var links = document.getElementsByTagName('link'),
|
||||
typePattern = /^text\/(x-)?less$/;
|
||||
var links = document.getElementsByTagName('link'),
|
||||
typePattern = /^text\/(x-)?less$/;
|
||||
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
|
||||
(links[i].type.match(typePattern)))) {
|
||||
testFunc(links[i]);
|
||||
}
|
||||
for (var i = 0; i < links.length; i++) {
|
||||
if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
|
||||
(links[i].type.match(typePattern)))) {
|
||||
testFunc(links[i]);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
var testSheet = function(sheet) {
|
||||
it(sheet.id + " should match the expected output", function() {
|
||||
var lessOutputId = sheet.id.replace("original-", ""),
|
||||
expectedOutputId = "expected-" + lessOutputId,
|
||||
lessOutput = document.getElementById(lessOutputId).innerText,
|
||||
expectedOutputHref = document.getElementById(expectedOutputId).href,
|
||||
expectedOutput = loadFile(expectedOutputHref);
|
||||
it(sheet.id + " should match the expected output", function() {
|
||||
var lessOutputId = sheet.id.replace("original-", ""),
|
||||
expectedOutputId = "expected-" + lessOutputId,
|
||||
lessOutputObj,
|
||||
lessOutput,
|
||||
expectedOutputHref = document.getElementById(expectedOutputId).href,
|
||||
expectedOutput = loadFile(expectedOutputHref);
|
||||
|
||||
waitsFor(function() {
|
||||
return expectedOutput.loaded;
|
||||
}, "failed to load expected outout", 10000);
|
||||
|
||||
runs(function() {
|
||||
// use sheet to do testing
|
||||
expect(expectedOutput.text).toEqual(lessOutput);
|
||||
});
|
||||
// Browser spec generates less on the fly, so we need to loose control
|
||||
waitsFor(function() {
|
||||
lessOutputObj = document.getElementById(lessOutputId);
|
||||
// the type condition is necessary because of inline browser tests
|
||||
return lessOutputObj !== null && lessOutputObj.type === "text/css";
|
||||
}, "generation of " + lessOutputId + "", 700);
|
||||
|
||||
runs(function() {
|
||||
lessOutput = lessOutputObj.innerText;
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return expectedOutput.loaded;
|
||||
}, "failed to load expected outout", 10000);
|
||||
|
||||
runs(function() {
|
||||
// use sheet to do testing
|
||||
expect(expectedOutput.text).toEqual(lessOutput);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
//TODO: do it cleaner - the same way as in css
|
||||
|
||||
function extractId(href) {
|
||||
return href.replace(/^[a-z-]+:\/+?[^\/]+/, '') // Remove protocol & domain
|
||||
.replace(/^\//, '') // Remove root /
|
||||
.replace(/\.[a-zA-Z]+$/, '') // Remove simple extension
|
||||
.replace(/[^\.\w-]+/g, '-') // Replace illegal characters
|
||||
.replace(/\./g, ':'); // Replace dots with colons(for valid id)
|
||||
}
|
||||
|
||||
var testErrorSheet = function(sheet) {
|
||||
it(sheet.id + " should match an error", function() {
|
||||
var lessHref = sheet.href,
|
||||
id = sheet.id.replace(/^original-less:/, "less-error-message:"),
|
||||
errorHref = lessHref.replace(/.less$/, ".txt"),
|
||||
errorFile = loadFile(errorHref),
|
||||
actualErrorElement = document.getElementById(id),
|
||||
actualErrorMsg;
|
||||
it(sheet.id + " should match an error", function() {
|
||||
var lessHref = sheet.href,
|
||||
id = "less-error-message:" + extractId(lessHref),
|
||||
// id = sheet.id.replace(/^original-less:/, "less-error-message:"),
|
||||
errorHref = lessHref.replace(/.less$/, ".txt"),
|
||||
errorFile = loadFile(errorHref),
|
||||
actualErrorElement,
|
||||
actualErrorMsg;
|
||||
|
||||
describe("the error", function() {
|
||||
expect(actualErrorElement).not.toBe(null);
|
||||
});
|
||||
|
||||
actualErrorMsg = actualErrorElement.innerText
|
||||
.replace(/\n\d+/g, function(lineNo) { return lineNo + " "; })
|
||||
.replace(/\n\s*in /g, " in ")
|
||||
.replace("\n\n", "\n");
|
||||
// Less.js sets 10ms timer in order to add error message on top of page.
|
||||
waitsFor(function() {
|
||||
actualErrorElement = document.getElementById(id);
|
||||
return actualErrorElement !== null;
|
||||
}, "error message was not generated", 70);
|
||||
|
||||
waitsFor(function() {
|
||||
return errorFile.loaded;
|
||||
}, "failed to load expected outout", 10000);
|
||||
|
||||
runs(function() {
|
||||
var errorTxt = errorFile.text
|
||||
.replace("{path}", "")
|
||||
.replace("{pathrel}", "")
|
||||
.replace("{pathhref}", "http://localhost:8081/less/errors/")
|
||||
.replace("{404status}", " (404)");
|
||||
expect(errorTxt).toEqual(actualErrorMsg);
|
||||
if (errorTxt == actualErrorMsg) {
|
||||
actualErrorElement.style.display = "none";
|
||||
}
|
||||
runs(function() {
|
||||
actualErrorMsg = actualErrorElement.innerText
|
||||
.replace(/\n\d+/g, function(lineNo) {
|
||||
return lineNo + " ";
|
||||
})
|
||||
.replace(/\n\s*in /g, " in ")
|
||||
.replace("\n\n", "\n");
|
||||
});
|
||||
|
||||
waitsFor(function() {
|
||||
return errorFile.loaded;
|
||||
}, "failed to load expected outout", 10000);
|
||||
|
||||
runs(function() {
|
||||
var errorTxt = errorFile.text
|
||||
.replace("{path}", "")
|
||||
.replace("{pathrel}", "")
|
||||
.replace("{pathhref}", "http://localhost:8081/test/less/errors/")
|
||||
.replace("{404status}", " (404)");
|
||||
expect(errorTxt).toEqual(actualErrorMsg);
|
||||
if (errorTxt == actualErrorMsg) {
|
||||
actualErrorElement.style.display = "none";
|
||||
}
|
||||
});
|
||||
});
|
||||
};
|
||||
@@ -115,20 +152,23 @@ var testErrorSheetConsole = function(sheet) {
|
||||
.replace("{404status}", " (404)")
|
||||
.trim();
|
||||
expect(errorTxt).toEqual(actualErrorMsg);
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
var loadFile = function(href) {
|
||||
var request = new XMLHttpRequest(),
|
||||
response = { loaded: false, text: ""};
|
||||
request.open('GET', href, true);
|
||||
request.onload = function(e) {
|
||||
response.text = request.response.replace(/\r/g, "");
|
||||
response.loaded = true;
|
||||
}
|
||||
request.send();
|
||||
return response;
|
||||
var request = new XMLHttpRequest(),
|
||||
response = {
|
||||
loaded: false,
|
||||
text: ""
|
||||
};
|
||||
request.open('GET', href, true);
|
||||
request.onload = function(e) {
|
||||
response.text = request.response.replace(/\r/g, "");
|
||||
response.loaded = true;
|
||||
};
|
||||
request.send();
|
||||
return response;
|
||||
};
|
||||
|
||||
(function() {
|
||||
@@ -154,7 +194,7 @@ var loadFile = function(href) {
|
||||
|
||||
function execJasmine() {
|
||||
setTimeout(function() {
|
||||
jasmineEnv.execute();
|
||||
jasmineEnv.execute();
|
||||
}, 3000);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
@import "http://localhost:8081/browser/less/imports/modify-this.css";
|
||||
@import "http://localhost:8081/browser/less/imports/modify-again.css";
|
||||
@import "http://localhost:8081/test/browser/less/imports/modify-this.css";
|
||||
@import "http://localhost:8081/test/browser/less/imports/modify-again.css";
|
||||
.modify {
|
||||
my-url: url("http://localhost:8081/browser/less/imports/a.png");
|
||||
my-url: url("http://localhost:8081/test/browser/less/imports/a.png");
|
||||
}
|
||||
.modify {
|
||||
my-url: url("http://localhost:8081/browser/less/imports/b.png");
|
||||
my-url: url("http://localhost:8081/test/browser/less/imports/b.png");
|
||||
}
|
||||
@font-face {
|
||||
src: url("/fonts/garamond-pro.ttf");
|
||||
src: local(Futura-Medium), url(http://localhost:8081/browser/less/relative-urls/fonts.svg#MyGeometricModern) format("svg");
|
||||
src: local(Futura-Medium), url(http://localhost:8081/test/browser/less/relative-urls/fonts.svg#MyGeometricModern) format("svg");
|
||||
}
|
||||
#shorthands {
|
||||
background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
|
||||
}
|
||||
#misc {
|
||||
background-image: url(http://localhost:8081/browser/less/relative-urls/images/image.jpg);
|
||||
background-image: url(http://localhost:8081/test/browser/less/relative-urls/images/image.jpg);
|
||||
}
|
||||
#data-uri {
|
||||
background: url(data:image/png;charset=utf-8;base64,
|
||||
@@ -28,8 +28,8 @@
|
||||
background: transparent url('data:image/svg+xml, <svg version="1.1"><g></g></svg>');
|
||||
}
|
||||
.comma-delimited {
|
||||
background: url(http://localhost:8081/browser/less/relative-urls/bg.jpg) no-repeat, url(http://localhost:8081/browser/less/relative-urls/bg.png) repeat-x top left, url(http://localhost:8081/browser/less/relative-urls/bg);
|
||||
background: url(http://localhost:8081/test/browser/less/relative-urls/bg.jpg) no-repeat, url(http://localhost:8081/test/browser/less/relative-urls/bg.png) repeat-x top left, url(http://localhost:8081/test/browser/less/relative-urls/bg);
|
||||
}
|
||||
.values {
|
||||
url: url('http://localhost:8081/browser/less/relative-urls/Trebuchet');
|
||||
url: url('http://localhost:8081/test/browser/less/relative-urls/Trebuchet');
|
||||
}
|
||||
|
||||
@@ -1,20 +1,20 @@
|
||||
@import "http://localhost:8081/browser/less/modify-this.css";
|
||||
@import "http://localhost:8081/browser/less/modify-again.css";
|
||||
@import "http://localhost:8081/test/browser/less/modify-this.css";
|
||||
@import "http://localhost:8081/test/browser/less/modify-again.css";
|
||||
.modify {
|
||||
my-url: url("http://localhost:8081/browser/less/a.png");
|
||||
my-url: url("http://localhost:8081/test/browser/less/a.png");
|
||||
}
|
||||
.modify {
|
||||
my-url: url("http://localhost:8081/browser/less/b.png");
|
||||
my-url: url("http://localhost:8081/test/browser/less/b.png");
|
||||
}
|
||||
@font-face {
|
||||
src: url("/fonts/garamond-pro.ttf");
|
||||
src: local(Futura-Medium), url(http://localhost:8081/browser/less/fonts.svg#MyGeometricModern) format("svg");
|
||||
src: local(Futura-Medium), url(http://localhost:8081/test/browser/less/fonts.svg#MyGeometricModern) format("svg");
|
||||
}
|
||||
#shorthands {
|
||||
background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
|
||||
}
|
||||
#misc {
|
||||
background-image: url(http://localhost:8081/browser/less/images/image.jpg);
|
||||
background-image: url(http://localhost:8081/test/browser/less/images/image.jpg);
|
||||
}
|
||||
#data-uri {
|
||||
background: url(data:image/png;charset=utf-8;base64,
|
||||
@@ -28,23 +28,23 @@
|
||||
background: transparent url('data:image/svg+xml, <svg version="1.1"><g></g></svg>');
|
||||
}
|
||||
.comma-delimited {
|
||||
background: url(http://localhost:8081/browser/less/bg.jpg) no-repeat, url(http://localhost:8081/browser/less/bg.png) repeat-x top left, url(http://localhost:8081/browser/less/bg);
|
||||
background: url(http://localhost:8081/test/browser/less/bg.jpg) no-repeat, url(http://localhost:8081/test/browser/less/bg.png) repeat-x top left, url(http://localhost:8081/test/browser/less/bg);
|
||||
}
|
||||
.values {
|
||||
url: url('http://localhost:8081/browser/less/Trebuchet');
|
||||
url: url('http://localhost:8081/test/browser/less/Trebuchet');
|
||||
}
|
||||
#data-uri {
|
||||
uri: url('http://localhost:8081/data/image.jpg');
|
||||
uri: url('http://localhost:8081/test/data/image.jpg');
|
||||
}
|
||||
#data-uri-guess {
|
||||
uri: url('http://localhost:8081/data/image.jpg');
|
||||
uri: url('http://localhost:8081/test/data/image.jpg');
|
||||
}
|
||||
#data-uri-ascii {
|
||||
uri-1: url('http://localhost:8081/data/page.html');
|
||||
uri-2: url('http://localhost:8081/data/page.html');
|
||||
uri-1: url('http://localhost:8081/test/data/page.html');
|
||||
uri-2: url('http://localhost:8081/test/data/page.html');
|
||||
}
|
||||
#data-uri-toobig {
|
||||
uri: url('http://localhost:8081/data/data-uri-fail.png');
|
||||
uri: url('http://localhost:8081/test/data/data-uri-fail.png');
|
||||
}
|
||||
#svg-functions {
|
||||
background-image: url('data:image/svg+xml,<?xml version="1.0" ?><svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="100%" height="100%" viewBox="0 0 1 1" preserveAspectRatio="none"><linearGradient id="gradient" gradientUnits="userSpaceOnUse" x1="0%" y1="0%" x2="0%" y2="100%"><stop offset="0%" stop-color="#000000"/><stop offset="100%" stop-color="#ffffff"/></linearGradient><rect x="0" y="0" width="1" height="1" fill="url(#gradient)" /></svg>');
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import ".././imports/urls.less";
|
||||
@import "http://localhost:8081/browser/less/imports/urls2.less";
|
||||
@import "http://localhost:8081/test/browser/less/imports/urls2.less";
|
||||
@font-face {
|
||||
src: url("/fonts/garamond-pro.ttf");
|
||||
src: local(Futura-Medium),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import "../imports/urls.less";
|
||||
@import "http://localhost:8081/browser/less/imports/urls2.less";
|
||||
@import "http://localhost:8081/test/browser/less/imports/urls2.less";
|
||||
@font-face {
|
||||
src: url("/fonts/garamond-pro.ttf");
|
||||
src: local(Futura-Medium),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import "../imports/urls.less";
|
||||
@import "http://localhost:8081/browser/less/imports/urls2.less";
|
||||
@import "http://localhost:8081/test/browser/less/imports/urls2.less";
|
||||
@font-face {
|
||||
src: url("/fonts/garamond-pro.ttf");
|
||||
src: local(Futura-Medium),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
@import "imports/urls.less";
|
||||
@import "http://localhost:8081/browser/less/imports/urls2.less";
|
||||
@import "http://localhost:8081/test/browser/less/imports/urls2.less";
|
||||
@font-face {
|
||||
src: url("/fonts/garamond-pro.ttf");
|
||||
src: local(Futura-Medium),
|
||||
|
||||
@@ -2,31 +2,35 @@ var webpage = require('webpage');
|
||||
var server = require('webserver').create();
|
||||
var system = require('system');
|
||||
var fs = require('fs');
|
||||
var host, port = 8081;
|
||||
var host;
|
||||
var port = 8081;
|
||||
|
||||
var listening = server.listen(port, function (request, response) {
|
||||
//console.log("Requested "+request.url);
|
||||
|
||||
var filename = ("test/" + request.url.slice(1)).replace(/[\\\/]/g, fs.separator);
|
||||
|
||||
if (!fs.exists(filename) || !fs.isFile(filename)) {
|
||||
response.statusCode = 404;
|
||||
response.write("<html><head></head><body><h1>File Not Found</h1><h2>File:"+filename+"</h2></body></html>");
|
||||
response.close();
|
||||
return;
|
||||
}
|
||||
var listening = server.listen(port, function(request, response) {
|
||||
//console.log("Requested " + request.url);
|
||||
|
||||
// we set the headers here
|
||||
response.statusCode = 200;
|
||||
response.headers = {"Cache": "no-cache", "Content-Type": "text/html"};
|
||||
|
||||
response.write(fs.read(filename));
|
||||
|
||||
var filename = ("test/" + request.url.slice(1)).replace(/[\\\/]/g, fs.separator);
|
||||
|
||||
if (!fs.exists(filename) || !fs.isFile(filename)) {
|
||||
response.statusCode = 404;
|
||||
response.write("<html><head></head><body><h1>File Not Found</h1><h2>File:" + filename + "</h2></body></html>");
|
||||
response.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// we set the headers here
|
||||
response.statusCode = 200;
|
||||
response.headers = {
|
||||
"Cache": "no-cache",
|
||||
"Content-Type": "text/html"
|
||||
};
|
||||
|
||||
response.write(fs.read(filename));
|
||||
|
||||
response.close();
|
||||
});
|
||||
if (!listening) {
|
||||
console.log("could not create web server listening on port " + port);
|
||||
phantom.exit();
|
||||
console.log("could not create web server listening on port " + port);
|
||||
phantom.exit();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -42,100 +46,105 @@ if (!listening) {
|
||||
* @param timeOutMillis the max amount of time to wait. If not specified, 3 sec is used.
|
||||
* @param timeOutErrorMessage the error message if time out occurs
|
||||
*/
|
||||
|
||||
function waitFor(testFx, onReady, timeOutMillis, timeOutErrorMessage) {
|
||||
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 10001, //< Default Max Timeout is 10s
|
||||
start = new Date().getTime(),
|
||||
condition = false,
|
||||
interval = setInterval(function() {
|
||||
if ( (new Date().getTime() - start < maxtimeOutMillis) && !condition ) {
|
||||
// If not time-out yet and condition not yet fulfilled
|
||||
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
|
||||
} else {
|
||||
if(!condition) {
|
||||
// If condition still not fulfilled (timeout but condition is 'false')
|
||||
console.log(timeOutErrorMessage || "'waitFor()' timeout");
|
||||
phantom.exit(1);
|
||||
} else {
|
||||
// Condition fulfilled (timeout and/or condition is 'true')
|
||||
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
|
||||
clearInterval(interval); //< Stop this interval
|
||||
}
|
||||
}
|
||||
}, 100); //< repeat check every 100ms
|
||||
};
|
||||
var maxtimeOutMillis = timeOutMillis ? timeOutMillis : 10001, //< Default Max Timeout is 10s
|
||||
start = new Date().getTime(),
|
||||
condition = false,
|
||||
interval = setInterval(function() {
|
||||
if ((new Date().getTime() - start < maxtimeOutMillis) && !condition) {
|
||||
// If not time-out yet and condition not yet fulfilled
|
||||
condition = (typeof(testFx) === "string" ? eval(testFx) : testFx()); //< defensive code
|
||||
} else {
|
||||
if (!condition) {
|
||||
// If condition still not fulfilled (timeout but condition is 'false')
|
||||
console.log(timeOutErrorMessage || "'waitFor()' timeout");
|
||||
phantom.exit(1);
|
||||
} else {
|
||||
// Condition fulfilled (timeout and/or condition is 'true')
|
||||
typeof(onReady) === "string" ? eval(onReady) : onReady(); //< Do what it's supposed to do once the condition is fulfilled
|
||||
clearInterval(interval); //< Stop this interval
|
||||
}
|
||||
}
|
||||
}, 100); //< repeat check every 100ms
|
||||
}
|
||||
|
||||
function testPage(url) {
|
||||
var page = webpage.create();
|
||||
page.open(url, function (status) {
|
||||
if (status !== "success") {
|
||||
console.log("Unable to access network - " + status);
|
||||
phantom.exit();
|
||||
} else {
|
||||
waitFor(function(){
|
||||
return page.evaluate(function(){
|
||||
return document.body && document.body.querySelector &&
|
||||
document.body.querySelector('.symbolSummary .pending') === null &&
|
||||
document.body.querySelector('.results') !== null;
|
||||
});
|
||||
}, function(){
|
||||
page.onConsoleMessage = function (msg) {
|
||||
console.log(msg);
|
||||
};
|
||||
var exitCode = page.evaluate(function(){
|
||||
console.log('');
|
||||
console.log(document.body.querySelector('.description').innerText);
|
||||
var list = document.body.querySelectorAll('.results > #details > .specDetail.failed');
|
||||
if (list && list.length > 0) {
|
||||
console.log('');
|
||||
console.log(list.length + ' test(s) FAILED:');
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
var el = list[i],
|
||||
desc = el.querySelector('.description'),
|
||||
msg = el.querySelector('.resultMessage.fail');
|
||||
console.log('');
|
||||
console.log(desc.innerText);
|
||||
console.log(msg.innerText);
|
||||
console.log('');
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText);
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
testFinished(exitCode);
|
||||
},
|
||||
10000, // 10 second timeout
|
||||
"Test failed waiting for jasmine results on page: " + url);
|
||||
}
|
||||
});
|
||||
var page = webpage.create();
|
||||
page.open(url, function(status) {
|
||||
if (status !== "success") {
|
||||
console.log("Unable to access network - " + status);
|
||||
phantom.exit();
|
||||
} else {
|
||||
waitFor(function() {
|
||||
return page.evaluate(function() {
|
||||
return document.body && document.body.querySelector &&
|
||||
document.body.querySelector('.symbolSummary .pending') === null &&
|
||||
document.body.querySelector('.results') !== null;
|
||||
});
|
||||
}, function() {
|
||||
page.onConsoleMessage = function(msg) {
|
||||
console.log(msg);
|
||||
};
|
||||
var exitCode = page.evaluate(function() {
|
||||
console.log('');
|
||||
console.log(document.body.querySelector('.description').innerText);
|
||||
var list = document.body.querySelectorAll('.results > #details > .specDetail.failed');
|
||||
if (list && list.length > 0) {
|
||||
console.log('');
|
||||
console.log(list.length + ' test(s) FAILED:');
|
||||
for (var i = 0; i < list.length; ++i) {
|
||||
var el = list[i],
|
||||
desc = el.querySelector('.description'),
|
||||
msg = el.querySelector('.resultMessage.fail');
|
||||
console.log('');
|
||||
console.log(desc.innerText);
|
||||
console.log(msg.innerText);
|
||||
console.log('');
|
||||
}
|
||||
return 1;
|
||||
} else {
|
||||
console.log(document.body.querySelector('.alert > .passingAlert.bar').innerText);
|
||||
return 0;
|
||||
}
|
||||
});
|
||||
testFinished(exitCode);
|
||||
},
|
||||
10000, // 10 second timeout
|
||||
"Test failed waiting for jasmine results on page: " + url);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function scanDirectory(path, regex) {
|
||||
var files = [];
|
||||
fs.list(path).forEach(function (file) {
|
||||
if (file.match(regex)) {
|
||||
files.push(file);
|
||||
}
|
||||
});
|
||||
return files;
|
||||
};
|
||||
var files = [];
|
||||
fs.list(path).forEach(function(file) {
|
||||
if (file.match(regex)) {
|
||||
files.push(file);
|
||||
}
|
||||
});
|
||||
return files;
|
||||
}
|
||||
|
||||
var totalTests = 0,
|
||||
totalFailed = 0,
|
||||
totalDone = 0;
|
||||
totalFailed = 0,
|
||||
totalDone = 0;
|
||||
|
||||
function testFinished(failed) {
|
||||
if (failed) { totalFailed++; }
|
||||
totalDone++;
|
||||
if (totalDone === totalTests) { phantom.exit(totalFailed > 0 ? 1 : 0); }
|
||||
if (failed) {
|
||||
totalFailed++;
|
||||
}
|
||||
totalDone++;
|
||||
if (totalDone === totalTests) {
|
||||
phantom.exit(totalFailed > 0 ? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
if (system.args.length != 2 && system.args[1] != "--no-tests") {
|
||||
var files = scanDirectory("test/browser/", /^test-runner-.+\.htm$/);
|
||||
totalTests = files.length;
|
||||
console.log("found " + files.length + " tests");
|
||||
files.forEach(function(file) {
|
||||
testPage("http://localhost:8081/browser/" + file);
|
||||
});
|
||||
var files = scanDirectory("test/browser/", /^test-runner-.+\.htm$/);
|
||||
totalTests = files.length;
|
||||
console.log("found " + files.length + " tests");
|
||||
files.forEach(function(file) {
|
||||
testPage("http://localhost:8081/browser/" + file);
|
||||
});
|
||||
}
|
||||
42
test/browser/runner-browser-options.js
Normal file
42
test/browser/runner-browser-options.js
Normal file
@@ -0,0 +1,42 @@
|
||||
var less = {};
|
||||
|
||||
// There originally run inside describe method. However, since they have not
|
||||
// been inside it, they run at jasmine compile time (not runtime). It all
|
||||
// worked cause less.js was in async mode and custom phantom runner had
|
||||
// different setup then grunt-contrib-jasmine. They have been created before
|
||||
// less.js run, even as they have been defined in spec.
|
||||
|
||||
// test inline less in style tags by grabbing an assortment of less files and doing `@import`s
|
||||
var testFiles = ['charsets', 'colors', 'comments', 'css-3', 'strings', 'media', 'mixins'],
|
||||
testSheets = [];
|
||||
|
||||
// setup style tags with less and link tags pointing to expected css output
|
||||
for (var i = 0; i < testFiles.length; i++) {
|
||||
var file = testFiles[i],
|
||||
lessPath = '/test/less/' + file + '.less',
|
||||
cssPath = '/test/css/' + file + '.css',
|
||||
lessStyle = document.createElement('style'),
|
||||
cssLink = document.createElement('link'),
|
||||
lessText = '@import "' + lessPath + '";';
|
||||
|
||||
lessStyle.type = 'text/less';
|
||||
lessStyle.id = file;
|
||||
lessStyle.href = file;
|
||||
|
||||
if (lessStyle.styleSheet) {
|
||||
lessStyle.styleSheet.cssText = lessText;
|
||||
} else {
|
||||
lessStyle.innerHTML = lessText;
|
||||
}
|
||||
|
||||
cssLink.rel = 'stylesheet';
|
||||
cssLink.type = 'text/css';
|
||||
cssLink.href = cssPath;
|
||||
cssLink.id = 'expected-' + file;
|
||||
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
|
||||
head.appendChild(lessStyle);
|
||||
head.appendChild(cssLink);
|
||||
testSheets[i] = lessStyle;
|
||||
}
|
||||
12
test/browser/runner-browser-spec.js
Normal file
12
test/browser/runner-browser-spec.js
Normal file
@@ -0,0 +1,12 @@
|
||||
describe("less.js browser behaviour", function() {
|
||||
testLessEqualsInDocument();
|
||||
|
||||
it("has some log messages", function() {
|
||||
expect(logMessages.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
for (var i = 0; i < testFiles.length; i++) {
|
||||
var sheet = testSheets[i];
|
||||
testSheet(sheet);
|
||||
}
|
||||
});
|
||||
@@ -1,42 +0,0 @@
|
||||
describe("less.js browser behaviour", function() {
|
||||
testLessEqualsInDocument();
|
||||
|
||||
it("has some log messages", function() {
|
||||
expect(logMessages.length).toBeGreaterThan(0);
|
||||
});
|
||||
|
||||
// test inline less in style tags by grabbing an assortment of less files and doing `@import`s
|
||||
var testFiles = ['charsets', 'colors', 'comments', 'css-3', 'strings', 'media', 'mixins'],
|
||||
testSheets = [];
|
||||
|
||||
// setup style tags with less and link tags pointing to expected css output
|
||||
for (var i = 0; i < testFiles.length; i++) {
|
||||
var file = testFiles[i],
|
||||
lessPath = '/less/' + file + '.less',
|
||||
cssPath = '/css/' + file + '.css',
|
||||
lessStyle = document.createElement('style'),
|
||||
cssLink = document.createElement('link'),
|
||||
lessText = '@import "' + lessPath + '";';
|
||||
lessStyle.type = 'text/less';
|
||||
lessStyle.id = file;
|
||||
if (lessStyle.styleSheet) {
|
||||
lessStyle.styleSheet.cssText = lessText;
|
||||
} else {
|
||||
lessStyle.innerHTML = lessText;
|
||||
}
|
||||
cssLink.rel = 'stylesheet';
|
||||
cssLink.type = 'text/css';
|
||||
cssLink.href = cssPath;
|
||||
cssLink.id = 'expected-' + file;
|
||||
|
||||
var head = document.getElementsByTagName('head')[0];
|
||||
head.appendChild(lessStyle);
|
||||
head.appendChild(cssLink);
|
||||
testSheets[i] = lessStyle;
|
||||
}
|
||||
|
||||
for (var i = 0; i < testFiles.length; i++) {
|
||||
var sheet = testSheets[i];
|
||||
testSheet(sheet);
|
||||
}
|
||||
});
|
||||
3
test/browser/runner-errors-options.js
Normal file
3
test/browser/runner-errors-options.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var less = {};
|
||||
less.strictUnits = true;
|
||||
|
||||
4
test/browser/runner-errors-spec.js
Normal file
4
test/browser/runner-errors-spec.js
Normal file
@@ -0,0 +1,4 @@
|
||||
describe("less.js error tests", function() {
|
||||
testLessErrorsInDocument();
|
||||
});
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
less.strictUnits = true;
|
||||
|
||||
describe("less.js error tests", function() {
|
||||
testLessErrorsInDocument();
|
||||
});
|
||||
4
test/browser/runner-legacy-options.js
Normal file
4
test/browser/runner-legacy-options.js
Normal file
@@ -0,0 +1,4 @@
|
||||
var less = {};
|
||||
less.strictMath = false;
|
||||
less.strictUnits = false;
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
less.strictMath = false;
|
||||
less.strictUnits = false;
|
||||
|
||||
describe("less.js legacy tests", function() {
|
||||
testLessEqualsInDocument();
|
||||
});
|
||||
});
|
||||
15
test/browser/runner-main-options.js
Normal file
15
test/browser/runner-main-options.js
Normal file
@@ -0,0 +1,15 @@
|
||||
var less = {};
|
||||
less.strictMath = true;
|
||||
less.functions = {
|
||||
add: function(a, b) {
|
||||
return new(less.tree.Dimension)(a.value + b.value);
|
||||
},
|
||||
increment: function(a) {
|
||||
return new(less.tree.Dimension)(a.value + 1);
|
||||
},
|
||||
_color: function(str) {
|
||||
if (str.value === "evil red") {
|
||||
return new(less.tree.Color)("600");
|
||||
}
|
||||
}
|
||||
};
|
||||
3
test/browser/runner-main-spec.js
Normal file
3
test/browser/runner-main-spec.js
Normal file
@@ -0,0 +1,3 @@
|
||||
describe("less.js main tests", function() {
|
||||
testLessEqualsInDocument();
|
||||
});
|
||||
@@ -1,15 +0,0 @@
|
||||
less.functions = {
|
||||
add: function (a, b) {
|
||||
return new(less.tree.Dimension)(a.value + b.value);
|
||||
},
|
||||
increment: function (a) {
|
||||
return new(less.tree.Dimension)(a.value + 1);
|
||||
},
|
||||
_color: function (str) {
|
||||
if (str.value === "evil red") { return new(less.tree.Color)("600") }
|
||||
}
|
||||
};
|
||||
|
||||
describe("less.js main tests", function() {
|
||||
testLessEqualsInDocument();
|
||||
});
|
||||
2
test/browser/runner-modify-vars-options.js
Normal file
2
test/browser/runner-modify-vars-options.js
Normal file
@@ -0,0 +1,2 @@
|
||||
/* exported less */
|
||||
var less = {};
|
||||
42
test/browser/runner-modify-vars-spec.js
Normal file
42
test/browser/runner-modify-vars-spec.js
Normal file
@@ -0,0 +1,42 @@
|
||||
var alreadyRun = false;
|
||||
|
||||
describe("less.js modify vars", function() {
|
||||
beforeEach(function() {
|
||||
// simulating "setUp" or "beforeAll" method
|
||||
var lessOutputObj;
|
||||
if (alreadyRun)
|
||||
return;
|
||||
|
||||
alreadyRun = true;
|
||||
|
||||
// wait until the sheet is compiled first time
|
||||
waitsFor(function() {
|
||||
lessOutputObj = document.getElementById("less:test-less-simple");
|
||||
return lessOutputObj !== null;
|
||||
}, "first generation of less:test-less-simple", 7000);
|
||||
|
||||
// modify variables
|
||||
runs(function() {
|
||||
lessOutputObj.type = "not compiled yet";
|
||||
less.modifyVars({
|
||||
var1: "green",
|
||||
var2: "purple"
|
||||
});
|
||||
});
|
||||
|
||||
// wait until variables are modified
|
||||
waitsFor(function() {
|
||||
lessOutputObj = document.getElementById("less:test-less-simple");
|
||||
return lessOutputObj !== null && lessOutputObj.type === "text/css";
|
||||
}, "second generation of less:test-less-simple", 7000);
|
||||
|
||||
});
|
||||
|
||||
testLessEqualsInDocument();
|
||||
it("Should log only 2 XHR requests", function() {
|
||||
var xhrLogMessages = logMessages.filter(function(item) {
|
||||
return (/XHR: Getting '/).test(item);
|
||||
});
|
||||
expect(xhrLogMessages.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
@@ -1,14 +0,0 @@
|
||||
|
||||
setTimeout(function(){
|
||||
less.modifyVars({var1: "green", var2: "purple"});
|
||||
}, 1000);
|
||||
|
||||
describe("less.js modify vars", function() {
|
||||
testLessEqualsInDocument();
|
||||
it("Should log only 2 XHR requests", function() {
|
||||
var xhrLogMessages = logMessages.filter(function(item) {
|
||||
return /XHR: Getting '/.test(item);
|
||||
})
|
||||
expect(xhrLogMessages.length).toEqual(2);
|
||||
});
|
||||
});
|
||||
4
test/browser/runner-no-js-errors-options.js
Normal file
4
test/browser/runner-no-js-errors-options.js
Normal file
@@ -0,0 +1,4 @@
|
||||
var less = {};
|
||||
|
||||
less.strictUnits = true;
|
||||
less.javascriptEnabled = false;
|
||||
4
test/browser/runner-no-js-errors-spec.js
Normal file
4
test/browser/runner-no-js-errors-spec.js
Normal file
@@ -0,0 +1,4 @@
|
||||
describe("less.js javascript disabled error tests", function() {
|
||||
testLessErrorsInDocument();
|
||||
});
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
less.strictUnits = true;
|
||||
less.javascriptEnabled = false;
|
||||
|
||||
describe("less.js javascript disabled error tests", function() {
|
||||
testLessErrorsInDocument();
|
||||
});
|
||||
3
test/browser/runner-production-options.js
Normal file
3
test/browser/runner-production-options.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var less = {};
|
||||
less.env = "production";
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
less.env = "production";
|
||||
|
||||
describe("less.js production behaviour", function() {
|
||||
it("doesn't log any messages", function() {
|
||||
expect(logMessages.length).toEqual(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
3
test/browser/runner-relative-urls-options.js
Normal file
3
test/browser/runner-relative-urls-options.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var less = {};
|
||||
less.relativeUrls = true;
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
less.relativeUrls = true;
|
||||
describe("less.js browser test - relative url's", function() {
|
||||
testLessEqualsInDocument();
|
||||
});
|
||||
});
|
||||
3
test/browser/runner-rootpath-options.js
Normal file
3
test/browser/runner-rootpath-options.js
Normal file
@@ -0,0 +1,3 @@
|
||||
var less = {};
|
||||
less.rootpath = "https://www.github.com/";
|
||||
|
||||
4
test/browser/runner-rootpath-relative-options.js
Normal file
4
test/browser/runner-rootpath-relative-options.js
Normal file
@@ -0,0 +1,4 @@
|
||||
var less = {};
|
||||
less.rootpath = "https://www.github.com/cloudhead/less.js/";
|
||||
less.relativeUrls = true;
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
less.rootpath = "https://www.github.com/cloudhead/less.js/";
|
||||
less.relativeUrls = true;
|
||||
describe("less.js browser test - rootpath and relative url's", function() {
|
||||
testLessEqualsInDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,4 +1,3 @@
|
||||
less.rootpath = "https://www.github.com/";
|
||||
describe("less.js browser test - rootpath url's", function() {
|
||||
testLessEqualsInDocument();
|
||||
});
|
||||
});
|
||||
@@ -1,11 +0,0 @@
|
||||
<script src="/browser/jasmine.js" type="text/javascript"></script>
|
||||
<script src="/browser/jasmine-html.js" type="text/javascript"></script>
|
||||
<script src="/browser/common.js" type="text/javascript"></script>
|
||||
<script src="/browser/es5.js" type="text/javascript"></script>
|
||||
<script src="/browser/runner-{runner-name}.js" type="text/javascript"></script>
|
||||
<script src="/browser/less.js" type="text/javascript"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/browser/jasmine.css" />
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
47
test/browser/test-runner-template.tmpl
Normal file
47
test/browser/test-runner-template.tmpl
Normal file
@@ -0,0 +1,47 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>Jasmine Spec Runner</title>
|
||||
|
||||
<!-- generate script tags for tests -->
|
||||
<% var generateScriptTags = function(allScripts) { allScripts.forEach(function(script){ %>
|
||||
<script src="<%= script %>"></script>
|
||||
<% }); }; %>
|
||||
|
||||
<!-- for each test, generate CSS/LESS link tags -->
|
||||
<% scripts.src.forEach(function(fullLessName) {
|
||||
var pathParts = fullLessName.split('/');
|
||||
var fullCssName = fullLessName.replace(/less/g, 'css');
|
||||
var lessName = pathParts[pathParts.length - 1];
|
||||
var name = lessName.split('.')[0]; %>
|
||||
<!-- the tags to be generated -->
|
||||
<link id="original-less:test-less-<%= name %>" title="test-less-<%= name %>" rel="stylesheet/less" type="text/css" href="<%= fullLessName %>">
|
||||
<link id="expected-less:test-less-<%= name %>" rel="stylesheet" type="text/css" href="<%= fullCssName %>">
|
||||
<% }); %>
|
||||
|
||||
<!-- generate grunt-contrib-jasmine link tags -->
|
||||
<% css.forEach(function(style){ %>
|
||||
<link rel="stylesheet" type="text/css" href="<%= style %>">
|
||||
<% }) %>
|
||||
|
||||
<!-- inital grunt-contrib-jasmine scripts -->
|
||||
<% generateScriptTags([].concat(scripts.polyfills, scripts.jasmine)); %>
|
||||
|
||||
<!-- Helpers - The less options -->
|
||||
<% generateScriptTags(scripts.helpers); %>
|
||||
|
||||
<!-- Vendor - less.js and common code -->
|
||||
<% generateScriptTags(scripts.vendor); %>
|
||||
|
||||
<!-- Spec -->
|
||||
<% generateScriptTags(scripts.specs); %>
|
||||
|
||||
<!-- final grunt-contrib-jasmine scripts -->
|
||||
<% generateScriptTags([].concat(scripts.reporters, scripts.start)); %>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<!-- content -->
|
||||
</body>
|
||||
</html>
|
||||
@@ -26,7 +26,7 @@ less.tree.functions._color = function (str) {
|
||||
if (str.value === "evil red") { return new(less.tree.Color)("600"); }
|
||||
};
|
||||
|
||||
sys.puts("\n" + stylize("LESS", 'underline') + "\n");
|
||||
console.log("\n" + stylize("LESS", 'underline') + "\n");
|
||||
|
||||
runTestSet({strictMath: true, relativeUrls: true, silent: true});
|
||||
runTestSet({strictMath: true, strictUnits: true}, "errors/",
|
||||
@@ -72,7 +72,6 @@ function testSourcemap(name, err, compiledLess, doReplacements, sourcemap) {
|
||||
} else {
|
||||
difference("FAIL", expectedSourcemap, sourcemap);
|
||||
}
|
||||
sys.puts("");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -94,7 +93,6 @@ function testErrors(name, err, compiledLess, doReplacements) {
|
||||
difference("FAIL", expectedErr, errMessage);
|
||||
}
|
||||
}
|
||||
sys.puts("");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -120,16 +118,19 @@ function checkGlobalLeaks() {
|
||||
function runTestSet(options, foldername, verifyFunction, nameModifier, doReplacements, getFilename) {
|
||||
foldername = foldername || "";
|
||||
|
||||
if(!doReplacements)
|
||||
if(!doReplacements) {
|
||||
doReplacements = globalReplacements;
|
||||
}
|
||||
|
||||
fs.readdirSync(path.join('test/less/', foldername)).forEach(function (file) {
|
||||
if (! /\.less/.test(file)) { return; }
|
||||
|
||||
var name = foldername + path.basename(file, '.less');
|
||||
|
||||
if (oneTestOnly && name !== oneTestOnly) { return; }
|
||||
|
||||
if (oneTestOnly && name !== oneTestOnly) {
|
||||
return;
|
||||
}
|
||||
|
||||
totalTests++;
|
||||
|
||||
if (options.sourceMap) {
|
||||
@@ -163,14 +164,12 @@ function runTestSet(options, foldername, verifyFunction, nameModifier, doReplace
|
||||
} else {
|
||||
difference("FAIL", css, less);
|
||||
}
|
||||
sys.puts("");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function diff(left, right) {
|
||||
sys.puts("");
|
||||
require('diff').diffLines(left, right).forEach(function(item) {
|
||||
if(item.added || item.removed) {
|
||||
var text = item.value.replace("\n", String.fromCharCode(182) + "\n");
|
||||
@@ -179,16 +178,17 @@ function diff(left, right) {
|
||||
sys.print(item.value);
|
||||
}
|
||||
});
|
||||
console.log("");
|
||||
}
|
||||
|
||||
function fail(msg) {
|
||||
sys.print(stylize(msg, 'red'));
|
||||
console.error(stylize(msg, 'red'));
|
||||
failedTests++;
|
||||
endTest();
|
||||
}
|
||||
|
||||
function difference(msg, left, right) {
|
||||
sys.print(stylize(msg, 'yellow'));
|
||||
console.warn(stylize(msg, 'yellow'));
|
||||
failedTests++;
|
||||
|
||||
diff(left, right);
|
||||
@@ -196,7 +196,7 @@ function difference(msg, left, right) {
|
||||
}
|
||||
|
||||
function ok(msg) {
|
||||
sys.print(stylize(msg, 'green'));
|
||||
console.log(stylize(msg, 'green'));
|
||||
passedTests++;
|
||||
endTest();
|
||||
}
|
||||
@@ -204,21 +204,20 @@ function ok(msg) {
|
||||
function endTest() {
|
||||
var leaked = checkGlobalLeaks();
|
||||
if (failedTests + passedTests === totalTests) {
|
||||
sys.puts("");
|
||||
sys.puts("");
|
||||
console.log("");
|
||||
if (failedTests > 0) {
|
||||
sys.print(failedTests);
|
||||
sys.print(stylize(" Failed", "red"));
|
||||
sys.print(", " + passedTests + " passed");
|
||||
console.error(failedTests + stylize(" Failed", "red") + ", " + passedTests + " passed");
|
||||
} else {
|
||||
sys.print(stylize("All Passed ", "green"));
|
||||
sys.print(passedTests + " run");
|
||||
console.log(stylize("All Passed ", "green") + passedTests + " run");
|
||||
}
|
||||
if (leaked.length > 0) {
|
||||
sys.puts("");
|
||||
sys.puts("");
|
||||
sys.print(stylize("Global leak detected: ", "red") + leaked.join(', '));
|
||||
sys.print("\n");
|
||||
console.log("");
|
||||
console.warn(stylize("Global leak detected: ", "red") + leaked.join(', '));
|
||||
}
|
||||
|
||||
if (leaked.length || failedTests) {
|
||||
//process.exit(1);
|
||||
process.on('exit', function() { process.reallyExit(1) });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
{"version":3,"file":"sourcemaps/basic.css","sources":["testweb/sourcemaps/basic.less"],"names":[],"mappings":"AAMG;EACD,YAAA;EAJA,UAAA;EAWA,iBAAA;EALA,WAAA;EACA,mBAAA;;AAJC,EASC;AATD,EASM;EACL,gBAAA;;AACE,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFD;AAEH,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFD;EAGH,UAAA;;AALJ;AAAK;AAUA;EATL,iBAAA;;AADA,EAEE;AAFG,EAEH;AAFF,EAEO;AAFF,EAEE;AAQF,OARH;AAQG,OARE;EACL,gBAAA;;AACE,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFD;AAEH,EAFF,GAEM,KAFD;AAEH,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFN;AAEE,EAFF,GAEM,KAFD;AAEH,EAFF,GAEM,KAFD;AAEH,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFD;AAEH,EAFG,GAEC,KAFD;AAEH,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFN;AAEE,EAFG,GAEC,KAFD;AAEH,EAFG,GAEC,KAFD;AAQF,OARH,GAQG,UARH;AAQG,OARH,GAEM,KAFN;AAQG,OARH,GAQG,UARE;AAQF,OARH,GAEM,KAFD;AAEH,EAFF,GAQG,UARH;AAEE,EAFF,GAQG,UARE;AAQF,OARE,GAQF,UARH;AAQG,OARE,GAEC,KAFN;AAQG,OARE,GAQF,UARE;AAQF,OARE,GAEC,KAFD;AAEH,EAFG,GAQF,UARH;AAEE,EAFG,GAQF,UARE;EAGH,UAAA;;AAKC;EACL,WAAA"}
|
||||
Reference in New Issue
Block a user