start refactoring toCSS so we will be able to collect sourcemap information at the same time

This commit is contained in:
Luke Page
2013-07-11 22:08:38 +01:00
parent 24e2b01d6e
commit 4db7c883cf
26 changed files with 300 additions and 199 deletions

View File

@@ -29,6 +29,9 @@
},
visitDirective: function(directiveNode, visitArgs) {
if (directiveNode.currentFileInfo.reference && !directiveNode.isReferenced) {
return [];
}
if (directiveNode.name === "@charset") {
// Only output the debug info together with subsequent @charset definitions
// a comment (or @media statement) before the actual @charset directive would

View File

@@ -34,6 +34,7 @@ tree.find = function (obj, fun) {
}
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(', ') + ']';
@@ -42,4 +43,14 @@ tree.jsify = function (obj) {
}
};
tree.toCSS = function (env) {
var strs = [];
this.genCSS(env, {
add: function(chunk, node) {
strs.push(chunk);
}
});
return strs.join('');
};
})(require('./tree'));

View File

@@ -9,13 +9,21 @@ tree.Alpha.prototype = {
this.value = visitor.visit(this.value);
},
eval: function (env) {
if (this.value.eval) { this.value = this.value.eval(env); }
if (this.value.eval) { return new tree.Alpha(this.value.eval(env)); }
return this;
},
toCSS: function () {
return "alpha(opacity=" +
(this.value.toCSS ? this.value.toCSS() : this.value) + ")";
}
genCSS: function (env, output) {
output.add("alpha(opacity=");
if (this.value.genCSS) {
this.value.genCSS(env, output);
} else {
output.add(this.value);
}
output.add(")");
},
toCSS: tree.toCSS
};
})(require('../tree'));

View File

@@ -5,10 +5,7 @@ tree.Anonymous = function (string) {
};
tree.Anonymous.prototype = {
type: "Anonymous",
toCSS: function () {
return this.value;
},
eval: function () { return this },
eval: function () { return this; },
compare: function (x) {
if (!x.toCSS) {
return -1;
@@ -22,7 +19,11 @@ tree.Anonymous.prototype = {
}
return left < right ? -1 : 1;
}
},
genCSS: function (env, output) {
output.add(this.value);
},
toCSS: tree.toCSS
};
})(require('../tree'));

View File

@@ -9,15 +9,21 @@ tree.Assignment.prototype = {
accept: function (visitor) {
this.value = visitor.visit(this.value);
},
toCSS: function () {
return this.key + '=' + (this.value.toCSS ? this.value.toCSS() : this.value);
},
eval: function (env) {
if (this.value.eval) {
return new(tree.Assignment)(this.key, this.value.eval(env));
}
return this;
}
},
genCSS: function (env, output) {
output.add(this.key + '=');
if (this.value.genCSS) {
this.value.genCSS(env, output);
} else {
output.add(this.value);
}
},
toCSS: tree.toCSS
};
})(require('../tree'));

View File

@@ -46,15 +46,24 @@ tree.Call.prototype = {
index: this.index, filename: this.currentFileInfo.filename };
}
}
// 2.
return new(tree.Anonymous)(this.name +
"(" + args.map(function (a) { return a.toCSS(env); }).join(', ') + ")");
return new tree.Call(this.name, args, this.index, this.currentFileInfo);
},
toCSS: function (env) {
return this.eval(env).toCSS();
}
genCSS: function (env, output) {
output.add(this.name + "(");
for(var i = 0; i < this.args.length; i++) {
this.args[i].genCSS(env, output);
if (i + 1 < this.args.length) {
output.add(", ");
}
}
output.add(")");
},
toCSS: tree.toCSS
};
})(require('../tree'));

View File

@@ -27,14 +27,16 @@ tree.Color.prototype = {
eval: function () { return this },
luma: function () { return (0.2126 * this.rgb[0] / 255) + (0.7152 * this.rgb[1] / 255) + (0.0722 * this.rgb[2] / 255); },
//
// 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.
//
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env, doNotCompress) {
var compress = env && env.compress && !doNotCompress;
// 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 (this.alpha < 1.0) {
return "rgba(" + this.rgb.map(function (c) {
return Math.round(c);
@@ -50,7 +52,7 @@ tree.Color.prototype = {
color = color.split('');
// Convert color to short format
if (color[0] == color[1] && color[2] == color[3] && color[4] == color[5]) {
if (color[0] === color[1] && color[2] === color[3] && color[4] === color[5]) {
color = color[0] + color[2] + color[4];
} else {
color = color.join('');

View File

@@ -7,13 +7,13 @@ tree.Comment = function (value, silent, index, currentFileInfo) {
};
tree.Comment.prototype = {
type: "Comment",
toCSS: function (env) {
var debugInfo = "";
genCSS: function (env, output) {
if (this.debugInfo) {
debugInfo = tree.debugInfo(env, this);
output.add(tree.debugInfo(env, this));
}
return debugInfo + this.value;
output.add(this.value);
},
toCSS: tree.toCSS,
isSilent: function(env) {
var isReference = (this.currentFileInfo && this.currentFileInfo.reference && !this.isReferenced),
isCompressed = env.compress && !this.value.match(/^\/\*!/);

View File

@@ -20,6 +20,9 @@ tree.Dimension.prototype = {
toColor: function () {
return new(tree.Color)([this.value, this.value, this.value]);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
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());
@@ -104,202 +107,207 @@ tree.Dimension.prototype = {
},
unify: function () {
return this.convertTo({ length: 'm', duration: 's', angle: 'rad' });
return this.convertTo({ length: 'm', duration: 's', angle: 'rad' });
},
convertTo: function (conversions) {
var value = this.value, unit = this.unit.clone(),
i, groupName, group, conversion, targetUnit, derivedConversions = {};
var value = this.value, unit = this.unit.clone(),
i, groupName, group, conversion, targetUnit, derivedConversions = {}, applyUnit;
if (typeof conversions === 'string') {
for(i in tree.UnitConversions) {
if (tree.UnitConversions[i].hasOwnProperty(conversions)) {
derivedConversions = {};
derivedConversions[i] = conversions;
}
}
conversions = derivedConversions;
}
for (groupName in conversions) {
if (conversions.hasOwnProperty(groupName)) {
targetUnit = conversions[groupName];
group = tree.UnitConversions[groupName];
unit.map(function (atomicUnit, denominator) {
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) {
if (group.hasOwnProperty(atomicUnit)) {
if (denominator) {
value = value / (group[atomicUnit] / group[targetUnit]);
} else {
value = value * (group[atomicUnit] / group[targetUnit]);
}
if (denominator) {
value = value / (group[atomicUnit] / group[targetUnit]);
} else {
value = value * (group[atomicUnit] / group[targetUnit]);
}
return targetUnit;
return targetUnit;
}
return atomicUnit;
});
};
for (groupName in conversions) {
if (conversions.hasOwnProperty(groupName)) {
targetUnit = conversions[groupName];
group = tree.UnitConversions[groupName];
unit.map(applyUnit);
}
}
}
unit.cancel();
unit.cancel();
return new(tree.Dimension)(value, unit);
return new(tree.Dimension)(value, unit);
}
};
// http://www.w3.org/TR/css3-values/#absolute-lengths
tree.UnitConversions = {
length: {
'm': 1,
'cm': 0.01,
'mm': 0.001,
'in': 0.0254,
'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
}
length: {
'm': 1,
'cm': 0.01,
'mm': 0.001,
'in': 0.0254,
'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
}
};
tree.Unit = function (numerator, denominator, backupUnit) {
this.numerator = numerator ? numerator.slice(0).sort() : [];
this.denominator = denominator ? denominator.slice(0).sort() : [];
this.backupUnit = 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);
},
type: "Unit",
clone: function () {
return new tree.Unit(this.numerator.slice(0), this.denominator.slice(0), this.backupUnit);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
if (this.numerator.length >= 1) {
return this.numerator[0];
}
if (this.denominator.length >= 1) {
return this.denominator[0];
}
if ((!env || !env.strictUnits) && this.backupUnit) {
return this.backupUnit;
}
return "";
},
toCSS: function (env) {
if (this.numerator.length >= 1) {
return this.numerator[0];
}
if (this.denominator.length >= 1) {
return this.denominator[0];
}
if ((!env || !env.strictUnits) && this.backupUnit) {
return this.backupUnit;
}
return "";
},
toString: function () {
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 : -1;
},
},
is: function (unitString) {
return this.toString() === unitString;
},
compare: function (other) {
return this.is(other.toString()) ? 0 : -1;
},
isAngle: function () {
return tree.UnitConversions.angle.hasOwnProperty(this.toCSS());
},
is: function (unitString) {
return this.toString() === unitString;
},
isEmpty: function () {
return this.numerator.length == 0 && this.denominator.length == 0;
},
isAngle: function () {
return tree.UnitConversions.angle.hasOwnProperty(this.toCSS());
},
isSingular: function() {
return this.numerator.length <= 1 && this.denominator.length == 0;
},
isEmpty: function () {
return this.numerator.length == 0 && this.denominator.length == 0;
},
map: function(callback) {
var i;
isSingular: function() {
return this.numerator.length <= 1 && this.denominator.length == 0;
},
for (i = 0; i < this.numerator.length; i++) {
this.numerator[i] = callback(this.numerator[i], false);
}
map: function(callback) {
var i;
for (i = 0; i < this.denominator.length; i++) {
this.denominator[i] = callback(this.denominator[i], true);
}
},
usedUnits: function() {
var group, groupName, result = {};
for (groupName in tree.UnitConversions) {
if (tree.UnitConversions.hasOwnProperty(groupName)) {
group = tree.UnitConversions[groupName];
this.map(function (atomicUnit) {
if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
result[groupName] = atomicUnit;
}
return atomicUnit;
});
}
}
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;
for (i = 0; i < this.numerator.length; i++) {
this.numerator[i] = callback(this.numerator[i], false);
}
counter[atomicUnit] = (counter[atomicUnit] || 0) + 1;
}
for (i = 0; i < this.denominator.length; i++) {
atomicUnit = this.denominator[i];
if (!backup) {
backup = atomicUnit;
for (i = 0; i < this.denominator.length; i++) {
this.denominator[i] = callback(this.denominator[i], true);
}
counter[atomicUnit] = (counter[atomicUnit] || 0) - 1;
}
},
this.numerator = [];
this.denominator = [];
usedUnits: function() {
var group, groupName, result = {}, mapUnit;
for (atomicUnit in counter) {
if (counter.hasOwnProperty(atomicUnit)) {
var count = counter[atomicUnit];
mapUnit = function (atomicUnit) {
if (group.hasOwnProperty(atomicUnit) && !result[groupName]) {
result[groupName] = 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);
}
return atomicUnit;
};
for (groupName in tree.UnitConversions) {
if (tree.UnitConversions.hasOwnProperty(groupName)) {
group = tree.UnitConversions[groupName];
this.map(mapUnit);
}
}
}
}
if (this.numerator.length === 0 && this.denominator.length === 0 && backup) {
this.backupUnit = backup;
}
return result;
},
this.numerator.sort();
this.denominator.sort();
}
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();
}
};
})(require('../tree'));

View File

@@ -17,17 +17,17 @@ tree.Directive.prototype = {
this.rules = visitor.visit(this.rules);
this.value = visitor.visit(this.value);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
if (this.currentFileInfo.reference && !this.isReferenced) {
return "";
}
if (this.rules) {
var css = "";
for(var i = 0; i < this.rules.length; i++) {
//this.rules[i].root = true;
css += this.rules[i].toCSS(env).trim() + "\n";
css += this.rules[i].toCSS(env);// + "\n";
if (i + 1 < this.rules.length) {
css += "\n";
}
}
css = css.trim().replace(/\n/g, '\n ');
return this.name + (env.compress ? '{' : ' {\n ') + css + (env.compress ? '}': '\n}\n');

View File

@@ -24,6 +24,9 @@ tree.Element.prototype = {
this.value.eval ? this.value.eval(env) : this.value,
this.index);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
var value = (this.value.toCSS ? this.value.toCSS(env) : this.value);
if (value == '' && this.combinator.value.charAt(0) == '&') {
@@ -48,6 +51,9 @@ tree.Attribute.prototype = {
return new(tree.Attribute)(this.key.eval ? this.key.eval(env) : this.key,
this.op, (this.value && this.value.eval) ? this.value.eval(env) : this.value);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
var value = this.key.toCSS ? this.key.toCSS(env) : this.key;
@@ -69,6 +75,9 @@ tree.Combinator = function (value) {
};
tree.Combinator.prototype = {
type: "Combinator",
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
return {
'' : '',

View File

@@ -33,11 +33,15 @@ tree.Expression.prototype = {
}
return returnValue;
},
toCSS: function (env) {
return this.value.map(function (e) {
return e.toCSS ? e.toCSS(env) : '';
}).join(' ');
genCSS: function (env, output) {
for(var i = 0; i < this.value.length; i++) {
this.value[i].genCSS(env, output);
if (i + 1 < this.value.length) {
output.add(" ");
}
}
},
toCSS: tree.toCSS,
throwAwayComments: function () {
this.value = this.value.filter(function(v) {
return !(v instanceof tree.Comment);

View File

@@ -48,6 +48,9 @@ tree.Import.prototype = {
this.root = visitor.visit(this.root);
}
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
var features = this.features ? ' ' + this.features.toCSS(env) : '';

View File

@@ -4,6 +4,9 @@ tree.Keyword = function (value) { this.value = value };
tree.Keyword.prototype = {
type: "Keyword",
eval: function () { return this; },
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function () { return this.value; },
compare: function (other) {
if (other instanceof tree.Keyword) {

View File

@@ -16,6 +16,9 @@ tree.Media.prototype = {
this.features = visitor.visit(this.features);
this.rules = visitor.visit(this.rules);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
var features = this.features.toCSS(env);

View File

@@ -8,6 +8,9 @@ tree.Negative.prototype = {
accept: function (visitor) {
this.value = visitor.visit(this.value);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
return '-' + this.value.toCSS(env);
},

View File

@@ -34,6 +34,9 @@ tree.Operation.prototype = {
return new(tree.Operation)(this.op, [a, b], this.isSpaced);
}
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
var separator = this.isSpaced ? " " : "";
return this.operands[0].toCSS() + separator + this.op + separator + this.operands[1].toCSS();

View File

@@ -9,6 +9,9 @@ tree.Paren.prototype = {
accept: function (visitor) {
this.value = visitor.visit(this.value);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
return '(' + this.value.toCSS(env).trim() + ')';
},

View File

@@ -9,6 +9,9 @@ tree.Quoted = function (str, content, escaped, index, currentFileInfo) {
};
tree.Quoted.prototype = {
type: "Quoted",
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function () {
if (this.escaped) {
return this.value;

View File

@@ -16,6 +16,9 @@ tree.Rule.prototype = {
accept: function (visitor) {
this.value = visitor.visit(this.value);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
if (this.variable) { return ""; }
else {

View File

@@ -174,6 +174,9 @@ tree.Ruleset.prototype = {
});
return this._lookups[key] = rules;
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
//
// Entry point for code generation
//

View File

@@ -53,6 +53,9 @@ tree.Selector.prototype = {
return extend.eval(env);
}), evaldCondition);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
if (this._css) { return this._css }

View File

@@ -5,10 +5,13 @@ tree.UnicodeDescriptor = function (value) {
};
tree.UnicodeDescriptor.prototype = {
type: "UnicodeDescriptor",
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
return this.value;
},
eval: function () { return this }
eval: function () { return this; }
};
})(require('../tree'));

View File

@@ -9,6 +9,9 @@ tree.URL.prototype = {
accept: function (visitor) {
this.value = visitor.visit(this.value);
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function () {
return "url(" + this.value.toCSS() + ")";
},

View File

@@ -17,6 +17,9 @@ tree.Value.prototype = {
}));
}
},
genCSS: function (env, output) {
output.add(this.toCSS(env));
},
toCSS: function (env) {
return this.value.map(function (e) {
return e.toCSS(env);

View File

@@ -8,11 +8,11 @@
"The Core Less Team"
],
"bugs": {
"url": "https://github.com/cloudhead/less.js/issues"
"url": "https://github.com/less/less.js/issues"
},
"repository": {
"type": "git",
"url": "https://github.com/cloudhead/less.js.git"
"url": "https://github.com/less/less.js.git"
},
"bin": {
"lessc": "./bin/lessc"
@@ -34,7 +34,8 @@
"mime": "1.2.x",
"request": ">=2.12.0",
"mkdirp": "~0.3.4",
"clean-css": "1.0.x"
"clean-css": "1.0.x",
"source-map": "0.1.x"
},
"devDependencies": {
"diff": "~1.0"
@@ -67,7 +68,7 @@
"licenses": [
{
"type": "Apache v2",
"url": "https://github.com/cloudhead/less.js/blob/master/LICENSE"
"url": "https://github.com/less/less.js/blob/master/LICENSE"
}
]
}