Add temporary bundled copy of less.js.

This is for use until we have less.js packaged in production.
This commit is contained in:
Max Goodman
2012-11-07 13:54:54 -08:00
parent 0b88e33b59
commit f52f223bcc
104 changed files with 10958 additions and 1 deletions

View File

@@ -135,7 +135,7 @@ endef
$(foreach plugin,$(PLUGINS),$(eval $(call PLUGIN_STATIC_TEMPLATE,$(plugin))))
#### Stylesheets
LESSC := lessc
LESSC := r2/lib/contrib/less.js/bin/lessc
CSS_COMPRESS := $(PYTHON) r2/lib/contrib/rcssmin.py
CSS_SOURCE_DIR := $(STATIC_BUILD_DIR)/css

View File

@@ -0,0 +1,41 @@
1.3.0
@media bubbling
Support arbitrary entities as selectors
Variadic argument support, see: https://gist.github.com/1933613
Behaviour of zero-arity mixins has changed, see link above.
Allow '@import' directives in any selector
Media-query features can now be a variable
Automatic merging of media-query conditions
Fix global variable leaks
Fix error message on wrong-arity call
Fix an '@arguments' behaviour bug
Fix '::' selector output
Fix a bug when using @media with mixins
1.2.1
Fix imports on browser
Improve error reporting on browser
Fix Runtime error reports from imported files
Fix 'File not found' import error reporting
1.2.0
Mixin guards
New function `percentage`
New `color` function to parse hex color strings
New type-checking stylesheet functions
Fix Rhino support
Fix bug in string arguments to mixin call
Fix error reporting when index is 0
Fix browser support in webkit and IE
Fix string interpolation bug when var is empty
Support '!important' after mixin calls
Support vanilla @keyframes directive
Support variables in certain css selectors, like 'nth-child'
Support @media and @import features properly
Improve @import support with media features
Improve error reports from imported files
Improve function call error reporting
Improve error-reporting

View File

@@ -0,0 +1,179 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
Copyright (c) 2009-2010 Alexis Sellier

View File

@@ -0,0 +1,75 @@
#
# 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
less:
@@mkdir -p dist
@@touch ${DIST}
@@cat ${HEADER} | sed s/@VERSION/${VERSION}/ > ${DIST}
@@echo "(function (window, undefined) {" >> ${DIST}
@@cat build/require.js\
build/amd.js\
build/ecma-5.js\
${SRC}/parser.js\
${SRC}/functions.js\
${SRC}/colors.js\
${SRC}/tree/*.js\
${SRC}/tree.js\
${SRC}/browser.js >> ${DIST}
@@echo "})(window);" >> ${DIST}
@@echo ${DIST} built.
rhino:
@@mkdir -p dist
@@touch ${RHINO}
@@cat build/require-rhino.js\
build/ecma-5.js\
${SRC}/parser.js\
${SRC}/functions.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.
server: less
cp dist/less-${VERSION}.js test/html/
cd test/html && python -m SimpleHTTPServer
clean:
git rm dist/*
dist: clean min
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

View File

@@ -0,0 +1,20 @@
less.js
=======
The **dynamic** stylesheet language.
<http://lesscss.org>
about
-----
This is the JavaScript, and now official, stable version of LESS.
For more information, visit <http://lesscss.org>.
license
-------
See `LICENSE` file.
> Copyright (c) 2009-2011 Alexis Sellier

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,47 @@
var path = require('path'),
fs = require('fs'),
sys = require('util');
var less = require('../lib/less');
var file = path.join(__dirname, 'benchmark.less');
if (process.argv[2]) { file = path.join(process.cwd(), process.argv[2]) }
fs.readFile(file, 'utf8', function (e, data) {
var tree, css, start, end, total;
sys.puts("Benchmarking...\n", path.basename(file) + " (" +
parseInt(data.length / 1024) + " KB)", "");
start = new(Date);
new(less.Parser)({ optimization: 2 }).parse(data, function (err, tree) {
end = new(Date);
total = end - start;
sys.puts("Parsing: " +
total + " ms (" +
parseInt(1000 / total *
data.length / 1024) + " KB\/s)");
start = new(Date);
css = tree.toCSS();
end = new(Date);
sys.puts("Generation: " + (end - start) + " ms (" +
parseInt(1000 / (end - start) *
data.length / 1024) + " KB\/s)");
total += end - start;
sys.puts("Total: " + total + "ms (" +
parseInt(1000 / total * data.length / 1024) + " KB/s)");
if (err) {
less.writeError(err);
process.exit(3);
}
});
});

View File

@@ -0,0 +1,143 @@
#!/usr/bin/env node
// Note: modified slightly to hobble along on Ubuntu Natty's ancient Node.
var path = require('path'),
fs = require('fs'),
sys = require('util');
try {
var os = require('os');
} catch (e) {}
var less = require('../lib/less');
var args = process.argv.slice(1);
var options = {
compress: false,
yuicompress: false,
optimization: 1,
silent: false,
paths: [],
color: true,
strictImports: false
};
args = args.filter(function (arg) {
var match;
if (match = arg.match(/^-I(.+)$/)) {
options.paths.push(match[1]);
return false;
}
if (match = arg.match(/^--?([a-z][0-9a-z-]*)(?:=([^\s]+))?$/i)) { arg = match[1] }
else { return arg }
switch (arg) {
case 'v':
case 'version':
sys.puts("lessc " + less.version.join('.') + " (LESS Compiler) [JavaScript]");
process.exit(0);
case 'verbose':
options.verbose = true;
break;
case 's':
case 'silent':
options.silent = true;
break;
case 'strict-imports':
options.strictImports = true;
break;
case 'h':
case 'help':
sys.puts("usage: lessc source [destination]");
process.exit(0);
case 'x':
case 'compress':
options.compress = true;
break;
case 'yui-compress':
options.yuicompress = true;
break;
case 'no-color':
options.color = false;
break;
case 'include-path':
options.paths = match[2].split(os.type().match(/Windows/) ? ';' : ':')
.map(function(p) {
if (p) {
return path.resolve(process.cwd(), p);
}
});
break;
case 'O0': options.optimization = 0; break;
case 'O1': options.optimization = 1; break;
case 'O2': options.optimization = 2; break;
}
});
var input = args[1];
if (input && input != '-' && path.resolve) {
input = path.resolve(process.cwd(), input);
}
var output = args[2];
if (output && path.resolve) {
output = path.resolve(process.cwd(), output);
}
var css, fd, tree;
if (! input) {
sys.puts("lessc: no input files");
process.exit(1);
}
var parseLessFile = function (e, data) {
if (e) {
sys.puts("lessc: " + e.message);
process.exit(1);
}
new(less.Parser)({
paths: [path.dirname(input)].concat(options.paths),
optimization: options.optimization,
filename: input,
strictImports: options.strictImports
}).parse(data, function (err, tree) {
if (err) {
less.writeError(err, options);
process.exit(1);
} else {
try {
css = tree.toCSS({
compress: options.compress,
yuicompress: options.yuicompress
});
if (output) {
fd = fs.openSync(output, "w");
fs.writeSync(fd, css, 0, "utf8");
} else {
sys.print(css);
}
} catch (e) {
less.writeError(e, options);
process.exit(2);
}
}
});
};
if (input != '-') {
fs.readFile(input, 'utf-8', parseLessFile);
} else {
process.stdin.resume();
process.stdin.setEncoding('utf8');
var buffer = '';
process.stdin.on('data', function(data) {
buffer += data;
});
process.stdin.on('end', function() {
parseLessFile(false, buffer);
});
}

View File

@@ -0,0 +1,380 @@
//
// browser.js - client-side engine
//
var isFileProtocol = (location.protocol === 'file:' ||
location.protocol === 'chrome:' ||
location.protocol === 'chrome-extension:' ||
location.protocol === 'resource:');
less.env = less.env || (location.hostname == '127.0.0.1' ||
location.hostname == '0.0.0.0' ||
location.hostname == 'localhost' ||
location.port.length > 0 ||
isFileProtocol ? 'development'
: 'production');
// Load styles asynchronously (default: false)
//
// This is set to `false` by default, so that the body
// doesn't start loading before the stylesheets are parsed.
// Setting this to `true` can result in flickering.
//
less.async = false;
// Interval between watch polls
less.poll = less.poll || (isFileProtocol ? 1000 : 1500);
//
// Watch mode
//
less.watch = function () { return this.watchMode = true };
less.unwatch = function () { return this.watchMode = false };
if (less.env === 'development') {
less.optimization = 0;
if (/!watch/.test(location.hash)) {
less.watch();
}
less.watchTimer = setInterval(function () {
if (less.watchMode) {
loadStyleSheets(function (e, root, _, sheet, env) {
if (root) {
createCSS(root.toCSS(), sheet, env.lastModified);
}
});
}
}, less.poll);
} else {
less.optimization = 3;
}
var cache;
try {
cache = (typeof(window.localStorage) === 'undefined') ? null : window.localStorage;
} catch (_) {
cache = null;
}
//
// Get all <link> tags with the 'rel' attribute set to "stylesheet/less"
//
var links = document.getElementsByTagName('link');
var typePattern = /^text\/(x-)?less$/;
less.sheets = [];
for (var i = 0; i < links.length; i++) {
if (links[i].rel === 'stylesheet/less' || (links[i].rel.match(/stylesheet/) &&
(links[i].type.match(typePattern)))) {
less.sheets.push(links[i]);
}
}
less.refresh = function (reload) {
var startTime, endTime;
startTime = endTime = new(Date);
loadStyleSheets(function (e, root, _, sheet, env) {
if (env.local) {
log("loading " + sheet.href + " from cache.");
} else {
log("parsed " + sheet.href + " successfully.");
createCSS(root.toCSS(), sheet, env.lastModified);
}
log("css for " + sheet.href + " generated in " + (new(Date) - endTime) + 'ms');
(env.remaining === 0) && log("css generated in " + (new(Date) - startTime) + 'ms');
endTime = new(Date);
}, reload);
loadStyles();
};
less.refreshStyles = loadStyles;
less.refresh(less.env === 'development');
function loadStyles() {
var styles = document.getElementsByTagName('style');
for (var i = 0; i < styles.length; i++) {
if (styles[i].type.match(typePattern)) {
new(less.Parser)().parse(styles[i].innerHTML || '', function (e, tree) {
var css = tree.toCSS();
var style = styles[i];
style.type = 'text/css';
if (style.styleSheet) {
style.styleSheet.cssText = css;
} else {
style.innerHTML = css;
}
});
}
}
}
function loadStyleSheets(callback, reload) {
for (var i = 0; i < less.sheets.length; i++) {
loadStyleSheet(less.sheets[i], callback, reload, less.sheets.length - (i + 1));
}
}
function loadStyleSheet(sheet, callback, reload, remaining) {
var url = window.location.href.replace(/[#?].*$/, '');
var href = sheet.href.replace(/\?.*$/, '');
var css = cache && cache.getItem(href);
var timestamp = cache && cache.getItem(href + ':timestamp');
var styles = { css: css, timestamp: timestamp };
// Stylesheets in IE don't always return the full path
if (! /^(https?|file):/.test(href)) {
if (href.charAt(0) == "/") {
href = window.location.protocol + "//" + window.location.host + href;
} else {
href = url.slice(0, url.lastIndexOf('/') + 1) + href;
}
}
var filename = href.match(/([^\/]+)$/)[1];
xhr(sheet.href, sheet.type, function (data, lastModified) {
if (!reload && styles && lastModified &&
(new(Date)(lastModified).valueOf() ===
new(Date)(styles.timestamp).valueOf())) {
// Use local copy
createCSS(styles.css, sheet);
callback(null, null, data, sheet, { local: true, remaining: remaining });
} else {
// Use remote copy (re-parse)
try {
new(less.Parser)({
optimization: less.optimization,
paths: [href.replace(/[\w\.-]+$/, '')],
mime: sheet.type,
filename: filename
}).parse(data, function (e, root) {
if (e) { return error(e, href) }
try {
callback(e, root, data, sheet, { local: false, lastModified: lastModified, remaining: remaining });
removeNode(document.getElementById('less-error-message:' + extractId(href)));
} catch (e) {
error(e, href);
}
});
} catch (e) {
error(e, href);
}
}
}, function (status, url) {
throw new(Error)("Couldn't load " + url + " (" + status + ")");
});
}
function extractId(href) {
return href.replace(/^[a-z]+:\/\/?[^\/]+/, '' ) // Remove protocol & domain
.replace(/^\//, '' ) // Remove root /
.replace(/\?.*$/, '' ) // Remove query
.replace(/\.[^\.\/]+$/, '' ) // Remove file extension
.replace(/[^\.\w-]+/g, '-') // Replace illegal characters
.replace(/\./g, ':'); // Replace dots with colons(for valid id)
}
function createCSS(styles, sheet, lastModified) {
var css;
// Strip the query-string
var href = sheet.href ? sheet.href.replace(/\?.*$/, '') : '';
// If there is no title set, use the filename, minus the extension
var id = 'less:' + (sheet.title || extractId(href));
// If the stylesheet doesn't exist, create a new node
if ((css = document.getElementById(id)) === null) {
css = document.createElement('style');
css.type = 'text/css';
css.media = sheet.media || 'screen';
css.id = id;
document.getElementsByTagName('head')[0].appendChild(css);
}
if (css.styleSheet) { // IE
try {
css.styleSheet.cssText = styles;
} catch (e) {
throw new(Error)("Couldn't reassign styleSheet.cssText.");
}
} else {
(function (node) {
if (css.childNodes.length > 0) {
if (css.firstChild.nodeValue !== node.nodeValue) {
css.replaceChild(node, css.firstChild);
}
} else {
css.appendChild(node);
}
})(document.createTextNode(styles));
}
// Don't update the local store if the file wasn't modified
if (lastModified && cache) {
log('saving ' + href + ' to cache.');
cache.setItem(href, styles);
cache.setItem(href + ':timestamp', lastModified);
}
}
function xhr(url, type, callback, errback) {
var xhr = getXMLHttpRequest();
var async = isFileProtocol ? false : less.async;
if (typeof(xhr.overrideMimeType) === 'function') {
xhr.overrideMimeType('text/css');
}
xhr.open('GET', url, async);
xhr.setRequestHeader('Accept', type || 'text/x-less, text/css; q=0.9, */*; q=0.5');
xhr.send(null);
if (isFileProtocol) {
if (xhr.status === 0 || (xhr.status >= 200 && xhr.status < 300)) {
callback(xhr.responseText);
} else {
errback(xhr.status, url);
}
} else if (async) {
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
handleResponse(xhr, callback, errback);
}
};
} else {
handleResponse(xhr, callback, errback);
}
function handleResponse(xhr, callback, errback) {
if (xhr.status >= 200 && xhr.status < 300) {
callback(xhr.responseText,
xhr.getResponseHeader("Last-Modified"));
} else if (typeof(errback) === 'function') {
errback(xhr.status, url);
}
}
}
function getXMLHttpRequest() {
if (window.XMLHttpRequest) {
return new(XMLHttpRequest);
} else {
try {
return new(ActiveXObject)("MSXML2.XMLHTTP.3.0");
} catch (e) {
log("browser doesn't support AJAX.");
return null;
}
}
}
function removeNode(node) {
return node && node.parentNode.removeChild(node);
}
function log(str) {
if (less.env == 'development' && typeof(console) !== "undefined") { console.log('less: ' + str) }
}
function error(e, href) {
var id = 'less-error-message:' + extractId(href);
var template = '<li><label>{line}</label><pre class="{class}">{content}</pre></li>';
var elem = document.createElement('div'), timer, content, error = [];
var filename = e.filename || href;
elem.id = id;
elem.className = "less-error-message";
content = '<h3>' + (e.message || 'There is an error in your .less file') +
'</h3>' + '<p>in <a href="' + filename + '">' + filename + "</a> ";
var errorline = function (e, i, classname) {
if (e.extract[i]) {
error.push(template.replace(/\{line\}/, parseInt(e.line) + (i - 1))
.replace(/\{class\}/, classname)
.replace(/\{content\}/, e.extract[i]));
}
};
if (e.stack) {
content += '<br/>' + e.stack.split('\n').slice(1).join('<br/>');
} else if (e.extract) {
errorline(e, 0, '');
errorline(e, 1, 'line');
errorline(e, 2, '');
content += 'on line ' + e.line + ', column ' + (e.column + 1) + ':</p>' +
'<ul>' + error.join('') + '</ul>';
}
elem.innerHTML = content;
// CSS for error messages
createCSS([
'.less-error-message ul, .less-error-message li {',
'list-style-type: none;',
'margin-right: 15px;',
'padding: 4px 0;',
'margin: 0;',
'}',
'.less-error-message label {',
'font-size: 12px;',
'margin-right: 15px;',
'padding: 4px 0;',
'color: #cc7777;',
'}',
'.less-error-message pre {',
'color: #dd6666;',
'padding: 4px 0;',
'margin: 0;',
'display: inline-block;',
'}',
'.less-error-message pre.line {',
'color: #ff0000;',
'}',
'.less-error-message h3 {',
'font-size: 20px;',
'font-weight: bold;',
'padding: 15px 0 5px 0;',
'margin: 0;',
'}',
'.less-error-message a {',
'color: #10a',
'}',
'.less-error-message .error {',
'color: red;',
'font-weight: bold;',
'padding-bottom: 2px;',
'border-bottom: 1px dashed red;',
'}'
].join('\n'), { title: 'error-message' });
elem.style.cssText = [
"font-family: Arial, sans-serif",
"border: 1px solid #e00",
"background-color: #eee",
"border-radius: 5px",
"-webkit-border-radius: 5px",
"-moz-border-radius: 5px",
"color: #e00",
"padding: 15px",
"margin-bottom: 15px"
].join(';');
if (less.env == 'development') {
timer = setInterval(function () {
if (document.body) {
if (document.getElementById(id)) {
document.body.replaceChild(elem, document.getElementById(id));
} else {
document.body.insertBefore(elem, document.body.firstChild);
}
clearInterval(timer);
}
}, 10);
}
}

View File

@@ -0,0 +1,152 @@
(function (tree) {
tree.colors = {
'aliceblue':'#f0f8ff',
'antiquewhite':'#faebd7',
'aqua':'#00ffff',
'aquamarine':'#7fffd4',
'azure':'#f0ffff',
'beige':'#f5f5dc',
'bisque':'#ffe4c4',
'black':'#000000',
'blanchedalmond':'#ffebcd',
'blue':'#0000ff',
'blueviolet':'#8a2be2',
'brown':'#a52a2a',
'burlywood':'#deb887',
'cadetblue':'#5f9ea0',
'chartreuse':'#7fff00',
'chocolate':'#d2691e',
'coral':'#ff7f50',
'cornflowerblue':'#6495ed',
'cornsilk':'#fff8dc',
'crimson':'#dc143c',
'cyan':'#00ffff',
'darkblue':'#00008b',
'darkcyan':'#008b8b',
'darkgoldenrod':'#b8860b',
'darkgray':'#a9a9a9',
'darkgrey':'#a9a9a9',
'darkgreen':'#006400',
'darkkhaki':'#bdb76b',
'darkmagenta':'#8b008b',
'darkolivegreen':'#556b2f',
'darkorange':'#ff8c00',
'darkorchid':'#9932cc',
'darkred':'#8b0000',
'darksalmon':'#e9967a',
'darkseagreen':'#8fbc8f',
'darkslateblue':'#483d8b',
'darkslategray':'#2f4f4f',
'darkslategrey':'#2f4f4f',
'darkturquoise':'#00ced1',
'darkviolet':'#9400d3',
'deeppink':'#ff1493',
'deepskyblue':'#00bfff',
'dimgray':'#696969',
'dimgrey':'#696969',
'dodgerblue':'#1e90ff',
'firebrick':'#b22222',
'floralwhite':'#fffaf0',
'forestgreen':'#228b22',
'fuchsia':'#ff00ff',
'gainsboro':'#dcdcdc',
'ghostwhite':'#f8f8ff',
'gold':'#ffd700',
'goldenrod':'#daa520',
'gray':'#808080',
'grey':'#808080',
'green':'#008000',
'greenyellow':'#adff2f',
'honeydew':'#f0fff0',
'hotpink':'#ff69b4',
'indianred':'#cd5c5c',
'indigo':'#4b0082',
'ivory':'#fffff0',
'khaki':'#f0e68c',
'lavender':'#e6e6fa',
'lavenderblush':'#fff0f5',
'lawngreen':'#7cfc00',
'lemonchiffon':'#fffacd',
'lightblue':'#add8e6',
'lightcoral':'#f08080',
'lightcyan':'#e0ffff',
'lightgoldenrodyellow':'#fafad2',
'lightgray':'#d3d3d3',
'lightgrey':'#d3d3d3',
'lightgreen':'#90ee90',
'lightpink':'#ffb6c1',
'lightsalmon':'#ffa07a',
'lightseagreen':'#20b2aa',
'lightskyblue':'#87cefa',
'lightslategray':'#778899',
'lightslategrey':'#778899',
'lightsteelblue':'#b0c4de',
'lightyellow':'#ffffe0',
'lime':'#00ff00',
'limegreen':'#32cd32',
'linen':'#faf0e6',
'magenta':'#ff00ff',
'maroon':'#800000',
'mediumaquamarine':'#66cdaa',
'mediumblue':'#0000cd',
'mediumorchid':'#ba55d3',
'mediumpurple':'#9370d8',
'mediumseagreen':'#3cb371',
'mediumslateblue':'#7b68ee',
'mediumspringgreen':'#00fa9a',
'mediumturquoise':'#48d1cc',
'mediumvioletred':'#c71585',
'midnightblue':'#191970',
'mintcream':'#f5fffa',
'mistyrose':'#ffe4e1',
'moccasin':'#ffe4b5',
'navajowhite':'#ffdead',
'navy':'#000080',
'oldlace':'#fdf5e6',
'olive':'#808000',
'olivedrab':'#6b8e23',
'orange':'#ffa500',
'orangered':'#ff4500',
'orchid':'#da70d6',
'palegoldenrod':'#eee8aa',
'palegreen':'#98fb98',
'paleturquoise':'#afeeee',
'palevioletred':'#d87093',
'papayawhip':'#ffefd5',
'peachpuff':'#ffdab9',
'peru':'#cd853f',
'pink':'#ffc0cb',
'plum':'#dda0dd',
'powderblue':'#b0e0e6',
'purple':'#800080',
'red':'#ff0000',
'rosybrown':'#bc8f8f',
'royalblue':'#4169e1',
'saddlebrown':'#8b4513',
'salmon':'#fa8072',
'sandybrown':'#f4a460',
'seagreen':'#2e8b57',
'seashell':'#fff5ee',
'sienna':'#a0522d',
'silver':'#c0c0c0',
'skyblue':'#87ceeb',
'slateblue':'#6a5acd',
'slategray':'#708090',
'slategrey':'#708090',
'snow':'#fffafa',
'springgreen':'#00ff7f',
'steelblue':'#4682b4',
'tan':'#d2b48c',
'teal':'#008080',
'thistle':'#d8bfd8',
'tomato':'#ff6347',
'transparent':'rgba(0,0,0,0)',
'turquoise':'#40e0d0',
'violet':'#ee82ee',
'wheat':'#f5deb3',
'white':'#ffffff',
'whitesmoke':'#f5f5f5',
'yellow':'#ffff00',
'yellowgreen':'#9acd32'
};
})(require('./tree'));

View File

@@ -0,0 +1,355 @@
/**
* cssmin.js
* Author: Stoyan Stefanov - http://phpied.com/
* This is a JavaScript port of the CSS minification tool
* distributed with YUICompressor, itself a port
* of the cssmin utility by Isaac Schlueter - http://foohack.com/
* Permission is hereby granted to use the JavaScript version under the same
* conditions as the YUICompressor (original YUICompressor note below).
*/
/*
* YUI Compressor
* http://developer.yahoo.com/yui/compressor/
* Author: Julien Lecomte - http://www.julienlecomte.net/
* Copyright (c) 2011 Yahoo! Inc. All rights reserved.
* The copyrights embodied in the content of this file are licensed
* by Yahoo! Inc. under the BSD (revised) open source license.
*/
var YAHOO = YAHOO || {};
YAHOO.compressor = YAHOO.compressor || {};
/**
* Utility method to replace all data urls with tokens before we start
* compressing, to avoid performance issues running some of the subsequent
* regexes against large strings chunks.
*
* @private
* @method _extractDataUrls
* @param {String} css The input css
* @param {Array} The global array of tokens to preserve
* @returns String The processed css
*/
YAHOO.compressor._extractDataUrls = function (css, preservedTokens) {
// Leave data urls alone to increase parse performance.
var maxIndex = css.length - 1,
appendIndex = 0,
startIndex,
endIndex,
terminator,
foundTerminator,
sb = [],
m,
preserver,
token,
pattern = /url\(\s*(["']?)data\:/g;
// Since we need to account for non-base64 data urls, we need to handle
// ' and ) being part of the data string. Hence switching to indexOf,
// to determine whether or not we have matching string terminators and
// handling sb appends directly, instead of using matcher.append* methods.
while ((m = pattern.exec(css)) !== null) {
startIndex = m.index + 4; // "url(".length()
terminator = m[1]; // ', " or empty (not quoted)
if (terminator.length === 0) {
terminator = ")";
}
foundTerminator = false;
endIndex = pattern.lastIndex - 1;
while(foundTerminator === false && endIndex+1 <= maxIndex) {
endIndex = css.indexOf(terminator, endIndex + 1);
// endIndex == 0 doesn't really apply here
if ((endIndex > 0) && (css.charAt(endIndex - 1) !== '\\')) {
foundTerminator = true;
if (")" != terminator) {
endIndex = css.indexOf(")", endIndex);
}
}
}
// Enough searching, start moving stuff over to the buffer
sb.push(css.substring(appendIndex, m.index));
if (foundTerminator) {
token = css.substring(startIndex, endIndex);
token = token.replace(/\s+/g, "");
preservedTokens.push(token);
preserver = "url(___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___)";
sb.push(preserver);
appendIndex = endIndex + 1;
} else {
// No end terminator found, re-add the whole match. Should we throw/warn here?
sb.push(css.substring(m.index, pattern.lastIndex));
appendIndex = pattern.lastIndex;
}
}
sb.push(css.substring(appendIndex));
return sb.join("");
};
/**
* Utility method to compress hex color values of the form #AABBCC to #ABC.
*
* DOES NOT compress CSS ID selectors which match the above pattern (which would break things).
* e.g. #AddressForm { ... }
*
* DOES NOT compress IE filters, which have hex color values (which would break things).
* e.g. filter: chroma(color="#FFFFFF");
*
* DOES NOT compress invalid hex values.
* e.g. background-color: #aabbccdd
*
* @private
* @method _compressHexColors
* @param {String} css The input css
* @returns String The processed css
*/
YAHOO.compressor._compressHexColors = function(css) {
// Look for hex colors inside { ... } (to avoid IDs) and which don't have a =, or a " in front of them (to avoid filters)
var pattern = /(\=\s*?["']?)?#([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])([0-9a-f])(\}|[^0-9a-f{][^{]*?\})/gi,
m,
index = 0,
isFilter,
sb = [];
while ((m = pattern.exec(css)) !== null) {
sb.push(css.substring(index, m.index));
isFilter = m[1];
if (isFilter) {
// Restore, maintain case, otherwise filter will break
sb.push(m[1] + "#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]));
} else {
if (m[2].toLowerCase() == m[3].toLowerCase() &&
m[4].toLowerCase() == m[5].toLowerCase() &&
m[6].toLowerCase() == m[7].toLowerCase()) {
// Compress.
sb.push("#" + (m[3] + m[5] + m[7]).toLowerCase());
} else {
// Non compressible color, restore but lower case.
sb.push("#" + (m[2] + m[3] + m[4] + m[5] + m[6] + m[7]).toLowerCase());
}
}
index = pattern.lastIndex = pattern.lastIndex - m[8].length;
}
sb.push(css.substring(index));
return sb.join("");
};
YAHOO.compressor.cssmin = function (css, linebreakpos) {
var startIndex = 0,
endIndex = 0,
i = 0, max = 0,
preservedTokens = [],
comments = [],
token = '',
totallen = css.length,
placeholder = '';
css = this._extractDataUrls(css, preservedTokens);
// collect all comment blocks...
while ((startIndex = css.indexOf("/*", startIndex)) >= 0) {
endIndex = css.indexOf("*/", startIndex + 2);
if (endIndex < 0) {
endIndex = totallen;
}
token = css.slice(startIndex + 2, endIndex);
comments.push(token);
css = css.slice(0, startIndex + 2) + "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + (comments.length - 1) + "___" + css.slice(endIndex);
startIndex += 2;
}
// preserve strings so their content doesn't get accidentally minified
css = css.replace(/("([^\\"]|\\.|\\)*")|('([^\\']|\\.|\\)*')/g, function (match) {
var i, max, quote = match.substring(0, 1);
match = match.slice(1, -1);
// maybe the string contains a comment-like substring?
// one, maybe more? put'em back then
if (match.indexOf("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_") >= 0) {
for (i = 0, max = comments.length; i < max; i = i + 1) {
match = match.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", comments[i]);
}
}
// minify alpha opacity in filter strings
match = match.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity=");
preservedTokens.push(match);
return quote + "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___" + quote;
});
// strings are safe, now wrestle the comments
for (i = 0, max = comments.length; i < max; i = i + 1) {
token = comments[i];
placeholder = "___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___";
// ! in the first position of the comment means preserve
// so push to the preserved tokens keeping the !
if (token.charAt(0) === "!") {
preservedTokens.push(token);
css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
continue;
}
// \ in the last position looks like hack for Mac/IE5
// shorten that to /*\*/ and the next one to /**/
if (token.charAt(token.length - 1) === "\\") {
preservedTokens.push("\\");
css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
i = i + 1; // attn: advancing the loop
preservedTokens.push("");
css = css.replace("___YUICSSMIN_PRESERVE_CANDIDATE_COMMENT_" + i + "___", "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
continue;
}
// keep empty comments after child selectors (IE7 hack)
// e.g. html >/**/ body
if (token.length === 0) {
startIndex = css.indexOf(placeholder);
if (startIndex > 2) {
if (css.charAt(startIndex - 3) === '>') {
preservedTokens.push("");
css = css.replace(placeholder, "___YUICSSMIN_PRESERVED_TOKEN_" + (preservedTokens.length - 1) + "___");
}
}
}
// in all other cases kill the comment
css = css.replace("/*" + placeholder + "*/", "");
}
// Normalize all whitespace strings to single spaces. Easier to work with that way.
css = css.replace(/\s+/g, " ");
// Remove the spaces before the things that should not have spaces before them.
// But, be careful not to turn "p :link {...}" into "p:link{...}"
// Swap out any pseudo-class colons with the token, and then swap back.
css = css.replace(/(^|\})(([^\{:])+:)+([^\{]*\{)/g, function (m) {
return m.replace(":", "___YUICSSMIN_PSEUDOCLASSCOLON___");
});
css = css.replace(/\s+([!{};:>+\(\)\],])/g, '$1');
css = css.replace(/___YUICSSMIN_PSEUDOCLASSCOLON___/g, ":");
// retain space for special IE6 cases
css = css.replace(/:first-(line|letter)(\{|,)/g, ":first-$1 $2");
// no space after the end of a preserved comment
css = css.replace(/\*\/ /g, '*/');
// If there is a @charset, then only allow one, and push to the top of the file.
css = css.replace(/^(.*)(@charset "[^"]*";)/gi, '$2$1');
css = css.replace(/^(\s*@charset [^;]+;\s*)+/gi, '$1');
// Put the space back in some cases, to support stuff like
// @media screen and (-webkit-min-device-pixel-ratio:0){
css = css.replace(/\band\(/gi, "and (");
// Remove the spaces after the things that should not have spaces after them.
css = css.replace(/([!{}:;>+\(\[,])\s+/g, '$1');
// remove unnecessary semicolons
css = css.replace(/;+\}/g, "}");
// Replace 0(px,em,%) with 0.
css = css.replace(/([\s:])(0)(px|em|%|in|cm|mm|pc|pt|ex)/gi, "$1$2");
// Replace 0 0 0 0; with 0.
css = css.replace(/:0 0 0 0(;|\})/g, ":0$1");
css = css.replace(/:0 0 0(;|\})/g, ":0$1");
css = css.replace(/:0 0(;|\})/g, ":0$1");
// Replace background-position:0; with background-position:0 0;
// same for transform-origin
css = css.replace(/(background-position|transform-origin|webkit-transform-origin|moz-transform-origin|o-transform-origin|ms-transform-origin):0(;|\})/gi, function(all, prop, tail) {
return prop.toLowerCase() + ":0 0" + tail;
});
// Replace 0.6 to .6, but only when preceded by : or a white-space
css = css.replace(/(:|\s)0+\.(\d+)/g, "$1.$2");
// Shorten colors from rgb(51,102,153) to #336699
// This makes it more likely that it'll get further compressed in the next step.
css = css.replace(/rgb\s*\(\s*([0-9,\s]+)\s*\)/gi, function () {
var i, rgbcolors = arguments[1].split(',');
for (i = 0; i < rgbcolors.length; i = i + 1) {
rgbcolors[i] = parseInt(rgbcolors[i], 10).toString(16);
if (rgbcolors[i].length === 1) {
rgbcolors[i] = '0' + rgbcolors[i];
}
}
return '#' + rgbcolors.join('');
});
// Shorten colors from #AABBCC to #ABC.
css = this._compressHexColors(css);
// border: none -> border:0
css = css.replace(/(border|border-top|border-right|border-bottom|border-right|outline|background):none(;|\})/gi, function(all, prop, tail) {
return prop.toLowerCase() + ":0" + tail;
});
// shorter opacity IE filter
css = css.replace(/progid:DXImageTransform\.Microsoft\.Alpha\(Opacity=/gi, "alpha(opacity=");
// Remove empty rules.
css = css.replace(/[^\};\{\/]+\{\}/g, "");
if (linebreakpos >= 0) {
// Some source control tools don't like it when files containing lines longer
// than, say 8000 characters, are checked in. The linebreak option is used in
// that case to split long lines after a specific column.
startIndex = 0;
i = 0;
while (i < css.length) {
i = i + 1;
if (css[i - 1] === '}' && i - startIndex > linebreakpos) {
css = css.slice(0, i) + '\n' + css.slice(i);
startIndex = i;
}
}
}
// Replace multiple semi-colons in a row by a single one
// See SF bug #1980989
css = css.replace(/;;+/g, ";");
// restore preserved comments and strings
for (i = 0, max = preservedTokens.length; i < max; i = i + 1) {
css = css.replace("___YUICSSMIN_PRESERVED_TOKEN_" + i + "___", preservedTokens[i]);
}
// Trim the final string (for any leading or trailing white spaces)
css = css.replace(/^\s+|\s+$/g, "");
return css;
};
exports.compressor = YAHOO.compressor;

View File

@@ -0,0 +1,228 @@
(function (tree) {
tree.functions = {
rgb: function (r, g, b) {
return this.rgba(r, g, b, 1.0);
},
rgba: function (r, g, b, a) {
var rgb = [r, g, b].map(function (c) { return number(c) }),
a = number(a);
return new(tree.Color)(rgb, a);
},
hsl: function (h, s, l) {
return this.hsla(h, s, l, 1.0);
},
hsla: function (h, s, l, a) {
h = (number(h) % 360) / 360;
s = number(s); l = number(l); a = number(a);
var m2 = l <= 0.5 ? l * (s + 1) : l + s - l * s;
var m1 = l * 2 - m2;
return this.rgba(hue(h + 1/3) * 255,
hue(h) * 255,
hue(h - 1/3) * 255,
a);
function hue(h) {
h = h < 0 ? h + 1 : (h > 1 ? h - 1 : h);
if (h * 6 < 1) return m1 + (m2 - m1) * h * 6;
else if (h * 2 < 1) return m2;
else if (h * 3 < 2) return m1 + (m2 - m1) * (2/3 - h) * 6;
else return m1;
}
},
hue: function (color) {
return new(tree.Dimension)(Math.round(color.toHSL().h));
},
saturation: function (color) {
return new(tree.Dimension)(Math.round(color.toHSL().s * 100), '%');
},
lightness: function (color) {
return new(tree.Dimension)(Math.round(color.toHSL().l * 100), '%');
},
alpha: function (color) {
return new(tree.Dimension)(color.toHSL().a);
},
saturate: function (color, amount) {
var hsl = color.toHSL();
hsl.s += amount.value / 100;
hsl.s = clamp(hsl.s);
return hsla(hsl);
},
desaturate: function (color, amount) {
var hsl = color.toHSL();
hsl.s -= amount.value / 100;
hsl.s = clamp(hsl.s);
return hsla(hsl);
},
lighten: function (color, amount) {
var hsl = color.toHSL();
hsl.l += amount.value / 100;
hsl.l = clamp(hsl.l);
return hsla(hsl);
},
darken: function (color, amount) {
var hsl = color.toHSL();
hsl.l -= amount.value / 100;
hsl.l = clamp(hsl.l);
return hsla(hsl);
},
fadein: function (color, amount) {
var hsl = color.toHSL();
hsl.a += amount.value / 100;
hsl.a = clamp(hsl.a);
return hsla(hsl);
},
fadeout: function (color, amount) {
var hsl = color.toHSL();
hsl.a -= amount.value / 100;
hsl.a = clamp(hsl.a);
return hsla(hsl);
},
fade: function (color, amount) {
var hsl = color.toHSL();
hsl.a = amount.value / 100;
hsl.a = clamp(hsl.a);
return hsla(hsl);
},
spin: function (color, amount) {
var hsl = color.toHSL();
var hue = (hsl.h + amount.value) % 360;
hsl.h = hue < 0 ? 360 + hue : hue;
return hsla(hsl);
},
//
// Copyright (c) 2006-2009 Hampton Catlin, Nathan Weizenbaum, and Chris Eppstein
// http://sass-lang.com
//
mix: function (color1, color2, weight) {
var p = weight.value / 100.0;
var w = p * 2 - 1;
var a = color1.toHSL().a - color2.toHSL().a;
var w1 = (((w * a == -1) ? w : (w + a) / (1 + w * a)) + 1) / 2.0;
var w2 = 1 - w1;
var rgb = [color1.rgb[0] * w1 + color2.rgb[0] * w2,
color1.rgb[1] * w1 + color2.rgb[1] * w2,
color1.rgb[2] * w1 + color2.rgb[2] * w2];
var alpha = color1.alpha * p + color2.alpha * (1 - p);
return new(tree.Color)(rgb, alpha);
},
greyscale: function (color) {
return this.desaturate(color, new(tree.Dimension)(100));
},
e: function (str) {
return new(tree.Anonymous)(str instanceof tree.JavaScript ? str.evaluated : str);
},
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, ...*/) {
var args = Array.prototype.slice.call(arguments, 1),
str = quoted.value;
for (var i = 0; i < args.length; i++) {
str = str.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);
},
round: function (n) {
return this._math('round', n);
},
ceil: function (n) {
return this._math('ceil', n);
},
floor: function (n) {
return this._math('floor', n);
},
_math: function (fn, n) {
if (n instanceof tree.Dimension) {
return new(tree.Dimension)(Math[fn](number(n)), n.unit);
} else if (typeof(n) === 'number') {
return Math[fn](n);
} else {
throw { type: "Argument", message: "argument must be a number" };
}
},
argb: function (color) {
return new(tree.Anonymous)(color.toARGB());
},
percentage: function (n) {
return new(tree.Dimension)(n.value * 100, '%');
},
color: function (n) {
if (n instanceof tree.Quoted) {
return new(tree.Color)(n.value.slice(1));
} else {
throw { type: "Argument", message: "argument must be a string" };
}
},
iscolor: function (n) {
return this._isa(n, tree.Color);
},
isnumber: function (n) {
return this._isa(n, tree.Dimension);
},
isstring: function (n) {
return this._isa(n, tree.Quoted);
},
iskeyword: function (n) {
return this._isa(n, tree.Keyword);
},
isurl: function (n) {
return this._isa(n, tree.URL);
},
ispixel: function (n) {
return (n instanceof tree.Dimension) && n.unit === 'px' ? tree.True : tree.False;
},
ispercentage: function (n) {
return (n instanceof tree.Dimension) && n.unit === '%' ? tree.True : tree.False;
},
isem: function (n) {
return (n instanceof tree.Dimension) && n.unit === 'em' ? tree.True : tree.False;
},
_isa: function (n, Type) {
return (n instanceof Type) ? tree.True : tree.False;
}
};
function hsla(hsla) {
return tree.functions.hsla(hsla.h, hsla.s, hsla.l, hsla.a);
}
function number(n) {
if (n instanceof tree.Dimension) {
return parseFloat(n.unit == '%' ? n.value / 100 : n.value);
} else if (typeof(n) === 'number') {
return n;
} else {
throw {
error: "RuntimeError",
message: "color functions take numbers as parameters"
};
}
}
function clamp(val) {
return Math.min(1, Math.max(0, val));
}
})(require('./tree'));

View File

@@ -0,0 +1,148 @@
var path = require('path'),
sys = require('util'),
fs = require('fs');
var less = {
version: [1, 3, 0],
Parser: require('./parser').Parser,
importer: require('./parser').importer,
tree: require('./tree'),
render: function (input, options, callback) {
options = options || {};
if (typeof(options) === 'function') {
callback = options, options = {};
}
var parser = new(less.Parser)(options),
ee;
if (callback) {
parser.parse(input, function (e, root) {
callback(e, root && root.toCSS && root.toCSS(options));
});
} else {
ee = new(require('events').EventEmitter);
process.nextTick(function () {
parser.parse(input, function (e, root) {
if (e) { ee.emit('error', e) }
else { ee.emit('success', root.toCSS(options)) }
});
});
return ee;
}
},
writeError: function (ctx, options) {
options = options || {};
var message = "";
var extract = ctx.extract;
var error = [];
var stylize = options.color ? less.stylize : function (str) { return str };
if (options.silent) { return }
if (ctx.stack) { return sys.error(stylize(ctx.stack, 'red')) }
if (!ctx.hasOwnProperty('index')) {
return sys.error(ctx.stack || ctx.message);
}
if (typeof(extract[0]) === 'string') {
error.push(stylize((ctx.line - 1) + ' ' + extract[0], 'grey'));
}
if (extract[1]) {
error.push(ctx.line + ' ' + extract[1].slice(0, ctx.column)
+ stylize(stylize(stylize(extract[1][ctx.column], 'bold')
+ extract[1].slice(ctx.column + 1), 'red'), 'inverse'));
}
if (typeof(extract[2]) === 'string') {
error.push(stylize((ctx.line + 1) + ' ' + extract[2], 'grey'));
}
error = error.join('\n') + '\033[0m\n';
message += stylize(ctx.type + 'Error: ' + ctx.message, 'red');
ctx.filename && (message += stylize(' in ', 'red') + ctx.filename +
stylize(':' + ctx.line + ':' + ctx.column, 'grey'));
sys.error(message, error);
if (ctx.callLine) {
sys.error(stylize('from ', 'red') + (ctx.filename || ''));
sys.error(stylize(ctx.callLine, 'grey') + ' ' + ctx.callExtract);
}
}
};
['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'
].forEach(function (n) {
require('./tree/' + n);
});
less.Parser.importer = function (file, paths, callback, env) {
var pathname;
// TODO: Undo this at some point,
// or use different approach.
paths.unshift('.');
for (var i = 0; i < paths.length; i++) {
try {
pathname = path.join(paths[i], file);
fs.statSync(pathname);
break;
} catch (e) {
pathname = null;
}
}
if (pathname) {
fs.readFile(pathname, 'utf-8', function(e, data) {
if (e) return callback(e);
new(less.Parser)({
paths: [path.dirname(pathname)].concat(paths),
filename: pathname
}).parse(data, function (e, root) {
callback(e, root, data);
});
});
} else {
if (typeof(env.errback) === "function") {
env.errback(file, paths, callback);
} else {
callback({ type: 'File', message: "'" + file + "' wasn't found.\n" });
}
}
}
require('./functions');
require('./colors');
for (var k in less) { exports[k] = less[k] }
// Stylize a string
function stylize(str, style) {
var styles = {
'bold' : [1, 22],
'inverse' : [7, 27],
'underline' : [4, 24],
'yellow' : [33, 39],
'green' : [32, 39],
'red' : [31, 39],
'grey' : [90, 39]
};
return '\033[' + styles[style][0] + 'm' + str +
'\033[' + styles[style][1] + 'm';
}
less.stylize = stylize;

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,62 @@
var name;
function loadStyleSheet(sheet, callback, reload, remaining) {
var sheetName = name.slice(0, name.lastIndexOf('/') + 1) + sheet.href;
var input = readFile(sheetName);
var parser = new less.Parser({
paths: [sheet.href.replace(/[\w\.-]+$/, '')]
});
parser.parse(input, function (e, root) {
if (e) {
print("Error: " + e);
quit(1);
}
callback(root, sheet, { local: false, lastModified: 0, remaining: remaining });
});
// callback({}, sheet, { local: true, remaining: remaining });
}
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) {
name = args[0];
var output = args[1];
if (!name) {
print('No files present in the fileset; Check your pattern match in build.xml');
quit(1);
}
path = name.split("/");path.pop();path=path.join("/")
var input = readFile(name);
if (!input) {
print('lesscss: couldn\'t open file ' + name);
quit(1);
}
var result;
var parser = new less.Parser();
parser.parse(input, function (e, root) {
if (e) {
quit(1);
} else {
result = root.toCSS();
if (output) {
writeFile(output, result);
print("Written to " + output);
} else {
print(result);
}
quit(0);
}
});
print("done");
}(arguments));

View File

@@ -0,0 +1,17 @@
(function (tree) {
tree.find = function (obj, fun) {
for (var i = 0, r; i < obj.length; i++) {
if (r = fun.call(obj, obj[i])) { return r }
}
return null;
};
tree.jsify = function (obj) {
if (Array.isArray(obj.value) && (obj.value.length > 1)) {
return '[' + obj.value.map(function (v) { return v.toCSS(false) }).join(', ') + ']';
} else {
return obj.toCSS(false);
}
};
})(require('./tree'));

View File

@@ -0,0 +1,17 @@
(function (tree) {
tree.Alpha = function (val) {
this.value = val;
};
tree.Alpha.prototype = {
toCSS: function () {
return "alpha(opacity=" +
(this.value.toCSS ? this.value.toCSS() : this.value) + ")";
},
eval: function (env) {
if (this.value.eval) { this.value = this.value.eval(env) }
return this;
}
};
})(require('../tree'));

View File

@@ -0,0 +1,13 @@
(function (tree) {
tree.Anonymous = function (string) {
this.value = string.value || string;
};
tree.Anonymous.prototype = {
toCSS: function () {
return this.value;
},
eval: function () { return this }
};
})(require('../tree'));

View File

@@ -0,0 +1,17 @@
(function (tree) {
tree.Assignment = function (key, val) {
this.key = key;
this.value = val;
};
tree.Assignment.prototype = {
toCSS: function () {
return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value);
},
eval: function (env) {
if (this.value.eval) { this.value = this.value.eval(env) }
return this;
}
};
})(require('../tree'));

View File

@@ -0,0 +1,48 @@
(function (tree) {
//
// A function call node.
//
tree.Call = function (name, args, index, filename) {
this.name = name;
this.args = args;
this.index = index;
this.filename = filename;
};
tree.Call.prototype = {
//
// When evaluating a function call,
// we either find the function in `tree.functions` [1],
// in which case we call it, passing the evaluated arguments,
// or we simply print it out as it appeared originally [2].
//
// The *functions.js* file contains the built-in functions.
//
// The reason why we evaluate the arguments, is in the case where
// we try to pass a variable to a function, like: `saturate(@color)`.
// The function should receive the value, not the variable.
//
eval: function (env) {
var args = this.args.map(function (a) { return a.eval(env) });
if (this.name in tree.functions) { // 1.
try {
return tree.functions[this.name].apply(tree.functions, args);
} catch (e) {
throw { type: e.type || "Runtime",
message: "error evaluating function `" + this.name + "`" +
(e.message ? ': ' + e.message : ''),
index: this.index, filename: this.filename };
}
} else { // 2.
return new(tree.Anonymous)(this.name +
"(" + args.map(function (a) { return a.toCSS() }).join(', ') + ")");
}
},
toCSS: function (env) {
return this.eval(env).toCSS();
}
};
})(require('../tree'));

View File

@@ -0,0 +1,101 @@
(function (tree) {
//
// RGB Colors - #ff0014, #eee
//
tree.Color = function (rgb, a) {
//
// The end goal here, is to parse the arguments
// into an integer triplet, such as `128, 255, 0`
//
// This facilitates operations and conversions.
//
if (Array.isArray(rgb)) {
this.rgb = rgb;
} else if (rgb.length == 6) {
this.rgb = rgb.match(/.{2}/g).map(function (c) {
return parseInt(c, 16);
});
} else {
this.rgb = rgb.split('').map(function (c) {
return parseInt(c + c, 16);
});
}
this.alpha = typeof(a) === 'number' ? a : 1;
};
tree.Color.prototype = {
eval: function () { return this },
//
// 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.
//
toCSS: function () {
if (this.alpha < 1.0) {
return "rgba(" + this.rgb.map(function (c) {
return Math.round(c);
}).concat(this.alpha).join(', ') + ")";
} else {
return '#' + this.rgb.map(function (i) {
i = Math.round(i);
i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
return i.length === 1 ? '0' + i : i;
}).join('');
}
},
//
// Operations have to be done per-channel, if not,
// channels will spill onto each other. Once we have
// our result, in the form of an integer triplet,
// we create a new Color node to hold the result.
//
operate: function (op, other) {
var result = [];
if (! (other instanceof tree.Color)) {
other = other.toColor();
}
for (var c = 0; c < 3; c++) {
result[c] = tree.operate(op, this.rgb[c], other.rgb[c]);
}
return new(tree.Color)(result, this.alpha + other.alpha);
},
toHSL: function () {
var r = this.rgb[0] / 255,
g = this.rgb[1] / 255,
b = this.rgb[2] / 255,
a = this.alpha;
var max = Math.max(r, g, b), min = Math.min(r, g, b);
var h, s, l = (max + min) / 2, d = max - min;
if (max === min) {
h = s = 0;
} else {
s = l > 0.5 ? d / (2 - max - min) : d / (max + min);
switch (max) {
case r: h = (g - b) / d + (g < b ? 6 : 0); break;
case g: h = (b - r) / d + 2; break;
case b: h = (r - g) / d + 4; break;
}
h /= 6;
}
return { h: h * 360, s: s, l: l, a: a };
},
toARGB: function () {
var argb = [Math.round(this.alpha * 255)].concat(this.rgb);
return '#' + argb.map(function (i) {
i = Math.round(i);
i = (i > 255 ? 255 : (i < 0 ? 0 : i)).toString(16);
return i.length === 1 ? '0' + i : i;
}).join('');
}
};
})(require('../tree'));

View File

@@ -0,0 +1,14 @@
(function (tree) {
tree.Comment = function (value, silent) {
this.value = value;
this.silent = !!silent;
};
tree.Comment.prototype = {
toCSS: function (env) {
return env.compress ? '' : this.value;
},
eval: function () { return this }
};
})(require('../tree'));

View File

@@ -0,0 +1,42 @@
(function (tree) {
tree.Condition = function (op, l, r, i, negate) {
this.op = op.trim();
this.lvalue = l;
this.rvalue = r;
this.index = i;
this.negate = negate;
};
tree.Condition.prototype.eval = function (env) {
var a = this.lvalue.eval(env),
b = this.rvalue.eval(env);
var i = this.index, result;
var result = (function (op) {
switch (op) {
case 'and':
return a && b;
case 'or':
return a || b;
default:
if (a.compare) {
result = a.compare(b);
} else if (b.compare) {
result = b.compare(a);
} else {
throw { type: "Type",
message: "Unable to perform comparison",
index: i };
}
switch (result) {
case -1: return op === '<' || op === '=<';
case 0: return op === '=' || op === '>=' || op === '=<';
case 1: return op === '>' || op === '>=';
}
}
})(this.op);
return this.negate ? !result : result;
};
})(require('../tree'));

View File

@@ -0,0 +1,49 @@
(function (tree) {
//
// A number with a unit
//
tree.Dimension = function (value, unit) {
this.value = parseFloat(value);
this.unit = unit || null;
};
tree.Dimension.prototype = {
eval: function () { return this },
toColor: function () {
return new(tree.Color)([this.value, this.value, this.value]);
},
toCSS: function () {
var css = this.value + this.unit;
return css;
},
// In an operation between two Dimensions,
// we default to the first Dimension's unit,
// so `1px + 2em` will yield `3px`.
// In the future, we could implement some unit
// conversions such that `100cm + 10mm` would yield
// `101cm`.
operate: function (op, other) {
return new(tree.Dimension)
(tree.operate(op, this.value, other.value),
this.unit || other.unit);
},
// TODO: Perform unit conversion before comparing
compare: function (other) {
if (other instanceof tree.Dimension) {
if (other.value > this.value) {
return -1;
} else if (other.value < this.value) {
return 1;
} else {
return 0;
}
} else {
return -1;
}
}
};
})(require('../tree'));

View File

@@ -0,0 +1,35 @@
(function (tree) {
tree.Directive = function (name, value, features) {
this.name = name;
if (Array.isArray(value)) {
this.ruleset = new(tree.Ruleset)([], value);
this.ruleset.allowImports = true;
} else {
this.value = value;
}
};
tree.Directive.prototype = {
toCSS: function (ctx, env) {
if (this.ruleset) {
this.ruleset.root = true;
return this.name + (env.compress ? '{' : ' {\n ') +
this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') +
(env.compress ? '}': '\n}\n');
} else {
return this.name + ' ' + this.value.toCSS() + ';\n';
}
},
eval: function (env) {
env.frames.unshift(this);
this.ruleset = this.ruleset && this.ruleset.eval(env);
env.frames.shift();
return this;
},
variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) },
find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) },
rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) }
};
})(require('../tree'));

View File

@@ -0,0 +1,52 @@
(function (tree) {
tree.Element = function (combinator, value, index) {
this.combinator = combinator instanceof tree.Combinator ?
combinator : new(tree.Combinator)(combinator);
if (typeof(value) === 'string') {
this.value = value.trim();
} else if (value) {
this.value = value;
} else {
this.value = "";
}
this.index = index;
};
tree.Element.prototype.eval = function (env) {
return new(tree.Element)(this.combinator,
this.value.eval ? this.value.eval(env) : this.value,
this.index);
};
tree.Element.prototype.toCSS = function (env) {
var value = (this.value.toCSS ? this.value.toCSS(env) : this.value);
if (value == '' && this.combinator.value.charAt(0) == '&') {
return '';
} else {
return this.combinator.toCSS(env || {}) + value;
}
};
tree.Combinator = function (value) {
if (value === ' ') {
this.value = ' ';
} else if (value === '& ') {
this.value = '& ';
} else {
this.value = value ? value.trim() : "";
}
};
tree.Combinator.prototype.toCSS = function (env) {
return {
'' : '',
' ' : ' ',
'&' : '',
'& ' : ' ',
':' : ' :',
'+' : env.compress ? '+' : ' + ',
'~' : env.compress ? '~' : ' ~ ',
'>' : env.compress ? '>' : ' > '
}[this.value];
};
})(require('../tree'));

View File

@@ -0,0 +1,23 @@
(function (tree) {
tree.Expression = function (value) { this.value = value };
tree.Expression.prototype = {
eval: function (env) {
if (this.value.length > 1) {
return new(tree.Expression)(this.value.map(function (e) {
return e.eval(env);
}));
} else if (this.value.length === 1) {
return this.value[0].eval(env);
} else {
return this;
}
},
toCSS: function (env) {
return this.value.map(function (e) {
return e.toCSS ? e.toCSS(env) : '';
}).join(' ');
}
};
})(require('../tree'));

View File

@@ -0,0 +1,83 @@
(function (tree) {
//
// CSS @import node
//
// The general strategy here is that we don't want to wait
// for the parsing to be completed, before we start importing
// the file. That's because in the context of a browser,
// most of the time will be spent waiting for the server to respond.
//
// On creation, we push the import path to our import queue, though
// `import,push`, we also pass it a callback, which it'll call once
// the file has been fetched, and parsed.
//
tree.Import = function (path, imports, features, once, index) {
var that = this;
this.once = once;
this.index = index;
this._path = path;
this.features = features && new(tree.Value)(features);
// The '.less' extension is optional
if (path instanceof tree.Quoted) {
this.path = /\.(le?|c)ss(\?.*)?$/.test(path.value) ? path.value : path.value + '.less';
} else {
this.path = path.value.value || path.value;
}
this.css = /css(\?.*)?$/.test(this.path);
// Only pre-compile .less files
if (! this.css) {
imports.push(this.path, function (e, root, imported) {
if (e) { e.index = index }
if (imported && that.once) that.skip = imported;
that.root = root || new(tree.Ruleset)([], []);
});
}
};
//
// The actual import node doesn't return anything, when converted to CSS.
// The reason is that it's used at the evaluation stage, so that the rules
// it imports can be treated like any other rules.
//
// In `eval`, we make sure all Import nodes get evaluated, recursively, so
// we end up with a flat structure, which can easily be imported in the parent
// ruleset.
//
tree.Import.prototype = {
toCSS: function (env) {
var features = this.features ? ' ' + this.features.toCSS(env) : '';
if (this.css) {
return "@import " + this._path.toCSS() + features + ';\n';
} else {
return "";
}
},
eval: function (env) {
var ruleset, features = this.features && this.features.eval(env);
if (this.skip) return [];
if (this.css) {
return this;
} else {
ruleset = new(tree.Ruleset)([], this.root.rules.slice(0));
for (var i = 0; i < ruleset.rules.length; i++) {
if (ruleset.rules[i] instanceof tree.Import) {
Array.prototype
.splice
.apply(ruleset.rules,
[i, 1].concat(ruleset.rules[i].eval(env)));
}
}
return this.features ? new(tree.Media)(ruleset.rules, this.features.value) : ruleset.rules;
}
}
};
})(require('../tree'));

View File

@@ -0,0 +1,51 @@
(function (tree) {
tree.JavaScript = function (string, index, escaped) {
this.escaped = escaped;
this.expression = string;
this.index = index;
};
tree.JavaScript.prototype = {
eval: function (env) {
var result,
that = this,
context = {};
var expression = this.expression.replace(/@\{([\w-]+)\}/g, function (_, name) {
return tree.jsify(new(tree.Variable)('@' + name, that.index).eval(env));
});
try {
expression = new(Function)('return (' + expression + ')');
} catch (e) {
throw { message: "JavaScript evaluation error: `" + expression + "`" ,
index: this.index };
}
for (var k in env.frames[0].variables()) {
context[k.slice(1)] = {
value: env.frames[0].variables()[k].value,
toJS: function () {
return this.value.eval(env).toCSS();
}
};
}
try {
result = expression.call(context);
} catch (e) {
throw { message: "JavaScript evaluation error: '" + e.name + ': ' + e.message + "'" ,
index: this.index };
}
if (typeof(result) === 'string') {
return new(tree.Quoted)('"' + result + '"', result, this.escaped, this.index);
} else if (Array.isArray(result)) {
return new(tree.Anonymous)(result.join(', '));
} else {
return new(tree.Anonymous)(result);
}
}
};
})(require('../tree'));

View File

@@ -0,0 +1,19 @@
(function (tree) {
tree.Keyword = function (value) { this.value = value };
tree.Keyword.prototype = {
eval: function () { return this },
toCSS: function () { return this.value },
compare: function (other) {
if (other instanceof tree.Keyword) {
return other.value === this.value ? 0 : 1;
} else {
return -1;
}
}
};
tree.True = new(tree.Keyword)('true');
tree.False = new(tree.Keyword)('false');
})(require('../tree'));

View File

@@ -0,0 +1,114 @@
(function (tree) {
tree.Media = function (value, features) {
var el = new(tree.Element)('&', null, 0),
selectors = [new(tree.Selector)([el])];
this.features = new(tree.Value)(features);
this.ruleset = new(tree.Ruleset)(selectors, value);
this.ruleset.allowImports = true;
};
tree.Media.prototype = {
toCSS: function (ctx, env) {
var features = this.features.toCSS(env);
this.ruleset.root = (ctx.length === 0 || ctx[0].multiMedia);
return '@media ' + features + (env.compress ? '{' : ' {\n ') +
this.ruleset.toCSS(ctx, env).trim().replace(/\n/g, '\n ') +
(env.compress ? '}': '\n}\n');
},
eval: function (env) {
if (!env.mediaBlocks) {
env.mediaBlocks = [];
env.mediaPath = [];
}
var blockIndex = env.mediaBlocks.length;
env.mediaPath.push(this);
env.mediaBlocks.push(this);
var media = new(tree.Media)([], []);
media.features = this.features.eval(env);
env.frames.unshift(this.ruleset);
media.ruleset = this.ruleset.eval(env);
env.frames.shift();
env.mediaBlocks[blockIndex] = media;
env.mediaPath.pop();
return env.mediaPath.length === 0 ? media.evalTop(env) :
media.evalNested(env)
},
variable: function (name) { return tree.Ruleset.prototype.variable.call(this.ruleset, name) },
find: function () { return tree.Ruleset.prototype.find.apply(this.ruleset, arguments) },
rulesets: function () { return tree.Ruleset.prototype.rulesets.apply(this.ruleset) },
evalTop: function (env) {
var result = this;
// Render all dependent Media blocks.
if (env.mediaBlocks.length > 1) {
var el = new(tree.Element)('&', null, 0);
var selectors = [new(tree.Selector)([el])];
result = new(tree.Ruleset)(selectors, env.mediaBlocks);
result.multiMedia = true;
}
delete env.mediaBlocks;
delete env.mediaPath;
return result;
},
evalNested: function (env) {
var i, value,
path = env.mediaPath.concat([this]);
// Extract the media-query conditions separated with `,` (OR).
for (i = 0; i < path.length; i++) {
value = path[i].features instanceof tree.Value ?
path[i].features.value : path[i].features;
path[i] = Array.isArray(value) ? value : [value];
}
// Trace all permutations to generate the resulting media-query.
//
// (a, b and c) with nested (d, e) ->
// a and d
// a and e
// b and c and d
// b and c and e
this.features = new(tree.Value)(this.permute(path).map(function (path) {
path = path.map(function (fragment) {
return fragment.toCSS ? fragment : new(tree.Anonymous)(fragment);
});
for(i = path.length - 1; i > 0; i--) {
path.splice(i, 0, new(tree.Anonymous)("and"));
}
return new(tree.Expression)(path);
}));
// Fake a tree-node that doesn't output anything.
return new(tree.Ruleset)([], []);
},
permute: function (arr) {
if (arr.length === 0) {
return [];
} else if (arr.length === 1) {
return arr[0];
} else {
var result = [];
var rest = this.permute(arr.slice(1));
for (var i = 0; i < rest.length; i++) {
for (var j = 0; j < arr[0].length; j++) {
result.push([arr[0][j]].concat(rest[i]));
}
}
return result;
}
}
};
})(require('../tree'));

View File

@@ -0,0 +1,146 @@
(function (tree) {
tree.mixin = {};
tree.mixin.Call = function (elements, args, index, filename, important) {
this.selector = new(tree.Selector)(elements);
this.arguments = args;
this.index = index;
this.filename = filename;
this.important = important;
};
tree.mixin.Call.prototype = {
eval: function (env) {
var mixins, args, rules = [], match = false;
for (var i = 0; i < env.frames.length; i++) {
if ((mixins = env.frames[i].find(this.selector)).length > 0) {
args = this.arguments && this.arguments.map(function (a) {
return { name: a.name, value: a.value.eval(env) };
});
for (var m = 0; m < mixins.length; m++) {
if (mixins[m].match(args, env)) {
try {
Array.prototype.push.apply(
rules, mixins[m].eval(env, this.arguments, this.important).rules);
match = true;
} catch (e) {
throw { message: e.message, index: this.index, filename: this.filename, stack: e.stack };
}
}
}
if (match) {
return rules;
} else {
throw { type: 'Runtime',
message: 'No matching definition was found for `' +
this.selector.toCSS().trim() + '(' +
this.arguments.map(function (a) {
return a.toCSS();
}).join(', ') + ")`",
index: this.index, filename: this.filename };
}
}
}
throw { type: 'Name',
message: this.selector.toCSS().trim() + " is undefined",
index: this.index, filename: this.filename };
}
};
tree.mixin.Definition = function (name, params, rules, condition, variadic) {
this.name = name;
this.selectors = [new(tree.Selector)([new(tree.Element)(null, name)])];
this.params = params;
this.condition = condition;
this.variadic = variadic;
this.arity = params.length;
this.rules = rules;
this._lookups = {};
this.required = params.reduce(function (count, p) {
if (!p.name || (p.name && !p.value)) { return count + 1 }
else { return count }
}, 0);
this.parent = tree.Ruleset.prototype;
this.frames = [];
};
tree.mixin.Definition.prototype = {
toCSS: function () { return "" },
variable: function (name) { return this.parent.variable.call(this, name) },
variables: function () { return this.parent.variables.call(this) },
find: function () { return this.parent.find.apply(this, arguments) },
rulesets: function () { return this.parent.rulesets.apply(this) },
evalParams: function (env, args) {
var frame = new(tree.Ruleset)(null, []), varargs, arg;
for (var i = 0, val, name; i < this.params.length; i++) {
arg = args && args[i]
if (arg && arg.name) {
frame.rules.unshift(new(tree.Rule)(arg.name, arg.value.eval(env)));
args.splice(i, 1);
i--;
continue;
}
if (name = this.params[i].name) {
if (this.params[i].variadic && args) {
varargs = [];
for (var j = i; j < args.length; j++) {
varargs.push(args[j].value.eval(env));
}
frame.rules.unshift(new(tree.Rule)(name, new(tree.Expression)(varargs).eval(env)));
} else if (val = (arg && arg.value) || this.params[i].value) {
frame.rules.unshift(new(tree.Rule)(name, val.eval(env)));
} else {
throw { type: 'Runtime', message: "wrong number of arguments for " + this.name +
' (' + args.length + ' for ' + this.arity + ')' };
}
}
}
return frame;
},
eval: function (env, args, important) {
var frame = this.evalParams(env, args), context, _arguments = [], rules, start;
for (var i = 0; i < Math.max(this.params.length, args && args.length); i++) {
_arguments.push((args[i] && args[i].value) || this.params[i].value);
}
frame.rules.unshift(new(tree.Rule)('@arguments', new(tree.Expression)(_arguments).eval(env)));
rules = important ?
this.rules.map(function (r) {
return new(tree.Rule)(r.name, r.value, '!important', r.index);
}) : this.rules.slice(0);
return new(tree.Ruleset)(null, rules).eval({
frames: [this, frame].concat(this.frames, env.frames)
});
},
match: function (args, env) {
var argsLength = (args && args.length) || 0, len, frame;
if (! this.variadic) {
if (argsLength < this.required) { return false }
if (argsLength > this.params.length) { return false }
if ((this.required > 0) && (argsLength > this.params.length)) { return false }
}
if (this.condition && !this.condition.eval({
frames: [this.evalParams(env, args)].concat(env.frames)
})) { return false }
len = Math.min(argsLength, this.arity);
for (var i = 0; i < len; i++) {
if (!this.params[i].name) {
if (args[i].value.eval(env).toCSS() != this.params[i].value.eval(env).toCSS()) {
return false;
}
}
}
return true;
}
};
})(require('../tree'));

View File

@@ -0,0 +1,32 @@
(function (tree) {
tree.Operation = function (op, operands) {
this.op = op.trim();
this.operands = operands;
};
tree.Operation.prototype.eval = function (env) {
var a = this.operands[0].eval(env),
b = this.operands[1].eval(env),
temp;
if (a instanceof tree.Dimension && b instanceof tree.Color) {
if (this.op === '*' || this.op === '+') {
temp = b, b = a, a = temp;
} else {
throw { name: "OperationError",
message: "Can't substract or divide a color from a number" };
}
}
return a.operate(this.op, b);
};
tree.operate = function (op, a, b) {
switch (op) {
case '+': return a + b;
case '-': return a - b;
case '*': return a * b;
case '/': return a / b;
}
};
})(require('../tree'));

View File

@@ -0,0 +1,16 @@
(function (tree) {
tree.Paren = function (node) {
this.value = node;
};
tree.Paren.prototype = {
toCSS: function (env) {
return '(' + this.value.toCSS(env) + ')';
},
eval: function (env) {
return new(tree.Paren)(this.value.eval(env));
}
};
})(require('../tree'));

View File

@@ -0,0 +1,29 @@
(function (tree) {
tree.Quoted = function (str, content, escaped, i) {
this.escaped = escaped;
this.value = content || '';
this.quote = str.charAt(0);
this.index = i;
};
tree.Quoted.prototype = {
toCSS: function () {
if (this.escaped) {
return this.value;
} else {
return this.quote + this.value + this.quote;
}
},
eval: function (env) {
var that = this;
var value = this.value.replace(/`([^`]+)`/g, function (_, exp) {
return new(tree.JavaScript)(exp, that.index, true).eval(env).value;
}).replace(/@\{([\w-]+)\}/g, function (_, name) {
var v = new(tree.Variable)('@' + name, that.index).eval(env);
return ('value' in v) ? v.value : v.toCSS();
});
return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index);
}
};
})(require('../tree'));

View File

@@ -0,0 +1,42 @@
(function (tree) {
tree.Rule = function (name, value, important, index, inline) {
this.name = name;
this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]);
this.important = important ? ' ' + important.trim() : '';
this.index = index;
this.inline = inline || false;
if (name.charAt(0) === '@') {
this.variable = true;
} else { this.variable = false }
};
tree.Rule.prototype.toCSS = function (env) {
if (this.variable) { return "" }
else {
return this.name + (env.compress ? ':' : ': ') +
this.value.toCSS(env) +
this.important + (this.inline ? "" : ";");
}
};
tree.Rule.prototype.eval = function (context) {
return new(tree.Rule)(this.name,
this.value.eval(context),
this.important,
this.index, this.inline);
};
tree.Shorthand = function (a, b) {
this.a = a;
this.b = b;
};
tree.Shorthand.prototype = {
toCSS: function (env) {
return this.a.toCSS(env) + "/" + this.b.toCSS(env);
},
eval: function () { return this }
};
})(require('../tree'));

View File

@@ -0,0 +1,225 @@
(function (tree) {
tree.Ruleset = function (selectors, rules, strictImports) {
this.selectors = selectors;
this.rules = rules;
this._lookups = {};
this.strictImports = strictImports;
};
tree.Ruleset.prototype = {
eval: function (env) {
var selectors = this.selectors && this.selectors.map(function (s) { return s.eval(env) });
var ruleset = new(tree.Ruleset)(selectors, this.rules.slice(0), this.strictImports);
ruleset.root = this.root;
ruleset.allowImports = this.allowImports;
// push the current ruleset to the frames stack
env.frames.unshift(ruleset);
// Evaluate imports
if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) {
for (var i = 0; i < ruleset.rules.length; i++) {
if (ruleset.rules[i] instanceof tree.Import) {
Array.prototype.splice
.apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env)));
}
}
}
// Store the frames around mixin definitions,
// so they can be evaluated like closures when the time comes.
for (var i = 0; i < ruleset.rules.length; i++) {
if (ruleset.rules[i] instanceof tree.mixin.Definition) {
ruleset.rules[i].frames = env.frames.slice(0);
}
}
// Evaluate mixin calls.
for (var i = 0; i < ruleset.rules.length; i++) {
if (ruleset.rules[i] instanceof tree.mixin.Call) {
Array.prototype.splice
.apply(ruleset.rules, [i, 1].concat(ruleset.rules[i].eval(env)));
}
}
// Evaluate everything else
for (var i = 0, rule; i < ruleset.rules.length; i++) {
rule = ruleset.rules[i];
if (! (rule instanceof tree.mixin.Definition)) {
ruleset.rules[i] = rule.eval ? rule.eval(env) : rule;
}
}
// Pop the stack
env.frames.shift();
return ruleset;
},
match: function (args) {
return !args || args.length === 0;
},
variables: function () {
if (this._variables) { return this._variables }
else {
return this._variables = this.rules.reduce(function (hash, r) {
if (r instanceof tree.Rule && r.variable === true) {
hash[r.name] = r;
}
return hash;
}, {});
}
},
variable: function (name) {
return this.variables()[name];
},
rulesets: function () {
if (this._rulesets) { return this._rulesets }
else {
return this._rulesets = this.rules.filter(function (r) {
return (r instanceof tree.Ruleset) || (r instanceof tree.mixin.Definition);
});
}
},
find: function (selector, self) {
self = self || this;
var rules = [], rule, match,
key = selector.toCSS();
if (key in this._lookups) { return this._lookups[key] }
this.rulesets().forEach(function (rule) {
if (rule !== self) {
for (var j = 0; j < rule.selectors.length; j++) {
if (match = selector.match(rule.selectors[j])) {
if (selector.elements.length > rule.selectors[j].elements.length) {
Array.prototype.push.apply(rules, rule.find(
new(tree.Selector)(selector.elements.slice(1)), self));
} else {
rules.push(rule);
}
break;
}
}
}
});
return this._lookups[key] = rules;
},
//
// Entry point for code generation
//
// `context` holds an array of arrays.
//
toCSS: function (context, env) {
var css = [], // The CSS output
rules = [], // node.Rule instances
_rules = [], //
rulesets = [], // node.Ruleset instances
paths = [], // Current selectors
selector, // The fully rendered selector
rule;
if (! this.root) {
if (context.length === 0) {
paths = this.selectors.map(function (s) { return [s] });
} else {
this.joinSelectors(paths, context, this.selectors);
}
}
// Compile rules and rulesets
for (var i = 0; i < this.rules.length; i++) {
rule = this.rules[i];
if (rule.rules || (rule instanceof tree.Directive) || (rule instanceof tree.Media)) {
rulesets.push(rule.toCSS(paths, env));
} else if (rule instanceof tree.Comment) {
if (!rule.silent) {
if (this.root) {
rulesets.push(rule.toCSS(env));
} else {
rules.push(rule.toCSS(env));
}
}
} else {
if (rule.toCSS && !rule.variable) {
rules.push(rule.toCSS(env));
} else if (rule.value && !rule.variable) {
rules.push(rule.value.toString());
}
}
}
rulesets = rulesets.join('');
// If this is the root node, we don't render
// a selector, or {}.
// Otherwise, only output if this ruleset has rules.
if (this.root) {
css.push(rules.join(env.compress ? '' : '\n'));
} else {
if (rules.length > 0) {
selector = paths.map(function (p) {
return p.map(function (s) {
return s.toCSS(env);
}).join('').trim();
}).join(env.compress ? ',' : ',\n');
// Remove duplicates
for (var i = rules.length - 1; i >= 0; i--) {
if (_rules.indexOf(rules[i]) === -1) {
_rules.unshift(rules[i]);
}
}
rules = _rules;
css.push(selector,
(env.compress ? '{' : ' {\n ') +
rules.join(env.compress ? '' : '\n ') +
(env.compress ? '}' : '\n}\n'));
}
}
css.push(rulesets);
return css.join('') + (env.compress ? '\n' : '');
},
joinSelectors: function (paths, context, selectors) {
for (var s = 0; s < selectors.length; s++) {
this.joinSelector(paths, context, selectors[s]);
}
},
joinSelector: function (paths, context, selector) {
var before = [], after = [], beforeElements = [],
afterElements = [], hasParentSelector = false, el;
for (var i = 0; i < selector.elements.length; i++) {
el = selector.elements[i];
if (el.combinator.value.charAt(0) === '&') {
hasParentSelector = true;
}
if (hasParentSelector) afterElements.push(el);
else beforeElements.push(el);
}
if (! hasParentSelector) {
afterElements = beforeElements;
beforeElements = [];
}
if (beforeElements.length > 0) {
before.push(new(tree.Selector)(beforeElements));
}
if (afterElements.length > 0) {
after.push(new(tree.Selector)(afterElements));
}
for (var c = 0; c < context.length; c++) {
paths.push(before.concat(context[c]).concat(after));
}
}
};
})(require('../tree'));

View File

@@ -0,0 +1,42 @@
(function (tree) {
tree.Selector = function (elements) {
this.elements = elements;
if (this.elements[0].combinator.value === "") {
this.elements[0].combinator.value = ' ';
}
};
tree.Selector.prototype.match = function (other) {
var len = this.elements.length,
olen = other.elements.length,
max = Math.min(len, olen);
if (len < olen) {
return false;
} else {
for (var i = 0; i < max; i++) {
if (this.elements[i].value !== other.elements[i].value) {
return false;
}
}
}
return true;
};
tree.Selector.prototype.eval = function (env) {
return new(tree.Selector)(this.elements.map(function (e) {
return e.eval(env);
}));
};
tree.Selector.prototype.toCSS = function (env) {
if (this._css) { return this._css }
return this._css = this.elements.map(function (e) {
if (typeof(e) === 'string') {
return ' ' + e.trim();
} else {
return e.toCSS(env);
}
}).join('');
};
})(require('../tree'));

View File

@@ -0,0 +1,25 @@
(function (tree) {
tree.URL = function (val, paths) {
if (val.data) {
this.attrs = val;
} else {
// Add the base path if the URL is relative and we are in the browser
if (typeof(window) !== 'undefined' && !/^(?:https?:\/\/|file:\/\/|data:|\/)/.test(val.value) && paths.length > 0) {
val.value = paths[0] + (val.value.charAt(0) === '/' ? val.value.slice(1) : val.value);
}
this.value = val;
this.paths = paths;
}
};
tree.URL.prototype = {
toCSS: function () {
return "url(" + (this.attrs ? 'data:' + this.attrs.mime + this.attrs.charset + this.attrs.base64 + this.attrs.data
: this.value.toCSS()) + ")";
},
eval: function (ctx) {
return this.attrs ? this : new(tree.URL)(this.value.eval(ctx), this.paths);
}
};
})(require('../tree'));

View File

@@ -0,0 +1,24 @@
(function (tree) {
tree.Value = function (value) {
this.value = value;
this.is = 'value';
};
tree.Value.prototype = {
eval: function (env) {
if (this.value.length === 1) {
return this.value[0].eval(env);
} else {
return new(tree.Value)(this.value.map(function (v) {
return v.eval(env);
}));
}
},
toCSS: function (env) {
return this.value.map(function (e) {
return e.toCSS(env);
}).join(env.compress ? ',' : ', ');
}
};
})(require('../tree'));

View File

@@ -0,0 +1,26 @@
(function (tree) {
tree.Variable = function (name, index, file) { this.name = name, this.index = index, this.file = file };
tree.Variable.prototype = {
eval: function (env) {
var variable, v, name = this.name;
if (name.indexOf('@@') == 0) {
name = '@' + new(tree.Variable)(name.slice(1)).eval(env).value;
}
if (variable = tree.find(env.frames, function (frame) {
if (v = frame.variable(name)) {
return v.value.eval(env);
}
})) { return variable }
else {
throw { type: 'Name',
message: "variable " + name + " is undefined",
filename: this.file,
index: this.index };
}
}
};
})(require('../tree'));

View File

@@ -0,0 +1,13 @@
{
"name" : "less",
"description" : "Leaner CSS",
"url" : "http://lesscss.org",
"keywords" : ["css", "parser", "lesscss", "browser"],
"author" : "Alexis Sellier <self@cloudhead.net>",
"contributors" : [],
"version" : "1.3.0",
"bin" : { "lessc": "./bin/lessc" },
"main" : "./lib/less/index",
"directories" : { "test": "./test" },
"engines" : { "node": ">=0.4.0" }
}

View File

@@ -0,0 +1,58 @@
#yelow #short {
color: #fea;
}
#yelow #long {
color: #ffeeaa;
}
#yelow #rgba {
color: rgba(255, 238, 170, 0.1);
}
#yelow #argb {
color: #1affeeaa;
}
#blue #short {
color: #00f;
}
#blue #long {
color: #0000ff;
}
#blue #rgba {
color: rgba(0, 0, 255, 0.1);
}
#blue #argb {
color: #1a0000ff;
}
#alpha #hsla {
color: rgba(61, 45, 41, 0.6);
}
#overflow .a {
color: #000000;
}
#overflow .b {
color: #ffffff;
}
#overflow .c {
color: #ffffff;
}
#overflow .d {
color: #00ff00;
}
#grey {
color: #c8c8c8;
}
#808080 {
color: #808080;
}
#00ff00 {
color: #00ff00;
}
.lightenblue {
color: #3333ff;
}
.darkenblue {
color: #0000cc;
}
.unknowncolors {
color: blue2;
border: 2px solid superred;
}

View File

@@ -0,0 +1,56 @@
/******************\
* *
* Comment Header *
* *
\******************/
/*
Comment
*/
/*
* Comment Test
*
* - cloudhead (http://cloudhead.net)
*
*/
/* Colors
* ------
* #EDF8FC (background blue)
* #166C89 (darkest blue)
*
* Text:
* #333 (standard text) // A comment within a comment!
* #1F9EC9 (standard link)
*
*/
/* @group Variables
------------------- */
#comments {
/**/
color: red;
/* A C-style comment */
background-color: orange;
font-size: 12px;
/* lost comment */
content: "content";
border: 1px solid black;
padding: 0;
margin: 2em;
}
/* commented out
#more-comments {
color: grey;
}
*/
.selector,
.lots,
.comments {
color: #808080, /* blue */ #ffa500;
-webkit-border-radius: 2px /* webkit only */;
-moz-border-radius: 8px /* moz only with operation */;
}
#last {
color: #0000ff;
}

View File

@@ -0,0 +1,58 @@
.comma-delimited {
background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg);
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;
}
@font-face {
font-family: Headline;
src: local(Futura-Medium), url(fonts.svg#MyGeometricModern) format("svg");
}
.other {
-moz-transform: translate(0, 11em) rotate(-90deg);
}
p:not([class*="lead"]) {
color: black;
}
input[type="text"].class#id[attr=32]:not(1) {
color: white;
}
div#id.class[a=1][b=2].class:not(1) {
color: white;
}
ul.comma > li:not(:only-child)::after {
color: white;
}
ol.comma > li:nth-last-child(2)::after {
color: white;
}
li:nth-child(4n+1),
li:nth-child(-5n),
li:nth-child(-n+2) {
color: white;
}
a[href^="http://"] {
color: black;
}
a[href$="http://"] {
color: black;
}
form[data-disabled] {
color: black;
}
p::before {
color: black;
}
#issue322 {
-webkit-animation: anim2 7s infinite ease-in-out;
}
@-webkit-keyframes frames {
0% {
border: 1px;
}
5.5% {
border: 2px;
}
100% {
border: 3px;
}
}

View File

@@ -0,0 +1,20 @@
.escape\|random\|char {
color: red;
}
.mixin\!tUp {
font-weight: bold;
}
.\34 04 {
background: red;
}
.\34 04 strong {
color: #ff00ff;
font-weight: bold;
}
.trailingTest\+ {
color: red;
}
/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */
\62\6c\6f \63 \6B \0071 \000075o\74 e {
color: silver;
}

View File

@@ -0,0 +1,89 @@
@charset "utf-8";
div {
color: black;
}
div {
width: 99%;
}
* {
min-width: 45em;
}
h1,
h2 > a > p,
h3 {
color: none;
}
div.class {
color: blue;
}
div#id {
color: green;
}
.class#id {
color: purple;
}
.one.two.three {
color: grey;
}
@media print {
font-size: 3em;
}
@media screen {
font-size: 10px;
}
@font-face {
font-family: 'Garamond Pro';
src: url("/fonts/garamond-pro.ttf");
}
a:hover,
a:link {
color: #999;
}
p,
p:first-child {
text-transform: none;
}
q:lang(no) {
quotes: none;
}
p + h1 {
font-size: 2.2em;
}
#shorthands {
border: 1px solid #000;
font: 12px/16px Arial;
font: 100%/16px Arial;
margin: 1px 0;
padding: 0 auto;
background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
}
#more-shorthands {
margin: 0;
padding: 1px 0 2px 0;
font: normal small/20px 'Trebuchet MS', Verdana, sans-serif;
}
.misc {
-moz-border-radius: 2px;
display: -moz-inline-stack;
width: .1em;
background-color: #009998;
background-image: url(images/image.jpg);
background: -webkit-gradient(linear, left top, left bottom, from(#ff0000), to(#0000ff));
margin: ;
filter: alpha(opacity=100);
}
#important {
color: red !important;
width: 100%!important;
height: 20px ! important;
}
#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==);
}
#svg-data-uri {
background: transparent url('data:image/svg+xml, <svg version="1.1"><g></g></svg>');
}

View File

@@ -0,0 +1,43 @@
#functions {
color: #660000;
width: 16;
height: undefined("self");
border-width: 5;
variable: 11;
}
#built-in {
escaped: -Some::weird(#thing, y);
lighten: #ffcccc;
darken: #330000;
saturate: #203c31;
desaturate: #29332f;
greyscale: #2e2e2e;
spin-p: #bf6a40;
spin-n: #bf4055;
format: "rgb(32, 128, 64)";
format-string: "hello world";
format-multiple: "hello earth 2";
format-url-encode: "red is %23ff0000";
eformat: rgb(32, 128, 64);
hue: 98;
saturation: 12%;
lightness: 95%;
rounded: 11;
roundedpx: 3px;
percentage: 20%;
color: #ff0011;
}
#built-in .is-a {
color: true;
color1: true;
color2: true;
keyword: true;
number: true;
string: true;
pixel: true;
percent: true;
em: true;
}
#alpha {
alpha: rgba(153, 94, 51, 0.6);
}

View File

@@ -0,0 +1,5 @@
.nav {
filter: progid:dximagetransform.microsoft.alpha(opacity=20);
filter: progid:dximagetransform.microsoft.alpha(opacity=0);
filter: progid:dximagetransform.microsoft.gradient(startColorstr="#333333", endColorstr="#000000", GradientType=0);
}

View File

@@ -0,0 +1,9 @@
@import "import-test-d.css";
.mixin {
height: 10px;
color: #ff0000;
}
#import {
color: #ff0000;
}

View File

@@ -0,0 +1,23 @@
@import "import-test-d.css";
@import url(http://fonts.googleapis.com/css?family=Open+Sans);
@import url(something.css) screen and (color) and (max-width: 600px);
#import {
color: #ff0000;
}
.mixin {
height: 10px;
color: #ff0000;
}
#import-test {
height: 10px;
color: #ff0000;
width: 10px;
height: 30%;
}
@media screen and (max-width: 600px) {
body {
width: 100%;
}
}

View File

@@ -0,0 +1,22 @@
.eval {
js: 42;
js: 2;
js: "hello world";
js: 1, 2, 3;
title: "node";
ternary: true;
}
.scope {
var: 42;
escaped: 7px;
}
.vars {
width: 8;
}
.escape-interpol {
width: hello world;
}
.arrays {
ary: "1, 2, 3";
ary1: "1, 2, 3";
}

View File

@@ -0,0 +1,3 @@
.lazy-eval {
width: 100%;
}

View File

@@ -0,0 +1,79 @@
@media print {
.class {
color: blue;
}
.class .sub {
width: 42;
}
.top,
header > h1 {
color: #444444;
}
}
@media screen {
body {
max-width: 480;
}
}
@media all and (orientation: portrait) {
aside {
float: none;
}
}
@media handheld and (min-width: 42), screen and (min-width: 20em) {
body {
max-width: 480px;
}
}
@media print {
body {
padding: 20px;
}
body header {
background-color: red;
}
}
@media print and (orientation: landscape) {
body {
margin-left: 20px;
}
}
@media a, b and c {
body {
width: 95%;
}
}
@media a and x, b and c and x, a and y, b and c and y {
body {
width: 100%;
}
}
.a {
background: black;
}
@media handheld {
.a {
background: white;
}
}
@media handheld and (max-width: 100px) {
.a {
background: red;
}
}
.b {
background: black;
}
@media handheld {
.b {
background: white;
}
}
@media handheld and (max-width: 200px) {
.b {
background: red;
}
}
@media only screen and (max-width: 200px) {
width: 480px;
}

View File

@@ -0,0 +1,74 @@
#hidden {
color: transparent;
}
#hidden1 {
color: transparent;
}
.two-args {
color: blue;
width: 10px;
height: 99%;
border: 2px dotted #000000;
}
.one-arg {
width: 15px;
height: 49%;
}
.no-parens {
width: 5px;
height: 49%;
}
.no-args {
width: 5px;
height: 49%;
}
.var-args {
width: 45;
height: 17%;
}
.multi-mix {
width: 10px;
height: 29%;
margin: 4;
padding: 5;
}
body {
padding: 30px;
color: #ff0000;
}
.scope-mix {
width: 8;
}
.content {
width: 600px;
}
.content .column {
margin: 600px;
}
#same-var-name {
radius: 5px;
}
#var-inside {
width: 10px;
}
.arguments {
border: 1px solid #000000;
width: 1px;
}
.arguments2 {
border: 0px;
width: 0px;
}
.arguments3 {
border: 0px;
width: 0px;
}
.arguments4 {
border: 0 1 2 3 4;
rest: 1 2 3 4;
width: 0;
}
.edge-case {
border: "{";
width: "{";
}

View File

@@ -0,0 +1,9 @@
.class {
width: 99px;
}
.overwrite {
width: 99px;
}
.nested .class {
width: 5px;
}

View File

@@ -0,0 +1,58 @@
.light1 {
color: white;
margin: 1px;
}
.light2 {
color: black;
margin: 1px;
}
.max1 {
width: 6;
}
.max2 {
width: 8;
}
.glob1 {
margin: auto auto;
}
.ops1 {
height: gt-or-eq;
height: lt-or-eq;
}
.ops2 {
height: gt-or-eq;
height: not-eq;
}
.ops3 {
height: lt-or-eq;
height: not-eq;
}
.default1 {
content: default;
}
.test1 {
content: "true.";
}
.test2 {
content: "false.";
}
.test3 {
content: "false.";
}
.test4 {
content: "false.";
}
.test5 {
content: "false.";
}
.bool1 {
content: true and true;
content: true;
content: false, true;
content: false and true and true, true;
content: false, true and true;
content: false, false, true;
content: false, true and true and true, false;
content: not false;
content: not false and false, not false;
}

View File

@@ -0,0 +1,17 @@
.class {
border: 1;
boxer: 1;
border: 2 !important;
boxer: 2 !important;
border: 3;
boxer: 3;
border: 4 !important;
boxer: 4 !important;
border: 5;
boxer: 5;
border: 0 !important;
boxer: 0 !important;
border: 9 !important;
border: 9;
boxer: 9;
}

View File

@@ -0,0 +1,20 @@
.named-arg {
color: blue;
width: 5px;
height: 99%;
text-align: center;
}
.class {
width: 5px;
height: 19%;
}
.named-args2 {
width: 15px;
height: 49%;
color: #646464;
}
.named-args3 {
width: 5px;
height: 29%;
color: #123456;
}

View File

@@ -0,0 +1,14 @@
.class .inner {
height: 300;
}
.class .inner .innest {
width: 30;
border-width: 60;
}
.class2 .inner {
height: 600;
}
.class2 .inner .innest {
width: 60;
border-width: 120;
}

View File

@@ -0,0 +1,47 @@
.zero {
variadic: true;
zero: 0;
one: 1;
two: 2;
three: 3;
}
.one {
variadic: true;
one: 1;
one-req: 1;
two: 2;
three: 3;
}
.two {
variadic: true;
two: 2;
three: 3;
}
.three {
variadic: true;
three-req: 3;
three: 3;
}
.left {
left: 1;
}
.right {
right: 1;
}
.border-right {
color: black;
border-right: 4px;
}
.border-left {
color: black;
border-left: 4px;
}
.only-right {
right: 33;
}
.only-left {
left: 33;
}
.left-right {
both: 330;
}

View File

@@ -0,0 +1,71 @@
.mixin {
border: 1px solid black;
}
.mixout {
border-color: orange;
}
.borders {
border-style: dashed;
}
#namespace .borders {
border-style: dotted;
}
#namespace .biohazard {
content: "death";
}
#namespace .biohazard .man {
color: transparent;
}
#theme > .mixin {
background-color: grey;
}
#container {
color: black;
border: 1px solid black;
border-color: orange;
background-color: grey;
}
#header .milk {
color: white;
border: 1px solid black;
background-color: grey;
}
#header #cookie {
border-style: dashed;
}
#header #cookie .chips {
border-style: dotted;
}
#header #cookie .chips .calories {
color: black;
border: 1px solid black;
border-color: orange;
background-color: grey;
}
.secure-zone {
color: transparent;
}
.direct {
border-style: dotted;
}
.bo,
.bar {
width: 100%;
}
.bo {
border: 1px;
}
.ar.bo.ca {
color: black;
}
.jo.ki {
background: none;
}
.extended {
width: 100%;
border: 1px;
background: none;
}
.foo .bar {
width: 100%;
}

View File

@@ -0,0 +1,49 @@
#operations {
color: #111111;
height: 9px;
width: 3em;
substraction: 0;
division: 1;
}
#operations .spacing {
height: 9px;
width: 3em;
}
.with-variables {
height: 16em;
width: 24em;
size: 1cm;
}
.with-functions {
color: #646464;
color: #ff8080;
color: #c94a4a;
}
.negative {
height: 0px;
width: 4px;
}
.shorthands {
padding: -1px 2px 0 -4px;
}
.rem-dimensions {
font-size: 5.5rem;
}
.colors {
color: #123;
border-color: #334455;
background-color: #000000;
}
.colors .other {
color: #222222;
border-color: #222222;
}
.negations {
variable: -4px;
variable1: 0px;
variable2: 0px;
variable3: 8px;
variable4: 0px;
paren: -4px;
paren2: 16px;
}

View File

@@ -0,0 +1,20 @@
.parens {
border: 2px solid #000000;
margin: 1px 3px 16 3;
width: 36;
padding: 2px 36px;
}
.more-parens {
padding: 8 4 4 4px;
width: 96;
height: 113;
margin: 12;
}
.nested-parens {
width: 71;
height: 6;
}
.mixed-units {
margin: 2px 4em 1 5pc;
padding: 6px 1em 2px 2;
}

View File

@@ -0,0 +1,33 @@
#first > .one {
font-size: 2em;
}
#first > .one > #second .two > #deux {
width: 50%;
}
#first > .one > #second .two > #deux #third {
height: 100%;
}
#first > .one > #second .two > #deux #third:focus {
color: black;
}
#first > .one > #second .two > #deux #third:focus #fifth > #sixth .seventh #eighth + #ninth {
color: purple;
}
#first > .one > #second .two > #deux #fourth,
#first > .one > #second .two > #deux #five,
#first > .one > #second .two > #deux #six {
color: #110000;
}
#first > .one > #second .two > #deux #fourth .seven,
#first > .one > #second .two > #deux #five .seven,
#first > .one > #second .two > #deux #six .seven,
#first > .one > #second .two > #deux #fourth .eight > #nine,
#first > .one > #second .two > #deux #five .eight > #nine,
#first > .one > #second .two > #deux #six .eight > #nine {
border: 1px solid black;
}
#first > .one > #second .two > #deux #fourth #ten,
#first > .one > #second .two > #deux #five #ten,
#first > .one > #second .two > #deux #six #ten {
color: red;
}

View File

@@ -0,0 +1,15 @@
.tiny-scope {
color: #998899;
}
.scope1 {
color: #0000ff;
border-color: #000000;
}
.scope1 .scope2 {
color: #0000ff;
}
.scope1 .scope2 .scope3 {
color: #ff0000;
border-color: #000000;
background-color: #ffffff;
}

View File

@@ -0,0 +1,69 @@
h1 a:hover,
h2 a:hover,
h3 a:hover,
h1 p:hover,
h2 p:hover,
h3 p:hover {
color: red;
}
#all {
color: blue;
}
#the {
color: blue;
}
#same {
color: blue;
}
ul,
li,
div,
q,
blockquote,
textarea {
margin: 0;
}
td {
margin: 0;
padding: 0;
}
td,
input {
line-height: 1em;
}
a {
color: red;
}
a:hover {
color: blue;
}
div a {
color: green;
}
p a span {
color: yellow;
}
.foo .bar .qux,
.foo .baz .qux {
display: block;
}
.qux .foo .bar,
.qux .foo .baz {
display: inline;
}
.qux .foo .bar .biz,
.qux .foo .baz .biz {
display: none;
}
.other ::fnord {
color: #ff0000;
}
.other::fnord {
color: #ff0000;
}
.other ::bnord {
color: #ff0000;
}
.other::bnord {
color: #ff0000;
}

View File

@@ -0,0 +1,40 @@
#strings {
background-image: url("http://son-of-a-banana.com");
quotes: "~" "~";
content: "#*%:&^,)!.(~*})";
empty: "";
brackets: "{" "}";
escapes: "\"hello\" \\world";
escapes2: "\"llo";
}
#comments {
content: "/* hello */ // not-so-secret";
}
#single-quote {
quotes: "'" "'";
content: '""#!&""';
empty: '';
semi-colon: ';';
}
#escaped {
filter: DX.Transform.MS.BS.filter(opacity=50);
}
#one-line {
image: url(http://tooks.com);
}
#crazy {
image: url(http://), "}", url("http://}");
}
#interpolation {
url: "http://lesscss.org/dev/image.jpg";
url2: "http://lesscss.org/image-256.jpg";
url3: "http://lesscss.org#445566";
url4: "http://lesscss.org/hello";
url5: "http://lesscss.org/54.4";
}
.mix-mul-class {
color: #0000ff;
color: #ff0000;
color: #000000;
color: #ffa500;
}

View File

@@ -0,0 +1,27 @@
.variables {
width: 14cm;
}
.variables {
height: 24px;
color: #888888;
font-family: "Trebuchet MS", Verdana, sans-serif;
quotes: "~" "~";
}
.redefinition {
three: 3;
}
.values {
font-family: 'Trebuchet', 'Trebuchet', 'Trebuchet';
color: #888888 !important;
url: url('Trebuchet');
multi: something 'A', B, C, 'Trebuchet';
}
.variable-names {
name: 'hello';
}
.alpha {
filter: alpha(opacity=42);
}
a:nth-child(2) {
border: 1px;
}

View File

@@ -0,0 +1,38 @@
.whitespace {
color: white;
}
.whitespace {
color: white;
}
.whitespace {
color: white;
}
.whitespace {
color: white;
}
.whitespace {
color: white ;
}
.white,
.space,
.mania {
color: white;
}
.no-semi-column {
color: #ffffff;
}
.no-semi-column {
color: white;
white-space: pre;
}
.no-semi-column {
border: 2px solid #ffffff;
}
.newlines {
background: the,
great,
wall;
border: 2px
solid
black;
}

View File

@@ -0,0 +1,73 @@
var path = require('path'),
fs = require('fs'),
sys = require('util');
var less = require('../lib/less');
less.tree.functions.add = function (a, b) {
return new(less.tree.Dimension)(a.value + b.value);
}
less.tree.functions.increment = function (a) {
return new(less.tree.Dimension)(a.value + 1);
}
less.tree.functions._color = function (str) {
if (str.value === "evil red") { return new(less.tree.Color)("600") }
}
sys.puts("\n" + stylize("LESS", 'underline') + "\n");
fs.readdirSync('test/less').forEach(function (file) {
if (! /\.less/.test(file)) { return }
toCSS('test/less/' + file, function (err, less) {
var name = path.basename(file, '.less');
fs.readFile(path.join('test/css', name) + '.css', 'utf-8', function (e, css) {
sys.print("- " + name + ": ")
if (less === css) { sys.print(stylize('OK', 'green')) }
else if (err) {
sys.print(stylize("ERROR: " + (err && err.message), 'red'));
} else {
sys.print(stylize("FAIL", 'yellow'));
}
sys.puts("");
});
});
});
function toCSS(path, callback) {
var tree, css;
fs.readFile(path, 'utf-8', function (e, str) {
if (e) { return callback(e) }
new(less.Parser)({
paths: [require('path').dirname(path)],
optimization: 0
}).parse(str, function (err, tree) {
if (err) {
callback(err);
} else {
try {
css = tree.toCSS();
callback(null, css);
} catch (e) {
callback(e);
}
}
});
});
}
// Stylize a string
function stylize(str, style) {
var styles = {
'bold' : [1, 22],
'inverse' : [7, 27],
'underline' : [4, 24],
'yellow' : [33, 39],
'green' : [32, 39],
'red' : [31, 39]
};
return '\033[' + styles[style][0] + 'm' + str +
'\033[' + styles[style][1] + 'm';
}

View File

@@ -0,0 +1,65 @@
#yelow {
#short {
color: #fea;
}
#long {
color: #ffeeaa;
}
#rgba {
color: rgba(255, 238, 170, 0.1);
}
#argb {
color: argb(rgba(255, 238, 170, 0.1));
}
}
#blue {
#short {
color: #00f;
}
#long {
color: #0000ff;
}
#rgba {
color: rgba(0, 0, 255, 0.1);
}
#argb {
color: argb(rgba(0, 0, 255, 0.1));
}
}
#alpha #hsla {
color: hsla(11, 20%, 20%, 0.6);
}
#overflow {
.a { color: #111111 - #444444; } // #000000
.b { color: #eee + #fff; } // #ffffff
.c { color: #aaa * 3; } // #ffffff
.d { color: #00ee00 + #009900; } // #00ff00
}
#grey {
color: rgb(200, 200, 200);
}
#808080 {
color: hsl(50, 0%, 50%);
}
#00ff00 {
color: hsl(120, 100%, 50%);
}
.lightenblue {
color: lighten(blue, 10%);
}
.darkenblue {
color: darken(blue, 10%);
}
.unknowncolors {
color: blue2;
border: 2px solid superred;
}

View File

@@ -0,0 +1,65 @@
/******************\
* *
* Comment Header *
* *
\******************/
/*
Comment
*/
/*
* Comment Test
*
* - cloudhead (http://cloudhead.net)
*
*/
////////////////
@var: "content";
////////////////
/* Colors
* ------
* #EDF8FC (background blue)
* #166C89 (darkest blue)
*
* Text:
* #333 (standard text) // A comment within a comment!
* #1F9EC9 (standard link)
*
*/
/* @group Variables
------------------- */
#comments /* boo */ {
/**/ // An empty comment
color: red; /* A C-style comment */
background-color: orange; // A little comment
font-size: 12px;
/* lost comment */ content: @var;
border: 1px solid black;
// padding & margin //
padding: 0; // }{ '"
margin: 2em;
} //
/* commented out
#more-comments {
color: grey;
}
*/
.selector /* .with */, .lots, /* of */ .comments {
color: grey, /* blue */ orange;
-webkit-border-radius: 2px /* webkit only */;
-moz-border-radius: 2px * 4 /* moz only with operation */;
}
#last { color: blue }
//

View File

@@ -0,0 +1,65 @@
.comma-delimited {
background: url(bg.jpg) no-repeat, url(bg.png) repeat-x top left, url(bg);
text-shadow: -1px -1px 1px red, 6px 5px 5px yellow;
-moz-box-shadow: 0pt 0pt 2px rgba(255, 255, 255, 0.4) inset,
0pt 4px 6px rgba(255, 255, 255, 0.4) inset;
}
@font-face {
font-family: Headline;
src: local(Futura-Medium),
url(fonts.svg#MyGeometricModern) format("svg");
}
.other {
-moz-transform: translate(0, 11em) rotate(-90deg);
}
p:not([class*="lead"]) {
color: black;
}
input[type="text"].class#id[attr=32]:not(1) {
color: white;
}
div#id.class[a=1][b=2].class:not(1) {
color: white;
}
ul.comma > li:not(:only-child)::after {
color: white;
}
ol.comma > li:nth-last-child(2)::after {
color: white;
}
li:nth-child(4n+1),
li:nth-child(-5n),
li:nth-child(-n+2) {
color: white;
}
a[href^="http://"] {
color: black;
}
a[href$="http://"] {
color: black;
}
form[data-disabled] {
color: black;
}
p::before {
color: black;
}
#issue322 {
-webkit-animation: anim2 7s infinite ease-in-out;
}
@-webkit-keyframes frames {
0% { border: 1px }
5.5% { border: 2px }
100% { border: 3px }
}

View File

@@ -0,0 +1,28 @@
@ugly: fuchsia;
.escape\|random\|char {
color: red;
}
.mixin\!tUp {
font-weight: bold;
}
// class="404"
.\34 04 {
background: red;
strong {
color: @ugly;
.mixin\!tUp;
}
}
.trailingTest\+ {
color: red;
}
/* This hideous test of hideousness checks for the selector "blockquote" with various permutations of hex escapes */
\62\6c\6f \63 \6B \0071 \000075o\74 e {
color: silver;
}

View File

@@ -0,0 +1,100 @@
@charset "utf-8";
div { color: black; }
div { width: 99%; }
* {
min-width: 45em;
}
h1, h2 > a > p, h3 {
color: none;
}
div.class {
color: blue;
}
div#id {
color: green;
}
.class#id {
color: purple;
}
.one.two.three {
color: grey;
}
@media print {
font-size: 3em;
}
@media screen {
font-size: 10px;
}
@font-face {
font-family: 'Garamond Pro';
src: url("/fonts/garamond-pro.ttf");
}
a:hover, a:link {
color: #999;
}
p, p:first-child {
text-transform: none;
}
q:lang(no) {
quotes: none;
}
p + h1 {
font-size: 2.2em;
}
#shorthands {
border: 1px solid #000;
font: 12px/16px Arial;
font: 100%/16px Arial;
margin: 1px 0;
padding: 0 auto;
background: url("http://www.lesscss.org/spec.html") no-repeat 0 4px;
}
#more-shorthands {
margin: 0;
padding: 1px 0 2px 0;
font: normal small/20px 'Trebuchet MS', Verdana, sans-serif;
}
.misc {
-moz-border-radius: 2px;
display: -moz-inline-stack;
width: .1em;
background-color: #009998;
background-image: url(images/image.jpg);
background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
margin: ;
filter: alpha(opacity=100);
}
#important {
color: red !important;
width: 100%!important;
height: 20px ! important;
}
#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==);
}
#svg-data-uri {
background: transparent url('data:image/svg+xml, <svg version="1.1"><g></g></svg>');
}

View File

@@ -0,0 +1,49 @@
#functions {
@var: 10;
color: _color("evil red"); // #660000
width: increment(15);
height: undefined("self");
border-width: add(2, 3);
variable: increment(@var);
}
#built-in {
@r: 32;
escaped: e("-Some::weird(#thing, y)");
lighten: lighten(#ff0000, 40%);
darken: darken(#ff0000, 40%);
saturate: saturate(#29332f, 20%);
desaturate: desaturate(#203c31, 20%);
greyscale: greyscale(#203c31);
spin-p: spin(hsl(340, 50%, 50%), 40);
spin-n: spin(hsl(30, 50%, 50%), -40);
format: %("rgb(%d, %d, %d)", @r, 128, 64);
format-string: %("hello %s", "world");
format-multiple: %("hello %s %d", "earth", 2);
format-url-encode: %('red is %A', #ff0000);
eformat: e(%("rgb(%d, %d, %d)", @r, 128, 64));
hue: hue(hsl(98, 12%, 95%));
saturation: saturation(hsl(98, 12%, 95%));
lightness: lightness(hsl(98, 12%, 95%));
rounded: round(@r/3);
roundedpx: round(10px / 3);
percentage: percentage(10px / 50);
color: color("#ff0011");
.is-a {
color: iscolor(#ddd);
color1: iscolor(red);
color2: iscolor(rgb(0, 0, 0));
keyword: iskeyword(hello);
number: isnumber(32);
string: isstring("hello");
pixel: ispixel(32px);
percent: ispercentage(32%);
em: isem(32em);
}
}
#alpha {
alpha: darken(hsla(25, 50%, 50%, 0.6), 10%);
}

View File

@@ -0,0 +1,8 @@
@fat: 0;
@cloudhead: "#000000";
.nav {
filter: progid:DXImageTransform.Microsoft.Alpha(opacity = 20);
filter: progid:DXImageTransform.Microsoft.Alpha(opacity=@fat);
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr="#333333", endColorstr=@cloudhead, GradientType=@fat);
}

View File

@@ -0,0 +1,3 @@
@import-once "import/import-test-a";
@import-once "import/import-test-b";
@import-once "import/import-test-c";

View File

@@ -0,0 +1,11 @@
@import url("import/import-test-a.less");
@import url(http://fonts.googleapis.com/css?family=Open+Sans);
@import url(something.css) screen and (color) and (max-width: 600px);
#import-test {
.mixin;
width: 10px;
height: @a + 10%;
}
@import "import/import-test-e" screen and (max-width: 600px);

View File

@@ -0,0 +1,2 @@
@import "import-test-b.less";
@a: 20%;

View File

@@ -0,0 +1,8 @@
@import "import-test-c";
@b: 100%;
.mixin {
height: 10px;
color: @c;
}

View File

@@ -0,0 +1,7 @@
@import "import-test-d.css";
@c: red;
#import {
color: @c;
}

View File

@@ -0,0 +1 @@
#css { color: yellow; }

View File

@@ -0,0 +1,2 @@
body { width: 100% }

View File

@@ -0,0 +1,27 @@
.eval {
js: `42`;
js: `1 + 1`;
js: `"hello world"`;
js: `[1, 2, 3]`;
title: `process.title`;
ternary: `(1 + 1 == 2 ? true : false)`;
}
.scope {
@foo: 42;
var: `this.foo.toJS()`;
escaped: ~`2 + 5 + 'px'`;
}
.vars {
@var: `4 + 4`;
width: @var;
}
.escape-interpol {
@world: "world";
width: ~`"hello" + " " + @{world}`;
}
.arrays {
@ary: 1, 2, 3;
@ary2: 1 2 3;
ary: `@{ary}.join(', ')`;
ary1: `@{ary2}.join(', ')`;
}

View File

@@ -0,0 +1,6 @@
@var: @a;
@a: 100%;
.lazy-eval {
width: @var;
}

View File

@@ -0,0 +1,79 @@
// For now, variables can't be declared inside @media blocks.
@var: 42;
@media print {
.class {
color: blue;
.sub {
width: @var;
}
}
.top, header > h1 {
color: #222 * 2;
}
}
@media screen {
@base: 8;
body { max-width: @base * 60; }
}
@media all and (orientation:portrait) {
aside { float: none; }
}
@media handheld and (min-width: @var), screen and (min-width: 20em) {
body {
max-width: 480px;
}
}
body {
@media print {
padding: 20px;
header {
background-color: red;
}
@media (orientation:landscape) {
margin-left: 20px;
}
}
}
body {
@media a, b and c {
width: 95%;
@media x, y {
width: 100%;
}
}
}
.mediaMixin(@fallback: 200px) {
background: black;
@media handheld {
background: white;
@media (max-width: @fallback) {
background: red;
}
}
}
.a {
.mediaMixin(100px);
}
.b {
.mediaMixin();
}
@smartphone: ~"only screen and (max-width: 200px)";
@media @smartphone {
width: 480px;
}

View File

@@ -0,0 +1,130 @@
.mixin (@a: 1px, @b: 50%) {
width: @a * 5;
height: @b - 1%;
}
.mixina (@style, @width, @color: black) {
border: @width @style @color;
}
.mixiny
(@a: 0, @b: 0) {
margin: @a;
padding: @b;
}
.hidden() {
color: transparent; // asd
}
#hidden {
.hidden;
}
#hidden1 {
.hidden();
}
.two-args {
color: blue;
.mixin(2px, 100%);
.mixina(dotted, 2px);
}
.one-arg {
.mixin(3px);
}
.no-parens {
.mixin;
}
.no-args {
.mixin();
}
.var-args {
@var: 9;
.mixin(@var, @var * 2);
}
.multi-mix {
.mixin(2px, 30%);
.mixiny(4, 5);
}
.maxa(@arg1: 10, @arg2: #f00) {
padding: @arg1 * 2px;
color: @arg2;
}
body {
.maxa(15);
}
@glob: 5;
.global-mixin(@a:2) {
width: @glob + @a;
}
.scope-mix {
.global-mixin(3);
}
.nested-ruleset (@width: 200px) {
width: @width;
.column { margin: @width; }
}
.content {
.nested-ruleset(600px);
}
//
.same-var-name2(@radius) {
radius: @radius;
}
.same-var-name(@radius) {
.same-var-name2(@radius);
}
#same-var-name {
.same-var-name(5px);
}
//
.var-inside () {
@var: 10px;
width: @var;
}
#var-inside { .var-inside; }
.mixin-arguments (@width: 0px, ...) {
border: @arguments;
width: @width;
}
.arguments {
.mixin-arguments(1px, solid, black);
}
.arguments2 {
.mixin-arguments();
}
.arguments3 {
.mixin-arguments;
}
.mixin-arguments2 (@width, @rest...) {
border: @arguments;
rest: @rest;
width: @width;
}
.arguments4 {
.mixin-arguments2(0, 1, 2, 3, 4);
}
// Edge cases
.edge-case {
.mixin-arguments("{");
}

View File

@@ -0,0 +1,26 @@
.scope {
@var: 99px;
.mixin () {
width: @var;
}
}
.class {
.scope > .mixin;
}
.overwrite {
@var: 0px;
.scope > .mixin;
}
.nested {
@var: 5px;
.mixin () {
width: @var;
}
.class {
@var: 10px;
.mixin;
}
}

View File

@@ -0,0 +1,94 @@
// Stacking, functions..
.light (@a) when (lightness(@a) > 50%) {
color: white;
}
.light (@a) when (lightness(@a) < 50%) {
color: black;
}
.light (@a) {
margin: 1px;
}
.light1 { .light(#ddd) }
.light2 { .light(#444) }
// Arguments against each other
.max (@a, @b) when (@a > @b) {
width: @a;
}
.max (@a, @b) when (@a < @b) {
width: @b;
}
.max1 { .max(3, 6) }
.max2 { .max(8, 1) }
// Globals inside guards
@g: auto;
.glob (@a) when (@a = @g) {
margin: @a @g;
}
.glob1 { .glob(auto) }
// Other operators
.ops (@a) when (@a >= 0) {
height: gt-or-eq;
}
.ops (@a) when (@a =< 0) {
height: lt-or-eq;
}
.ops (@a) when not(@a = 0) {
height: not-eq;
}
.ops1 { .ops(0) }
.ops2 { .ops(1) }
.ops3 { .ops(-1) }
// Scope and default values
@a: auto;
.default (@a: inherit) when (@a = inherit) {
content: default;
}
.default1 { .default }
// true & false keywords
.test (@a) when (@a) {
content: "true.";
}
.test (@a) when not (@a) {
content: "false.";
}
.test1 { .test(true) }
.test2 { .test(false) }
.test3 { .test(1) }
.test4 { .test(boo) }
.test5 { .test("true") }
// Boolean expressions
.bool () when (true) and (false) { content: true and false } // FALSE
.bool () when (true) and (true) { content: true and true } // TRUE
.bool () when (true) { content: true } // TRUE
.bool () when (false) and (false) { content: true } // FALSE
.bool () when (false), (true) { content: false, true } // TRUE
.bool () when (false) and (true) and (true), (true) { content: false and true and true, true } // TRUE
.bool () when (true) and (true) and (false), (false) { content: true and true and false, false } // FALSE
.bool () when (false), (true) and (true) { content: false, true and true } // TRUE
.bool () when (false), (false), (true) { content: false, false, true } // TRUE
.bool () when (false), (false) and (true), (false) { content: false, false and true, false } // FALSE
.bool () when (false), (true) and (true) and (true), (false) { content: false, true and true and true, false } // TRUE
.bool () when not (false) { content: not false }
.bool () when not (true) and not (false) { content: not true and not false }
.bool () when not (true) and not (true) { content: not true and not true }
.bool () when not (false) and (false), not (false) { content: not false and false, not false }
.bool1 { .bool }

View File

@@ -0,0 +1,18 @@
.mixin (9) {
border: 9 !important;
}
.mixin (@a: 0) {
border: @a;
boxer: @a;
}
.class {
.mixin(1);
.mixin(2) !important;
.mixin(3);
.mixin(4) !important;
.mixin(5);
.mixin !important;
.mixin(9);
}

View File

@@ -0,0 +1,31 @@
.mixin (@a: 1px, @b: 50%) {
width: @a * 5;
height: @b - 1%;
}
.mixin (@a: 1px, @b: 50%) when (@b > 75%){
text-align: center;
}
.named-arg {
color: blue;
.mixin(@b: 100%);
}
.class {
@var: 20%;
.mixin(@b: @var);
}
.mixin2 (@a: 1px, @b: 50%, @c: 50) {
width: @a * 5;
height: @b - 1%;
color: #000000 + @c;
}
.named-args2 {
.mixin2(3px, @c: 100);
}
.named-args3 {
.mixin2(@b: 30%, @c: #123456);
}

View File

@@ -0,0 +1,22 @@
.mix-inner (@var) {
border-width: @var;
}
.mix (@a: 10) {
.inner {
height: @a * 10;
.innest {
width: @a;
.mix-inner(@a * 2);
}
}
}
.class {
.mix(30);
}
.class2 {
.mix(60);
}

View File

@@ -0,0 +1,99 @@
.mixin (...) {
variadic: true;
}
.mixin () {
zero: 0;
}
.mixin (@a: 1px) {
one: 1;
}
.mixin (@a) {
one-req: 1;
}
.mixin (@a: 1px, @b: 2px) {
two: 2;
}
.mixin (@a, @b, @c) {
three-req: 3;
}
.mixin (@a: 1px, @b: 2px, @c: 3px) {
three: 3;
}
.zero {
.mixin();
}
.one {
.mixin(1);
}
.two {
.mixin(1, 2);
}
.three {
.mixin(1, 2, 3);
}
//
.mixout ('left') {
left: 1;
}
.mixout ('right') {
right: 1;
}
.left {
.mixout('left');
}
.right {
.mixout('right');
}
//
.border (@side, @width) {
color: black;
.border-side(@side, @width);
}
.border-side (left, @w) {
border-left: @w;
}
.border-side (right, @w) {
border-right: @w;
}
.border-right {
.border(right, 4px);
}
.border-left {
.border(left, 4px);
}
//
.border-radius (@r) {
both: @r * 10;
}
.border-radius (@r, left) {
left: @r;
}
.border-radius (@r, right) {
right: @r;
}
.only-right {
.border-radius(33, right);
}
.only-left {
.border-radius(33, left);
}
.left-right {
.border-radius(33);
}

View File

@@ -0,0 +1,67 @@
.mixin { border: 1px solid black; }
.mixout { border-color: orange; }
.borders { border-style: dashed; }
#namespace {
.borders {
border-style: dotted;
}
.biohazard {
content: "death";
.man {
color: transparent;
}
}
}
#theme {
> .mixin {
background-color: grey;
}
}
#container {
color: black;
.mixin;
.mixout;
#theme > .mixin;
}
#header {
.milk {
color: white;
.mixin;
#theme > .mixin;
}
#cookie {
.chips {
#namespace .borders;
.calories {
#container;
}
}
.borders;
}
}
.secure-zone { #namespace .biohazard .man; }
.direct {
#namespace > .borders;
}
.bo, .bar {
width: 100%;
}
.bo {
border: 1px;
}
.ar.bo.ca {
color: black;
}
.jo.ki {
background: none;
}
.extended {
.bo;
.jo.ki;
}
.foo .bar {
.bar;
}

View File

@@ -0,0 +1,62 @@
#operations {
color: #110000 + #000011 + #001100; // #111111
height: 10px / 2px + 6px - 1px * 2; // 9px
width: 2 * 4 - 5em; // 3em
.spacing {
height: 10px / 2px+6px-1px*2;
width: 2 * 4-5em;
}
substraction: 20 - 10 - 5 - 5; // 0
division: 20 / 5 / 4; // 1
}
@x: 4;
@y: 12em;
.with-variables {
height: @x + @y; // 16em
width: 12 + @y; // 24em
size: 5cm - @x; // 1cm
}
.with-functions {
color: rgb(200, 200, 200) / 2;
color: 2 * hsl(0, 50%, 50%);
color: rgb(10, 10, 10) + hsl(0, 50%, 50%);
}
@z: -2;
.negative {
height: 2px + @z; // 0px
width: 2px - @z; // 4px
}
.shorthands {
padding: -1px 2px 0 -4px; //
}
.rem-dimensions {
font-size: 20rem / 5 + 1.5rem; // 5.5rem
}
.colors {
color: #123; // #112233
border-color: #234 + #111111; // #334455
background-color: #222222 - #fff; // #000000
.other {
color: 2 * #111; // #222222
border-color: #333333 / 3 + #111; // #222222
}
}
.negations {
@var: 4px;
variable: -@var; // 4
variable1: -@var + @var; // 0
variable2: @var + -@var; // 0
variable3: @var - -@var; // 8
variable4: -@var - -@var; // 0
paren: -(@var); // -4px
paren2: -(2 + 2) * -@var; // 16
}

View File

@@ -0,0 +1,26 @@
.parens {
@var: 1px;
border: (@var * 2) solid black;
margin: (@var * 1) (@var + 2) (4 * 4) 3;
width: (6 * 6);
padding: 2px (6px * 6px);
}
.more-parens {
@var: (2 * 2);
padding: (2 * @var) 4 4 (@var * 1px);
width: (@var * @var) * 6;
height: (7 * 7) + (8 * 8);
margin: 4 * (5 + 5) / 2 - (@var * 2);
//margin: (6 * 6)px;
}
.nested-parens {
width: 2 * (4 * (2 + (1 + 6))) - 1;
height: ((2+3)*(2+3) / (9-4)) + 1;
}
.mixed-units {
margin: 2px 4em 1 5pc;
padding: (2px + 4px) 1em 2px 2;
}

View File

@@ -0,0 +1,30 @@
#first > .one {
> #second .two > #deux {
width: 50%;
#third {
&:focus {
color: black;
#fifth {
> #sixth {
.seventh #eighth {
+ #ninth {
color: purple;
}
}
}
}
}
height: 100%;
}
#fourth, #five, #six {
color: #110000;
.seven, .eight > #nine {
border: 1px solid black;
}
#ten {
color: red;
}
}
}
font-size: 2em;
}

View File

@@ -0,0 +1,32 @@
@x: blue;
@z: transparent;
@mix: none;
.mixin {
@mix: #989;
}
.tiny-scope {
color: @mix; // #989
.mixin;
}
.scope1 {
@y: orange;
@z: black;
color: @x; // blue
border-color: @z; // black
.hidden {
@x: #131313;
}
.scope2 {
@y: red;
color: @x; // blue
.scope3 {
@local: white;
color: @y; // red
border-color: @z; // black
background-color: @local; // white
}
}
}

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