mirror of
https://github.com/less/less.js.git
synced 2026-01-22 13:48:03 -05:00
Working but extremly ugly version. Desperately needs clean up.
This commit is contained in:
@@ -858,9 +858,11 @@ var Parser = function Parser(context, imports, fileInfo) {
|
||||
c = this.combinator();
|
||||
|
||||
e = parserInput.$re(/^(?:\d+\.\d+|\d+)%/) || parserInput.$re(/^(?:[.#]?|:*)(?:[\w-]|[^\x00-\x9f]|\\(?:[A-Fa-f0-9]{1,6} ?|[^A-Fa-f0-9]))+/) ||
|
||||
parserInput.$char('*') || parserInput.$char('&') || this.attribute() || parserInput.$re(/^\([^()@]+\)/) || parserInput.$re(/^[\.#](?=@)/) ||
|
||||
parserInput.$char('*') || parserInput.$char('&') || this.attribute() || parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#](?=@)/) ||
|
||||
//parserInput.$char('*') || parserInput.$char('&') || this.attribute() || parserInput.$re(/^\([^()@]+\)/) || parserInput.$re(/^[\.#](?=@)/) ||
|
||||
this.entities.variableCurly();
|
||||
|
||||
|
||||
if (! e) {
|
||||
parserInput.save();
|
||||
if (parserInput.$char('(')) {
|
||||
|
||||
@@ -2,6 +2,7 @@ var Node = require("./node"),
|
||||
Rule = require("./rule"),
|
||||
Selector = require("./selector"),
|
||||
Element = require("./element"),
|
||||
Paren = require("./paren"),
|
||||
contexts = require("../contexts"),
|
||||
defaultFunc = require("../functions/default"),
|
||||
getDebugInfo = require("./debug-info");
|
||||
@@ -426,162 +427,229 @@ Ruleset.prototype.joinSelectors = function (paths, context, selectors) {
|
||||
this.joinSelector(paths, context, selectors[s]);
|
||||
}
|
||||
};
|
||||
Ruleset.prototype.joinSelector = function (paths, context, selector) {
|
||||
function replaceNextPartMeri(attachToPrefix, replacement, appender, originalSelector) {
|
||||
var newSelectorPath, afterParentJoin, lastSelector, newJoinedSelectorEmpty, newJoinedSelector;
|
||||
// our new selector path
|
||||
newSelectorPath = [];
|
||||
// selectors from the parent after the join
|
||||
afterParentJoin = [];
|
||||
newJoinedSelectorEmpty = true;
|
||||
|
||||
var i, j, k,
|
||||
hasParentSelector, newSelectors, el, sel, parentSel,
|
||||
newSelectorPath, afterParentJoin, newJoinedSelector,
|
||||
newJoinedSelectorEmpty, lastSelector, currentElements,
|
||||
selectorsMultiplied;
|
||||
//construct the joined selector - if & is the first thing this will be empty,
|
||||
// if not newJoinedSelector will be the last set of elements in the selector
|
||||
if (attachToPrefix.length > 0) {
|
||||
newSelectorPath = attachToPrefix.slice(0);
|
||||
lastSelector = newSelectorPath.pop();
|
||||
newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
|
||||
newJoinedSelectorEmpty = false;
|
||||
}
|
||||
else {
|
||||
newJoinedSelector = originalSelector.createDerived([]);
|
||||
}
|
||||
|
||||
for (i = 0; i < selector.elements.length; i++) {
|
||||
el = selector.elements[i];
|
||||
if (el.value === '&') {
|
||||
hasParentSelector = true;
|
||||
}
|
||||
//put together the parent selectors after the join
|
||||
if (replacement.length > 1) {
|
||||
afterParentJoin = afterParentJoin.concat(replacement.slice(1));
|
||||
}
|
||||
|
||||
if (replacement.length > 0) {
|
||||
newJoinedSelectorEmpty = false;
|
||||
|
||||
// /deep/ is a combinator that is valid without anything in front of it
|
||||
// so if the & does not have a combinator that is "" or " " then
|
||||
// and there is a combinator on the parent, then grab that.
|
||||
// this also allows + a { & .b { .a & { ... though not sure why you would want to do that
|
||||
var combinator = appender.combinator,
|
||||
parentEl = replacement[0].elements[0];
|
||||
if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
|
||||
combinator = parentEl.combinator;
|
||||
}
|
||||
// join the elements so far with the first part of the parent
|
||||
newJoinedSelector.elements.push(new Element(combinator, parentEl.value, appender.index, appender.currentFileInfo));
|
||||
newJoinedSelector.elements = newJoinedSelector.elements.concat(replacement[0].elements.slice(1));
|
||||
}
|
||||
|
||||
if (!hasParentSelector) {
|
||||
if (context.length > 0) {
|
||||
for (i = 0; i < context.length; i++) {
|
||||
paths.push(context[i].concat(selector));
|
||||
}
|
||||
}
|
||||
else {
|
||||
paths.push([selector]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!newJoinedSelectorEmpty) {
|
||||
// now add the joined selector
|
||||
newSelectorPath.push(newJoinedSelector);
|
||||
}
|
||||
|
||||
// The paths are [[Selector]]
|
||||
// The first list is a list of comma separated selectors
|
||||
// The inner list is a list of inheritance separated selectors
|
||||
// e.g.
|
||||
// .a, .b {
|
||||
// .c {
|
||||
// }
|
||||
// }
|
||||
// == [[.a] [.c]] [[.b] [.c]]
|
||||
//
|
||||
// and the rest of the parent
|
||||
newSelectorPath = newSelectorPath.concat(afterParentJoin);
|
||||
return newSelectorPath;
|
||||
}
|
||||
function replaceInnerParentSelector(paths, context, selector) {
|
||||
var i, j, k, currentElements, newSelectors, selectorsMultiplied, parentSel, sel, el, encounteredParentSelector = false;
|
||||
function findNestedSelector(element) {
|
||||
var maybeSelector;
|
||||
if (element.value.type !== 'Paren')
|
||||
return null;
|
||||
|
||||
// the elements from the current selector so far
|
||||
currentElements = [];
|
||||
// the current list of new selectors to add to the path.
|
||||
// We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
|
||||
// by the parents
|
||||
newSelectors = [[]];
|
||||
maybeSelector = element.value.value;
|
||||
if (maybeSelector.type !== 'Selector')
|
||||
return null;
|
||||
|
||||
for (i = 0; i < selector.elements.length; i++) {
|
||||
el = selector.elements[i];
|
||||
// non parent reference elements just get added
|
||||
if (el.value !== "&") {
|
||||
currentElements.push(el);
|
||||
} else {
|
||||
// the new list of selectors to add
|
||||
selectorsMultiplied = [];
|
||||
return maybeSelector;
|
||||
}
|
||||
// the elements from the current selector so far
|
||||
currentElements = [];
|
||||
// the current list of new selectors to add to the path.
|
||||
// We will build it up. We initiate it with one empty selector as we "multiply" the new selectors
|
||||
// by the parents
|
||||
newSelectors = [
|
||||
[]
|
||||
];
|
||||
|
||||
// merge the current list of non parent selector elements
|
||||
// on to the current list of selectors to add
|
||||
if (currentElements.length > 0) {
|
||||
this.mergeElementsOnToSelectors(currentElements, newSelectors);
|
||||
}
|
||||
for (i = 0; i < selector.elements.length; i++) {
|
||||
el = selector.elements[i];
|
||||
// non parent reference elements just get added
|
||||
if (el.value !== "&") {
|
||||
var nestedSelector = findNestedSelector(el);
|
||||
if (nestedSelector != null) {
|
||||
selectorsMultiplied = [];
|
||||
// merge the current list of non parent selector elements
|
||||
// on to the current list of selectors to add
|
||||
this.mergeElementsOnToSelectors(currentElements, newSelectors);
|
||||
|
||||
// loop through our current selectors
|
||||
var nestedPathsWtf = [], replaced;
|
||||
replaced = replaceInnerParentSelector.call(this, nestedPathsWtf, context, nestedSelector);
|
||||
encounteredParentSelector = encounteredParentSelector || replaced;
|
||||
for (k = 0; k < nestedPathsWtf.length; k++) {
|
||||
|
||||
var replacementParen = new Paren(nestedPathsWtf[0][0]);
|
||||
var replacementElement = new Element(null, replacementParen, el.index, el.currentFileInfo);
|
||||
var replacementSelector = new Selector([replacementElement]);
|
||||
var replacements = [replacementSelector];
|
||||
//replaceNextPartMeri(attachToPrefix, replacement, appender, originalSelector)
|
||||
for (j = 0; j < newSelectors.length; j++) {
|
||||
sel = newSelectors[j];
|
||||
// if we don't have any parent paths, the & might be in a mixin so that it can be used
|
||||
// whether there are parents or not
|
||||
if (context.length === 0) {
|
||||
// the combinator used on el should now be applied to the next element instead so that
|
||||
// it is not lost
|
||||
if (sel.length > 0) {
|
||||
sel[0].elements = sel[0].elements.slice(0);
|
||||
sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
|
||||
}
|
||||
selectorsMultiplied.push(sel);
|
||||
}
|
||||
else {
|
||||
// and the parent selectors
|
||||
for (k = 0; k < context.length; k++) {
|
||||
parentSel = context[k];
|
||||
// We need to put the current selectors
|
||||
// then join the last selector's elements on to the parents selectors
|
||||
|
||||
// our new selector path
|
||||
newSelectorPath = [];
|
||||
// selectors from the parent after the join
|
||||
afterParentJoin = [];
|
||||
newJoinedSelectorEmpty = true;
|
||||
|
||||
//construct the joined selector - if & is the first thing this will be empty,
|
||||
// if not newJoinedSelector will be the last set of elements in the selector
|
||||
if (sel.length > 0) {
|
||||
newSelectorPath = sel.slice(0);
|
||||
lastSelector = newSelectorPath.pop();
|
||||
newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
|
||||
newJoinedSelectorEmpty = false;
|
||||
}
|
||||
else {
|
||||
newJoinedSelector = selector.createDerived([]);
|
||||
}
|
||||
|
||||
//put together the parent selectors after the join
|
||||
if (parentSel.length > 1) {
|
||||
afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
|
||||
}
|
||||
|
||||
if (parentSel.length > 0) {
|
||||
newJoinedSelectorEmpty = false;
|
||||
|
||||
// /deep/ is a combinator that is valid without anything in front of it
|
||||
// so if the & does not have a combinator that is "" or " " then
|
||||
// and there is a combinator on the parent, then grab that.
|
||||
// this also allows + a { & .b { .a & { ... though not sure why you would want to do that
|
||||
var combinator = el.combinator,
|
||||
parentEl = parentSel[0].elements[0];
|
||||
if (combinator.emptyOrWhitespace && !parentEl.combinator.emptyOrWhitespace) {
|
||||
combinator = parentEl.combinator;
|
||||
}
|
||||
// join the elements so far with the first part of the parent
|
||||
newJoinedSelector.elements.push(new Element(combinator, parentEl.value, el.index, el.currentFileInfo));
|
||||
newJoinedSelector.elements = newJoinedSelector.elements.concat(parentSel[0].elements.slice(1));
|
||||
}
|
||||
|
||||
if (!newJoinedSelectorEmpty) {
|
||||
// now add the joined selector
|
||||
newSelectorPath.push(newJoinedSelector);
|
||||
}
|
||||
|
||||
// and the rest of the parent
|
||||
newSelectorPath = newSelectorPath.concat(afterParentJoin);
|
||||
|
||||
// add that to our new set of selectors
|
||||
selectorsMultiplied.push(newSelectorPath);
|
||||
}
|
||||
}
|
||||
sel = newSelectors[j];
|
||||
var entirelyNewSelectorPath = replaceNextPartMeri(sel, replacements, el, selector);
|
||||
selectorsMultiplied.push(entirelyNewSelectorPath); // this causes cucle
|
||||
}
|
||||
|
||||
// our new selectors has been multiplied, so reset the state
|
||||
newSelectors = selectorsMultiplied;
|
||||
currentElements = [];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// if we have any elements left over (e.g. .a& .b == .b)
|
||||
// add them on to all the current selectors
|
||||
if (currentElements.length > 0) {
|
||||
this.mergeElementsOnToSelectors(currentElements, newSelectors);
|
||||
}
|
||||
} else {
|
||||
currentElements.push(el);
|
||||
}
|
||||
|
||||
for (i = 0; i < newSelectors.length; i++) {
|
||||
if (newSelectors[i].length > 0) {
|
||||
paths.push(newSelectors[i]);
|
||||
} else {
|
||||
encounteredParentSelector = true;
|
||||
// the new list of selectors to add
|
||||
selectorsMultiplied = [];
|
||||
|
||||
// merge the current list of non parent selector elements
|
||||
// on to the current list of selectors to add
|
||||
this.mergeElementsOnToSelectors(currentElements, newSelectors);
|
||||
|
||||
// loop through our current selectors
|
||||
for (j = 0; j < newSelectors.length; j++) {
|
||||
sel = newSelectors[j];
|
||||
// if we don't have any parent paths, the & might be in a mixin so that it can be used
|
||||
// whether there are parents or not
|
||||
if (context.length === 0) {
|
||||
// the combinator used on el should now be applied to the next element instead so that
|
||||
// it is not lost
|
||||
if (sel.length > 0) {
|
||||
sel[0].elements = sel[0].elements.slice(0);
|
||||
sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
|
||||
}
|
||||
selectorsMultiplied.push(sel);
|
||||
}
|
||||
else {
|
||||
// and the parent selectors
|
||||
for (k = 0; k < context.length; k++) {
|
||||
parentSel = context[k];
|
||||
// We need to put the current selectors
|
||||
// then join the last selector's elements on to the parents selectors
|
||||
var newSelectorPath = replaceNextPartMeri(sel, parentSel, el, selector);
|
||||
// add that to our new set of selectors
|
||||
selectorsMultiplied.push(newSelectorPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// our new selectors has been multiplied, so reset the state
|
||||
newSelectors = selectorsMultiplied;
|
||||
currentElements = [];
|
||||
}
|
||||
}
|
||||
|
||||
// if we have any elements left over (e.g. .a& .b == .b)
|
||||
// add them on to all the current selectors
|
||||
this.mergeElementsOnToSelectors(currentElements, newSelectors);
|
||||
|
||||
for (i = 0; i < newSelectors.length; i++) {
|
||||
if (newSelectors[i].length > 0) {
|
||||
paths.push(newSelectors[i]);
|
||||
}
|
||||
}
|
||||
|
||||
return encounteredParentSelector;
|
||||
}
|
||||
Ruleset.prototype.joinSelector = function (paths, context, selector) {
|
||||
|
||||
var i, hasParentSelector, el;
|
||||
|
||||
for (i = 0; i < selector.elements.length; i++) {
|
||||
el = selector.elements[i];
|
||||
if (el.value === '&') {
|
||||
hasParentSelector = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (false) {
|
||||
if (context.length > 0) {
|
||||
console.log('context: full');
|
||||
for (i = 0; i < context.length; i++) {
|
||||
paths.push(context[i].concat(selector));
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log('context: empty');
|
||||
paths.push([selector]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// The paths are [[Selector]]
|
||||
// The first list is a list of comma separated selectors
|
||||
// The inner list is a list of inheritance separated selectors
|
||||
// e.g.
|
||||
// .a, .b {
|
||||
// .c {
|
||||
// }
|
||||
// }
|
||||
// == [[.a] [.c]] [[.b] [.c]]
|
||||
//
|
||||
var newPaths = [];
|
||||
var encounteredParentSelector = replaceInnerParentSelector.call(this, newPaths, context, selector);
|
||||
|
||||
if (true && !encounteredParentSelector) {
|
||||
newPaths = [];
|
||||
if (context.length > 0) {
|
||||
console.log('context: full');
|
||||
for (i = 0; i < context.length; i++) {
|
||||
newPaths.push(context[i].concat(selector));
|
||||
}
|
||||
}
|
||||
else {
|
||||
console.log('context: empty');
|
||||
newPaths.push([selector]);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < newPaths.length; i++) {
|
||||
paths.push(newPaths[i]);
|
||||
}
|
||||
|
||||
};
|
||||
Ruleset.prototype.mergeElementsOnToSelectors = function(elements, selectors) {
|
||||
var i, sel;
|
||||
|
||||
if (elements.length === 0) {
|
||||
return ;
|
||||
}
|
||||
if (selectors.length === 0) {
|
||||
selectors.push([ new Selector(elements) ]);
|
||||
return;
|
||||
|
||||
@@ -126,13 +126,13 @@ a {
|
||||
selector: interpolated;
|
||||
}
|
||||
.test {
|
||||
&:nth-child(@{num}) {
|
||||
selector: interpolated;
|
||||
}
|
||||
&:nth-child(odd):not(:nth-child(3)) {
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
&:nth-child(@{num}) {
|
||||
selector: interpolated;
|
||||
}
|
||||
&:nth-child(odd):not(:nth-child(3)) {
|
||||
color: #ff0000;
|
||||
}
|
||||
}
|
||||
[prop],
|
||||
[prop=10%],
|
||||
[prop="value@{num}"],
|
||||
|
||||
Reference in New Issue
Block a user