Fixes #1880 - Adds two new math modes and deprecates strictMath

This commit is contained in:
Matthew Dean
2018-07-06 23:37:28 -07:00
parent d5f669e237
commit 76c1034533
42 changed files with 1410 additions and 46 deletions

View File

@@ -4,6 +4,7 @@ var path = require('path'),
fs = require('../lib/less-node/fs'),
os = require('os'),
utils = require('../lib/less/utils'),
MATH = require('../lib/less/math-constants'),
errno,
mkdirp;
@@ -481,8 +482,17 @@ function processPluginQueue() {
break;
case 'sm':
case 'strict-math':
console.warning('Strict math is deprecated. Use --math');
if (checkArgFunc(arg, match[2])) {
options.strictMath = checkBooleanArg(match[2]);
if (checkBooleanArg(match[2])) {
options.math = MATH.STRICT_LEGACY;
}
}
break;
case 'm':
case 'math':
if (checkArgFunc(arg, match[2])) {
options.math = match[2];
}
break;
case 'su':

View File

@@ -43,7 +43,5 @@ module.exports = function(window, options) {
options.onReady = true;
}
// TODO: deprecate and remove 'inlineJavaScript' thing - where it came from at all?
options.javascriptEnabled = (options.javascriptEnabled || options.inlineJavaScript) ? true : false;
options.javascriptEnabled = options.javascriptEnabled ? true : false;
};

View File

@@ -48,9 +48,13 @@ var lessc_helper = {
console.log(' -rp, --rootpath=URL Sets rootpath for url rewriting in relative imports and urls');
console.log(' Works with or without the relative-urls option.');
console.log(' -ru, --relative-urls Re-writes relative urls to the base less file.');
console.log(' -sm=on|off Turns on or off strict math, where in strict mode, math.');
console.log(' --strict-math=on|off Requires brackets. This option may default to on and then');
console.log(' be removed in the future.');
console.log('');
console.log(' -m=, --math=');
console.log(' always Less will eagerly perform math operations always.');
console.log(' parens-division Math performed except for division (/) operator');
console.log(' parens-all Math only performed inside parentheses');
console.log(' strict-legacy Parens required in very strict terms (legacy --strict-math)');
console.log('');
console.log(' -su=on|off Allows mixed units, e.g. 1px+1em or 1px*1px which have units');
console.log(' --strict-units=on|off that cannot be represented.');
console.log(' --global-var=\'VAR=VALUE\' Defines a variable that can be referenced by the file.');
@@ -64,6 +68,9 @@ var lessc_helper = {
console.log(' or --clean-css="advanced"');
console.log('');
console.log('-------------------------- Deprecated ----------------');
console.log(' -sm=on|off Legacy parens-only math. Use --math');
console.log(' --strict-math=on|off ');
console.log('');
console.log(' --line-numbers=TYPE Outputs filename and line numbers.');
console.log(' TYPE can be either \'comments\', which will output');
console.log(' the debug info within comments, \'mediaquery\'');

View File

@@ -1,5 +1,6 @@
var contexts = {};
module.exports = contexts;
var MATH = require('./math-constants');
var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
if (!original) { return; }
@@ -43,7 +44,7 @@ var evalCopyProperties = [
'paths', // additional include paths
'compress', // whether to compress
'ieCompat', // whether to enforce IE compatibility (IE8 data-uri)
'strictMath', // whether math has to be within parenthesis
'math', // whether math has to be within parenthesis
'strictUnits', // whether units need to evaluate correctly
'sourceMap', // whether to output a source map
'importMultiple', // whether we are currently importing multiple copies
@@ -94,10 +95,10 @@ contexts.Eval.prototype.isMathOn = function (op) {
if (!this.mathOn) {
return false;
}
if (op === '/' && this.strictMath && (!this.parensStack || !this.parensStack.length)) {
if (op === '/' && this.math !== MATH.ALWAYS && (!this.parensStack || !this.parensStack.length)) {
return false;
}
if (this.strictMath === true) {
if (this.math > MATH.PARENS_DIVISION) {
return this.parensStack && this.parensStack.length;
}
return true;

View File

@@ -44,8 +44,13 @@ module.exports = function() {
/* Compatibility with IE8. Used for limiting data-uri length */
ieCompat: false, // true until 3.0
/* Without this option on, Less will try and process all math in your css */
strictMath: false,
/* How to process math
* 0 always - eagerly try to solve all operations
* 1 parens-division - require parens for division "/"
* 2 parens-all - require parens for all operations
* 3 strict-legacy - legacy strict behavior (super-strict)
*/
math: 0,
/* Without this option, less attempts to guess at the output unit when it does maths. */
strictUnits: false,

View File

@@ -0,0 +1,6 @@
module.exports = {
ALWAYS: 0,
PARENS_DIVISION: 1,
PARENS_ALL: 2,
STRICT_LEGACY: 3
};

View File

@@ -10,10 +10,10 @@ module.exports = function(environment, ParseTree, ImportManager) {
if (typeof options === 'function') {
callback = options;
options = utils.defaults(this.options, {});
options = utils.copyOptions(this.options, {});
}
else {
options = utils.defaults(this.options, options || {});
options = utils.copyOptions(this.options, options || {});
}
if (!callback) {

View File

@@ -5,10 +5,10 @@ module.exports = function(environment, ParseTree, ImportManager) {
var render = function (input, options, callback) {
if (typeof options === 'function') {
callback = options;
options = utils.defaults(this.options, {});
options = utils.copyOptions(this.options, {});
}
else {
options = utils.defaults(this.options, options || {});
options = utils.copyOptions(this.options, options || {});
}
if (!callback) {

View File

@@ -1,7 +1,8 @@
var Node = require('./node'),
Value = require('./value'),
Keyword = require('./keyword'),
Anonymous = require('./anonymous');
Anonymous = require('./anonymous'),
MATH = require('../math-constants');
var Declaration = function (name, value, important, merge, index, currentFileInfo, inline, variable) {
this.name = name;
@@ -41,7 +42,7 @@ Declaration.prototype.genCSS = function (context, output) {
output.add(this.important + ((this.inline || (context.lastRule && context.compress)) ? '' : ';'), this._fileInfo, this._index);
};
Declaration.prototype.eval = function (context) {
var strictMathBypass = false, prevMath, name = this.name, evaldValue, variable = this.variable;
var mathBypass = false, prevMath, name = this.name, evaldValue, variable = this.variable;
if (typeof name !== 'string') {
// expand 'primitive' name directly to get
// things faster (~10% for benchmark.less):
@@ -49,10 +50,12 @@ Declaration.prototype.eval = function (context) {
name[0].value : evalName(context, name);
variable = false; // never treat expanded interpolation as new variable name
}
if (name === 'font' && !context.strictMath) {
strictMathBypass = true;
prevMath = context.strictMath;
context.strictMath = 'division';
// @todo remove when parens-division is default
if (name === 'font' && context.math === MATH.ALWAYS) {
mathBypass = true;
prevMath = context.math;
context.math = MATH.PARENS_DIVISION;
}
try {
context.importantScope.push({});
@@ -83,8 +86,8 @@ Declaration.prototype.eval = function (context) {
throw e;
}
finally {
if (strictMathBypass) {
context.strictMath = prevMath;
if (mathBypass) {
context.math = prevMath;
}
}
};

View File

@@ -1,6 +1,8 @@
var Node = require('./node'),
Paren = require('./paren'),
Comment = require('./comment');
Comment = require('./comment'),
Dimension = require('./dimension'),
MATH = require('../math-constants');
var Expression = function (value, noSpacing) {
this.value = value;
@@ -17,7 +19,8 @@ Expression.prototype.accept = function (visitor) {
Expression.prototype.eval = function (context) {
var returnValue,
mathOn = context.isMathOn(),
inParenthesis = this.parens && !this.parensInOp,
inParenthesis = this.parens &&
(context.math !== MATH.STRICT_LEGACY || !this.parensInOp),
doubleParen = false;
if (inParenthesis) {
context.inParenthesis();
@@ -40,7 +43,8 @@ Expression.prototype.eval = function (context) {
if (inParenthesis) {
context.outOfParenthesis();
}
if (this.parens && this.parensInOp && !mathOn && !doubleParen) {
if (this.parens && this.parensInOp && !mathOn && !doubleParen
&& (!(returnValue instanceof Dimension))) {
returnValue = new Paren(returnValue);
}
return returnValue;

View File

@@ -1,6 +1,7 @@
var Node = require('./node'),
Color = require('./color'),
Dimension = require('./dimension');
Dimension = require('./dimension'),
MATH = require('../math-constants');
var Operation = function (op, operands, isSpaced) {
this.op = op.trim();
@@ -26,6 +27,9 @@ Operation.prototype.eval = function (context) {
b = b.toColor();
}
if (!a.operate) {
if (a instanceof Operation && a.op === '/' && context.math === MATH.PARENS_DIVISION) {
return new Operation(this.op, [a, b], this.isSpaced);
}
throw { type: 'Operation',
message: 'Operation on an invalid type' };
}

View File

@@ -1,4 +1,6 @@
/* jshint proto: true */
var MATH = require('./math-constants');
var utils = {
getLocation: function(index, inputStream) {
var n = index + 1,
@@ -36,6 +38,28 @@ var utils = {
}
return cloned;
},
copyOptions: function(obj1, obj2) {
var opts = utils.defaults(obj1, obj2);
if (opts.strictMath) {
opts.math = MATH.STRICT_LEGACY;
}
if (opts.hasOwnProperty('math') && typeof opts.math === 'string') {
switch (opts.math.toLowerCase()) {
case 'always':
opts.math = MATH.ALWAYS;
break;
case 'parens-division':
opts.math = MATH.PARENS_DIVISION;
break;
case 'parens-all':
opts.math = MATH.PARENS_ALL;
break;
case 'strict-legacy':
opts.math = MATH.STRICT_LEGACY;
}
}
return opts;
},
defaults: function(obj1, obj2) {
if (!obj2._defaults || obj2._defaults !== obj1) {
for (var prop in obj1) {

View File

@@ -2,7 +2,7 @@ var less = {
logLevel: 4,
errorReporting: 'console',
javascriptEnabled: true,
strictMath: false
math: 'always'
};
// There originally run inside describe method. However, since they have not

View File

@@ -1,6 +1,6 @@
var less = {
strictUnits: true,
strictMath: true,
math: 'strict-legacy',
logLevel: 4,
javascriptEnabled: true
};

View File

@@ -1,6 +1,6 @@
var less = {
logLevel: 4,
errorReporting: 'console',
strictMath: false,
math: 'always',
strictUnits: false
};

View File

@@ -3,12 +3,12 @@
root2: calc(100% - 40px);
width: calc(50% + (25vh - 20px));
height: calc(50% + (25vh - 20px));
min-height: calc((10vh) + calc(5vh));
min-height: calc(10vh + calc(5vh));
foo: 3 calc(3 + 4) 11;
bar: calc(1 + 20%);
}
.b {
one: calc(100% - (20px));
one: calc(100% - 20px);
two: calc(100% - (10px + 10px));
three: calc(100% - (3 * 1));
four: calc(100% - (3 * 1));

View File

@@ -0,0 +1,10 @@
@media (min-width: 16 + 1) {
.foo {
bar: 1;
}
}
@media (min-width: 16 / 9) {
.foo {
bar: 1;
}
}

View File

@@ -0,0 +1,169 @@
#hidden {
color: transparent;
}
#hidden1 {
color: transparent;
}
.two-args {
color: blue;
width: 10px;
height: 99%;
depth: 100% - 1%;
border: 2px dotted black;
}
.one-arg {
width: 15px;
height: 49%;
depth: 50% - 1%;
}
.no-parens {
width: 5px;
height: 49%;
depth: 50% - 1%;
}
.no-args {
width: 5px;
height: 49%;
depth: 50% - 1%;
}
.var-args {
width: 45;
height: 8%;
depth: 18 / 2 - 1%;
}
.multi-mix {
width: 10px;
height: 29%;
depth: 30% - 1%;
margin: 4;
padding: 5;
}
body {
padding: 30px;
color: #f00;
}
.scope-mix {
width: 8;
}
.content {
width: 600px;
}
.content .column {
margin: 600px;
}
#same-var-name {
radius: 5px;
}
#var-inside {
width: 10px;
}
.arguments {
border: 1px solid black;
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: "{";
}
.slash-vs-math {
border-radius: 2px/5px;
border-radius: 5px/10px;
border-radius: 6px;
}
.comma-vs-semi-colon {
one: a;
two: b, c;
one: d, e;
two: f;
one: g;
one: h;
one: i;
one: j;
one: k;
two: l;
one: m, n;
one: o, p;
two: q;
one: r, s;
two: t;
}
#named-conflict {
four: a, 11, 12, 13;
four: a, 21, 22, 23;
}
.test-mixin-default-arg {
defaults: 1px 1px 1px;
defaults: 2px 2px 2px;
}
.selector {
margin: 2, 2, 2, 2;
}
.selector2 {
margin: 2, 2, 2, 2;
}
.selector3 {
margin: 4;
}
mixins-args-expand-op-1 {
m3: 1, 2, 3;
}
mixins-args-expand-op-2 {
m3: 4, 5, 6;
}
mixins-args-expand-op-3a {
m3: a, b, c;
}
mixins-args-expand-op-3b {
m4: 0, a, b, c;
}
mixins-args-expand-op-3c {
m4: a, b, c, 4;
}
mixins-args-expand-op-4a {
m3: a, b, c, d;
}
mixins-args-expand-op-4b {
m4: 0, a, b, c, d;
}
mixins-args-expand-op-4c {
m4: a, b, c, d, 4;
}
mixins-args-expand-op-5a {
m3: 1, 2, 3;
}
mixins-args-expand-op-5b {
m4: 0, 1, 2, 3;
}
mixins-args-expand-op-5c {
m4: 1, 2, 3, 4;
}
mixins-args-expand-op-6 {
m4: 0, 1, 2, 3;
}
mixins-args-expand-op-7 {
m4: 0, 1, 2, 3;
}
mixins-args-expand-op-8 {
m4: 1, 1.5, 2, 3;
}
mixins-args-expand-op-9 {
aa: 4 5 6 1 2 3 and again 4 5 6;
a4: and;
a8: 5;
}
#test-mixin-matching-when-default-2645 {
height: 20px;
}

View File

@@ -0,0 +1,37 @@
.parens {
border: 2px solid black;
margin: 1px 3px 16 3;
width: 36;
padding: 2px 36px;
}
.more-parens {
padding: 8 4 4 4px;
width-all: 96;
width-first: 16 * 6;
width-keep: 16 * 6;
height: calc(100% + (25vh - 20px));
height-keep: 49 + 64;
height-all: 113;
height-parts: 49 + 64;
margin-keep: 20 - 8;
margin-parts: 20 - 8;
margin-all: 12;
border-radius-keep: 4px * 2 / 4 + 3px;
border-radius-parts: 8px / 7px;
border-radius-all: 5px;
}
.negative {
neg-var: -1;
neg-var-paren: -1;
}
.nested-parens {
width: 2 * 36 - 1;
height: 5 + 1;
}
.mixed-units {
margin: 2px 4em 1 5pc;
padding: 6px 1em 2px 2;
}
.test-false-negatives {
a: (;
}

View File

@@ -0,0 +1,10 @@
@media (min-width: 17) {
.foo {
bar: 1;
}
}
@media (min-width: 16 / 9) {
.foo {
bar: 1;
}
}

View File

@@ -0,0 +1,169 @@
#hidden {
color: transparent;
}
#hidden1 {
color: transparent;
}
.two-args {
color: blue;
width: 10px;
height: 99%;
depth: 99%;
border: 2px dotted black;
}
.one-arg {
width: 15px;
height: 49%;
depth: 49%;
}
.no-parens {
width: 5px;
height: 49%;
depth: 49%;
}
.no-args {
width: 5px;
height: 49%;
depth: 49%;
}
.var-args {
width: 45;
height: 8%;
depth: 18 / 2 - 1%;
}
.multi-mix {
width: 10px;
height: 29%;
depth: 29%;
margin: 4;
padding: 5;
}
body {
padding: 30px;
color: #f00;
}
.scope-mix {
width: 8;
}
.content {
width: 600px;
}
.content .column {
margin: 600px;
}
#same-var-name {
radius: 5px;
}
#var-inside {
width: 10px;
}
.arguments {
border: 1px solid black;
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: "{";
}
.slash-vs-math {
border-radius: 2px/5px;
border-radius: 5px/10px;
border-radius: 6px;
}
.comma-vs-semi-colon {
one: a;
two: b, c;
one: d, e;
two: f;
one: g;
one: h;
one: i;
one: j;
one: k;
two: l;
one: m, n;
one: o, p;
two: q;
one: r, s;
two: t;
}
#named-conflict {
four: a, 11, 12, 13;
four: a, 21, 22, 23;
}
.test-mixin-default-arg {
defaults: 1px 1px 1px;
defaults: 2px 2px 2px;
}
.selector {
margin: 2, 2, 2, 2;
}
.selector2 {
margin: 2, 2, 2, 2;
}
.selector3 {
margin: 4;
}
mixins-args-expand-op-1 {
m3: 1, 2, 3;
}
mixins-args-expand-op-2 {
m3: 4, 5, 6;
}
mixins-args-expand-op-3a {
m3: a, b, c;
}
mixins-args-expand-op-3b {
m4: 0, a, b, c;
}
mixins-args-expand-op-3c {
m4: a, b, c, 4;
}
mixins-args-expand-op-4a {
m3: a, b, c, d;
}
mixins-args-expand-op-4b {
m4: 0, a, b, c, d;
}
mixins-args-expand-op-4c {
m4: a, b, c, d, 4;
}
mixins-args-expand-op-5a {
m3: 1, 2, 3;
}
mixins-args-expand-op-5b {
m4: 0, 1, 2, 3;
}
mixins-args-expand-op-5c {
m4: 1, 2, 3, 4;
}
mixins-args-expand-op-6 {
m4: 0, 1, 2, 3;
}
mixins-args-expand-op-7 {
m4: 0, 1, 2, 3;
}
mixins-args-expand-op-8 {
m4: 1, 1.5, 2, 3;
}
mixins-args-expand-op-9 {
aa: 4 5 6 1 2 3 and again 4 5 6;
a4: and;
a8: 5;
}
#test-mixin-matching-when-default-2645 {
height: 20px;
}

View File

@@ -10,4 +10,7 @@
a: 2;
b: 2px / 2;
c: 1px;
d: 1px;
e: 4px / 2;
f: 2px;
}

View File

@@ -0,0 +1,37 @@
.parens {
border: 2px solid black;
margin: 1px 3px 16 3;
width: 36;
padding: 2px 36px;
}
.more-parens {
padding: 8 4 4 4px;
width-all: 96;
width-first: 96;
width-keep: 96;
height: calc(100% + (25vh - 20px));
height-keep: 113;
height-all: 113;
height-parts: 113;
margin-keep: 12;
margin-parts: 12;
margin-all: 12;
border-radius-keep: 8px / 4 + 3px;
border-radius-parts: 8px / 7px;
border-radius-all: 5px;
}
.negative {
neg-var: -1;
neg-var-paren: -1;
}
.nested-parens {
width: 71;
height: 6;
}
.mixed-units {
margin: 2px 4em 1 5pc;
padding: 6px 1em 2px 2;
}
.test-false-negatives {
a: (;
}

View File

@@ -0,0 +1,95 @@
@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';
}
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;
}
#more-shorthands {
margin: 0;
padding: 1px 0 2px 0;
font: normal small / 20px 'Trebuchet MS', Verdana, sans-serif;
font: 0/0 a;
border-radius: 5px / 10px;
}
.misc {
-moz-border-radius: 2px;
display: -moz-inline-stack;
width: 0.1em;
background-color: #009998;
background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
margin: ;
filter: alpha(opacity=100);
width: auto\9;
}
.misc .nested-multiple {
multiple-semi-colons: yes;
}
#important {
color: red !important;
width: 100%!important;
height: 20px ! important;
}
@font-face {
font-family: font-a;
}
@font-face {
font-family: font-b;
}
.æøå {
margin: 0;
}

View File

@@ -0,0 +1,10 @@
@media (min-width: 16 + 1) {
.foo {
bar: 1;
}
}
@media (min-width: 16 / 9) {
.foo {
bar: 1;
}
}

View File

@@ -4,11 +4,15 @@
width: 36;
padding: 2px 36px;
}
.in-function {
value: 2 + 1;
}
.more-parens {
padding: 8 4 4 4px;
width-all: 96;
width-first: 16 * 6;
width-keep: (4 * 4) * 6;
height: calc(100% + (25vh - 20px));
height-keep: (7 * 7) + (8 * 8);
height-all: 113;
height-parts: 49 + 64;
@@ -21,7 +25,7 @@
}
.negative {
neg-var: -1;
neg-var-paren: -(1);
neg-var-paren: -1;
}
.nested-parens {
width: 2 * (4 * (2 + (1 + 6))) - 1;

View File

@@ -17,18 +17,16 @@ var testMap = [
ieCompat: true
}],
[{
strictMath: true,
math: 'strict-legacy',
ieCompat: true
<<<<<<< HEAD
}, "strict-math/"],
}, 'math/strict-legacy/'],
[{
strictMath: 'division'
}, "strict-math-division/"],
[{strictMath: true, strictUnits: true, javascriptEnabled: true}, "errors/",
=======
}, 'strict-math/'],
math: 'parens-all'
}, 'math/parens-all/'],
[{
math: 'parens-division'
}, 'math/parens-division/'],
[{strictMath: true, strictUnits: true, javascriptEnabled: true}, 'errors/',
>>>>>>> master
lessTester.testErrors, null],
[{strictMath: true, strictUnits: true, javascriptEnabled: false}, 'no-js-errors/',
lessTester.testErrors, null],
@@ -69,7 +67,7 @@ testMap.forEach(function(args) {
lessTester.runTestSet.apply(lessTester, args)
});
lessTester.testSyncronous({syncImport: true}, 'import');
lessTester.testSyncronous({syncImport: true}, 'strict-math/css');
lessTester.testSyncronous({syncImport: true}, 'math/strict-legacy/css');
lessTester.testNoOptions();
lessTester.testJSImport();
lessTester.finished();

View File

@@ -265,7 +265,7 @@ html {
}, {});
@conditional();
@falsey: if((@undefined), {
@falsey: if((false), {
color: orange;
}, {
color: purple;

View File

@@ -0,0 +1,9 @@
@var: 16;
@media (min-width: @var + 1) {
.foo { bar: 1; }
}
@media (min-width: @var / 9) {
.foo { bar: 1; }
}

View File

@@ -0,0 +1,264 @@
.mixin (@a: 1px, @b: 50%) {
width: (@a * 5);
height: (@b - 1%);
depth: @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) / 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("{");
}
// Division vs. Literal Slash
.border-radius(@r: 2px/5px) {
border-radius: @r;
}
.slash-vs-math {
.border-radius();
.border-radius(5px/10px);
.border-radius((3px * 2));
}
// semi-colon vs comma for delimiting
.mixin-takes-one(@a) {
one: @a;
}
.mixin-takes-two(@a; @b) {
one: @a;
two: @b;
}
.comma-vs-semi-colon {
.mixin-takes-two(@a : a; @b : b, c);
.mixin-takes-two(@a : d, e; @b : f);
.mixin-takes-one(@a: g);
.mixin-takes-one(@a : h;);
.mixin-takes-one(i);
.mixin-takes-one(j;);
.mixin-takes-two(k, l);
.mixin-takes-one(m, n;);
.mixin-takes-two(o, p; q);
.mixin-takes-two(r, s; t;);
}
.mixin-conflict(@a:defA, @b:defB, @c:defC) {
three: @a, @b, @c;
}
.mixin-conflict(@a:defA, @b:defB, @c:defC, @d:defD) {
four: @a, @b, @c, @d;
}
#named-conflict {
.mixin-conflict(11, 12, 13, @a:a);
.mixin-conflict(@a:a, 21, 22, 23);
}
@a: 3px;
.mixin-default-arg(@a: 1px, @b: @a, @c: @b) {
defaults: 1px 1px 1px;
defaults: 2px 2px 2px;
}
.test-mixin-default-arg {
.mixin-default-arg();
.mixin-default-arg(2px);
}
.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) {
margin: @margin;
}
.selector {
.mixin-comma-default1(#33acfe; 4);
}
.mixin-comma-default2(@margin: 2, 2, 2, 2;) {
margin: @margin;
}
.selector2 {
.mixin-comma-default2();
}
.mixin-comma-default3(@margin: 2, 2, 2, 2) {
margin: @margin;
}
.selector3 {
.mixin-comma-default3(4,2,2,2);
}
.test-calling-one-arg-mixin(@a) {
}
.test-calling-one-arg-mixin(@a, @b, @rest...) {
}
div {
.test-calling-one-arg-mixin(1);
}
mixins-args-expand-op- {
@x: 1, 2, 3;
@y: 4 5 6;
&1 {.m3(@x...)}
&2 {.m3(@y...)}
&3 {.wr(a, b, c)}
&4 {.wr(a; b; c, d)}
&5 {.wr(@x...)}
&6 {.m4(0; @x...)}
&7 {.m4(@x..., @a: 0)}
&8 {.m4(@b: 1.5; @x...)}
&9 {.aa(@y, @x..., and again, @y...)}
.m3(@a, @b, @c) {
m3: @a, @b, @c;
}
.m4(@a, @b, @c, @d) {
m4: @a, @b, @c, @d;
}
.wr(@a...) {
&a {.m3(@a...)}
&b {.m4(0, @a...)}
&c {.m4(@a..., 4)}
}
.aa(@a...) {
aa: @a;
a4: extract(@a, 5);
a8: extract(@a, 8);
}
}
#test-mixin-matching-when-default-2645 {
.mixin(@height) {
height: @height;
}
.mixin(@width, @height: 10px) {
width: @width;
.mixin(@height: @height);
}
.mixin(@height: 20px);
}

View File

@@ -12,6 +12,7 @@
width-all: ((@var * @var) * 6);
width-first: ((@var * @var)) * 6;
width-keep: (@var * @var) * 6;
height: calc(100% + (25vh - 20px));
height-keep: (7 * 7) + (8 * 8);
height-all: ((7 * 7) + (8 * 8));
height-parts: ((7 * 7)) + ((8 * 8));
@@ -21,7 +22,7 @@
border-radius-keep: 4px * (1 + 1) / @var + 3px;
border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px));
border-radius-all: (4px * (1 + 1) / @var + 3px);
//margin: (6 * 6)px;
// margin: (6 * 6)px;
}
.negative {

View File

@@ -0,0 +1,9 @@
@var: 16;
@media (min-width: @var + 1) {
.foo { bar: 1; }
}
@media (min-width: @var / 9) {
.foo { bar: 1; }
}

View File

@@ -0,0 +1,264 @@
.mixin (@a: 1px, @b: 50%) {
width: (@a * 5);
height: (@b - 1%);
depth: @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) / 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("{");
}
// Division vs. Literal Slash
.border-radius(@r: 2px/5px) {
border-radius: @r;
}
.slash-vs-math {
.border-radius();
.border-radius(5px/10px);
.border-radius((3px * 2));
}
// semi-colon vs comma for delimiting
.mixin-takes-one(@a) {
one: @a;
}
.mixin-takes-two(@a; @b) {
one: @a;
two: @b;
}
.comma-vs-semi-colon {
.mixin-takes-two(@a : a; @b : b, c);
.mixin-takes-two(@a : d, e; @b : f);
.mixin-takes-one(@a: g);
.mixin-takes-one(@a : h;);
.mixin-takes-one(i);
.mixin-takes-one(j;);
.mixin-takes-two(k, l);
.mixin-takes-one(m, n;);
.mixin-takes-two(o, p; q);
.mixin-takes-two(r, s; t;);
}
.mixin-conflict(@a:defA, @b:defB, @c:defC) {
three: @a, @b, @c;
}
.mixin-conflict(@a:defA, @b:defB, @c:defC, @d:defD) {
four: @a, @b, @c, @d;
}
#named-conflict {
.mixin-conflict(11, 12, 13, @a:a);
.mixin-conflict(@a:a, 21, 22, 23);
}
@a: 3px;
.mixin-default-arg(@a: 1px, @b: @a, @c: @b) {
defaults: 1px 1px 1px;
defaults: 2px 2px 2px;
}
.test-mixin-default-arg {
.mixin-default-arg();
.mixin-default-arg(2px);
}
.mixin-comma-default1(@color; @padding; @margin: 2, 2, 2, 2) {
margin: @margin;
}
.selector {
.mixin-comma-default1(#33acfe; 4);
}
.mixin-comma-default2(@margin: 2, 2, 2, 2;) {
margin: @margin;
}
.selector2 {
.mixin-comma-default2();
}
.mixin-comma-default3(@margin: 2, 2, 2, 2) {
margin: @margin;
}
.selector3 {
.mixin-comma-default3(4,2,2,2);
}
.test-calling-one-arg-mixin(@a) {
}
.test-calling-one-arg-mixin(@a, @b, @rest...) {
}
div {
.test-calling-one-arg-mixin(1);
}
mixins-args-expand-op- {
@x: 1, 2, 3;
@y: 4 5 6;
&1 {.m3(@x...)}
&2 {.m3(@y...)}
&3 {.wr(a, b, c)}
&4 {.wr(a; b; c, d)}
&5 {.wr(@x...)}
&6 {.m4(0; @x...)}
&7 {.m4(@x..., @a: 0)}
&8 {.m4(@b: 1.5; @x...)}
&9 {.aa(@y, @x..., and again, @y...)}
.m3(@a, @b, @c) {
m3: @a, @b, @c;
}
.m4(@a, @b, @c, @d) {
m4: @a, @b, @c, @d;
}
.wr(@a...) {
&a {.m3(@a...)}
&b {.m4(0, @a...)}
&c {.m4(@a..., 4)}
}
.aa(@a...) {
aa: @a;
a4: extract(@a, 5);
a8: extract(@a, 8);
}
}
#test-mixin-matching-when-default-2645 {
.mixin(@height) {
height: @height;
}
.mixin(@width, @height: 10px) {
width: @width;
.mixin(@height: @height);
}
.mixin(@height: 20px);
}

View File

@@ -0,0 +1,46 @@
.parens {
@var: 1px;
border: (@var * 2) solid black;
margin: (@var * 1) (@var + 2) (4 * 4) 3;
width: (6 * 6);
padding: 2px (6 * 6px);
}
.more-parens {
@var: (2 * 2);
padding: (2 * @var) 4 4 (@var * 1px);
width-all: ((@var * @var) * 6);
width-first: ((@var * @var)) * 6;
width-keep: (@var * @var) * 6;
height: calc(100% + (25vh - 20px));
height-keep: (7 * 7) + (8 * 8);
height-all: ((7 * 7) + (8 * 8));
height-parts: ((7 * 7)) + ((8 * 8));
margin-keep: (4 * (5 + 5) / 2) - (@var * 2);
margin-parts: ((4 * (5 + 5) / 2)) - ((@var * 2));
margin-all: ((4 * (5 + 5) / 2) + (-(@var * 2)));
border-radius-keep: 4px * (1 + 1) / @var + 3px;
border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px));
border-radius-all: (4px * (1 + 1) / @var + 3px);
// margin: (6 * 6)px;
}
.negative {
@var: 1;
neg-var: -@var; // -1 ?
neg-var-paren: -(@var); // -(1) ?
}
.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;
}
.test-false-negatives {
a: ~"(";
}

View File

@@ -0,0 +1,108 @@
@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';
}
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;
}
#more-shorthands {
margin: 0;
padding: 1px 0 2px 0;
font: normal small/20px 'Trebuchet MS', Verdana, sans-serif;
font: 0/0 a;
border-radius: 5px / 10px;
}
.misc {
-moz-border-radius: 2px;
display: -moz-inline-stack;
width: .1em;
background-color: #009998;
background: -webkit-gradient(linear, left top, left bottom, from(red), to(blue));
margin: ;
.nested-multiple {
multiple-semi-colons: yes;;;;;;
};
filter: alpha(opacity=100);
width: auto\9;
}
#important {
color: red !important;
width: 100%!important;
height: 20px ! important;
}
.def-font(@name) {
@font-face {
font-family: @name
}
}
.def-font(font-a);
.def-font(font-b);
.æøå {
margin: 0;
}

View File

@@ -0,0 +1,9 @@
@var: 16;
@media (min-width: @var + 1) {
.foo { bar: 1; }
}
@media (min-width: @var / 9) {
.foo { bar: 1; }
}

View File

@@ -0,0 +1,50 @@
.parens {
@var: 1px;
border: (@var * 2) solid black;
margin: (@var * 1) (@var + 2) (4 * 4) 3;
width: (6 * 6);
padding: 2px (6 * 6px);
}
.in-function {
value: min((1 + 1)) + 1;
}
.more-parens {
@var: (2 * 2);
padding: (2 * @var) 4 4 (@var * 1px);
width-all: ((@var * @var) * 6);
width-first: ((@var * @var)) * 6;
width-keep: (@var * @var) * 6;
height: calc(100% + (25vh - 20px));
height-keep: (7 * 7) + (8 * 8);
height-all: ((7 * 7) + (8 * 8));
height-parts: ((7 * 7)) + ((8 * 8));
margin-keep: (4 * (5 + 5) / 2) - (@var * 2);
margin-parts: ((4 * (5 + 5) / 2)) - ((@var * 2));
margin-all: ((4 * (5 + 5) / 2) + (-(@var * 2)));
border-radius-keep: 4px * (1 + 1) / @var + 3px;
border-radius-parts: ((4px * (1 + 1))) / ((@var + 3px));
border-radius-all: (4px * (1 + 1) / @var + 3px);
// margin: (6 * 6)px;
}
.negative {
@var: 1;
neg-var: -@var; // -1 ?
neg-var-paren: -(@var); // -(1) ?
}
.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;
}
.test-false-negatives {
a: ~"(";
}