mirror of
https://github.com/less/less.js.git
synced 2026-04-09 03:00:20 -04:00
Added support and tests for !merge() syntax #700
This commit is contained in:
@@ -425,7 +425,7 @@ less.Parser = function Parser(env) {
|
||||
}
|
||||
value = new(tree.Value)([value]);
|
||||
}
|
||||
return new(tree.Rule)('@' + k, value, false, 0);
|
||||
return new(tree.Rule)('@' + k, value, false, null, 0);
|
||||
});
|
||||
evalEnv.frames = [new(tree.Ruleset)(null, variables)];
|
||||
}
|
||||
@@ -1230,7 +1230,7 @@ less.Parser = function Parser(env) {
|
||||
}
|
||||
},
|
||||
rule: function (tryAnonymous) {
|
||||
var name, value, c = input.charAt(i), important;
|
||||
var name, value, c = input.charAt(i), important, merge, match;
|
||||
save();
|
||||
|
||||
if (c === '.' || c === '#' || c === '&') { return }
|
||||
@@ -1242,10 +1242,12 @@ less.Parser = function Parser(env) {
|
||||
($(this.value) || $(this.anonymousValue)) :
|
||||
($(this.anonymousValue) || $(this.value));
|
||||
|
||||
|
||||
important = $(this.important);
|
||||
merge = $(this.merge);
|
||||
|
||||
if (value && $(this.end)) {
|
||||
return new(tree.Rule)(name, value, important, memo, env.currentFileInfo);
|
||||
return new (tree.Rule)(name, value, important, merge, memo, env.currentFileInfo);
|
||||
} else {
|
||||
furthest = i;
|
||||
restore();
|
||||
@@ -1338,7 +1340,7 @@ less.Parser = function Parser(env) {
|
||||
e = $(this.value);
|
||||
if ($(')')) {
|
||||
if (p && e) {
|
||||
nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, i, env.currentFileInfo, true)));
|
||||
nodes.push(new(tree.Paren)(new(tree.Rule)(p, e, null, null, i, env.currentFileInfo, true)));
|
||||
} else if (e) {
|
||||
nodes.push(new(tree.Paren)(e));
|
||||
} else {
|
||||
@@ -1495,6 +1497,20 @@ less.Parser = function Parser(env) {
|
||||
return $(/^! *important/);
|
||||
}
|
||||
},
|
||||
merge: function () {
|
||||
var separator;
|
||||
if (input.charAt(i) === '!') {
|
||||
if ($(/^! *merge\(/)) {
|
||||
if (input.charAt(i) === ")") {
|
||||
separator = " ";
|
||||
} else {
|
||||
separator = $(/[^)]/);
|
||||
}
|
||||
expect(")");
|
||||
}
|
||||
}
|
||||
return separator;
|
||||
},
|
||||
sub: function () {
|
||||
var a, e;
|
||||
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
(function (tree) {
|
||||
|
||||
tree.Rule = function (name, value, important, index, currentFileInfo, inline) {
|
||||
tree.Rule = function (name, value, important, merge, index, currentFileInfo, inline) {
|
||||
this.name = name;
|
||||
this.value = (value instanceof tree.Value) ? value : new(tree.Value)([value]);
|
||||
this.important = important ? ' ' + important.trim() : '';
|
||||
this.merge = merge;
|
||||
this.index = index;
|
||||
this.currentFileInfo = currentFileInfo;
|
||||
this.inline = inline || false;
|
||||
@@ -43,6 +44,7 @@ tree.Rule.prototype = {
|
||||
return new(tree.Rule)(this.name,
|
||||
this.value.eval(env),
|
||||
this.important,
|
||||
this.merge,
|
||||
this.index, this.currentFileInfo, this.inline);
|
||||
}
|
||||
finally {
|
||||
@@ -55,6 +57,7 @@ tree.Rule.prototype = {
|
||||
return new(tree.Rule)(this.name,
|
||||
this.value,
|
||||
"!important",
|
||||
this.merge,
|
||||
this.index, this.currentFileInfo, this.inline);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -178,6 +178,7 @@ tree.Ruleset.prototype = {
|
||||
debugInfo, // Line number debugging
|
||||
rule;
|
||||
|
||||
this.mergeRules();
|
||||
// Compile rules and rulesets
|
||||
for (var i = 0; i < this.rules.length; i++) {
|
||||
rule = this.rules[i];
|
||||
@@ -454,6 +455,41 @@ tree.Ruleset.prototype = {
|
||||
sel.push(new(tree.Selector)(elements));
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
mergeRules: function () {
|
||||
var groups = {},
|
||||
parts,
|
||||
rule,
|
||||
key;
|
||||
|
||||
for (var i = 0; i < this.rules.length; i++) {
|
||||
rule = this.rules[i];
|
||||
|
||||
if ((rule instanceof tree.Rule) && rule.merge) {
|
||||
key = [rule.name,
|
||||
rule.important ? "!" : "",
|
||||
rule.merge].join(",");
|
||||
|
||||
if (!groups[key]) {
|
||||
parts = groups[key] = [];
|
||||
} else {
|
||||
this.rules.splice(i--, 1);
|
||||
}
|
||||
|
||||
parts.push(rule);
|
||||
}
|
||||
}
|
||||
|
||||
Object.keys(groups).map(function (k) {
|
||||
parts = groups[k];
|
||||
|
||||
if (parts.length > 1) {
|
||||
parts[0].value = new (tree.Value)(parts.map(function (p) {
|
||||
return p.value;
|
||||
}), rule.merge);
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
})(require('../tree'));
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
(function (tree) {
|
||||
|
||||
tree.Value = function (value) {
|
||||
tree.Value = function (value, separator) {
|
||||
this.value = value;
|
||||
this.separator = separator ? separator : ",";
|
||||
};
|
||||
tree.Value.prototype = {
|
||||
type: "Value",
|
||||
@@ -20,7 +21,7 @@ tree.Value.prototype = {
|
||||
toCSS: function (env) {
|
||||
return this.value.map(function (e) {
|
||||
return e.toCSS(env);
|
||||
}).join(env.compress ? ',' : ', ');
|
||||
}).join(this.separator + ((env.compress || this.separator === " ") ? "" : " "));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
26
test/css/merge.css
Normal file
26
test/css/merge.css
Normal file
@@ -0,0 +1,26 @@
|
||||
.test1 {
|
||||
transform: rotate(90deg) skew(30deg) scale(2, 4);
|
||||
}
|
||||
.test2 {
|
||||
transform: rotate(90deg) skew(30deg);
|
||||
transform: scaleX(45deg);
|
||||
}
|
||||
.test3 {
|
||||
background: url(img1.png), url(img2.png);
|
||||
}
|
||||
.test4 {
|
||||
transform: rotate(90deg) skew(30deg);
|
||||
transform: scaleX(45deg);
|
||||
}
|
||||
.test5 {
|
||||
transform: scaleX(45deg);
|
||||
background: url(img1.png);
|
||||
}
|
||||
.test6 {
|
||||
transform: rotate(90deg) skew(30deg);
|
||||
transform: scale(2, 4) !important;
|
||||
}
|
||||
.test7 {
|
||||
transform: rotate(90deg) skew(30deg);
|
||||
transform: scale(2, 4) !important;
|
||||
}
|
||||
57
test/less/merge.less
Normal file
57
test/less/merge.less
Normal file
@@ -0,0 +1,57 @@
|
||||
.first-transform() {
|
||||
transform: rotate(90deg) skew(30deg) !merge();
|
||||
}
|
||||
.second-transform() {
|
||||
transform: scale(2,4) !merge();
|
||||
}
|
||||
.third-transform() {
|
||||
transform: scaleX(45deg);
|
||||
}
|
||||
.fourth-transform() {
|
||||
transform: scaleX(45deg) !merge(,);
|
||||
}
|
||||
.fifth-transform() {
|
||||
transform: scale(2,4) !important !merge();
|
||||
}
|
||||
.first-background() {
|
||||
background: url(img1.png) !merge(,);
|
||||
}
|
||||
.second-background() {
|
||||
background: url(img2.png) !merge(,);
|
||||
}
|
||||
|
||||
.test1 {
|
||||
// Can merge values with space separator
|
||||
.first-transform();
|
||||
.second-transform();
|
||||
}
|
||||
.test2 {
|
||||
// Wont merge values without !merge directive, for backwards compatibility with css
|
||||
.first-transform();
|
||||
.third-transform();
|
||||
}
|
||||
.test3 {
|
||||
// Can merge values with explicit separator
|
||||
.first-background();
|
||||
.second-background();
|
||||
}
|
||||
.test4 {
|
||||
// Wont merge values from two sources with different seperators
|
||||
.first-transform();
|
||||
.fourth-transform();
|
||||
}
|
||||
.test5 {
|
||||
// Wont merge values from two sources with the same seperators but different properties
|
||||
.fourth-transform();
|
||||
.first-background();
|
||||
}
|
||||
.test6 {
|
||||
// Wont merge values from sources that merked as !important, for backwards compatibility with css
|
||||
.first-transform();
|
||||
.fifth-transform();
|
||||
}
|
||||
.test7 {
|
||||
// Wont merge values from mixins that merked as !important, for backwards compatibility with css
|
||||
.first-transform();
|
||||
.second-transform() !important;
|
||||
}
|
||||
Reference in New Issue
Block a user