Skip to content

Commit

Permalink
Fixes less#1880 - Adds two new math modes and deprecates strictMath
Browse files Browse the repository at this point in the history
  • Loading branch information
matthew-dean committed Jul 7, 2018
1 parent d5f669e commit 76c1034
Show file tree
Hide file tree
Showing 42 changed files with 1,410 additions and 46 deletions.
12 changes: 11 additions & 1 deletion bin/lessc
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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':
Expand Down
4 changes: 1 addition & 3 deletions lib/less-browser/add-default-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
13 changes: 10 additions & 3 deletions lib/less-node/lessc-helper.js
Original file line number Diff line number Diff line change
Expand Up @@ -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.');
Expand All @@ -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\'');
Expand Down
7 changes: 4 additions & 3 deletions lib/less/contexts.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
var contexts = {};
module.exports = contexts;
var MATH = require('./math-constants');

var copyFromOriginal = function copyFromOriginal(original, destination, propertiesToCopy) {
if (!original) { return; }
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
9 changes: 7 additions & 2 deletions lib/less/default-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
6 changes: 6 additions & 0 deletions lib/less/math-constants.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
module.exports = {
ALWAYS: 0,
PARENS_DIVISION: 1,
PARENS_ALL: 2,
STRICT_LEGACY: 3
};
4 changes: 2 additions & 2 deletions lib/less/parse.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 2 additions & 2 deletions lib/less/render.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
19 changes: 11 additions & 8 deletions lib/less/tree/declaration.js
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -41,18 +42,20 @@ 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):
name = (name.length === 1) && (name[0] instanceof Keyword) ?
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({});
Expand Down Expand Up @@ -83,8 +86,8 @@ Declaration.prototype.eval = function (context) {
throw e;
}
finally {
if (strictMathBypass) {
context.strictMath = prevMath;
if (mathBypass) {
context.math = prevMath;
}
}
};
Expand Down
10 changes: 7 additions & 3 deletions lib/less/tree/expression.js
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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();
Expand All @@ -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;
Expand Down
6 changes: 5 additions & 1 deletion lib/less/tree/operation.js
Original file line number Diff line number Diff line change
@@ -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();
Expand All @@ -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' };
}
Expand Down
24 changes: 24 additions & 0 deletions lib/less/utils.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* jshint proto: true */
var MATH = require('./math-constants');

var utils = {
getLocation: function(index, inputStream) {
var n = index + 1,
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion test/browser/runner-browser-options.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion test/browser/runner-errors-options.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var less = {
strictUnits: true,
strictMath: true,
math: 'strict-legacy',
logLevel: 4,
javascriptEnabled: true
};
2 changes: 1 addition & 1 deletion test/browser/runner-legacy-options.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
var less = {
logLevel: 4,
errorReporting: 'console',
strictMath: false,
math: 'always',
strictUnits: false
};
4 changes: 2 additions & 2 deletions test/css/calc.css
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down
File renamed without changes.
10 changes: 10 additions & 0 deletions test/css/math/parens-all/media-math.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
@media (min-width: 16 + 1) {
.foo {
bar: 1;
}
}
@media (min-width: 16 / 9) {
.foo {
bar: 1;
}
}

0 comments on commit 76c1034

Please sign in to comment.