stylecow-plugin-nested-rules
Advanced tools
| { | ||
| "class": "Root", | ||
| "children": [ | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "body" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "p" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "blue", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "html" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "body" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "active" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "body" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "blue", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "html" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "body" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "span" | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "active" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "body" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "span" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "blue", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } |
| body { | ||
| p { | ||
| color: blue; | ||
| } | ||
| html &, | ||
| .active & { | ||
| color: blue; | ||
| span { | ||
| color: blue; | ||
| } | ||
| } | ||
| } |
| body p { | ||
| color: blue; | ||
| } | ||
| html body, .active body { | ||
| color: blue; | ||
| } | ||
| html body span, .active body span { | ||
| color: blue; | ||
| } |
| { | ||
| "class": "Root", | ||
| "children": [ | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "foo" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "red", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "foo" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "bar" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "black", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Media", | ||
| "name": "media", | ||
| "children": [ | ||
| { | ||
| "class": "MediaQueries", | ||
| "children": [ | ||
| { | ||
| "class": "MediaQuery", | ||
| "children": [ | ||
| { | ||
| "class": "ConditionalExpression", | ||
| "children": [ | ||
| { | ||
| "class": "ConditionalFeature", | ||
| "name": "min-width", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Unit", | ||
| "name": "px", | ||
| "children": [ | ||
| { | ||
| "class": "Number", | ||
| "name": 500 | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "foo" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "bar" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "blue", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "foo" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "bar" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "span" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "green", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "foo" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "bar" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "p" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "black", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Media", | ||
| "name": "media", | ||
| "children": [ | ||
| { | ||
| "class": "MediaQueries", | ||
| "children": [ | ||
| { | ||
| "class": "MediaQuery", | ||
| "children": [ | ||
| { | ||
| "class": "ConditionalExpression", | ||
| "children": [ | ||
| { | ||
| "class": "ConditionalFeature", | ||
| "name": "min-width", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Unit", | ||
| "name": "px", | ||
| "children": [ | ||
| { | ||
| "class": "Number", | ||
| "name": 500 | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Keyword", | ||
| "name": "and" | ||
| }, | ||
| { | ||
| "class": "ConditionalExpression", | ||
| "children": [ | ||
| { | ||
| "class": "ConditionalExpression", | ||
| "children": [ | ||
| { | ||
| "class": "ConditionalFeature", | ||
| "name": "max-width", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Unit", | ||
| "name": "px", | ||
| "children": [ | ||
| { | ||
| "class": "Number", | ||
| "name": 899 | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Rule", | ||
| "children": [ | ||
| { | ||
| "class": "Selectors", | ||
| "children": [ | ||
| { | ||
| "class": "Selector", | ||
| "children": [ | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "foo" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "ClassSelector", | ||
| "name": "bar" | ||
| }, | ||
| { | ||
| "class": "Combinator", | ||
| "name": " " | ||
| }, | ||
| { | ||
| "class": "TypeSelector", | ||
| "name": "p" | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| }, | ||
| { | ||
| "class": "Block", | ||
| "children": [ | ||
| { | ||
| "class": "Declaration", | ||
| "name": "color", | ||
| "vendor": null, | ||
| "children": [ | ||
| { | ||
| "class": "Value", | ||
| "children": [ | ||
| { | ||
| "class": "Keyword", | ||
| "name": "red", | ||
| "vendor": null | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } | ||
| ] | ||
| } |
| .foo { | ||
| color: red; | ||
| .bar { | ||
| color: black; | ||
| @media (min-width: 500px) { | ||
| color: blue; | ||
| span { | ||
| color: green; | ||
| } | ||
| p { | ||
| color: black; | ||
| @media (max-width: 899px) { | ||
| color: red; | ||
| } | ||
| } | ||
| } | ||
| } | ||
| } |
| .foo { | ||
| color: red; | ||
| } | ||
| .foo .bar { | ||
| color: black; | ||
| } | ||
| @media (min-width: 500px) { | ||
| .foo .bar { | ||
| color: blue; | ||
| } | ||
| .foo .bar span { | ||
| color: green; | ||
| } | ||
| .foo .bar p { | ||
| color: black; | ||
| } | ||
| } | ||
| @media (min-width: 500px) and ((max-width: 899px)) { | ||
| .foo .bar p { | ||
| color: red; | ||
| } | ||
| } |
+81
-23
@@ -18,3 +18,3 @@ module.exports = function (stylecow) { | ||
| if (child.type === 'AtRule' && child.name === 'media') { | ||
| nestedMedia(parentRule, child, index + offset); | ||
| nestedRuleMedia(parentRule, child, index + offset); | ||
| ++offset; | ||
@@ -36,3 +36,29 @@ } | ||
| function nestedMedia(parentRule, media, parentRuleIndex) { | ||
| //Merge nested @media | ||
| stylecow.addTask({ | ||
| filter: { | ||
| type: 'AtRule', | ||
| name: 'media' | ||
| }, | ||
| fn: function (parentMedia) { | ||
| var index = parentMedia.index(); | ||
| var offset = 1; | ||
| parentMedia | ||
| .getChild('Block') | ||
| .getChildren({ | ||
| type: 'AtRule', | ||
| name: 'media' | ||
| }) | ||
| .forEach(function (child) { | ||
| nestedMedia(parentMedia, child, index + offset); | ||
| }); | ||
| if (!parentMedia.getChild('Block').length) { | ||
| parentRule.remove(); | ||
| } | ||
| } | ||
| }); | ||
| function nestedRuleMedia(parentRule, media, parentRuleIndex) { | ||
| var rule = new stylecow.Rule(); | ||
@@ -65,2 +91,18 @@ | ||
| function nestedMedia(parentMedia, media, parentMediaIndex) { | ||
| var mediaQueries = media.getChild('MediaQueries'); | ||
| var mergedMediaQueries = new stylecow.MediaQueries(); | ||
| parentMedia | ||
| .getChild('MediaQueries') | ||
| .forEach(function (parentMediaQuery) { | ||
| mediaQueries.forEach(function (mediaQuery) { | ||
| mergedMediaQueries.push(mergeMediaQuery(parentMediaQuery.clone(), mediaQuery.clone())); | ||
| }); | ||
| }); | ||
| mediaQueries.replaceWith(mergedMediaQueries); | ||
| parentMedia.getParent().splice(parentMediaIndex, 0, media); | ||
| } | ||
| function nestedRule(parentRule, rule, parentRuleIndex) { | ||
@@ -74,3 +116,3 @@ var selectors = rule.getChild('Selectors'); | ||
| selectors.forEach(function (selector) { | ||
| mergedSelectors.push(merge(parentSelector.clone(), selector.clone())); | ||
| mergedSelectors.push(mergeSelector(parentSelector.clone(), selector.clone())); | ||
| }); | ||
@@ -83,36 +125,52 @@ }); | ||
| function merge (selector, appendedSelector) { | ||
| var firstElement = appendedSelector.shift(); | ||
| function mergeSelector (selector, appendedSelector) { | ||
| var joinCombinator = appendedSelector.getChild({ | ||
| type: 'Combinator', | ||
| name: '&' | ||
| }); | ||
| // html { .foo { => html .foo | ||
| if (firstElement.type !== 'Combinator') { | ||
| var separator = (new stylecow.Combinator()).setName(' '); | ||
| selector.push(separator); | ||
| selector.push(firstElement); | ||
| if (!joinCombinator) { | ||
| if (appendedSelector[0].type !== 'Combinator') { | ||
| appendedSelector.unshift((new stylecow.Combinator()).setName(' ')); | ||
| } | ||
| joinCombinator = (new stylecow.Combinator()).setName('&'); | ||
| appendedSelector.unshift(joinCombinator); | ||
| } | ||
| // html { >.foo { => html>.foo | ||
| else if (firstElement.name !== '&') { | ||
| selector.push(firstElement); | ||
| } | ||
| // .foo { &html { => html.foo | ||
| else if (appendedSelector.length && appendedSelector[0].is('TypeSelector')) { | ||
| firstElement = appendedSelector.shift(); | ||
| //resolve .foo&html => html.foo | ||
| var next = joinCombinator.next(); | ||
| if (next && next.is('TypeSelector')) { | ||
| var combinators = selector.getChildren('Combinator'); | ||
| if (combinators.length) { | ||
| combinators.pop().after(firstElement); | ||
| combinators.pop().after(next); | ||
| } else { | ||
| selector.unshift(firstElement); | ||
| selector.unshift(next); | ||
| } | ||
| } | ||
| while (appendedSelector[0]) { | ||
| selector.push(appendedSelector[0]); | ||
| while (selector[0]) { | ||
| joinCombinator.before(selector.shift()); | ||
| } | ||
| return selector; | ||
| joinCombinator.remove(); | ||
| return appendedSelector; | ||
| } | ||
| function mergeMediaQuery (mediaQueries, appendedMediaQuery) { | ||
| var expression = new stylecow.ConditionalExpression(); | ||
| while (appendedMediaQuery[0]) { | ||
| expression.push(appendedMediaQuery.shift()); | ||
| } | ||
| var joinKeyword = (new stylecow.Keyword()).setName('and'); | ||
| mediaQueries.push(joinKeyword); | ||
| mediaQueries.push(expression); | ||
| return mediaQueries; | ||
| } | ||
| }; |
+1
-1
| { | ||
| "name": "stylecow-plugin-nested-rules", | ||
| "description": "Stylecow plugin to add support for nested rules.", | ||
| "version": "4.0.1", | ||
| "version": "4.1.0", | ||
| "author": "Oscar Otero <oom@oscarotero.com>", | ||
@@ -6,0 +6,0 @@ "homepage": "https://github.com/stylecow/stylecow-plugin-nested-rules", |
@@ -21,2 +21,2 @@ body { | ||
| } | ||
| } | ||
| } |
44312
80.65%19
46.15%1617
87.37%