[Pkg-javascript-commits] [less.js] 10/14: Merge https://github.com/less/less.js into nested-parent-selector-2026-v1
Jonas Smedegaard
dr at jones.dk
Mon Oct 26 23:29:17 UTC 2015
This is an automated email from the git hooks/post-receive script.
js pushed a commit to annotated tag v2.3.1
in repository less.js.
commit dc93dd54bfb0734db950a4d9c389cc1fec4bf39f
Merge: 964b991 d206167
Author: jurcovicovam <meri at meri.org>
Date: Wed Jan 28 10:46:49 2015 +0100
Merge https://github.com/less/less.js into nested-parent-selector-2026-v1
Conflicts:
lib/less/parser/parser.js
lib/less/tree/ruleset.js
.gitignore | 1 +
.jscsrc | 38 ++
.jshintrc | 2 -
CHANGELOG.md | 18 +
Gruntfile.js | 54 +-
bin/lessc | 688 ++++++++++++-----------
bower.json | 2 +-
dist/less.js | 378 ++++++++-----
dist/less.min.js | 12 +-
lib/less-browser/add-default-options.js | 6 +-
lib/less-browser/bootstrap.js | 18 +-
lib/less-browser/index.js | 28 +-
lib/less-browser/utils.js | 10 +-
lib/less-node/file-manager.js | 18 +-
lib/less-node/image-size.js | 48 +-
lib/less-node/lessc-helper.js | 6 +-
lib/less-node/url-file-manager.js | 4 +-
lib/less-rhino/index.js | 6 +-
lib/less/contexts.js | 1 -
lib/less/data/unit-conversions.js | 6 +-
lib/less/environment/abstract-file-manager.js | 8 +-
lib/less/functions/color-blending.js | 6 +-
lib/less/functions/color.js | 14 +-
lib/less/functions/data-uri.js | 36 +-
lib/less/functions/string.js | 4 +-
lib/less/functions/svg.js | 9 +-
lib/less/functions/types.js | 8 +-
lib/less/import-manager.js | 15 +-
lib/less/index.js | 2 +-
lib/less/parse-tree.js | 12 +-
lib/less/parse.js | 4 +
lib/less/parser/parser.js | 42 +-
lib/less/source-map-output.js | 6 +-
lib/less/transform-tree.js | 2 +-
lib/less/tree/assignment.js | 1 -
lib/less/tree/condition.js | 2 +-
lib/less/tree/debug-info.js | 8 +-
lib/less/tree/dimension.js | 2 +-
lib/less/tree/directive.js | 32 +-
lib/less/tree/import.js | 2 +-
lib/less/tree/index.js | 1 +
lib/less/tree/media.js | 5 +-
lib/less/tree/mixin-call.js | 7 +-
lib/less/tree/mixin-definition.js | 7 +-
lib/less/tree/quoted.js | 2 +-
lib/less/tree/rule.js | 5 +-
lib/less/tree/ruleset.js | 77 ++-
lib/less/tree/selector.js | 3 +-
lib/less/tree/url.js | 2 +-
lib/less/tree/value.js | 2 +-
lib/less/tree/variable.js | 2 +-
lib/less/visitors/extend-visitor.js | 52 +-
lib/less/visitors/import-sequencer.js | 44 +-
lib/less/visitors/import-visitor.js | 23 +-
lib/less/visitors/to-css-visitor.js | 42 +-
package.json | 10 +-
test/browser/common.js | 8 +-
test/browser/jasmine-jsreporter.js | 5 +-
test/browser/runner-errors-options.js | 1 -
test/browser/runner-errors-spec.js | 1 -
test/browser/runner-legacy-options.js | 1 -
test/browser/runner-no-js-errors-spec.js | 1 -
test/browser/runner-production-options.js | 1 -
test/browser/runner-relative-urls-options.js | 1 -
test/browser/runner-rootpath-options.js | 1 -
test/browser/runner-rootpath-relative-options.js | 1 -
test/browser/runner-strict-units-options.js | 1 -
test/copy-bom.js | 72 +++
test/css/comments.css | 1 +
test/css/functions.css | 1 +
test/css/import-reference.css | 25 +
test/css/mixins-important.css | 6 +
test/css/selectors.css | 2 +-
test/css/urls.css | 1 +
test/index.js | 22 +-
test/less-test.js | 129 +++--
test/less/comments.less | 1 +
test/less/functions.less | 4 +
test/less/import-reference.less | 4 +-
test/less/import.less | 2 +
test/less/import/import-reference.less | 38 ++
test/less/mixins-important.less | 12 +
test/less/selectors.less | 2 +-
test/less/urls.less | 3 +
test/modify-vars.js | 10 +-
85 files changed, 1370 insertions(+), 830 deletions(-)
diff --cc lib/less/parser/parser.js
index 6863979,daa3b71..4617412
--- a/lib/less/parser/parser.js
+++ b/lib/less/parser/parser.js
@@@ -857,11 -864,11 +864,12 @@@ var Parser = function Parser(context, i
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(/^[\.#](?=@)/) ||
+ 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(/^[\.#:](?=@)/) || this.entities.variableCurly();
++ parserInput.$re(/^\([^&()@]+\)/) || parserInput.$re(/^[\.#:](?=@)/) ||
+ this.entities.variableCurly();
-
if (! e) {
parserInput.save();
if (parserInput.$char('(')) {
diff --cc lib/less/tree/ruleset.js
index 49b3d78,2c1bb8a..f1bfc4a
--- a/lib/less/tree/ruleset.js
+++ b/lib/less/tree/ruleset.js
@@@ -430,243 -462,175 +463,245 @@@ Ruleset.prototype.joinSelectors = funct
Ruleset.prototype.joinSelector = function (paths, context, selector) {
- var i, j, k,
- hasParentSelector, newSelectors, el, sel, parentSel,
- newSelectorPath, afterParentJoin, newJoinedSelector,
- newJoinedSelectorEmpty, lastSelector, currentElements,
- selectorsMultiplied;
-
- for (i = 0; i < selector.elements.length; i++) {
- el = selector.elements[i];
- if (el.value === '&') {
- hasParentSelector = true;
- }
- }
-
- if (!hasParentSelector) {
- if (context.length > 0) {
- for (i = 0; i < context.length; i++) {
- paths.push(context[i].concat(selector));
+ function createParenthesis(elementsToPak, originalElement) {
+ var replacementParen, j;
+ if (elementsToPak.length === 0) {
+ replacementParen = new Paren(elementsToPak[0]);
+ } else {
+ var insideParent = [];
+ for (j = 0; j < elementsToPak.length; j++) {
+ insideParent.push(new Element(null, elementsToPak[j], originalElement.index, originalElement.currentFileInfo));
}
+ replacementParen = new Paren(new Selector(insideParent));
}
- else {
- 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]]
- //
-
- // 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 = [[]];
-
- 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 replacementParen;
+ }
+
+ function createSelector(containedElement, originalElement) {
+ var element, selector;
+ element = new Element(null, containedElement, originalElement.index, originalElement.currentFileInfo);
+ selector = new Selector([element]);
+ return selector;
+ }
+
+ // replace all parent selectors inside `inSelector` by content of `context` array
+ // resulting selectors are returned inside `paths` array
+ // returns true if `inSelector` contained at least one parent selector
+ function replaceParentSelector(paths, context, inSelector) {
+ // 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 i, j, k, currentElements, newSelectors, selectorsMultiplied, sel, el, hadParentSelector = false;
+ function findNestedSelector(element) {
+ var maybeSelector;
- if (element.value.type !== 'Paren')
++ if (element.value.type !== 'Paren') {
+ return null;
++ }
- // 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);
+ maybeSelector = element.value.value;
- if (maybeSelector.type !== 'Selector')
++ if (maybeSelector.type !== 'Selector') {
+ return null;
+ }
- // 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));
+ 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 = [
+ []
+ ];
+
+ for (i = 0; i < inSelector.elements.length; i++) {
+ el = inSelector.elements[i];
+ // non parent reference elements just get added
+ if (el.value !== "&") {
+ var nestedSelector = findNestedSelector(el);
+ if (nestedSelector != null) {
+ // merge the current list of non parent selector elements
+ // on to the current list of selectors to add
+ mergeElementsOnToSelectors(currentElements, newSelectors);
+
+ var nestedPaths = [], replaced, replacedNewSelectors = [];
+ replaced = replaceParentSelector(nestedPaths, context, nestedSelector);
+ hadParentSelector = hadParentSelector || replaced;
+ //the nestedPaths array should have only one member - replaceParentSelector does not multiply selectors
+ for (k = 0; k < nestedPaths.length; k++) {
+ var replacementSelector = createSelector(createParenthesis(nestedPaths[k], el), el);
+ addAllReplacementsIntoPath(newSelectors, [replacementSelector], el, inSelector, replacedNewSelectors);
}
- selectorsMultiplied.push(sel);
+ newSelectors = replacedNewSelectors;
+ currentElements = [];
+
+ } else {
+ currentElements.push(el);
}
- 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
+
+ } else {
+ hadParentSelector = 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
+ 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) {
- newSelectorPath = sel.slice(0);
- lastSelector = newSelectorPath.pop();
- newJoinedSelector = selector.createDerived(lastSelector.elements.slice(0));
- newJoinedSelectorEmpty = false;
+ sel[0].elements.push(new Element(el.combinator, '', el.index, el.currentFileInfo));
}
- else {
- newJoinedSelector = selector.createDerived([]);
+ selectorsMultiplied.push(sel);
+ }
+ else {
+ // and the parent selectors
+ for (k = 0; k < context.length; k++) {
+ // We need to put the current selectors
+ // then join the last selector's elements on to the parents selectors
+ var newSelectorPath = addReplacementIntoPath(sel, context[k], el, inSelector);
+ // add that to our new set of selectors
+ selectorsMultiplied.push(newSelectorPath);
}
+ }
+ }
- //put together the parent selectors after the join
- if (parentSel.length > 1) {
- afterParentJoin = afterParentJoin.concat(parentSel.slice(1));
- }
+ // our new selectors has been multiplied, so reset the state
+ newSelectors = selectorsMultiplied;
+ currentElements = [];
+ }
+ }
- 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 we have any elements left over (e.g. .a& .b == .b)
+ // add them on to all the current selectors
+ mergeElementsOnToSelectors(currentElements, newSelectors);
- if (!newJoinedSelectorEmpty) {
- // now add the joined selector
- newSelectorPath.push(newJoinedSelector);
- }
+ for (i = 0; i < newSelectors.length; i++) {
+ if (newSelectors[i].length > 0) {
+ paths.push(newSelectors[i]);
+ }
+ }
+
+ return hadParentSelector;
+ }
- // and the rest of the parent
- newSelectorPath = newSelectorPath.concat(afterParentJoin);
+ // joins selector path from `beginningPath` with selector path in `addPath`
+ // `replacedElement` contains element that is being replaced by `addPath`
+ // returns concatenated path
+ function addReplacementIntoPath(beginningPath, addPath, replacedElement, originalSelector) {
+ var newSelectorPath, lastSelector, newJoinedSelector;
+ // our new selector path
+ newSelectorPath = [];
- // add that to our new set of selectors
- selectorsMultiplied.push(newSelectorPath);
- }
- }
+ //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 (beginningPath.length > 0) {
+ newSelectorPath = beginningPath.slice(0);
+ lastSelector = newSelectorPath.pop();
+ newJoinedSelector = originalSelector.createDerived(lastSelector.elements.slice(0));
+ }
+ else {
+ newJoinedSelector = originalSelector.createDerived([]);
+ }
+
+ if (addPath.length > 0) {
+ // /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 = replacedElement.combinator, parentEl = addPath[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, replacedElement.index, replacedElement.currentFileInfo));
+ newJoinedSelector.elements = newJoinedSelector.elements.concat(addPath[0].elements.slice(1));
+ }
- // our new selectors has been multiplied, so reset the state
- newSelectors = selectorsMultiplied;
- currentElements = [];
+ // now add the joined selector - but only if it is not empty
+ if (newJoinedSelector.elements.length !== 0) {
+ newSelectorPath.push(newJoinedSelector);
}
- }
- // 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);
+ //put together the parent selectors after the join (e.g. the rest of the parent)
+ if (addPath.length > 1) {
+ newSelectorPath = newSelectorPath.concat(addPath.slice(1));
+ }
+ return newSelectorPath;
}
- for (i = 0; i < newSelectors.length; i++) {
- if (newSelectors[i].length > 0) {
- paths.push(newSelectors[i]);
+ // joins selector path from `beginningPath` with every selector path in `addPaths` array
+ // `replacedElement` contains element that is being replaced by `addPath`
+ // returns array with all concatenated paths
+ function addAllReplacementsIntoPath( beginningPath, addPaths, replacedElement, originalSelector, result) {
+ var j;
+ for (j = 0; j < beginningPath.length; j++) {
+ var newSelectorPath = addReplacementIntoPath(beginningPath[j], addPaths, replacedElement, originalSelector);
+ result.push(newSelectorPath);
}
+ return result;
}
-};
-Ruleset.prototype.mergeElementsOnToSelectors = function(elements, selectors) {
- var i, sel;
- if (selectors.length === 0) {
- selectors.push([ new Selector(elements) ]);
- return;
+ function mergeElementsOnToSelectors(elements, selectors) {
+ var i, sel;
+
+ if (elements.length === 0) {
+ return ;
+ }
+ if (selectors.length === 0) {
+ selectors.push([ new Selector(elements) ]);
+ return;
+ }
+
+ for (i = 0; i < selectors.length; i++) {
+ sel = selectors[i];
+
+ // if the previous thing in sel is a parent this needs to join on to it
+ if (sel.length > 0) {
+ sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
+ }
+ else {
+ sel.push(new Selector(elements));
+ }
+ }
}
- for (i = 0; i < selectors.length; i++) {
- sel = selectors[i];
+ // joinSelector code follows
+ var i, newPaths, hadParentSelector;
+
+ newPaths = [];
+ hadParentSelector = replaceParentSelector(newPaths, context, selector);
- // if the previous thing in sel is a parent this needs to join on to it
- if (sel.length > 0) {
- sel[sel.length - 1] = sel[sel.length - 1].createDerived(sel[sel.length - 1].elements.concat(elements));
+ if (!hadParentSelector) {
+ if (context.length > 0) {
+ newPaths = [];
+ for (i = 0; i < context.length; i++) {
+ newPaths.push(context[i].concat(selector));
+ }
}
else {
- sel.push(new Selector(elements));
+ newPaths = [[selector]];
}
}
+
+ for (i = 0; i < newPaths.length; i++) {
+ paths.push(newPaths[i]);
+ }
+
};
- module.exports = Ruleset;
+ module.exports = Ruleset;
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-javascript/less.js.git
More information about the Pkg-javascript-commits
mailing list