diff --git a/.tape.js b/.tape.js index 9c39e47..91a1503 100644 --- a/.tape.js +++ b/.tape.js @@ -122,6 +122,24 @@ module.exports = { expect: 'basic.import.expect.css', result: 'basic.import.result.css' }, + 'basic:import-override': { + message: 'importFrom with { preserve: false } should override root properties', + options: { + preserve: false, + importFrom: { + customProperties: { + '--color': 'rgb(0, 0, 0)', + '--color-2': 'yellow', + '--ref-color': 'var(--color)', + '--margin': '0 10px 20px 30px', + '--shadow-color': 'rgb(0,0,0)', + '--z-index': 10 + } + } + }, + expect: 'basic.import-override.expect.css', + result: 'basic.import-override.result.css' + }, 'basic:export': { message: 'supports { exportTo: { customProperties: { ... } } } usage', options: { diff --git a/src/index.js b/src/index.js index 6b24394..3feb6b5 100755 --- a/src/index.js +++ b/src/index.js @@ -28,8 +28,8 @@ export default postcss.plugin('postcss-custom-properties', opts => { const asyncTransform = async root => { const customProperties = Object.assign( {}, + getCustomPropertiesFromRoot(root, { preserve }), await customPropertiesPromise, - getCustomPropertiesFromRoot(root, { preserve }) ); await writeCustomPropertiesToExports(customProperties, exportTo); diff --git a/src/lib/transform-value-ast.js b/src/lib/transform-value-ast.js index c5e5cdc..ad4b28c 100644 --- a/src/lib/transform-value-ast.js +++ b/src/lib/transform-value-ast.js @@ -10,8 +10,20 @@ export default function transformValueAST(root, customProperties) { // conditionally replace a known custom property const nodes = asClonedArrayWithBeforeSpacing(customProperties[name], child.raws.before); + /** + * https://github.com/postcss/postcss-custom-properties/issues/221 + * https://github.com/postcss/postcss-custom-properties/issues/218 + * + * replaceWith loses node.raws values, so we need to save it and restore + */ + const raws = nodes.map(node => ({...node.raws})); + child.replaceWith(...nodes); + nodes.forEach((node, index) => { + node.raws = raws[index]; + }); + retransformValueAST({ nodes }, customProperties, name); } else if (fallbacks.length) { // conditionally replace a custom property with a fallback diff --git a/test/basic.css b/test/basic.css index d5abe7a..8c7f049 100644 --- a/test/basic.css +++ b/test/basic.css @@ -12,6 +12,9 @@ html { --circular: var(--circular-2); --circular-2: var(--circular); --margin: 0 10px 20px 30px; + --shadow-color: rgb(255,0,0); + --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); + --font-family: "Open Sans", sans-serif; color: var(--color); } @@ -38,6 +41,22 @@ html { color: var(--color); } +.test--color_spacing { + box-shadow: inset 0 -3px 0 var(--color); +} + +.test--preserve_whitespaces { + margin: var(--margin); +} + +.test--complex_values { + box-shadow: var(--shadow); +} + +.test--comma_separated_values { + font-family: var(--font-family); +} + .test--fallback { color: var(--color-2, blue); } @@ -54,10 +73,6 @@ html { color: var(--circular); } -.test--color_spacing { - box-shadow: inset 0 -3px 0 var(--color); -} - .test--z-index { z-index: var(--z-index); } diff --git a/test/basic.expect.css b/test/basic.expect.css index 68ef47d..52b16e9 100644 --- a/test/basic.expect.css +++ b/test/basic.expect.css @@ -12,6 +12,9 @@ html { --circular: var(--circular-2); --circular-2: var(--circular); --margin: 0 10px 20px 30px; + --shadow-color: rgb(255,0,0); + --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); + --font-family: "Open Sans", sans-serif; color: rgb(255, 0, 0); color: var(--color); } @@ -41,6 +44,26 @@ html { color: var(--color); } +.test--color_spacing { + box-shadow: inset 0 -3px 0 rgb(255, 0, 0); + box-shadow: inset 0 -3px 0 var(--color); +} + +.test--preserve_whitespaces { + margin: 0 10px 20px 30px; + margin: var(--margin); +} + +.test--complex_values { + box-shadow: 0 6px 14px 0 color(rgb(255,0,0) a(.15)); + box-shadow: var(--shadow); +} + +.test--comma_separated_values { + font-family: "Open Sans", sans-serif; + font-family: var(--font-family); +} + .test--fallback { color: blue; color: var(--color-2, blue); @@ -60,11 +83,6 @@ html { color: var(--circular); } -.test--color_spacing { - box-shadow: inset 0 -3px 0 rgb(255, 0, 0); - box-shadow: inset 0 -3px 0 var(--color); -} - .test--z-index { z-index: var(--z-index); } diff --git a/test/basic.import-is-empty.expect.css b/test/basic.import-is-empty.expect.css index 68ef47d..52b16e9 100644 --- a/test/basic.import-is-empty.expect.css +++ b/test/basic.import-is-empty.expect.css @@ -12,6 +12,9 @@ html { --circular: var(--circular-2); --circular-2: var(--circular); --margin: 0 10px 20px 30px; + --shadow-color: rgb(255,0,0); + --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); + --font-family: "Open Sans", sans-serif; color: rgb(255, 0, 0); color: var(--color); } @@ -41,6 +44,26 @@ html { color: var(--color); } +.test--color_spacing { + box-shadow: inset 0 -3px 0 rgb(255, 0, 0); + box-shadow: inset 0 -3px 0 var(--color); +} + +.test--preserve_whitespaces { + margin: 0 10px 20px 30px; + margin: var(--margin); +} + +.test--complex_values { + box-shadow: 0 6px 14px 0 color(rgb(255,0,0) a(.15)); + box-shadow: var(--shadow); +} + +.test--comma_separated_values { + font-family: "Open Sans", sans-serif; + font-family: var(--font-family); +} + .test--fallback { color: blue; color: var(--color-2, blue); @@ -60,11 +83,6 @@ html { color: var(--circular); } -.test--color_spacing { - box-shadow: inset 0 -3px 0 rgb(255, 0, 0); - box-shadow: inset 0 -3px 0 var(--color); -} - .test--z-index { z-index: var(--z-index); } diff --git a/test/basic.import-override.expect.css b/test/basic.import-override.expect.css new file mode 100644 index 0000000..d18fc7a --- /dev/null +++ b/test/basic.import-override.expect.css @@ -0,0 +1,77 @@ +:root { + color: rgb(0, 0, 0); +} + +.ignore-line { + /* postcss-custom-properties: ignore next */ + color: var(--color); + background-color: yellow; +} + +.ignore-block { + /* postcss-custom-properties: off */ + color: var(--color-2, blue); + box-shadow: inset 0 -3px 0 var(--color); + background-image: linear-gradient(to right, var(--color, transparent) 0%, var(--color, transparent) 100%); +} + +.test { + --skip: gray; + color: rgb(0, 0, 0); +} + +.test--color_spacing { + box-shadow: inset 0 -3px 0 rgb(0, 0, 0); +} + +.test--preserve_whitespaces { + margin: 0 10px 20px 30px; +} + +.test--complex_values { + box-shadow: 0 6px 14px 0 color(rgb(0,0,0) a(.15)); +} + +.test--comma_separated_values { + font-family: "Open Sans", sans-serif; +} + +.test--fallback { + color: yellow; +} + +.test--color_w_var { + color: rgb(0, 0, 0); +} + +.test--color_w_vars { + color: hsl(0, 100%, 50%); +} + +.test--circular_var { + color: var(--circular); +} + +.test--z-index { + z-index: 10; +} + +.test--nested-fallback { + z-index: 1; +} + +.text--calc { + width: calc((100% - 1px) + 10px); +} + +.test--linear-gradient { + background-image: linear-gradient(to right, rgb(0, 0, 0) 0%, rgb(0, 0, 0) 100%); +} + +.test--loose-formatting { + color: rgb(0, 0, 0)/*rtl:red*/; +} + +.test--combined-selector { + color: #053; +} diff --git a/test/basic.import.expect.css b/test/basic.import.expect.css index 6f9d71f..c3f53c7 100644 --- a/test/basic.import.expect.css +++ b/test/basic.import.expect.css @@ -12,6 +12,9 @@ html { --circular: var(--circular-2); --circular-2: var(--circular); --margin: 0 10px 20px 30px; + --shadow-color: rgb(255,0,0); + --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); + --font-family: "Open Sans", sans-serif; color: rgb(255, 0, 0); color: var(--color); } @@ -41,6 +44,26 @@ html { color: var(--color); } +.test--color_spacing { + box-shadow: inset 0 -3px 0 rgb(255, 0, 0); + box-shadow: inset 0 -3px 0 var(--color); +} + +.test--preserve_whitespaces { + margin: 0 10px 20px 30px; + margin: var(--margin); +} + +.test--complex_values { + box-shadow: 0 6px 14px 0 color(rgb(255,0,0) a(.15)); + box-shadow: var(--shadow); +} + +.test--comma_separated_values { + font-family: "Open Sans", sans-serif; + font-family: var(--font-family); +} + .test--fallback { color: yellow; color: var(--color-2, blue); @@ -60,11 +83,6 @@ html { color: var(--circular); } -.test--color_spacing { - box-shadow: inset 0 -3px 0 rgb(255, 0, 0); - box-shadow: inset 0 -3px 0 var(--color); -} - .test--z-index { z-index: 10; z-index: var(--z-index); diff --git a/test/basic.preserve.expect.css b/test/basic.preserve.expect.css index 082a519..8a926f8 100644 --- a/test/basic.preserve.expect.css +++ b/test/basic.preserve.expect.css @@ -20,6 +20,22 @@ color: rgb(255, 0, 0); } +.test--color_spacing { + box-shadow: inset 0 -3px 0 rgb(255, 0, 0); +} + +.test--preserve_whitespaces { + margin: 0 10px 20px 30px; +} + +.test--complex_values { + box-shadow: 0 6px 14px 0 color(rgb(255,0,0) a(.15)); +} + +.test--comma_separated_values { + font-family: "Open Sans", sans-serif; +} + .test--fallback { color: blue; } @@ -36,10 +52,6 @@ color: var(--circular); } -.test--color_spacing { - box-shadow: inset 0 -3px 0 rgb(255, 0, 0); -} - .test--z-index { z-index: var(--z-index); } diff --git a/test/export-properties.css b/test/export-properties.css index 42b896b..2c70d9d 100644 --- a/test/export-properties.css +++ b/test/export-properties.css @@ -8,5 +8,8 @@ --circular: var(--circular-2); --circular-2: var(--circular); --margin: 0 10px 20px 30px; + --shadow-color: rgb(255,0,0); + --shadow: 0 6px 14px 0 color(var(--shadow-color) a(.15)); + --font-family: "Open Sans" , sans-serif; --theme-color: #053; } diff --git a/test/export-properties.js b/test/export-properties.js index 3bf6561..f898cd3 100644 --- a/test/export-properties.js +++ b/test/export-properties.js @@ -9,6 +9,9 @@ module.exports = { '--circular': 'var(--circular-2)', '--circular-2': 'var(--circular)', '--margin': '0 10px 20px 30px', + '--shadow-color': 'rgb(255,0,0)', + '--shadow': '0 6px 14px 0 color(var(--shadow-color) a(.15))', + '--font-family': '"Open Sans" , sans-serif', '--theme-color': '#053' } }; diff --git a/test/export-properties.json b/test/export-properties.json index 83bbca4..dd55ef8 100644 --- a/test/export-properties.json +++ b/test/export-properties.json @@ -9,6 +9,9 @@ "--circular": "var(--circular-2)", "--circular-2": "var(--circular)", "--margin": "0 10px 20px 30px", + "--shadow-color": "rgb(255,0,0)", + "--shadow": "0 6px 14px 0 color(var(--shadow-color) a(.15))", + "--font-family": "\"Open Sans\" , sans-serif", "--theme-color": "#053" } } diff --git a/test/export-properties.mjs b/test/export-properties.mjs index 2950e73..0168900 100644 --- a/test/export-properties.mjs +++ b/test/export-properties.mjs @@ -8,5 +8,8 @@ export const customProperties = { '--circular': 'var(--circular-2)', '--circular-2': 'var(--circular)', '--margin': '0 10px 20px 30px', + '--shadow-color': 'rgb(255,0,0)', + '--shadow': '0 6px 14px 0 color(var(--shadow-color) a(.15))', + '--font-family': '"Open Sans" , sans-serif', '--theme-color': '#053' };