[Pkg-javascript-commits] [less.js] 108/285: Merge branch 'reworked-guard-comparison' of github.com:seven-phases-max/less.js into 2_0_0
Jonas Smedegaard
dr at jones.dk
Mon Oct 26 23:23:44 UTC 2015
This is an automated email from the git hooks/post-receive script.
js pushed a commit to annotated tag v2.0.0
in repository less.js.
commit cf0ac697678d49e2d898bb9d5f9f1a92f804cee9
Merge: e31442c c4e2514
Author: Luke Page <luke.a.page at gmail.com>
Date: Sat Sep 6 01:52:47 2014 +0100
Merge branch 'reworked-guard-comparison' of github.com:seven-phases-max/less.js into 2_0_0
Conflicts:
lib/less/tree.js
lib/less/tree/anonymous.js
lib/less/tree/color.js
lib/less/tree/condition.js
lib/less/tree/dimension.js
lib/less/tree/keyword.js
lib/less/tree/quoted.js
lib/less/tree/anonymous.js | 15 ++-------
lib/less/tree/color.js | 9 ++----
lib/less/tree/condition.js | 28 +++++------------
lib/less/tree/dimension.js | 37 +++++++++-------------
lib/less/tree/keyword.js | 7 -----
lib/less/tree/node.js | 39 +++++++++++++++++++++++
lib/less/tree/quoted.js | 25 ++++-----------
lib/less/tree/unit.js | 2 +-
test/css/mixins-guards.css | 74 ++++++++++++++++++++++++++++++++++++++++++++
test/less/mixins-guards.less | 43 +++++++++++++++++++++++++
10 files changed, 189 insertions(+), 90 deletions(-)
diff --cc lib/less/tree/anonymous.js
index 4c1695e,a960de6..d68d5df
--- a/lib/less/tree/anonymous.js
+++ b/lib/less/tree/anonymous.js
@@@ -7,29 -7,21 +7,18 @@@ var Anonymous = function (value, index
this.currentFileInfo = currentFileInfo;
this.rulesetLike = (typeof rulesetLike === 'undefined')? false : rulesetLike;
};
-tree.Anonymous.prototype = {
- type: "Anonymous",
- eval: function () {
- return new tree.Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike);
- },
- compare: function (other) {
- return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
- },
- isRulesetLike: function() {
- return this.rulesetLike;
- },
- genCSS: function (env, output) {
- output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
- },
- toCSS: tree.toCSS
+Anonymous.prototype = new Node();
+Anonymous.prototype.type = "Anonymous";
+Anonymous.prototype.eval = function () {
+ return new Anonymous(this.value, this.index, this.currentFileInfo, this.mapLines, this.rulesetLike);
};
- Anonymous.prototype.compare = function (x) {
- if (!x.toCSS) {
- return -1;
- }
-
- var left = this.toCSS(),
- right = x.toCSS();
-
- if (left === right) {
- return 0;
- }
--
- return left < right ? -1 : 1;
-})(require('../tree'));
++Anonymous.prototype.compare = function (other) {
++ return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
+};
+Anonymous.prototype.isRulesetLike = function() {
+ return this.rulesetLike;
+};
+Anonymous.prototype.genCSS = function (env, output) {
+ output.add(this.value, this.currentFileInfo, this.index, this.mapLines);
+};
+module.exports = Anonymous;
diff --cc lib/less/tree/color.js
index 5a51d1c,15303be..1de5809
--- a/lib/less/tree/color.js
+++ b/lib/less/tree/color.js
@@@ -25,165 -23,164 +25,162 @@@ var Color = function (rgb, a)
this.alpha = typeof(a) === 'number' ? a : 1;
};
-var transparentKeyword = "transparent";
-
-tree.Color.prototype = {
- type: "Color",
- eval: function () { return this; },
- luma: function () {
- var r = this.rgb[0] / 255,
- g = this.rgb[1] / 255,
- b = this.rgb[2] / 255;
-
- r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
- g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
- b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
-
- return 0.2126 * r + 0.7152 * g + 0.0722 * b;
- },
-
- genCSS: function (env, output) {
- output.add(this.toCSS(env));
- },
- toCSS: function (env, doNotCompress) {
- var compress = env && env.compress && !doNotCompress,
- alpha = tree.fround(env, this.alpha);
-
- // If we have some transparency, the only way to represent it
- // is via `rgba`. Otherwise, we use the hex representation,
- // which has better compatibility with older browsers.
- // Values are capped between `0` and `255`, rounded and zero-padded.
- if (alpha < 1) {
- if (alpha === 0 && this.isTransparentKeyword) {
- return transparentKeyword;
- }
- return "rgba(" + this.rgb.map(function (c) {
- return clamp(Math.round(c), 255);
- }).concat(clamp(alpha, 1))
- .join(',' + (compress ? '' : ' ')) + ")";
- } else {
- var color = this.toRGB();
-
- if (compress) {
- var splitcolor = color.split('');
-
- // Convert color to short format
- if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) {
- color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5];
- }
- }
-
- return color;
- }
- },
+Color.prototype = new Node();
+Color.prototype.type = "Color";
- //
- // 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 (env, op, other) {
- var rgb = [];
- var alpha = this.alpha * (1 - other.alpha) + other.alpha;
- for (var c = 0; c < 3; c++) {
- rgb[c] = tree.operate(env, op, this.rgb[c], other.rgb[c]);
- }
- return new(tree.Color)(rgb, alpha);
- },
-
- toRGB: function () {
- return toHex(this.rgb);
- },
-
- 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 };
- },
- //Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
- toHSV: 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, v = max;
-
- var d = max - min;
- if (max === 0) {
- s = 0;
- } else {
- s = d / max;
- }
+function clamp(v, max) {
+ return Math.min(Math.max(v, 0), max);
+}
- if (max === min) {
- h = 0;
- } else {
- 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;
+function toHex(v) {
+ return '#' + v.map(function (c) {
+ c = clamp(Math.round(c), 255);
+ return (c < 16 ? '0' : '') + c.toString(16);
+ }).join('');
+}
+
+Color.prototype.luma = function () {
+ var r = this.rgb[0] / 255,
+ g = this.rgb[1] / 255,
+ b = this.rgb[2] / 255;
+
+ r = (r <= 0.03928) ? r / 12.92 : Math.pow(((r + 0.055) / 1.055), 2.4);
+ g = (g <= 0.03928) ? g / 12.92 : Math.pow(((g + 0.055) / 1.055), 2.4);
+ b = (b <= 0.03928) ? b / 12.92 : Math.pow(((b + 0.055) / 1.055), 2.4);
+
+ return 0.2126 * r + 0.7152 * g + 0.0722 * b;
+};
+Color.prototype.genCSS = function (env, output) {
+ output.add(this.toCSS(env));
+};
+Color.prototype.toCSS = function (env, doNotCompress) {
+ var compress = env && env.compress && !doNotCompress, color, alpha;
+
+ // `keyword` is set if this color was originally
+ // converted from a named color string so we need
+ // to respect this and try to output named color too.
+ if (this.keyword) {
+ return this.keyword;
+ }
+
+ // 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.
+ alpha = this.fround(env, this.alpha);
+ if (alpha < 1) {
+ return "rgba(" + this.rgb.map(function (c) {
+ return clamp(Math.round(c), 255);
+ }).concat(clamp(alpha, 1))
+ .join(',' + (compress ? '' : ' ')) + ")";
+ }
+
+ color = this.toRGB();
+
+ if (compress) {
+ var splitcolor = color.split('');
+
+ // Convert color to short format
+ if (splitcolor[1] === splitcolor[2] && splitcolor[3] === splitcolor[4] && splitcolor[5] === splitcolor[6]) {
+ color = '#' + splitcolor[1] + splitcolor[3] + splitcolor[5];
}
- return { h: h * 360, s: s, v: v, a: a };
- },
- toARGB: function () {
- return toHex([this.alpha * 255].concat(this.rgb));
- },
- compare: function (x) {
- return (x.rgb &&
- x.rgb[0] === this.rgb[0] &&
- x.rgb[1] === this.rgb[1] &&
- x.rgb[2] === this.rgb[2] &&
- x.alpha === this.alpha) ? 0 : undefined;
}
-};
-tree.Color.fromKeyword = function(keyword) {
- keyword = keyword.toLowerCase();
+ return color;
+};
- if (tree.colors.hasOwnProperty(keyword)) {
- // detect named color
- return new(tree.Color)(tree.colors[keyword].slice(1));
+//
+// 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.
+//
+Color.prototype.operate = function (env, op, other) {
+ var rgb = [];
+ var alpha = this.alpha * (1 - other.alpha) + other.alpha;
+ for (var c = 0; c < 3; c++) {
+ rgb[c] = this._operate(env, op, this.rgb[c], other.rgb[c]);
}
- if (keyword === transparentKeyword) {
- var transparent = new(tree.Color)([0, 0, 0], 0);
- transparent.isTransparentKeyword = true;
- return transparent;
+ return new(Color)(rgb, alpha);
+};
+Color.prototype.toRGB = function () {
+ return toHex(this.rgb);
+};
+Color.prototype.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 };
};
+//Adapted from http://mjijackson.com/2008/02/rgb-to-hsl-and-rgb-to-hsv-color-model-conversion-algorithms-in-javascript
+Color.prototype.toHSV = 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, v = max;
+
+ var d = max - min;
+ if (max === 0) {
+ s = 0;
+ } else {
+ s = d / max;
+ }
-function toHex(v) {
- return '#' + v.map(function (c) {
- c = clamp(Math.round(c), 255);
- return (c < 16 ? '0' : '') + c.toString(16);
- }).join('');
-}
+ if (max === min) {
+ h = 0;
+ } else {
+ 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, v: v, a: a };
+};
+Color.prototype.toARGB = function () {
+ return toHex([this.alpha * 255].concat(this.rgb));
+};
+Color.prototype.compare = function (x) {
- if (!x.rgb) {
- return -1;
- }
-
- return (x.rgb[0] === this.rgb[0] &&
++ return (x.rgb &&
++ x.rgb[0] === this.rgb[0] &&
+ x.rgb[1] === this.rgb[1] &&
+ x.rgb[2] === this.rgb[2] &&
- x.alpha === this.alpha) ? 0 : -1;
++ x.alpha === this.alpha) ? 0 : undefined;
+};
-function clamp(v, max) {
- return Math.min(Math.max(v, 0), max);
-}
+Color.fromKeyword = function(keyword) {
+ var c, key = keyword.toLowerCase();
+ if (colors.hasOwnProperty(key)) {
+ c = new(Color)(colors[key].slice(1));
+ }
+ else if (key === "transparent") {
+ c = new(Color)([0, 0, 0], 0);
+ }
-})(require('../tree'));
+ if (c) {
+ c.keyword = keyword;
+ return c;
+ }
+};
+module.exports = Color;
diff --cc lib/less/tree/condition.js
index 464c96c,c9ef56c..27b3be5
--- a/lib/less/tree/condition.js
+++ b/lib/less/tree/condition.js
@@@ -7,41 -7,29 +7,27 @@@ var Condition = function (op, l, r, i,
this.index = i;
this.negate = negate;
};
-tree.Condition.prototype = {
- type: "Condition",
- accept: function (visitor) {
- this.lvalue = visitor.visit(this.lvalue);
- this.rvalue = visitor.visit(this.rvalue);
- },
- eval: function (env) {
- var result = (function (op, a, b) {
- switch (op) {
- case 'and': return a && b;
- case 'or': return a || b;
- default:
- switch (tree.compare(a, b)) {
- case -1: return op === '<' || op === '=<' || op === '<=';
- case 0: return op === '=' || op === '>=' || op === '=<' || op === '<=';
- case 1: return op === '>' || op === '>=';
- default: return false;
- }
- }
- }) (this.op, this.lvalue.eval(env), this.rvalue.eval(env));
-
- return this.negate ? !result : result;
- }
+Condition.prototype = new Node();
+Condition.prototype.type = "Condition";
+Condition.prototype.accept = function (visitor) {
+ this.lvalue = visitor.visit(this.lvalue);
+ this.rvalue = visitor.visit(this.rvalue);
};
+Condition.prototype.eval = function (env) {
- var a = this.lvalue.eval(env),
- b = this.rvalue.eval(env);
-
- var i = this.index, result;
-
- result = (function (op) {
++ var result = (function (op, a, b) {
+ switch (op) {
- case 'and':
- return a && b;
- case 'or':
- return a || b;
++ 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) {
++ switch (Node.compare(a, b)) {
+ case -1: return op === '<' || op === '=<' || op === '<=';
+ case 0: return op === '=' || op === '>=' || op === '=<' || op === '<=';
+ case 1: return op === '>' || op === '>=';
++ default: return false;
+ }
+ }
- })(this.op);
++ }) (this.op, this.lvalue.eval(env), this.rvalue.eval(env));
+
-})(require('../tree'));
+ return this.negate ? !result : result;
+};
+module.exports = Condition;
diff --cc lib/less/tree/dimension.js
index 84b92c0,aabf337..dfd00cf
--- a/lib/less/tree/dimension.js
+++ b/lib/less/tree/dimension.js
@@@ -6,159 -3,313 +6,150 @@@ var Node = require("./node.js")
//
// A number with a unit
//
-tree.Dimension = function (value, unit) {
+var Dimension = function (value, unit) {
this.value = parseFloat(value);
- this.unit = (unit && unit instanceof tree.Unit) ? unit :
- new(tree.Unit)(unit ? [unit] : undefined);
+ this.unit = (unit && unit instanceof Unit) ? unit :
+ new(Unit)(unit ? [unit] : undefined);
};
-tree.Dimension.prototype = {
- type: "Dimension",
- accept: function (visitor) {
- this.unit = visitor.visit(this.unit);
- },
- eval: function (env) {
- return this;
- },
- toColor: function () {
- return new(tree.Color)([this.value, this.value, this.value]);
- },
- genCSS: function (env, output) {
- if ((env && env.strictUnits) && !this.unit.isSingular()) {
- throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());
- }
-
- var value = tree.fround(env, this.value),
- strValue = String(value);
+Dimension.prototype = new Node();
+Dimension.prototype.type = "Dimension";
+Dimension.prototype.accept = function (visitor) {
+ this.unit = visitor.visit(this.unit);
+};
+Dimension.prototype.eval = function (env) {
+ return this;
+};
+Dimension.prototype.toColor = function () {
+ return new(Color)([this.value, this.value, this.value]);
+};
+Dimension.prototype.genCSS = function (env, output) {
+ if ((env && env.strictUnits) && !this.unit.isSingular()) {
+ throw new Error("Multiple units in dimension. Correct the units or use the unit function. Bad unit: "+this.unit.toString());
+ }
- if (value !== 0 && value < 0.000001 && value > -0.000001) {
- // would be output 1e-6 etc.
- strValue = value.toFixed(20).replace(/0+$/, "");
- }
+ var value = this.fround(env, this.value),
+ strValue = String(value);
- if (env && env.compress) {
- // Zero values doesn't need a unit
- if (value === 0 && this.unit.isLength()) {
- output.add(strValue);
- return;
- }
+ if (value !== 0 && value < 0.000001 && value > -0.000001) {
+ // would be output 1e-6 etc.
+ strValue = value.toFixed(20).replace(/0+$/, "");
+ }
- // Float values doesn't need a leading zero
- if (value > 0 && value < 1) {
- strValue = (strValue).substr(1);
- }
+ if (env && env.compress) {
+ // Zero values doesn't need a unit
+ if (value === 0 && this.unit.isLength()) {
+ output.add(strValue);
+ return;
}
- output.add(strValue);
- this.unit.genCSS(env, output);
- },
- toCSS: tree.toCSS,
-
- // In an operation between two Dimensions,
- // we default to the first Dimension's unit,
- // so `1px + 2` will yield `3px`.
- operate: function (env, op, other) {
- /*jshint noempty:false */
- var value = tree.operate(env, op, this.value, other.value),
- unit = this.unit.clone();
-
- if (op === '+' || op === '-') {
- if (unit.numerator.length === 0 && unit.denominator.length === 0) {
- unit.numerator = other.unit.numerator.slice(0);
- unit.denominator = other.unit.denominator.slice(0);
- } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) {
- // do nothing
- } else {
- other = other.convertTo(this.unit.usedUnits());
-
- if(env.strictUnits && other.unit.toString() !== unit.toString()) {
- throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() +
- "' and '" + other.unit.toString() + "'.");
- }
-
- value = tree.operate(env, op, this.value, other.value);
- }
- } else if (op === '*') {
- unit.numerator = unit.numerator.concat(other.unit.numerator).sort();
- unit.denominator = unit.denominator.concat(other.unit.denominator).sort();
- unit.cancel();
- } else if (op === '/') {
- unit.numerator = unit.numerator.concat(other.unit.denominator).sort();
- unit.denominator = unit.denominator.concat(other.unit.numerator).sort();
- unit.cancel();
+ // Float values doesn't need a leading zero
+ if (value > 0 && value < 1) {
+ strValue = (strValue).substr(1);
}
- return new(tree.Dimension)(value, unit);
- },
-
- compare: function (other) {
- var a, b;
-
- if (!(other instanceof tree.Dimension)) {
- return undefined;
- }
-
- if (this.unit.isEmpty() || other.unit.isEmpty()) {
- a = this;
- b = other;
- } else {
- a = this.unify();
- b = other.unify();
- if (a.unit.compare(b.unit) !== 0) {
- return undefined;
- }
- }
-
- return tree.numericCompare(a.value, b.value);
- },
-
- unify: function () {
- return this.convertTo({ length: 'px', duration: 's', angle: 'rad' });
- },
+ }
- convertTo: function (conversions) {
- var value = this.value, unit = this.unit.clone(),
- i, groupName, group, targetUnit, derivedConversions = {}, applyUnit;
+ output.add(strValue);
+ this.unit.genCSS(env, output);
+};
- if (typeof conversions === 'string') {
- for(i in tree.UnitConversions) {
- if (tree.UnitConversions[i].hasOwnProperty(conversions)) {
- derivedConversions = {};
- derivedConversions[i] = conversions;
- }
- }
- conversions = derivedConversions;
- }
- applyUnit = function (atomicUnit, denominator) {
- /*jshint loopfunc:true */
- if (group.hasOwnProperty(atomicUnit)) {
- if (denominator) {
- value = value / (group[atomicUnit] / group[targetUnit]);
- } else {
- value = value * (group[atomicUnit] / group[targetUnit]);
- }
+// In an operation between two Dimensions,
+// we default to the first Dimension's unit,
+// so `1px + 2` will yield `3px`.
+Dimension.prototype.operate = function (env, op, other) {
+ /*jshint noempty:false */
+ var value = this._operate(env, op, this.value, other.value),
+ unit = this.unit.clone();
+
+ if (op === '+' || op === '-') {
+ if (unit.numerator.length === 0 && unit.denominator.length === 0) {
+ unit.numerator = other.unit.numerator.slice(0);
+ unit.denominator = other.unit.denominator.slice(0);
+ } else if (other.unit.numerator.length === 0 && unit.denominator.length === 0) {
+ // do nothing
+ } else {
+ other = other.convertTo(this.unit.usedUnits());
- return targetUnit;
+ if(env.strictUnits && other.unit.toString() !== unit.toString()) {
+ throw new Error("Incompatible units. Change the units or use the unit function. Bad units: '" + unit.toString() +
+ "' and '" + other.unit.toString() + "'.");
}
- return atomicUnit;
- };
-
- for (groupName in conversions) {
- if (conversions.hasOwnProperty(groupName)) {
- targetUnit = conversions[groupName];
- group = tree.UnitConversions[groupName];
-
- unit.map(applyUnit);
- }
+ value = this._operate(env, op, this.value, other.value);
}
-
+ } else if (op === '*') {
+ unit.numerator = unit.numerator.concat(other.unit.numerator).sort();
+ unit.denominator = unit.denominator.concat(other.unit.denominator).sort();
+ unit.cancel();
+ } else if (op === '/') {
+ unit.numerator = unit.numerator.concat(other.unit.denominator).sort();
+ unit.denominator = unit.denominator.concat(other.unit.numerator).sort();
unit.cancel();
-
- return new(tree.Dimension)(value, unit);
}
+ return new(Dimension)(value, unit);
};
+Dimension.prototype.compare = function (other) {
- if (other instanceof Dimension) {
- var a, b,
- aValue, bValue;
++ var a, b;
- if (this.unit.isEmpty() || other.unit.isEmpty()) {
- a = this;
- b = other;
- } else {
- a = this.unify();
- b = other.unify();
- if (a.unit.compare(b.unit) !== 0) {
- return -1;
- }
- }
- aValue = a.value;
- bValue = b.value;
-// http://www.w3.org/TR/css3-values/#absolute-lengths
-tree.UnitConversions = {
- length: {
- 'm': 1,
- 'cm': 0.01,
- 'mm': 0.001,
- 'in': 0.0254,
- 'px': 0.0254 / 96,
- 'pt': 0.0254 / 72,
- 'pc': 0.0254 / 72 * 12
- },
- duration: {
- 's': 1,
- 'ms': 0.001
- },
- angle: {
- 'rad': 1/(2*Math.PI),
- 'deg': 1/360,
- 'grad': 1/400,
- 'turn': 1
++ if (!(other instanceof Dimension)) {
++ return undefined;
+ }
-};
- if (bValue > aValue) {
- return -1;
- } else if (bValue < aValue) {
- return 1;
- } else {
- return 0;
-tree.Unit = function (numerator, denominator, backupUnit) {
- this.numerator = numerator ? numerator.slice(0).sort() : [];
- this.denominator = denominator ? denominator.slice(0).sort() : [];
- this.backupUnit = backupUnit;
-};
-
-tree.Unit.prototype = {
- type: "Unit",
- clone: function () {
- return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
- },
- genCSS: function (env, output) {
- if (this.numerator.length >= 1) {
- output.add(this.numerator[0]);
- } else
- if (this.denominator.length >= 1) {
- output.add(this.denominator[0]);
- } else
- if ((!env || !env.strictUnits) && this.backupUnit) {
- output.add(this.backupUnit);
- }
- },
- toCSS: tree.toCSS,
-
- toString: function () {
- var i, returnStr = this.numerator.join("*");
- for (i = 0; i < this.denominator.length; i++) {
- returnStr += "/" + this.denominator[i];
- }
- return returnStr;
- },
-
- compare: function (other) {
- return this.is(other.toString()) ? 0 : undefined;
- },
-
- is: function (unitString) {
- return this.toString() === unitString;
- },
-
- isLength: function () {
- return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/));
- },
-
- isEmpty: function () {
- return this.numerator.length === 0 && this.denominator.length === 0;
- },
-
- isSingular: function() {
- return this.numerator.length <= 1 && this.denominator.length === 0;
- },
-
- map: function(callback) {
- var i;
-
- for (i = 0; i < this.numerator.length; i++) {
- this.numerator[i] = callback(this.numerator[i], false);
-- }
-
- for (i = 0; i < this.denominator.length; i++) {
- this.denominator[i] = callback(this.denominator[i], true);
++ if (this.unit.isEmpty() || other.unit.isEmpty()) {
++ a = this;
++ b = other;
+ } else {
- return -1;
++ a = this.unify();
++ b = other.unify();
++ if (a.unit.compare(b.unit) !== 0) {
++ return undefined;
+ }
- },
-
- usedUnits: function() {
- var group, result = {}, mapUnit;
-
- mapUnit = function (atomicUnit) {
- /*jshint loopfunc:true */
- if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
- result[groupName] = atomicUnit;
- }
-
- return atomicUnit;
- };
-
- for (var groupName in tree.UnitConversions) {
- if (tree.UnitConversions.hasOwnProperty(groupName)) {
- group = tree.UnitConversions[groupName];
+ }
+
- this.map(mapUnit);
++ return Node.numericCompare(a.value, b.value);
+};
+Dimension.prototype.unify = function () {
+ return this.convertTo({ length: 'px', duration: 's', angle: 'rad' });
+};
+Dimension.prototype.convertTo = function (conversions) {
+ var value = this.value, unit = this.unit.clone(),
+ i, groupName, group, targetUnit, derivedConversions = {}, applyUnit;
+
+ if (typeof conversions === 'string') {
+ for(i in unitConversions) {
+ if (unitConversions[i].hasOwnProperty(conversions)) {
+ derivedConversions = {};
+ derivedConversions[i] = conversions;
}
}
-
- return result;
- },
-
- cancel: function () {
- var counter = {}, atomicUnit, i, backup;
-
- for (i = 0; i < this.numerator.length; i++) {
- atomicUnit = this.numerator[i];
- if (!backup) {
- backup = atomicUnit;
+ conversions = derivedConversions;
+ }
+ applyUnit = function (atomicUnit, denominator) {
+ /*jshint loopfunc:true */
+ if (group.hasOwnProperty(atomicUnit)) {
+ if (denominator) {
+ value = value / (group[atomicUnit] / group[targetUnit]);
+ } else {
+ value = value * (group[atomicUnit] / group[targetUnit]);
}
- counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
- }
- for (i = 0; i < this.denominator.length; i++) {
- atomicUnit = this.denominator[i];
- if (!backup) {
- backup = atomicUnit;
- }
- counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
+ return targetUnit;
}
- this.numerator = [];
- this.denominator = [];
+ return atomicUnit;
+ };
- for (atomicUnit in counter) {
- if (counter.hasOwnProperty(atomicUnit)) {
- var count = counter[atomicUnit];
+ for (groupName in conversions) {
+ if (conversions.hasOwnProperty(groupName)) {
+ targetUnit = conversions[groupName];
+ group = unitConversions[groupName];
- if (count > 0) {
- for (i = 0; i < count; i++) {
- this.numerator.push(atomicUnit);
- }
- } else if (count < 0) {
- for (i = 0; i < -count; i++) {
- this.denominator.push(atomicUnit);
- }
- }
- }
+ unit.map(applyUnit);
}
+ }
- if (this.numerator.length === 0 && this.denominator.length === 0 && backup) {
- this.backupUnit = backup;
- }
+ unit.cancel();
- this.numerator.sort();
- this.denominator.sort();
- }
+ return new(Dimension)(value, unit);
};
-
-})(require('../tree'));
+module.exports = Dimension;
diff --cc lib/less/tree/keyword.js
index 7f99a71,4b633b7..c800692
--- a/lib/less/tree/keyword.js
+++ b/lib/less/tree/keyword.js
@@@ -1,21 -1,17 +1,14 @@@
-(function (tree) {
+var Node = require("./node.js");
-tree.Keyword = function (value) { this.value = value; };
-tree.Keyword.prototype = {
- type: "Keyword",
- eval: function () { return this; },
- genCSS: function (env, output) {
- if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; }
- output.add(this.value);
- },
- toCSS: tree.toCSS
+var Keyword = function (value) { this.value = value; };
+Keyword.prototype = new Node();
+Keyword.prototype.type = "Keyword";
+Keyword.prototype.genCSS = function (env, output) {
+ if (this.value === '%') { throw { type: "Syntax", message: "Invalid % without number" }; }
+ output.add(this.value);
};
- Keyword.prototype.compare = function (other) {
- if (other instanceof Keyword) {
- return other.value === this.value ? 0 : 1;
- } else {
- return -1;
- }
- };
-tree.True = new(tree.Keyword)('true');
-tree.False = new(tree.Keyword)('false');
+Keyword.True = new(Keyword)('true');
+Keyword.False = new(Keyword)('false');
-})(require('../tree'));
+module.exports = Keyword;
diff --cc lib/less/tree/node.js
index c6bdd57,0000000..dc14c65
mode 100644,000000..100644
--- a/lib/less/tree/node.js
+++ b/lib/less/tree/node.js
@@@ -1,35 -1,0 +1,74 @@@
+var Node = function() {
+};
+Node.prototype.toCSS = function (env) {
+ var strs = [];
+ this.genCSS(env, {
+ add: function(chunk, fileInfo, index) {
+ strs.push(chunk);
+ },
+ isEmpty: function () {
+ return strs.length === 0;
+ }
+ });
+ return strs.join('');
+};
+Node.prototype.genCSS = function (env, output) {
+ output.add(this.value);
+};
+Node.prototype.accept = function (visitor) {
+ this.value = visitor.visit(this.value);
+};
+Node.prototype.eval = function () { return this; };
+Node.prototype._operate = function (env, op, a, b) {
+ switch (op) {
+ case '+': return a + b;
+ case '-': return a - b;
+ case '*': return a * b;
+ case '/': return a / b;
+ }
+};
+Node.prototype.fround = function(env, value) {
+ var precision = env && env.numPrecision;
+ //add "epsilon" to ensure numbers like 1.000000005 (represented as 1.000000004999....) are properly rounded...
+ return (precision == null) ? value : Number((value + 2e-16).toFixed(precision));
+};
++Node.compare = function (a, b) {
++ /* returns:
++ -1: a < b
++ 0: a = b
++ 1: a > b
++ and *any* other value for a != b (e.g. undefined, NaN, -2 etc.) */
++
++ if ((a.compare) &&
++ // for "symmetric results" force toCSS-based comparison
++ // of Quoted or Anonymous if either value is one of those
++ !(b.type === "Quoted" || b.type === "Anonymous")) {
++ return a.compare(b);
++ } else if (b.compare) {
++ return -b.compare(a);
++ } else if (a.type !== b.type) {
++ return undefined;
++ }
++
++ a = a.value;
++ b = b.value;
++ if (!Array.isArray(a)) {
++ return a === b ? 0 : undefined;
++ }
++ if (a.length !== b.length) {
++ return undefined;
++ }
++ for (var i = 0; i < a.length; i++) {
++ if (Node.compare(a[i], b[i]) !== 0) {
++ return undefined;
++ }
++ }
++ return 0;
++};
++
++Node.numericCompare = function (a, b) {
++ return a < b ? -1
++ : a === b ? 0
++ : a > b ? 1 : undefined;
++};
+module.exports = Node;
diff --cc lib/less/tree/quoted.js
index c46f8d5,d20939e..3c599a9
--- a/lib/less/tree/quoted.js
+++ b/lib/less/tree/quoted.js
@@@ -1,54 -1,42 +1,41 @@@
- var JsEvalNode = require("./js-eval-node.js"),
-(function (tree) {
++var Node = require("./node.js"),
++ JsEvalNode = require("./js-eval-node.js"),
+ Variable = require("./variable.js");
-tree.Quoted = function (str, content, escaped, index, currentFileInfo) {
+var Quoted = function (str, content, escaped, index, currentFileInfo) {
this.escaped = escaped;
this.value = content || '';
this.quote = str.charAt(0);
this.index = index;
this.currentFileInfo = currentFileInfo;
};
-tree.Quoted.prototype = {
- type: "Quoted",
- genCSS: function (env, output) {
- if (!this.escaped) {
- output.add(this.quote, this.currentFileInfo, this.index);
- }
- output.add(this.value);
- if (!this.escaped) {
- output.add(this.quote);
- }
- },
- toCSS: tree.toCSS,
- 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, that.currentFileInfo).eval(env, true);
- return (v instanceof tree.Quoted) ? v.value : v.toCSS();
- });
- return new(tree.Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo);
- },
- compare: function (other) {
- // when comparing quoted strings allow the quote to differ
- if (other.type === "Quoted" && !this.escaped && !other.escaped) {
- return tree.numericCompare(this.value, other.value);
- } else {
- return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
- }
+Quoted.prototype = new JsEvalNode();
+Quoted.prototype.type = "Quoted";
+Quoted.prototype.genCSS = function (env, output) {
+ if (!this.escaped) {
+ output.add(this.quote, this.currentFileInfo, this.index);
+ }
+ output.add(this.value);
+ if (!this.escaped) {
+ output.add(this.quote);
}
};
-
-})(require('../tree'));
+Quoted.prototype.eval = function (env) {
+ var that = this;
+ var value = this.value.replace(/`([^`]+)`/g, function (_, exp) {
+ return String(that.evaluateJavaScript(exp, env));
+ }).replace(/@\{([\w-]+)\}/g, function (_, name) {
+ var v = new(Variable)('@' + name, that.index, that.currentFileInfo).eval(env, true);
+ return (v instanceof Quoted) ? v.value : v.toCSS();
+ });
+ return new(Quoted)(this.quote + value + this.quote, value, this.escaped, this.index, this.currentFileInfo);
+};
- Quoted.prototype.compare = function (x) {
- if (!x.toCSS) {
- return -1;
- }
-
- var left, right;
-
++Quoted.prototype.compare = function (other) {
+ // when comparing quoted strings allow the quote to differ
- if (x.type === "Quoted" && !this.escaped && !x.escaped) {
- left = x.value;
- right = this.value;
++ if (other.type === "Quoted" && !this.escaped && !other.escaped) {
++ return Node.numericCompare(this.value, other.value);
+ } else {
- left = this.toCSS();
- right = x.toCSS();
++ return other.toCSS && this.toCSS() === other.toCSS() ? 0 : undefined;
+ }
-
- if (left === right) {
- return 0;
- }
-
- return left < right ? -1 : 1;
+};
+module.exports = Quoted;
diff --cc lib/less/tree/unit.js
index b0f7740,0000000..64b6b4f
mode 100644,000000..100644
--- a/lib/less/tree/unit.js
+++ b/lib/less/tree/unit.js
@@@ -1,126 -1,0 +1,126 @@@
+var Node = require("./node.js"),
+ unitConversions = require("../data/unit-conversions.js");
+
+var Unit = function (numerator, denominator, backupUnit) {
+ this.numerator = numerator ? numerator.slice(0).sort() : [];
+ this.denominator = denominator ? denominator.slice(0).sort() : [];
+ this.backupUnit = backupUnit;
+};
+
+Unit.prototype = new Node();
+Unit.prototype.type = "Unit";
+Unit.prototype.clone = function () {
+ return new Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
+};
+Unit.prototype.genCSS = function (env, output) {
+ if (this.numerator.length >= 1) {
+ output.add(this.numerator[0]);
+ } else
+ if (this.denominator.length >= 1) {
+ output.add(this.denominator[0]);
+ } else
+ if ((!env || !env.strictUnits) && this.backupUnit) {
+ output.add(this.backupUnit);
+ }
+};
+Unit.prototype.toString = function () {
+ var i, returnStr = this.numerator.join("*");
+ for (i = 0; i < this.denominator.length; i++) {
+ returnStr += "/" + this.denominator[i];
+ }
+ return returnStr;
+};
+Unit.prototype.compare = function (other) {
- return this.is(other.toString()) ? 0 : -1;
++ return this.is(other.toString()) ? 0 : undefined;
+};
+Unit.prototype.is = function (unitString) {
+ return this.toString().toUpperCase() === unitString.toUpperCase();
+};
+Unit.prototype.isLength = function () {
+ return Boolean(this.toCSS().match(/px|em|%|in|cm|mm|pc|pt|ex/));
+};
+Unit.prototype.isEmpty = function () {
+ return this.numerator.length === 0 && this.denominator.length === 0;
+};
+Unit.prototype.isSingular = function() {
+ return this.numerator.length <= 1 && this.denominator.length === 0;
+};
+Unit.prototype.map = function(callback) {
+ var i;
+
+ for (i = 0; i < this.numerator.length; i++) {
+ this.numerator[i] = callback(this.numerator[i], false);
+ }
+
+ for (i = 0; i < this.denominator.length; i++) {
+ this.denominator[i] = callback(this.denominator[i], true);
+ }
+};
+Unit.prototype.usedUnits = function() {
+ var group, result = {}, mapUnit;
+
+ mapUnit = function (atomicUnit) {
+ /*jshint loopfunc:true */
+ if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
+ result[groupName] = atomicUnit;
+ }
+
+ return atomicUnit;
+ };
+
+ for (var groupName in unitConversions) {
+ if (unitConversions.hasOwnProperty(groupName)) {
+ group = unitConversions[groupName];
+
+ this.map(mapUnit);
+ }
+ }
+
+ return result;
+};
+Unit.prototype.cancel = function () {
+ var counter = {}, atomicUnit, i, backup;
+
+ for (i = 0; i < this.numerator.length; i++) {
+ atomicUnit = this.numerator[i];
+ if (!backup) {
+ backup = atomicUnit;
+ }
+ counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
+ }
+
+ for (i = 0; i < this.denominator.length; i++) {
+ atomicUnit = this.denominator[i];
+ if (!backup) {
+ backup = atomicUnit;
+ }
+ counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
+ }
+
+ this.numerator = [];
+ this.denominator = [];
+
+ for (atomicUnit in counter) {
+ if (counter.hasOwnProperty(atomicUnit)) {
+ var count = counter[atomicUnit];
+
+ if (count > 0) {
+ for (i = 0; i < count; i++) {
+ this.numerator.push(atomicUnit);
+ }
+ } else if (count < 0) {
+ for (i = 0; i < -count; i++) {
+ this.denominator.push(atomicUnit);
+ }
+ }
+ }
+ }
+
+ if (this.numerator.length === 0 && this.denominator.length === 0 && backup) {
+ this.backupUnit = backup;
+ }
+
+ this.numerator.sort();
+ this.denominator.sort();
+};
+module.exports = Unit;
diff --cc test/less/mixins-guards.less
index 525b815,8d1ad0e..1b27417
--- a/test/less/mixins-guards.less
+++ b/test/less/mixins-guards.less
@@@ -121,15 -121,58 +121,58 @@@
.stringguard(@str) when (@str = 'theme1') { content: @str is 'theme1'; }
.stringguard(@str) when not ('theme2' = @str) { content: @str is not 'theme2'; }
.stringguard(@str) when (~"theme1" = @str) { content: @str is theme1; }
-.stringguard(@str) {}
+.stringguard(@str) {}
.stringguardtest {
.stringguard("theme1");
- .stringguard("theme2");
+ .stringguard("theme2");
.stringguard('theme1');
.stringguard('theme2');
- .stringguard(theme1);
+ .stringguard(theme1);
}
+ .generic(@a, @b) {/**/}
+ .generic(@a, @b) when (@a = @b) {content: @a is equal to @b}
+ .generic(@a, @b) when (@b = @a) {content: @b is equal to @a too}
+ .generic(@a, @b) when (@a < @b) {content: @a is less than @b}
+ .generic(@a, @b) when (@b < @a) {content: @b is less than @a too}
+ .generic(@a, @b) when (@a > @b) {content: @a is greater than @b}
+ .generic(@a, @b) when (@b > @a) {content: @b is greater than @a too}
+ .generic(@a, @b) when not(@a = @b) {content: @a is not equal to @b}
+ .generic(@a, @b) when not(@b = @a) {content: @b is not equal to @a too}
+
+ .variouse-types-comparision {
+ .generic(true, false);
+ .generic(1, true);
+ .generic(2, 2px);
+ .generic(3, ~"3");
+ .generic(5, ~"4");
+ .generic(abc, ~"abc");
+ .generic(abc, "abc");
+ .generic('abc', "abd");
+ .generic(6, e("6"));
+ .generic(`9`, 8);
+ .generic(a, b);
+ .generic(1 2, 3);
+ }
+
+ .list-comparision {
+ .generic(a b c, a b c);
+ .generic(a b c, a b d);
+ .generic(a, b, c; a, b, c);
+ .generic(a, b, c; a, b, d);
+ .generic(1 2px 300ms, 1em 2 .3s);
+
+ @space-list: 1 2 3;
+ @comma-list: 1, 2, 3;
+ @compound: @space-list @comma-list;
+
+ .generic(@space-list, @comma-list);
+ .generic(@comma-list, ~"1, 2, 3");
+ .generic(@compound, @space-list @comma-list);
+ .generic(@compound, @comma-list @space-list);
+ .generic(@compound 4, ~"1 2 3 1, 2, 3 4");
+ }
+
.mixin(...) {
catch:all;
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/less.js.git
More information about the Pkg-javascript-commits
mailing list