change extends to work after selector joining. refactor findMatch ready for change to support properties across nesting

This commit is contained in:
Luke Page
2013-03-04 15:47:12 +00:00
parent bf74d88302
commit 59fb6cd1f7
5 changed files with 65 additions and 41 deletions

View File

@@ -34,14 +34,15 @@
// now find every selector and apply the extends that apply to all extends
// and the ones which apply to an individual extend
for(i = 0; i < rulesetNode.selectors.length; i++) {
var selector = rulesetNode.selectors[i];
extendList = selector.extendList.slice(0).concat(allSelectorsExtendList.map(function(allSelectorsExtend) {
for(i = 0; i < rulesetNode.paths.length; i++) {
var selectorPath = rulesetNode.paths[i],
selector = selectorPath[selectorPath.length-1];
extendList = selector.extendList.slice(0).concat(allSelectorsExtendList).map(function(allSelectorsExtend) {
return allSelectorsExtend.clone();
}));
});
for(j = 0; j < extendList.length; j++) {
extend = extendList[j];
extend.findSelfSelectors([[selector]].concat(this.contexts.slice(0)));
extend.findSelfSelectors(selectorPath);
this.allExtendsStack[this.allExtendsStack.length-1].push(extend);
}
}
@@ -97,41 +98,53 @@
var i, j, k, selector, element, allExtends = this.allExtendsStack[this.allExtendsStack.length-1], selectorsToAdd = [];
for(k = 0; k < allExtends.length; k++) {
for(i = 0; i < rulesetNode.selectors.length; i++) {
selector = rulesetNode.selectors[i];
var match = this.findMatch(allExtends[k], selector);
for(i = 0; i < rulesetNode.paths.length; i++) {
selectorPath = rulesetNode.paths[i];
var match = this.findMatch(allExtends[k], selectorPath);
if (match) {
selector = selectorPath[match.pathIndex];
allExtends[k].selfSelectors.forEach(function(selfSelector) {
var firstElement = new tree.Element(
var path = selectorPath.slice(0, match.pathIndex),
firstElement = new tree.Element(
match.initialCombinator,
selfSelector.elements[0].value,
selfSelector.elements[0].index
);
selectorsToAdd.push(new tree.Selector(
path.push(new tree.Selector(
selector.elements
.slice(0, match.index)
.concat([firstElement])
.concat(selfSelector.elements.slice(1))
.concat(selector.elements.slice(match.index + match.length))
));
path = path.concat(selectorPath.slice(match.pathIndex + 1, selectorPath.length));
selectorsToAdd.push(path);
});
}
}
}
rulesetNode.selectors = rulesetNode.selectors.concat(selectorsToAdd);
rulesetNode.paths = rulesetNode.paths.concat(selectorsToAdd);
},
findMatch: function (extend, selector) {
var i, j, element, hasMatch;
for(i = 0; i <= (selector.elements.length - extend.selector.elements.length); i++) {
hasMatch = true;
for(j = 0; j < extend.selector.elements.length; j++) {
if (extend.selector.elements[j].value !== selector.elements[i+j].value) {
hasMatch = false;
break;
findMatch: function (extend, selectorPath) {
var i, j, k, element, hasMatch, potentialMatches = [], potentialMatch;
for(k = 0; k < selectorPath.length; k++) {
selector = selectorPath[k];
for(i = 0; i < selector.elements.length; i++) {
hasMatch = true;
potentialMatch = {pathIndex: k, index: i};
for(j = 0; j < extend.selector.elements.length && i+j < selector.elements.length; j++) {
potentialMatch.matched = j;
if (extend.selector.elements[j].value !== selector.elements[i+j].value ||
(j > 0 && extend.selector.elements[j].combinator.value !== selector.elements[i+j].combinator.value)) {
potentialMatch = null;
break;
}
}
if (potentialMatch && potentialMatch.matched+1 === extend.selector.elements.length) {
potentialMatch.initialCombinator = selector.elements[i].combinator;
potentialMatch.length = extend.selector.elements.length;
return potentialMatch;
}
}
if (hasMatch) {
return {index: i, initialCombinator: selector.elements[i].combinator, length: extend.selector.elements.length};
}
}
return null;

View File

@@ -406,10 +406,10 @@ less.Parser = function Parser(env) {
try {
var evaldRoot = evaluate.call(this, evalEnv);
new(tree.processExtendsVisitor)()
new(tree.joinSelectorVisitor)()
.run(evaldRoot);
new(tree.joinSelectorVisitor)()
new(tree.processExtendsVisitor)()
.run(evaldRoot);
var css = evaldRoot.toCSS({

View File

@@ -18,22 +18,13 @@ tree.Extend.prototype = {
return new(tree.Extend)(this.selector, this.option, this.index);
},
findSelfSelectors: function (selectors) {
var selfSelectors = [];
var selfElements = [];
// multiplies out the selectors, e.g.
// [[.a],[.b,.c]] => [.a.b,.a.c]
(function loop(elem, i) {
if (selectors[i] && selectors[i].length) {
selectors[i].forEach(function(s) {
loop(s.elements.concat(elem), i + 1);
});
}
else {
selfSelectors.push({ elements: elem });
}
})([], 0);
for(i = 0; i < selectors.length; i++) {
selfElements = selfElements.concat(selectors[i].elements);
}
this.selfSelectors = selfSelectors;
this.selfSelectors = [{ elements: selfElements }];
}
};

View File

@@ -35,8 +35,17 @@ div.ext7,
}
.ext8.ext9,
.foo {
result: pick-up-both;
result: add-foo;
}
.ext8 .ext9,
.ext8 + .ext9,
.ext8 > .ext9,
.bar {
result: bar-matched;
}
.ext8.nomatch {
result: none;
}
.ext8 .ext9 {
result: match-nested;
}

View File

@@ -38,10 +38,21 @@ div.ext5,
}
.ext8.ext9 {
result: pick-up-both;
result: add-foo;
}
.ext8 .ext9,
.ext8 + .ext9,
.ext8 > .ext9 {
result: bar-matched;
}
.ext8.nomatch {
result: none;
}
.ext8 {
.ext9 {
result: match-nested;
}
}
.foo:extend(.ext8.ext9 all) {}
.foo:extend(.ext8.ext9 all) {}
.bar:extend(.ext8 .ext9 all) {}