diff --git a/CHANGELOG.md b/CHANGELOG.md index fc16a22..4cd88f6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,26 @@ -# v0.17.0 - 2020-4-24 +# v0.19.0 - 2023-04-12 + +- Fix nesting edge case with comma separated selectors + - Thank you to [@marapper](https://github.com/marapper) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/131) + +# v0.18.0 - 2021-05-11 + +- [breaking] Add basic postcss 8 support (older versions of PostCSS no longer compatible) + - Thank you to [@delucis](https://github.com/delucis) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/129) + + +# v0.17.0 - 2020-04-24 - Expand variables in AtRule properties - Thank you to [@pvande](https://github.com/pvande) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/104) - Merged via https://github.com/MadLittleMods/postcss-css-variables/pull/121 -# v0.16.0 - 2020-4-24 +# v0.16.0 - 2020-04-24 - Add ability to pass callback function to `options.preserve` to determine whether to preserve declaration - Thank you to [@ekatioz](https://github.com/ekatioz) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/116) -# v0.15.0 - 2020-4-24 +# v0.15.0 - 2020-04-24 - Fix algorithm to find balanced `var()` pairs and nested parenthesis - Thank you to [@Poetro](https://github.com/Poetro) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/112) @@ -19,55 +30,55 @@ - Fix regex in `resolve-value.js` to allow nested CSS functions - Thank you to [@juliovedovatto](https://github.com/juliovedovatto) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/97) -# v0.13.0 - 2019-6-17 +# v0.13.0 - 2019-06-17 - Add `options.preserveAtRulesOrder` so media queries are outputted in the order they are defined (as expected) - Thank you to [@erikthalen](https://github.com/erikthalen) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/92) via https://github.com/MadLittleMods/postcss-css-variables/pull/101 - Remove `calc` from readme table of contents for non-existent section - Thank you to [@AlexandreArpin](https://github.com/AlexandreArpin) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/99) -# v0.12.0 - 2019-2-21 +# v0.12.0 - 2019-02-21 - Accept whitespace in `var( --var )` expression - Thank you to [@benwest](https://github.com/benwest) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/93) -# v0.11.0 - 2018-10-9 +# v0.11.0 - 2018-10-09 - Fix JS-defined variables using `isImportant`, https://github.com/MadLittleMods/postcss-css-variables/pull/87 -# v0.10.0 - 2018-9-25 +# v0.10.0 - 2018-09-25 - Cast `opts.variables` variable values to string - Thank you to [@shonie](https://github.com/shonie) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/84) -# v0.9.0 - 2018-6-26 +# v0.9.0 - 2018-06-26 - Adds `opts.preserveInjectedVariables`, which when set to `false`, removes the `:root { ... }` custom property declarations added via `opts.variables` - Thank you to [@akdetrick](https://github.com/akdetrick) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/74) -# v0.8.1 - 2018-3-21 +# v0.8.1 - 2018-03-21 - Log `undefined` variables (available in `result.warnings()`) - Thank you to [@pixeldrew](https://github.com/pixeldrew) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/69) -# v0.8.0 - 2017-8-8 +# v0.8.0 - 2017-08-08 - Remove PostCSS `moveTo`/`append` deprecation warnings, [#50](https://github.com/MadLittleMods/postcss-css-variables/issues/50) - Thank you to [@modosc](https://github.com/modosc) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/56) -# v0.7.0 - 2017-3-12 +# v0.7.0 - 2017-03-12 - Resolve `var` usage in fallbacks, [#37](https://github.com/MadLittleMods/postcss-css-variables/issues/37) - Thank you to [@asvny](https://github.com/asvny) and [@marklu](https://github.com/marklu) for the contribution, [#39](https://github.com/MadLittleMods/postcss-css-variables/issues/39) -> [#49](https://github.com/MadLittleMods/postcss-css-variables/pull/49) -# v0.6.0 - 2016-9-23 +# v0.6.0 - 2016-09-23 - Update/refactor readme - Thank you to [@isiahmeadows](github.com/isiahmeadows) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/36) - Use string value for `undefined` variables to play nice with other plugins downstream - Thank you to [@vincentorback](github.com/vincentorback) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/44) -# v0.5.2 - 2016-8-24 +# v0.5.2 - 2016-08-24 - Fix [#42](https://github.com/MadLittleMods/postcss-css-variables/issues/42) where `opts.preserve` was not working inside at-rules - Thank you to [@muftiev](github.com/muftiev) for the [contribution](https://github.com/MadLittleMods/postcss-css-variables/pull/43) @@ -77,64 +88,64 @@ - Fix [postcss/postcss#611](https://github.com/postcss/postcss/issues/611) where we were trying to remove the root node on clean up - Improved test setup -# v0.5.0 - 2015-9-12 +# v0.5.0 - 2015-09-12 - Upgrade to PostCSS v5. Fix [#20](https://github.com/MadLittleMods/postcss-css-variables/issues/20) -# v0.4.0 - 2015-7-2 +# v0.4.0 - 2015-07-02 - Fix [#15](https://github.com/MadLittleMods/postcss-css-variables/issues/15) - Remove slowness from cloning the `root` with `node.clone().removeAll()`. Now using `./lib/shallow-clone-node.js` to avoid cloning children which will get removed right after. - Thank you to [@ddprrt](https://github.com/ddprrt) for bringing up the slowness issue in this article, [PostCSS misconceptions](https://medium.com/@ddprrt/postcss-misconceptions-faf5dc5038df). -# v0.3.9 - 2015-6-29 +# v0.3.9 - 2015-06-29 - Remove `opts` global leak. Fix [#13](https://github.com/MadLittleMods/postcss-css-variables/issues/13) -# v0.3.8 - 2015-5-28 +# v0.3.8 - 2015-05-28 - Add support for pseudo selectors `:hover` `:before` -# v0.3.7 - 2015-5-27 +# v0.3.7 - 2015-05-27 - Fix [#7](https://github.com/MadLittleMods/postcss-css-variables/issues/7): Support for child combinator - Added tests for child-combinator/direct-descendant coverage -# v0.3.6 - 2015-5-21 +# v0.3.6 - 2015-05-21 - Fix [#6](https://github.com/MadLittleMods/postcss-css-variables/issues/6). Variable usage in comma separated selector to use proper scope -# v0.3.5 - 2015-5-12 +# v0.3.5 - 2015-05-12 - Big refactor of code to reduce cyclomatic complexity. Still needs work though. - Fix variable referencing another variable resolution when being changed by at-rule in non-root rule -# v0.3.4 - 2015-5-12 +# v0.3.4 - 2015-05-12 - Fix variable referencing another variable resolution when being changed by at-rule -# v0.3.3 - 2015-5-11 +# v0.3.3 - 2015-05-11 - Add support for last piece of combinator chain in selector resolution matching. - `.foo + .bar` can match variables declared in `.bar` -# v0.3.1 - 2015-5-5 +# v0.3.1 - 2015-05-05 - Large overhaul of code to make it more robust on proper scope resolution. - Fix [#2]](https://github.com/MadLittleMods/postcss-css-variables/issues/2) -# v0.2.3 - 2015-5-4 +# v0.2.3 - 2015-05-04 - Add support for CSS4 descendant selector `>>` syntax -# v0.2.2 - 2015-5-1 +# v0.2.2 - 2015-05-01 - Automatically prefix any variables defined in `options.variables` with `--` (according to CSS custom property syntax). -# v0.2.1 - 2015-4-30 +# v0.2.1 - 2015-04-30 - Added support for descendant selector nesting instead of just physical space nesting - Fixed issue with comma separated rules. It was throwing a undefined is not a function error - Moved to external scope check `isUnderScope` instead of integrated into `resolveValue` - Added test for empty `var()` call. See [test/fixtures/empty-var-func.css](https://github.com/MadLittleMods/postcss-css-variables/blob/master/test/fixtures/empty-var-func.css) -# v0.1.0 - 2015-4-29 +# v0.1.0 - 2015-04-29 - First release diff --git a/README.md b/README.md index 42ce497..85f2185 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,7 @@ ### Install ``` -npm install postcss-css-variables --save-dev +npm install postcss postcss-css-variables --save-dev ``` ### Table of Contents diff --git a/index.js b/index.js index 23534e4..4174270 100644 --- a/index.js +++ b/index.js @@ -6,7 +6,6 @@ // For Debugging //var nomo = require('node-monkey').start({port: 50501}); -var postcss = require("postcss"); var extend = require("extend"); var shallowCloneNode = require("./lib/shallow-clone-node"); @@ -64,198 +63,199 @@ var defaults = { preserveAtRulesOrder: false }; -module.exports = postcss.plugin("postcss-css-variables", function(options) { +module.exports = (options = {}) => { var opts = extend({}, defaults, options); // Work with opts here - return function(css, result) { - // Transform CSS AST here - - /* * / - try { - /* */ - - // List of nodes that if empty, will be removed - // We use this because we don't want to modify the AST when we still need to reference these later on - var nodesToRemoveAtEnd = []; - - // Keep track of the injected from `opts.variables` to remove at the end - // if user passes `opts.preserveInjectedVariables = false` - var injectedDeclsToRemoveAtEnd = []; - - // Map of variable names to a list of declarations - var map = {}; - - // Add the js defined variables `opts.variables` to the map - map = extend( - map, - Object.keys(opts.variables).reduce(function( - prevVariableMap, - variableName - ) { - var variableEntry = opts.variables[variableName]; - // Automatically prefix any variable with `--` (CSS custom property syntax) if it doesn't have it already - variableName = - variableName.slice(0, 2) === "--" - ? variableName - : "--" + variableName; - var variableValue = (variableEntry || {}).value || variableEntry; - var isImportant = (variableEntry || {}).isImportant || false; - - // Add a root node to the AST - var variableRootRule = postcss.rule({ selector: ":root" }); - css.root().prepend(variableRootRule); - // Add the variable decl to the root node - var varDecl = postcss.decl({ - prop: variableName, - value: variableValue, - important: isImportant - }); - variableRootRule.append(varDecl); + return { + postcssPlugin: 'postcss-css-variables', + Once(css, { decl, result, rule }) { + // Transform CSS AST here + + /* * / + try { + /* */ + + // List of nodes that if empty, will be removed + // We use this because we don't want to modify the AST when we still need to reference these later on + var nodesToRemoveAtEnd = []; + + // Keep track of the injected from `opts.variables` to remove at the end + // if user passes `opts.preserveInjectedVariables = false` + var injectedDeclsToRemoveAtEnd = []; + + // Map of variable names to a list of declarations + var map = {}; + + // Add the js defined variables `opts.variables` to the map + map = extend( + map, + Object.keys(opts.variables).reduce(function( + prevVariableMap, + variableName + ) { + var variableEntry = opts.variables[variableName]; + // Automatically prefix any variable with `--` (CSS custom property syntax) if it doesn't have it already + variableName = + variableName.slice(0, 2) === "--" + ? variableName + : "--" + variableName; + var variableValue = (variableEntry || {}).value || variableEntry; + var isImportant = (variableEntry || {}).isImportant || false; + + // Add a root node to the AST + var variableRootRule = rule({ selector: ":root" }); + css.root().prepend(variableRootRule); + // Add the variable decl to the root node + var varDecl = decl({ + prop: variableName, + value: variableValue, + important: isImportant + }); + variableRootRule.append(varDecl); + + // Collect JS-injected variables for removal if `opts.preserveInjectedVariables = false` + if (!opts.preserveInjectedVariables) { + injectedDeclsToRemoveAtEnd.push(varDecl); + } - // Collect JS-injected variables for removal if `opts.preserveInjectedVariables = false` - if (!opts.preserveInjectedVariables) { - injectedDeclsToRemoveAtEnd.push(varDecl); - } + // Add the entry to the map + prevVariableMap[variableName] = ( + prevVariableMap[variableName] || [] + ).concat({ + decl: varDecl, + prop: variableName, + calculatedInPlaceValue: variableValue, + isImportant: isImportant, + variablesUsed: [], + parent: variableRootRule, + isUnderAtRule: false + }); + + return prevVariableMap; + }, + {}) + ); + + // Chainable helper function to log any messages (warnings) + var logResolveValueResult = function(valueResult) { + // Log any warnings that might of popped up + var warningList = [].concat(valueResult.warnings); + warningList.forEach(function(warningArgs) { + warningArgs = [].concat(warningArgs); + result.warn.apply(result, warningArgs); + }); - // Add the entry to the map - prevVariableMap[variableName] = ( - prevVariableMap[variableName] || [] - ).concat({ - decl: varDecl, - prop: variableName, - calculatedInPlaceValue: variableValue, - isImportant: isImportant, - variablesUsed: [], - parent: variableRootRule, - isUnderAtRule: false + // Keep the chain going + return valueResult; + }; + + // Collect all of the variables defined + // --------------------------------------------------------- + // --------------------------------------------------------- + //console.log('Collecting variables defined START'); + eachCssVariableDeclaration(css, function(decl) { + var declParentRule = decl.parent; + + var valueResults = logResolveValueResult(resolveValue(decl, map)); + // Split out each selector piece into its own declaration for easier logic down the road + decl.parent.selectors.forEach(function(selector) { + // Create a detached clone + var splitOutRule = shallowCloneNode(decl.parent); + splitOutRule.selector = selector; + splitOutRule.parent = decl.parent.parent; + + var declClone = decl.clone(); + splitOutRule.append(declClone); + + var prop = decl.prop; + map[prop] = (map[prop] || []).concat({ + decl: declClone, + prop: prop, + calculatedInPlaceValue: valueResults.value, + isImportant: decl.important || false, + variablesUsed: valueResults.variablesUsed, + parent: splitOutRule, + // variables inside root or at-rules (eg. @media, @support) + isUnderAtRule: splitOutRule.parent.type === "atrule" + }); }); - return prevVariableMap; - }, - {}) - ); - - // Chainable helper function to log any messages (warnings) - var logResolveValueResult = function(valueResult) { - // Log any warnings that might of popped up - var warningList = [].concat(valueResult.warnings); - warningList.forEach(function(warningArgs) { - warningArgs = [].concat(warningArgs); - result.warn.apply(result, warningArgs); - }); + let preserveDecl; + if (typeof opts.preserve === "function") { + preserveDecl = opts.preserve(decl); + } else { + preserveDecl = opts.preserve; + } + // Remove the variable declaration because they are pretty much useless after we resolve them + if (!preserveDecl) { + decl.remove(); + } + // Or we can also just show the computed value used for that variable + else if (preserveDecl === "computed") { + decl.value = valueResults.value; + } + // Otherwise just keep them as var declarations + //else {} - // Keep the chain going - return valueResult; - }; - - // Collect all of the variables defined - // --------------------------------------------------------- - // --------------------------------------------------------- - //console.log('Collecting variables defined START'); - eachCssVariableDeclaration(css, function(decl) { - var declParentRule = decl.parent; - - var valueResults = logResolveValueResult(resolveValue(decl, map)); - // Split out each selector piece into its own declaration for easier logic down the road - decl.parent.selectors.forEach(function(selector) { - // Create a detached clone - var splitOutRule = shallowCloneNode(decl.parent); - splitOutRule.selector = selector; - splitOutRule.parent = decl.parent.parent; - - var declClone = decl.clone(); - splitOutRule.append(declClone); - - var prop = decl.prop; - map[prop] = (map[prop] || []).concat({ - decl: declClone, - prop: prop, - calculatedInPlaceValue: valueResults.value, - isImportant: decl.important || false, - variablesUsed: valueResults.variablesUsed, - parent: splitOutRule, - // variables inside root or at-rules (eg. @media, @support) - isUnderAtRule: splitOutRule.parent.type === "atrule" - }); + // We add to the clean up list if we removed some variable declarations to make it become an empty rule + // We clean up later on because we don't want to modify the AST when we still need to reference these later on + if (declParentRule.nodes.length <= 0) { + nodesToRemoveAtEnd.push(declParentRule); + } }); + //console.log('Collecting variables defined END'); - let preserveDecl; - if (typeof opts.preserve === "function") { - preserveDecl = opts.preserve(decl); - } else { - preserveDecl = opts.preserve; - } - // Remove the variable declaration because they are pretty much useless after we resolve them - if (!preserveDecl) { - decl.remove(); - } - // Or we can also just show the computed value used for that variable - else if (preserveDecl === "computed") { - decl.value = valueResults.value; - } - // Otherwise just keep them as var declarations - //else {} + // Resolve variables everywhere + // --------------------------------------------------------- + // --------------------------------------------------------- - // We add to the clean up list if we removed some variable declarations to make it become an empty rule - // We clean up later on because we don't want to modify the AST when we still need to reference these later on - if (declParentRule.nodes.length <= 0) { - nodesToRemoveAtEnd.push(declParentRule); - } - }); - //console.log('Collecting variables defined END'); - - // Resolve variables everywhere - // --------------------------------------------------------- - // --------------------------------------------------------- - - // Collect all the rules that have declarations that use variables - var rulesThatHaveDeclarationsWithVariablesList = []; - css.walk(function(rule) { - // We're only interested in Containers with children. - if (rule.nodes === undefined) return; - - var doesRuleUseVariables = rule.nodes.some(function(node) { - if (node.type === "decl") { - var decl = node; - // If it uses variables - // and is not a variable declarations that we may be preserving from earlier - if ( - resolveValue.RE_VAR_FUNC.test(decl.value) && - !RE_VAR_PROP.test(decl.prop) - ) { - return true; - } - } + // Collect all the rules that have declarations that use variables + var rulesThatHaveDeclarationsWithVariablesList = []; + css.walk(function(rule) { + // We're only interested in Containers with children. + if (rule.nodes === undefined) return; - return false; - }); + var doesRuleUseVariables = rule.nodes.some(function(node) { + if (node.type === "decl") { + var decl = node; + // If it uses variables + // and is not a variable declarations that we may be preserving from earlier + if ( + resolveValue.RE_VAR_FUNC.test(decl.value) && + !RE_VAR_PROP.test(decl.prop) + ) { + return true; + } + } - if (doesRuleUseVariables) { - rulesThatHaveDeclarationsWithVariablesList.push(rule); - } - }); - - rulesThatHaveDeclarationsWithVariablesList.forEach(function(rule) { - var rulesToWorkOn = [].concat(rule); - // Split out the rule into each comma separated selector piece - // We only need to split if it's actually a Rule with multiple selectors (comma separated) - if (rule.type === "rule" && rule.selectors.length > 1) { - // Reverse the selectors so that we can cloneAfter in the same comma separated order - rulesToWorkOn = rule.selectors.reverse().map(function(selector) { - var ruleClone = rule.cloneAfter(); - ruleClone.selector = selector; - - return ruleClone; + return false; }); - rule.remove(); - } + if (doesRuleUseVariables) { + if (rule.type === "rule" && rule.selectors.length > 1) { + // Split out the rule into each comma separated selector piece + // We only need to split if it's actually a Rule with multiple selectors (comma separated) + // duplicate rules would be probably merged with cssnano (cannot be sure about nested) + rule.selectors.reverse().forEach(function(selector) { + var ruleClone = rule.cloneAfter(); + ruleClone.selector = selector; + + return ruleClone; + }); + + // Rules will be added to list in the next traverse + rule.remove(); + } else { + rulesThatHaveDeclarationsWithVariablesList.push(rule); + } + } + }); - // Resolve the declarations - rulesToWorkOn.forEach(function(ruleToWorkOn) { - ruleToWorkOn.nodes.slice(0).forEach(function(node) { + rulesThatHaveDeclarationsWithVariablesList.forEach(function(rule) { + // Resolve the declarations + rule.nodes.slice(0).forEach(function(node) { if (node.type === "decl") { var decl = node; resolveDecl( @@ -268,25 +268,27 @@ module.exports = postcss.plugin("postcss-css-variables", function(options) { } }); }); - }); - - // Clean up any nodes we don't want anymore - // We clean up at the end because we don't want to modify the AST when we still need to reference these later on - nodesToRemoveAtEnd.forEach(cleanUpNode); - - // Clean up JS-injected variables marked for removal - injectedDeclsToRemoveAtEnd.forEach(function(injectedDecl) { - injectedDecl.remove(); - }); - - //console.log('map', map); - - /* * / - } - catch(e) { - //console.log('e', e.message); - console.log('e', e.message, e.stack); - } - /* */ + + // Clean up any nodes we don't want anymore + // We clean up at the end because we don't want to modify the AST when we still need to reference these later on + nodesToRemoveAtEnd.forEach(cleanUpNode); + + // Clean up JS-injected variables marked for removal + injectedDeclsToRemoveAtEnd.forEach(function(injectedDecl) { + injectedDecl.remove(); + }); + + //console.log('map', map); + + /* * / + } + catch(e) { + //console.log('e', e.message); + console.log('e', e.message, e.stack); + } + /* */ + } }; -}); +}; + +module.exports.postcss = true; diff --git a/package.json b/package.json index 8fbb1d5..35c8403 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "postcss-css-variables", - "version": "0.17.0", + "version": "0.19.0", "description": "PostCSS plugin to transform CSS Custom Properties(CSS variables) syntax into a static representation", "keywords": [ "postcss", @@ -16,8 +16,7 @@ "dependencies": { "balanced-match": "^1.0.0", "escape-string-regexp": "^1.0.3", - "extend": "^3.0.1", - "postcss": "^6.0.8" + "extend": "^3.0.1" }, "devDependencies": { "bluebird": "^3.5.0", @@ -27,9 +26,13 @@ "eslint": "^4.4.1", "eslint-plugin-react": "^7.1.0", "mocha": "^5.2.0", + "postcss": "^8.2.6", "postcss-discard-comments": "^4.0.0", "postcss-normalize-whitespace": "^4.0.0" }, + "peerDependencies": { + "postcss": "^8.2.6" + }, "scripts": { "test": "mocha", "lint": "eslint ." diff --git a/test/fixtures/cascade-and-multiple-on-nested-rules.css b/test/fixtures/cascade-and-multiple-on-nested-rules.css new file mode 100644 index 0000000..cd5a678 --- /dev/null +++ b/test/fixtures/cascade-and-multiple-on-nested-rules.css @@ -0,0 +1,37 @@ +:root { + --some-width: 150px; +} +:root { + --White1: #FFF; +} + +.a, .b { + width: var(--some-width); + + .simple { + color: var(--White1); + } +} + +.a { + width: var(--some-width); + + a, label, &:after { + color: var(--White1); + } +} + +/* postcss-nested double parent selector case */ +.a, .b { + /* here variable */ + width: var(--some-width); + + /* and here another */ + a, label { + background: var(--White1); + + ol, ul { + width: var(--some-width); + } + } +} diff --git a/test/fixtures/cascade-and-multiple-on-nested-rules.expected.css b/test/fixtures/cascade-and-multiple-on-nested-rules.expected.css new file mode 100644 index 0000000..30a5568 --- /dev/null +++ b/test/fixtures/cascade-and-multiple-on-nested-rules.expected.css @@ -0,0 +1,87 @@ +.a { + width: 150px; + + .simple { + color: #FFF + } +} + +.b { + width: 150px; + + .simple { + color: #FFF + } +} + +.a { + width: 150px; + + a { + color: #FFF + } + + label { + color: #FFF + } + + &:after { + color: #FFF + } +} + +.a { + width: 150px; + + a { + background: #FFF; + + ol { + width: 150px; + } + + ul { + width: 150px; + } + } + + label { + background: #FFF; + + ol { + width: 150px; + } + + ul { + width: 150px; + } + } +} + +.b { + width: 150px; + + a { + background: #FFF; + + ol { + width: 150px; + } + + ul { + width: 150px; + } + } + + label { + background: #FFF; + + ol { + width: 150px; + } + + ul { + width: 150px; + } + } +} diff --git a/test/test.js b/test/test.js index 45a2f33..e8f0af8 100644 --- a/test/test.js +++ b/test/test.js @@ -186,6 +186,8 @@ describe("postcss-css-variables", function() { test("should cascade to nested rules", "cascade-on-nested-rules"); + test("should cascade to nested multiple rules", "cascade-and-multiple-on-nested-rules"); + test( "should cascade with calc-expression to nested rules", "cascade-with-calc-expression-on-nested-rules"