Add Sass like extend

This commit is contained in:
hokaccha
2011-12-05 23:19:13 +09:00
committed by Luke Page
parent 61e7bd6fb1
commit e793e81e92
10 changed files with 206 additions and 8 deletions

View File

@@ -85,13 +85,13 @@ var less = {
}
};
['color', 'directive', 'operation', 'dimension',
'keyword', 'variable', 'ruleset', 'element',
'selector', 'quoted', 'expression', 'rule',
'call', 'url', 'alpha', 'import',
'mixin', 'comment', 'anonymous', 'value',
'javascript', 'assignment', 'condition', 'paren',
'media', 'ratio', 'unicode-descriptor'
['color', 'directive', 'operation', 'dimension',
'keyword', 'variable', 'ruleset', 'element',
'selector', 'quoted', 'expression', 'rule',
'call', 'url', 'alpha', 'import',
'mixin', 'comment', 'anonymous', 'value',
'javascript', 'assignment', 'condition', 'paren',
'media', 'ratio', 'unicode-descriptor', 'extend'
].forEach(function (n) {
require('./tree/' + n);
});

View File

@@ -526,7 +526,8 @@ less.Parser = function Parser(env) {
var node, root = [];
while ((node = $(this.mixin.definition) || $(this.rule) || $(this.ruleset) ||
$(this.mixin.call) || $(this.comment) || $(this.directive))
$(this.mixin.call) || $(this.comment) || $(this.directive) ||
$(this.extend))
|| $(/^[\s\n]+/) || $(/^;+/)) {
node && root.push(node);
}
@@ -803,6 +804,23 @@ less.Parser = function Parser(env) {
if ((a = $(this.entity)) && $('/') && (b = $(this.entity))) {
return new(tree.Shorthand)(a, b);
}
},
//
// extend
//
extend: function() {
var elements = [], e, c, args, index = i, s = input.charAt(i);
if (s !== '+') { return }
while (e = $(/^\+[#.](?:[\w-]|\\(?:[a-fA-F0-9]{1,6} ?|[^a-fA-F0-9]))+/)) {
elements.push(new(tree.Element)(c, e.slice(1), i));
}
if (elements.length > 0 && ($(';') || peek('}'))) {
return new(tree.Extend)(elements, index);
}
restore();
},

51
lib/less/tree/extend.js Normal file
View File

@@ -0,0 +1,51 @@
(function (tree) {
tree.Extend = function Extend(elements, index) {
this.selector = new(tree.Selector)(elements);
this.index = index;
};
tree.Extend.prototype.eval = function Extend_eval(env) {
var selfSelectors = findSelfSelectors(env.selectors);
targetValue = this.selector.elements[0].value;
env.frames.forEach(function(frame) {
frame.rulesets().forEach(function(rule) {
rule.selectors.forEach(function(selector) {
selector.elements.forEach(function(element, idx) {
if (element.value === targetValue) {
selfSelectors.forEach(function(_selector) {
rule.selectors.push(new tree.Selector(
selector.elements
.slice(0, idx)
.concat(_selector.elements)
.concat(selector.elements.slice(idx + 1))
));
});
}
});
});
});
});
return this;
};
function findSelfSelectors(selectors) {
var ret = [];
(function loop(elem, i) {
if (selectors[i] && selectors[i].length) {
selectors[i].forEach(function(s) {
loop(s.elements.concat(elem), i + 1);
});
}
else {
ret.push({ elements: elem });
}
})([], 0);
return ret;
}
})(require('../tree'));

View File

@@ -23,6 +23,12 @@ tree.Ruleset.prototype = {
// push the current ruleset to the frames stack
env.frames.unshift(ruleset);
// currrent selectors
if (!env.selectors) {
env.selectors = [];
}
env.selectors.unshift(this.selectors);
// Evaluate imports
if (ruleset.root || ruleset.allowImports || !ruleset.strictImports) {
ruleset.evalImports(env);
@@ -59,6 +65,7 @@ tree.Ruleset.prototype = {
// Pop the stack
env.frames.shift();
env.selectors.shift();
if (env.mediaBlocks) {
for(var i = mediaBlockCount; i < env.mediaBlocks.length; i++) {