diff --git a/README.md b/README.md
index ad1dc2c..ea6978a 100644
--- a/README.md
+++ b/README.md
@@ -12,70 +12,56 @@ npm install postcss-css-variables --save-dev
### Table of Contents
- - [Code Playground](#code-playground)
- - [Usage](#usage)
- - [Syntax](#syntax)
- - [Defining Custom Properties with `--*`](#defining-custom-properties-with---)
- - [Using Variables/Custom Properties with `var()`](#using-variables-custom-properties-with-var)
- - [Features](#features)
- - [At-rules like `@media`, `@support`, etc.](#at-rules-like-media-support-etc)
- - [Pseudo-classes and Elements](#pseudo-classes-and-elements)
- - [Nested Rules](#nested-rules)
- - [Why?](#why)
- - [Interoperability](#interoperability)
- - [Differences from `postcss-custom-properties`](#differences-from-postcss-custom-properties)
- - [Caveats](#caveats)
- - [Options](#options)
- - [Quick Reference/Notes](#quick-referencenotes)
- - [Testing](#testing)
- - [Changelog](https://github.com/MadLittleMods/postcss-css-variables/blob/master/CHANGELOG.md)
-
+- [Code Playground](#code-playground)
+- [Usage](#usage)
+- [Syntax](#syntax) - [Defining Custom Properties with `--*`](#defining-custom-properties-with---) - [Using Variables/Custom Properties with `var()`](#using-variables-custom-properties-with-var)
+- [Features](#features) - [At-rules like `@media`, `@support`, etc.](#at-rules-like-media-support-etc) - [Pseudo-classes and Elements](#pseudo-classes-and-elements) - [Nested Rules](#nested-rules)
+- [Why?](#why) - [Interoperability](#interoperability) - [Differences from `postcss-custom-properties`](#differences-from-postcss-custom-properties)
+- [Caveats](#caveats)
+- [Options](#options)
+- [Quick Reference/Notes](#quick-referencenotes)
+- [Testing](#testing)
+- [Changelog](https://github.com/MadLittleMods/postcss-css-variables/blob/master/CHANGELOG.md)
# [Code Playground](https://madlittlemods.github.io/postcss-css-variables/playground/)
[Try it in the playground](https://madlittlemods.github.io/postcss-css-variables/playground/) and see what you think! Just add some CSS and see to see the final transformed/compiled CSS. You can try anything here in the playground, too.
-
# Usage
-[*For more general PostCSS usage, look here.*](https://github.com/postcss/postcss#usage)
+[_For more general PostCSS usage, look here._](https://github.com/postcss/postcss#usage)
```js
-var postcss = require('postcss');
-var cssvariables = require('postcss-css-variables');
+var postcss = require("postcss");
+var cssvariables = require("postcss-css-variables");
-var fs = require('fs');
+var fs = require("fs");
-var mycss = fs.readFileSync('input.css', 'utf8');
+var mycss = fs.readFileSync("input.css", "utf8");
// Process your CSS with postcss-css-variables
-var output = postcss([
- cssvariables(/*options*/)
- ])
- .process(mycss)
- .css;
+var output = postcss([cssvariables(/*options*/)]).process(mycss).css;
console.log(output);
```
-
# Syntax
### Defining Custom Properties with `--*`
A custom property is any property whose name starts with two dashes `--`. A property must be in a rule.
-*Note: `:root` is nothing more than the selector for the root DOM node. Any other selector like `.class`, `#id`, or even `#foo ~ .bar > span.baz` works.*
+_Note: `:root` is nothing more than the selector for the root DOM node. Any other selector like `.class`, `#id`, or even `#foo ~ .bar > span.baz` works._
```css
:root {
- --foo-width: 100px;
- --foo-bg-color: rgba(255, 0, 0, 0.85);
+ --foo-width: 100px;
+ --foo-bg-color: rgba(255, 0, 0, 0.85);
}
.foo {
- --foo-width: 100px;
- --foo-bg-color: rgba(255, 0, 0, 0.85);
+ --foo-width: 100px;
+ --foo-bg-color: rgba(255, 0, 0, 0.85);
}
```
@@ -83,41 +69,39 @@ Custom properties can be declared multiple times, but like variable scope in oth
```css
:root {
- --some-color: red;
+ --some-color: red;
}
.foo {
- /* red */
- color: var(--some-color);
+ /* red */
+ color: var(--some-color);
}
-
.bar {
- --some-color: blue;
- /* blue */
- color: var(--some-color);
+ --some-color: blue;
+ /* blue */
+ color: var(--some-color);
}
.bar:hover {
- --some-color: green;
- /* Automatically gets a `color: green;` declaration because we `--some-color` used within scope elsewhere */
+ --some-color: green;
+ /* Automatically gets a `color: green;` declaration because we `--some-color` used within scope elsewhere */
}
```
-*[W3C Draft: CSS Custom Properties for Cascading Variables, section 2](http://dev.w3.org/csswg/css-variables/#defining-variables)*
+_[W3C Draft: CSS Custom Properties for Cascading Variables, section 2](http://dev.w3.org/csswg/css-variables/#defining-variables)_
### Using Variables/Custom Properties with `var()`
```css
.foo {
- width: var(--foo-width);
- /* You can even provide a fallback */
- background: var(--foo-bg-color, #ff0000);
+ width: var(--foo-width);
+ /* You can even provide a fallback */
+ background: var(--foo-bg-color, #ff0000);
}
```
-*[W3C Draft: CSS Custom Properties for Cascading Variables, section 3](http://dev.w3.org/csswg/css-variables/#using-variables)*
-
+_[W3C Draft: CSS Custom Properties for Cascading Variables, section 3](http://dev.w3.org/csswg/css-variables/#using-variables)_
# Features
@@ -127,17 +111,17 @@ It's perfectly okay to declare CSS variables inside media queries and the like.
```css
:root {
- --width: 100px;
+ --width: 100px;
}
@media (max-width: 1000px) {
- :root {
- --width: 200px;
- }
+ :root {
+ --width: 200px;
+ }
}
.box {
- width: var(--width);
+ width: var(--width);
}
```
@@ -145,13 +129,13 @@ Will be transformed to:
```css
.box {
- width: 100px;
+ width: 100px;
}
@media (max-width: 1000px) {
- .box {
- width: 200px;
- }
+ .box {
+ width: 200px;
+ }
}
```
@@ -161,12 +145,12 @@ Psuedo-classes are also dealt with correctly, because it's easy to statically de
```css
.foo {
- --foo-color: red;
- color: var(--foo-color);
+ --foo-color: red;
+ color: var(--foo-color);
}
.foo:hover {
- --foo-color: green;
+ --foo-color: green;
}
```
@@ -174,11 +158,11 @@ Will be transformed to:
```css
.foo {
- color: red;
+ color: red;
}
.foo:hover {
- color: green;
+ color: green;
}
```
@@ -186,24 +170,21 @@ Will be transformed to:
This pairs very well with [`postcss-nested`](https://github.com/postcss/postcss-nested) or [`postcss-nesting`](https://github.com/jonathantneal/postcss-nesting), adding support for nested rules. For either, you must put the plugin before `postcss-css-variables` in the plugin stack so that the `&` references are expanded first (`postcss-css-variables` doesn't understand them). For example, with `postcss-nested`, your PostCSS setup would look like this:
-
```js
-var postcss = require('postcss');
-var cssvariables = require('postcss-css-variables');
-var nested = require('postcss-nested');
+var postcss = require("postcss");
+var cssvariables = require("postcss-css-variables");
+var nested = require("postcss-nested");
-var fs = require('fs');
+var fs = require("fs");
-var mycss = fs.readFileSync('input.css', 'utf8');
+var mycss = fs.readFileSync("input.css", "utf8");
var output = postcss([
- // Flatten/unnest rules
- nested,
- // Then process any CSS variables
- cssvariables(/*options*/)
- ])
- .process(mycss)
- .css;
+ // Flatten/unnest rules
+ nested,
+ // Then process any CSS variables
+ cssvariables(/*options*/)
+]).process(mycss).css;
console.log(output);
```
@@ -212,12 +193,12 @@ For a simple example with nesting:
```css
.box-foo {
- --some-width: 150px;
- width: var(--some-width);
+ --some-width: 150px;
+ width: var(--some-width);
- .box-bar {
- width: var(--some-width);
- }
+ .box-bar {
+ width: var(--some-width);
+ }
}
```
@@ -225,11 +206,11 @@ With also `postcss-nesting`, this will be transformed to:
```css
.box-foo {
- width: 150px;
+ width: 150px;
}
.box-foo .box-bar {
- width: 150px;
+ width: 150px;
}
```
@@ -237,21 +218,21 @@ For a more complex example with a media query:
```css
:root {
- --some-width: 150px;
+ --some-width: 150px;
}
.box-foo {
- width: var(--some-width);
+ width: var(--some-width);
- .box-bar {
- width: var(--some-width);
- }
+ .box-bar {
+ width: var(--some-width);
+ }
}
@media (max-width: 800px) {
- .box-foo {
- --some-width: 300px;
- }
+ .box-foo {
+ --some-width: 300px;
+ }
}
```
@@ -259,26 +240,24 @@ Will be transformed to:
```css
.box-foo {
- width: 150px;
+ width: 150px;
}
.box-foo .box-bar {
- width: 150px;
+ width: 150px;
}
@media (max-width: 800px) {
- .box-foo {
- width: 300px;
- }
+ .box-foo {
+ width: 300px;
+ }
- .box-foo .box-bar {
- width: 300px;
- }
+ .box-foo .box-bar {
+ width: 300px;
+ }
}
```
-
-
# Why?
This plugin was spawned out of a [discussion on the `cssnext` repo](https://github.com/cssnext/cssnext/issues/99) and a personal need.
@@ -295,14 +274,13 @@ In `postcss-css-variables`, this is not the case and they may be declared inside
Here's a quick overview of the differences:
- - CSS variables may be declared in any selector like `.foo` or `.foo .bar:hover`, and is not limited to just `:root`
- - CSS variables may be declared in `@media`, `@support`, and other at-rules.
- - CSS variables may be declared in `:hover` and other psuedo-classes, which get expanded properly.
- - Variables in nested rules can be deduced with the help of [`postcss-nested`](https://github.com/postcss/postcss-nested) or [`postcss-nesting`](https://github.com/jonathantneal/postcss-nesting).
+- CSS variables may be declared in any selector like `.foo` or `.foo .bar:hover`, and is not limited to just `:root`
+- CSS variables may be declared in `@media`, `@support`, and other at-rules.
+- CSS variables may be declared in `:hover` and other psuedo-classes, which get expanded properly.
+- Variables in nested rules can be deduced with the help of [`postcss-nested`](https://github.com/postcss/postcss-nested) or [`postcss-nesting`](https://github.com/jonathantneal/postcss-nesting).
Continue to the next section to see where some of these might be unsafe to do. There are reasons behind the ethos of why the other plugin, [`postcss-custom-properties`](https://github.com/postcss/postcss-custom-properties), is very limited in what it supports, due to differing opinions on what is okay to support.
-
# Caveats
When you declare a CSS variable inside one selector, but consume it in another, this does make an unsafe assumption about it which can be non-conforming in certain edge cases. Here is an example where these limitations result in non-conforming behavior.
@@ -311,17 +289,17 @@ Note the nested markup below. We only know about the DOM's inheritance from your
```html
- Black
+ Black
-
- Blue
+
+ Blue
-
- Green
+
+ Green
-
Blue with this plugin, but green per spec
-
+
Blue with this plugin, but green per spec
+
```
@@ -340,10 +318,8 @@ Note the nested markup below. We only know about the DOM's inheritance from your
}
```
-
[`postcss-custom-properties`](https://github.com/postcss/postcss-custom-properties) avoids this problem entirely by restricting itself to just the `:root` selector. This is because the developers there would prefer to not support a feature instead of something almost-spec-compliant like what `postcss-css-variables` does.
-
# Options
### `preserve` (default: `false`)
@@ -352,10 +328,10 @@ Allows you to preserve custom properties & var() usage in output.
Possible values:
- - `false`: Removes `--var` declarations and replaces `var()` with their resolved/computed values.
- - `true`: Keeps `var()` declarations in the output and has the computed value as a fallback declaration. Also keeps computed `--var` declarations.
- - `'computed'`: Keeps computed `--var` declarations in the output. Handy to make them available to your JavaScript.
- - `(declaration) => boolean|'computed'` : Handles preservation behavior based on the respective declaration.
+- `false`: Removes `--var` declarations and replaces `var()` with their resolved/computed values.
+- `true`: Keeps `var()` declarations in the output and has the computed value as a fallback declaration. Also keeps computed `--var` declarations.
+- `'computed'`: Keeps computed `--var` declarations in the output. Handy to make them available to your JavaScript.
+- `(declaration) => boolean|'computed'` : function/callback to programmatically return whether preserve the respective declaration
### `variables` (default: `{}`)
@@ -374,43 +350,36 @@ repeating custom property definitions in every module passed through this plugin
prevents JS-injected variables from appearing in output CSS.
```js
-var postcss = require('postcss');
-var cssvariables = require('postcss-css-variables');
+var postcss = require("postcss");
+var cssvariables = require("postcss-css-variables");
postcss([
- cssvariables({
- variables: {
- '--some-var': '100px',
- '--other-var': {
- value: '#00ff00'
- },
- '--important-var': {
- value: '#ff0000',
- isImportant: true
- }
- }
- })
-])
-.process(css, opts);
+ cssvariables({
+ variables: {
+ "--some-var": "100px",
+ "--other-var": {
+ value: "#00ff00"
+ },
+ "--important-var": {
+ value: "#ff0000",
+ isImportant: true
+ }
+ }
+ })
+]).process(css, opts);
```
-
### `preserveAtRulesOrder` (default: `false`)
Keeps your at-rules like media queries in the order to defined them.
Ideally, this would be defaulted to `true` and it will be in the next major version. All of the tests expecations need to be updated and probably just drop support for `preserveAtRulesOrder: false`
-
# Quick Reference/Notes
- - This plugin was spawned out of a [discussion on the `cssnext` repo](https://github.com/cssnext/cssnext/issues/99).
- - We provide a larger CSS variable feature subset than [`postcss-custom-properties`](https://github.com/postcss/postcss-custom-properties).
- - Related links and issues:
- - [var declared in media query should pull in properties that use/reference that var *on `cssnext/cssnext`*](https://github.com/cssnext/cssnext/issues/99)
- - [Investigate support for media-query scoped properties *on `postcss/postcss-custom-properties`*](https://github.com/postcss/postcss-custom-properties/issues/9)
- - [remove `:root` limitation by injecting rules with new declarations that just contains modified properties. *on `postcss/postcss-custom-properties`*](https://github.com/postcss/postcss-custom-properties/issues/1)
-
+- This plugin was spawned out of a [discussion on the `cssnext` repo](https://github.com/cssnext/cssnext/issues/99).
+- We provide a larger CSS variable feature subset than [`postcss-custom-properties`](https://github.com/postcss/postcss-custom-properties).
+- Related links and issues: - [var declared in media query should pull in properties that use/reference that var _on `cssnext/cssnext`_](https://github.com/cssnext/cssnext/issues/99) - [Investigate support for media-query scoped properties _on `postcss/postcss-custom-properties`_](https://github.com/postcss/postcss-custom-properties/issues/9) - [remove `:root` limitation by injecting rules with new declarations that just contains modified properties. _on `postcss/postcss-custom-properties`_](https://github.com/postcss/postcss-custom-properties/issues/1)
# Testing
diff --git a/test/fixtures/preserve-variables-conditionally.css b/test/fixtures/preserve-variables-conditionally.css
index 2e2f203..33cb840 100644
--- a/test/fixtures/preserve-variables-conditionally.css
+++ b/test/fixtures/preserve-variables-conditionally.css
@@ -1,21 +1,21 @@
:root {
- --color-one: #0000ff;
- --color-two: #00ff00;
- --color-three: var(--color-two);
+ --no-preserve: #0000ff;
+ --color-foo: #00ff00;
+ --color-bar: var(--color-two);
}
.before {
- prop: before;
- color: var(--color-one);
+ prop: before;
+ color: var(--no-preserve);
}
.after {
- color: var(--color-two);
- prop: after;
+ color: var(--color-foo);
+ prop: after;
}
.before-and-after {
- prop: before;
- color: var(--missing, #ff0000);
- otherprop: after;
-}
\ No newline at end of file
+ prop: before;
+ color: var(--missing, #ff0000);
+ otherprop: after;
+}
diff --git a/test/fixtures/preserve-variables-conditionally.expected.css b/test/fixtures/preserve-variables-conditionally.expected.css
index c9108ff..78a9d09 100644
--- a/test/fixtures/preserve-variables-conditionally.expected.css
+++ b/test/fixtures/preserve-variables-conditionally.expected.css
@@ -1,22 +1,22 @@
:root {
- --color-two: #00ff00;
- --color-three: var(--color-two);
+ --color-foo: #00ff00;
+ --color-bar: var(--color-two);
}
.before {
- prop: before;
- color: #0000ff;
+ prop: before;
+ color: #0000ff;
}
.after {
- color: #00ff00;
- color: var(--color-two);
- prop: after;
+ color: #00ff00;
+ color: var(--color-foo);
+ prop: after;
}
.before-and-after {
- prop: before;
- color: #ff0000;
- color: var(--missing, #ff0000);
- otherprop: after;
-}
\ No newline at end of file
+ prop: before;
+ color: #ff0000;
+ color: var(--missing, #ff0000);
+ otherprop: after;
+}
diff --git a/test/test.js b/test/test.js
index caafea2..a3704fa 100644
--- a/test/test.js
+++ b/test/test.js
@@ -1,302 +1,375 @@
-var Promise = require('bluebird');
-var fs = Promise.promisifyAll(require('fs'));
-var path = require('path');
+var Promise = require("bluebird");
+var fs = Promise.promisifyAll(require("fs"));
+var path = require("path");
-var chai = require('chai');
+var chai = require("chai");
var expect = chai.expect;
-var chaiAsPromised = require('chai-as-promised');
+var chaiAsPromised = require("chai-as-promised");
chai.use(chaiAsPromised);
-var postcss = require('postcss');
-var cssvariables = require('../');
-var cssnano = require('cssnano');
-var normalizeWhitespace = require('postcss-normalize-whitespace');
-var discardComments = require('postcss-discard-comments');
-
-var MOCK_JS_VARIABLES = {
- '--js-defined1': '75px',
- '--js-defined2': {
- value: '80px'
- },
- '--js-defined-important': {
- value: '#0f0',
- isImportant: true
- },
- // Should be automatically prefixed with `--`
- 'js-defined-no-prefix': '#ff0000'
+var postcss = require("postcss");
+var cssvariables = require("../");
+var cssnano = require("cssnano");
+var normalizeWhitespace = require("postcss-normalize-whitespace");
+var discardComments = require("postcss-discard-comments");
+
+var MOCK_JS_VARIABLES = {
+ "--js-defined1": "75px",
+ "--js-defined2": {
+ value: "80px"
+ },
+ "--js-defined-important": {
+ value: "#0f0",
+ isImportant: true
+ },
+ // Should be automatically prefixed with `--`
+ "js-defined-no-prefix": "#ff0000"
};
var NON_STRING_VARIABLES = {
- 'number-value': 50,
- 'zero-value': 0,
- 'null-value': null,
- 'undefined-value': undefined,
- 'object-value-passed-by-mistake': {},
- 'true-value': true,
- 'false-value': false,
+ "number-value": 50,
+ "zero-value": 0,
+ "null-value": null,
+ "undefined-value": undefined,
+ "object-value-passed-by-mistake": {},
+ "true-value": true,
+ "false-value": false
};
var testPlugin = function(filePath, expectedFilePath, options) {
- options = options || {};
- return Promise.props({
- actualBuffer: fs.readFileAsync(filePath),
- expectedBuffer: fs.readFileAsync(expectedFilePath)
- })
- .then(function({ actualBuffer, expectedBuffer }) {
- var actualResult = postcss([
- cssvariables(options),
- cssnano({
- preset: { plugins: [normalizeWhitespace, discardComments] }
- })
- ])
- .process(String(actualBuffer));
-
- var expectedResult = postcss([
- cssnano({
- preset: { plugins: [normalizeWhitespace, discardComments] }
- })
- ])
- .process(String(expectedBuffer));
-
- return Promise.props({
- actualResult: actualResult,
- expectedResult: expectedResult
- });
- })
- .then(({ actualResult, expectedResult }) => {
- expect(actualResult.css.replace(/\r?\n/g, '')).to.equal(expectedResult.css.replace(/\r?\n/g, ''));
- });
+ options = options || {};
+ return Promise.props({
+ actualBuffer: fs.readFileAsync(filePath),
+ expectedBuffer: fs.readFileAsync(expectedFilePath)
+ })
+ .then(function({ actualBuffer, expectedBuffer }) {
+ var actualResult = postcss([
+ cssvariables(options),
+ cssnano({
+ preset: { plugins: [normalizeWhitespace, discardComments] }
+ })
+ ]).process(String(actualBuffer));
+
+ var expectedResult = postcss([
+ cssnano({
+ preset: { plugins: [normalizeWhitespace, discardComments] }
+ })
+ ]).process(String(expectedBuffer));
+
+ return Promise.props({
+ actualResult: actualResult,
+ expectedResult: expectedResult
+ });
+ })
+ .then(({ actualResult, expectedResult }) => {
+ expect(actualResult.css.replace(/\r?\n/g, "")).to.equal(
+ expectedResult.css.replace(/\r?\n/g, "")
+ );
+ });
};
-var fixtureBasePath = './test/fixtures/';
+var fixtureBasePath = "./test/fixtures/";
var test = function(message, fixtureName, options) {
- it(message, function() {
- return testPlugin(
- path.join(fixtureBasePath, fixtureName + '.css'),
- path.join(fixtureBasePath, fixtureName + '.expected.css'),
- options
- );
- });
+ it(message, function() {
+ return testPlugin(
+ path.join(fixtureBasePath, fixtureName + ".css"),
+ path.join(fixtureBasePath, fixtureName + ".expected.css"),
+ options
+ );
+ });
};
-
-
-describe('postcss-css-variables', function() {
- // Just make sure it doesn't mangle anything
- test('should work when there are no var() functions to consume declarations', 'no-var-func');
- test('should work when there are no var() functions(just `:root`) to consume declarations', 'no-var-func-just-root');
- test('should work when no variable name passed to `var()`', 'empty-var-func');
-
-
- test('should work with variables declared in root', 'root-variable');
- test('should work with variables with parenthesis in fallback', 'fallback-with-parenthesis');
-
- test('should work with locally scoped variable in a non-root rule', 'local-variable-non-root');
-
-
- test(
- 'should work with any combinator selector if the last piece is the variable we have in the map',
- 'scope-last-piece-of-combinator-sequence'
- );
-
-
- test('should work with descendant selector type "nesting"', 'descendant-selector');
- test('should work with css4 descendant selector type "nesting"', 'css4-descendant-selector');
- test('should work with direct descendant selector', 'direct-descendant-selector');
-
- test(
- 'should work with direct descendant selector where variables are scoped in a descendant selector',
- 'direct-descendant-selector-descendant-scope'
- );
- test(
- 'should work with direct descendant selector where variables are scoped in a direct descendant selector',
- 'direct-descendant-selector-direct-descendant-scope'
- );
-
-
- test('should work with pseudo selectors', 'pseudo-selector');
- //test('should work with multiple pseudo selectors', 'pseudo-multi');
- test('should work with variables declared in pseudo selectors', 'pseudo-selector-declare-variable');
-
-
-
- test('should work with variables defined in comma separated selector', 'comma-separated-variable-declaration');
-
-
- test('should work use the correct variable in comma separated selector', 'comma-separated-variable-usage');
-
-
- test('should work with star selector', 'star-selector-scope');
-
- test('should work with `!important` variable declarations', 'important-variable-declaration');
-
-
-
- describe('with at-rules', function() {
- test('should add rule declaration of property in @media', 'media-query');
- test('should add rule declaration of property in @support', 'support-directive');
-
- test('should work with @media, preserving rule order', 'media-query-preserve-rule-order', { preserveAtRulesOrder: true });
-
- test('should work with nested @media', 'media-query-nested', { preserveAtRulesOrder: false });
- test('should work with nested @media, preserving rule order', 'media-query-nested-preserver-rule-order', { preserveAtRulesOrder: true });
-
-
- test('should cascade to nested rules', 'cascade-on-nested-rules');
-
- test('should cascade with calc-expression to nested rules', 'cascade-with-calc-expression-on-nested-rules');
-
- test('should cascade to nested rules in the proper scope. See issue #2', 'cascade-on-nested-rules-in-proper-scope');
- });
-
-
- test('should work with variables that reference other variables', 'variable-reference-other-variable');
-
- test(
- 'should work with variable with calc-expression that reference other variables',
- 'variable-with-calc-expression-reference-other-variable'
- );
-
- test(
- 'should work with variables that reference other variables with at-rule changing the value',
- 'variable-reference-other-variable-media-query1'
- );
- test(
- 'should work with local variables that reference other variables with at-rule changing the value',
- 'variable-reference-other-variable-media-query2'
- );
-
-
-
- test('should work with variables that try to self reference', 'self-reference');
- test('should work with variables that try to self reference and fallback properly', 'self-reference-fallback');
- test('should work with circular reference', 'circular-reference');
-
-
- describe('with `options.variables`', function() {
- test(
- 'should work with JS defined variables',
- 'js-defined',
- { variables: MOCK_JS_VARIABLES }
- );
- test(
- 'should work with JS defined important variables',
- 'js-defined-important',
- { variables: MOCK_JS_VARIABLES }
- );
- test(
- 'should preserve -- declarations and var() values with `options.variables` AND `options.preserve`',
- 'js-defined-preserve',
- {
- variables: MOCK_JS_VARIABLES,
- preserve: true
- }
- );
- test(
- 'should preserve var() values and clean injected declarations with `options.variables` AND `options.preserve` AND `options.preserveInjectedVariables: false`',
- 'js-defined-preserve-injected',
- {
- variables: MOCK_JS_VARIABLES,
- preserve: true,
- preserveInjectedVariables: false,
- }
- );
- test(
- 'should cast non-string values to string',
- 'js-defined-non-string-values-casted-to-string',
- {
- variables: NON_STRING_VARIABLES
- }
- );
- });
-
- describe('with `options.preserve`', function() {
- test(
- 'preserves variables when `preserve` is `true`',
- 'preserve-variables',
- { preserve: true }
- );
-
- test(
- 'preserves variables in @media when `preserve` is `true`',
- 'preserve-variables-in-media',
- { preserve: true }
- );
-
- test(
- 'preserves computed value when `preserve` is `\'computed\'`',
- 'preserve-computed',
- { preserve: 'computed' }
- );
-
- test(
- 'preserves variables when `preserve` function applies',
- 'preserve-variables-conditionally',
- {
- preserve: function (declaration) {
- return !(
- declaration.value.includes("--color-one")
- || declaration.prop.includes("--color-one")
- )
- }
- }
- );
- });
-
-
- describe('missing variable declarations', function() {
- test('should work with missing variables', 'missing-variable-usage');
- test('should use fallback value if provided with missing variables', 'missing-variable-should-fallback');
- it('should use string values for `undefined` values, see #22', function() {
- return fs.readFileAsync('./test/fixtures/missing-variable-usage.css', 'utf8')
- .then(function(buffer) {
- var contents = String(buffer);
- return postcss([
- cssvariables()
- ])
- .process(contents)
- .then(function(result) {
- var root = result.root;
- var fooRule = root.nodes[0];
- expect(fooRule.selector).to.equal('.box-foo');
- var colorDecl = fooRule.nodes[0];
- expect(colorDecl.value).to.be.a('string');
- expect(colorDecl.value).to.be.equal('undefined');
-
- expect(result.warnings().length).to.be.equal(1);
- expect(result.warnings()[0].type).to.be.equal('warning');
- expect(result.warnings()[0].text).to.be.equal('variable --missing is undefined and used without a fallback');
- });
- });
- });
- test('should use fallback variable if provided with missing variables', 'missing-variable-should-fallback-var');
- test('should use fallback variable if provided with missing variables calc', 'missing-variable-should-fallback-calc');
- test('should use fallback variable if provided with missing variables nested', 'missing-variable-should-fallback-nested');
- test('should not mangle outer function parentheses', 'nested-inside-other-func');
- test('should not mangle outer function parentheses - with fallback', 'nested-inside-other-func-with-fallback');
- test('should not mangle outer function parentheses - calc', 'nested-inside-calc-func');
- test('should not mangle outer function parentheses - calc with fallback', 'nested-inside-calc-func-with-fallback');
- test('should not mangle outer function parentheses - calc with fallback var()', 'nested-inside-calc-func-with-fallback-var');
- });
-
- test('should accept whitespace in var() declarations', 'whitespace-in-var-declaration' )
-
- it('should not parse malformed var() declarations', function() {
- return expect(testPlugin(
- './test/fixtures/malformed-variable-usage.css',
- './test/fixtures/malformed-variable-usage.expected.css'
- )
- ).to.eventually.be.rejected;
- });
-
- describe('rule clean up', function() {
- test(
- 'should clean up rules if we removed variable declarations to make it empty',
- 'remove-empty-rules-after-variable-collection'
- );
- test(
- 'should clean up neseted rules if we removed variable declarations to make it empty',
- 'remove-nested-empty-rules-after-variable-collection'
- );
- });
+describe("postcss-css-variables", function() {
+ // Just make sure it doesn't mangle anything
+ test(
+ "should work when there are no var() functions to consume declarations",
+ "no-var-func"
+ );
+ test(
+ "should work when there are no var() functions(just `:root`) to consume declarations",
+ "no-var-func-just-root"
+ );
+ test("should work when no variable name passed to `var()`", "empty-var-func");
+
+ test("should work with variables declared in root", "root-variable");
+ test(
+ "should work with variables with parenthesis in fallback",
+ "fallback-with-parenthesis"
+ );
+
+ test(
+ "should work with locally scoped variable in a non-root rule",
+ "local-variable-non-root"
+ );
+
+ test(
+ "should work with any combinator selector if the last piece is the variable we have in the map",
+ "scope-last-piece-of-combinator-sequence"
+ );
+
+ test(
+ 'should work with descendant selector type "nesting"',
+ "descendant-selector"
+ );
+ test(
+ 'should work with css4 descendant selector type "nesting"',
+ "css4-descendant-selector"
+ );
+ test(
+ "should work with direct descendant selector",
+ "direct-descendant-selector"
+ );
+
+ test(
+ "should work with direct descendant selector where variables are scoped in a descendant selector",
+ "direct-descendant-selector-descendant-scope"
+ );
+ test(
+ "should work with direct descendant selector where variables are scoped in a direct descendant selector",
+ "direct-descendant-selector-direct-descendant-scope"
+ );
+
+ test("should work with pseudo selectors", "pseudo-selector");
+ //test('should work with multiple pseudo selectors', 'pseudo-multi');
+ test(
+ "should work with variables declared in pseudo selectors",
+ "pseudo-selector-declare-variable"
+ );
+
+ test(
+ "should work with variables defined in comma separated selector",
+ "comma-separated-variable-declaration"
+ );
+
+ test(
+ "should work use the correct variable in comma separated selector",
+ "comma-separated-variable-usage"
+ );
+
+ test("should work with star selector", "star-selector-scope");
+
+ test(
+ "should work with `!important` variable declarations",
+ "important-variable-declaration"
+ );
+
+ describe("with at-rules", function() {
+ test("should add rule declaration of property in @media", "media-query");
+ test(
+ "should add rule declaration of property in @support",
+ "support-directive"
+ );
+
+ test(
+ "should work with @media, preserving rule order",
+ "media-query-preserve-rule-order",
+ { preserveAtRulesOrder: true }
+ );
+
+ test("should work with nested @media", "media-query-nested", {
+ preserveAtRulesOrder: false
+ });
+ test(
+ "should work with nested @media, preserving rule order",
+ "media-query-nested-preserver-rule-order",
+ { preserveAtRulesOrder: true }
+ );
+
+ test("should cascade to nested rules", "cascade-on-nested-rules");
+
+ test(
+ "should cascade with calc-expression to nested rules",
+ "cascade-with-calc-expression-on-nested-rules"
+ );
+
+ test(
+ "should cascade to nested rules in the proper scope. See issue #2",
+ "cascade-on-nested-rules-in-proper-scope"
+ );
+ });
+
+ test(
+ "should work with variables that reference other variables",
+ "variable-reference-other-variable"
+ );
+
+ test(
+ "should work with variable with calc-expression that reference other variables",
+ "variable-with-calc-expression-reference-other-variable"
+ );
+
+ test(
+ "should work with variables that reference other variables with at-rule changing the value",
+ "variable-reference-other-variable-media-query1"
+ );
+ test(
+ "should work with local variables that reference other variables with at-rule changing the value",
+ "variable-reference-other-variable-media-query2"
+ );
+
+ test(
+ "should work with variables that try to self reference",
+ "self-reference"
+ );
+ test(
+ "should work with variables that try to self reference and fallback properly",
+ "self-reference-fallback"
+ );
+ test("should work with circular reference", "circular-reference");
+
+ describe("with `options.variables`", function() {
+ test("should work with JS defined variables", "js-defined", {
+ variables: MOCK_JS_VARIABLES
+ });
+ test(
+ "should work with JS defined important variables",
+ "js-defined-important",
+ { variables: MOCK_JS_VARIABLES }
+ );
+ test(
+ "should preserve -- declarations and var() values with `options.variables` AND `options.preserve`",
+ "js-defined-preserve",
+ {
+ variables: MOCK_JS_VARIABLES,
+ preserve: true
+ }
+ );
+ test(
+ "should preserve var() values and clean injected declarations with `options.variables` AND `options.preserve` AND `options.preserveInjectedVariables: false`",
+ "js-defined-preserve-injected",
+ {
+ variables: MOCK_JS_VARIABLES,
+ preserve: true,
+ preserveInjectedVariables: false
+ }
+ );
+ test(
+ "should cast non-string values to string",
+ "js-defined-non-string-values-casted-to-string",
+ {
+ variables: NON_STRING_VARIABLES
+ }
+ );
+ });
+
+ describe("with `options.preserve`", function() {
+ test(
+ "preserves variables when `preserve` is `true`",
+ "preserve-variables",
+ { preserve: true }
+ );
+
+ test(
+ "preserves variables in @media when `preserve` is `true`",
+ "preserve-variables-in-media",
+ { preserve: true }
+ );
+
+ test(
+ "preserves computed value when `preserve` is `'computed'`",
+ "preserve-computed",
+ { preserve: "computed" }
+ );
+
+ test(
+ "preserves variables when `preserve` function applies",
+ "preserve-variables-conditionally",
+ {
+ preserve: function(declaration) {
+ return !(
+ declaration.prop.includes("--no-preserve") ||
+ declaration.value.includes("--no-preserve")
+ );
+ }
+ }
+ );
+ });
+
+ describe("missing variable declarations", function() {
+ test("should work with missing variables", "missing-variable-usage");
+ test(
+ "should use fallback value if provided with missing variables",
+ "missing-variable-should-fallback"
+ );
+ it("should use string values for `undefined` values, see #22", function() {
+ return fs
+ .readFileAsync("./test/fixtures/missing-variable-usage.css", "utf8")
+ .then(function(buffer) {
+ var contents = String(buffer);
+ return postcss([cssvariables()])
+ .process(contents)
+ .then(function(result) {
+ var root = result.root;
+ var fooRule = root.nodes[0];
+ expect(fooRule.selector).to.equal(".box-foo");
+ var colorDecl = fooRule.nodes[0];
+ expect(colorDecl.value).to.be.a("string");
+ expect(colorDecl.value).to.be.equal("undefined");
+
+ expect(result.warnings().length).to.be.equal(1);
+ expect(result.warnings()[0].type).to.be.equal("warning");
+ expect(result.warnings()[0].text).to.be.equal(
+ "variable --missing is undefined and used without a fallback"
+ );
+ });
+ });
+ });
+ test(
+ "should use fallback variable if provided with missing variables",
+ "missing-variable-should-fallback-var"
+ );
+ test(
+ "should use fallback variable if provided with missing variables calc",
+ "missing-variable-should-fallback-calc"
+ );
+ test(
+ "should use fallback variable if provided with missing variables nested",
+ "missing-variable-should-fallback-nested"
+ );
+ test(
+ "should not mangle outer function parentheses",
+ "nested-inside-other-func"
+ );
+ test(
+ "should not mangle outer function parentheses - with fallback",
+ "nested-inside-other-func-with-fallback"
+ );
+ test(
+ "should not mangle outer function parentheses - calc",
+ "nested-inside-calc-func"
+ );
+ test(
+ "should not mangle outer function parentheses - calc with fallback",
+ "nested-inside-calc-func-with-fallback"
+ );
+ test(
+ "should not mangle outer function parentheses - calc with fallback var()",
+ "nested-inside-calc-func-with-fallback-var"
+ );
+ });
+
+ test(
+ "should accept whitespace in var() declarations",
+ "whitespace-in-var-declaration"
+ );
+
+ it("should not parse malformed var() declarations", function() {
+ return expect(
+ testPlugin(
+ "./test/fixtures/malformed-variable-usage.css",
+ "./test/fixtures/malformed-variable-usage.expected.css"
+ )
+ ).to.eventually.be.rejected;
+ });
+
+ describe("rule clean up", function() {
+ test(
+ "should clean up rules if we removed variable declarations to make it empty",
+ "remove-empty-rules-after-variable-collection"
+ );
+ test(
+ "should clean up neseted rules if we removed variable declarations to make it empty",
+ "remove-nested-empty-rules-after-variable-collection"
+ );
+ });
});