From f897e5132c29532034d7fe3d59a1dc53e02c62a3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 14 Mar 2022 12:11:46 +0530 Subject: [PATCH 01/18] Implement url to variables plugin --- package.json | 2 +- scripts/postcss/css-url-to-variables.js | 54 +++++++++++++++++++ .../css-compile-variables.test.js} | 4 +- .../tests/css-url-to-variables.test.js | 48 +++++++++++++++++ 4 files changed, 105 insertions(+), 3 deletions(-) create mode 100644 scripts/postcss/css-url-to-variables.js rename scripts/postcss/{test.js => tests/css-compile-variables.test.js} (98%) create mode 100644 scripts/postcss/tests/css-url-to-variables.test.js diff --git a/package.json b/package.json index d506d872..af863ced 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ "lint-ts": "eslint src/ -c .ts-eslintrc.js --ext .ts", "lint-ci": "eslint src/", "test": "impunity --entry-point src/platform/web/main.js src/platform/web/Platform.js --force-esm-dirs lib/ src/ --root-dir src/", - "test:postcss": "impunity --entry-point scripts/postcss/test.js ", + "test:postcss": "impunity --entry-point scripts/postcss/tests/css-compile-variables.test.js scripts/postcss/tests/css-url-to-variables.test.js", "start": "vite --port 3000", "build": "vite build", "build:sdk": "./scripts/sdk/build.sh" diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js new file mode 100644 index 00000000..a9370117 --- /dev/null +++ b/scripts/postcss/css-url-to-variables.js @@ -0,0 +1,54 @@ +const valueParser = require("postcss-value-parser"); +let counter = 0; +const variableMap = new Map(); +const format = "icon-url" + +function extractUrl(decl) { + const value = decl.value; + const parsed = valueParser(value); + const variables = []; + parsed.walk(node => { + if (node.type !== "function" || node.value !== "url") { + return; + } + const urlStringNode = node.nodes[0]; + const variableName = `--${format}-${counter++}`; + variableMap.set(variableName, `"${urlStringNode.value}"`); + const varNode = { + type: "function", + value: "var", + nodes: [{ type: "word", value: variableName }], + }; + //replace the url-string node with this var-node + node.nodes[0] = varNode; + }); + decl.assign({prop: decl.prop, value: parsed.toString()}) + return variables; +} + +function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { + const newRule = new Rule({ selector: ":root", source: root.source }); + // Add derived css variables to :root + variableMap.forEach((value, key) => { + const declaration = new Declaration({ prop: key, value }); + newRule.append(declaration); + }); + root.append(newRule); +} + +/* * + * @type {import('postcss').PluginCreator} + */ +module.exports = (opts = {}) => { + return { + postcssPlugin: "postcss-url-to-variable", + + Once(root, { Rule, Declaration }) { + root.walkDecls(decl => extractUrl(decl)); + addResolvedVariablesToRootSelector(root, { Rule, Declaration }); + }, + }; +}; + +module.exports.postcss = true; + diff --git a/scripts/postcss/test.js b/scripts/postcss/tests/css-compile-variables.test.js similarity index 98% rename from scripts/postcss/test.js rename to scripts/postcss/tests/css-compile-variables.test.js index cccb3ea7..945d5d4d 100644 --- a/scripts/postcss/test.js +++ b/scripts/postcss/tests/css-compile-variables.test.js @@ -16,8 +16,8 @@ limitations under the License. const offColor = require("off-color").offColor; const postcss = require("postcss"); -const plugin = require("./css-compile-variables"); -const derive = require("./color").derive; +const plugin = require("../css-compile-variables"); +const derive = require("../color").derive; async function run(input, output, opts = {}, assert) { let result = await postcss([plugin({ ...opts, derive })]).process(input, { from: undefined, }); diff --git a/scripts/postcss/tests/css-url-to-variables.test.js b/scripts/postcss/tests/css-url-to-variables.test.js new file mode 100644 index 00000000..36a38345 --- /dev/null +++ b/scripts/postcss/tests/css-url-to-variables.test.js @@ -0,0 +1,48 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +const postcss = require("postcss"); +const plugin = require("../css-url-to-variables"); + +async function run(input, output, opts = {}, assert) { + let result = await postcss([plugin(opts)]).process(input, { from: undefined, }); + assert.strictEqual( + result.css.replaceAll(/\s/g, ""), + output.replaceAll(/\s/g, "") + ); + assert.strictEqual(result.warnings().length, 0); +} + +module.exports.tests = function tests() { + return { + "url is replaced with variable": async (assert) => { + const inputCSS = `div { + background: no-repeat center/80% url("../img/image.png"); + }`; + const outputCSS = + `div { + background: no-repeat center/80% url(var(--icon-url-0)); + }`+ + ` + :root { + --icon-url-0: "../img/image.png"; + } + `; + await run( inputCSS, outputCSS, { }, assert); + }, + }; +}; + From 3ae2b4dab4d2fe1a2cba37f1832541fb938909f3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 24 Mar 2022 16:34:15 +0530 Subject: [PATCH 02/18] Use two url() in test --- scripts/postcss/tests/css-url-to-variables.test.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/scripts/postcss/tests/css-url-to-variables.test.js b/scripts/postcss/tests/css-url-to-variables.test.js index 36a38345..645b1775 100644 --- a/scripts/postcss/tests/css-url-to-variables.test.js +++ b/scripts/postcss/tests/css-url-to-variables.test.js @@ -31,14 +31,21 @@ module.exports.tests = function tests() { "url is replaced with variable": async (assert) => { const inputCSS = `div { background: no-repeat center/80% url("../img/image.png"); + } + button { + background: url("/home/foo/bar/cool.jpg"); }`; const outputCSS = `div { background: no-repeat center/80% url(var(--icon-url-0)); + } + button { + background: url(var(--icon-url-1)); }`+ ` :root { --icon-url-0: "../img/image.png"; + --icon-url-1: "/home/foo/bar/cool.jpg"; } `; await run( inputCSS, outputCSS, { }, assert); From cbff912476c19d9395bfd86f935bc9df80708fb4 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 24 Mar 2022 16:36:01 +0530 Subject: [PATCH 03/18] Improve code quality --- scripts/postcss/css-url-to-variables.js | 35 ++++++++++++++++++------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index a9370117..a1a47971 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -1,7 +1,23 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + const valueParser = require("postcss-value-parser"); -let counter = 0; -const variableMap = new Map(); -const format = "icon-url" +let counter; +const urlVariables = new Map(); +const idToPrepend = "icon-url"; function extractUrl(decl) { const value = decl.value; @@ -12,14 +28,14 @@ function extractUrl(decl) { return; } const urlStringNode = node.nodes[0]; - const variableName = `--${format}-${counter++}`; - variableMap.set(variableName, `"${urlStringNode.value}"`); + const variableName = `${idToPrepend}-${counter++}`; + urlVariables.set(variableName, `"${urlStringNode.value}"`); const varNode = { type: "function", value: "var", - nodes: [{ type: "word", value: variableName }], + nodes: [{ type: "word", value: `--${variableName}` }], }; - //replace the url-string node with this var-node + // replace the url-string node with this var-node node.nodes[0] = varNode; }); decl.assign({prop: decl.prop, value: parsed.toString()}) @@ -29,8 +45,8 @@ function extractUrl(decl) { function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { const newRule = new Rule({ selector: ":root", source: root.source }); // Add derived css variables to :root - variableMap.forEach((value, key) => { - const declaration = new Declaration({ prop: key, value }); + urlVariables.forEach((value, key) => { + const declaration = new Declaration({ prop: `--${key}`, value }); newRule.append(declaration); }); root.append(newRule); @@ -40,6 +56,7 @@ function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { * @type {import('postcss').PluginCreator} */ module.exports = (opts = {}) => { + counter = 0; return { postcssPlugin: "postcss-url-to-variable", From b59d6970fcdc91359097e07cc51df1f91ca02514 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 24 Mar 2022 16:52:26 +0530 Subject: [PATCH 04/18] Fix code duplication in tests --- scripts/postcss/tests/common.js | 30 +++++++++++++++++++ .../tests/css-compile-variables.test.js | 16 +++------- .../tests/css-url-to-variables.test.js | 11 +------ 3 files changed, 35 insertions(+), 22 deletions(-) create mode 100644 scripts/postcss/tests/common.js diff --git a/scripts/postcss/tests/common.js b/scripts/postcss/tests/common.js new file mode 100644 index 00000000..78ae847e --- /dev/null +++ b/scripts/postcss/tests/common.js @@ -0,0 +1,30 @@ +/* +Copyright 2021 The Matrix.org Foundation C.I.C. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +const postcss = require("postcss"); + +module.exports.createTestRunner = function (plugin) { + return async function run(input, output, opts = {}, assert) { + let result = await postcss([plugin(opts)]).process(input, { from: undefined, }); + assert.strictEqual( + result.css.replaceAll(/\s/g, ""), + output.replaceAll(/\s/g, "") + ); + assert.strictEqual(result.warnings().length, 0); + }; +} + + diff --git a/scripts/postcss/tests/css-compile-variables.test.js b/scripts/postcss/tests/css-compile-variables.test.js index 945d5d4d..e20e195f 100644 --- a/scripts/postcss/tests/css-compile-variables.test.js +++ b/scripts/postcss/tests/css-compile-variables.test.js @@ -18,15 +18,7 @@ const offColor = require("off-color").offColor; const postcss = require("postcss"); const plugin = require("../css-compile-variables"); const derive = require("../color").derive; - -async function run(input, output, opts = {}, assert) { - let result = await postcss([plugin({ ...opts, derive })]).process(input, { from: undefined, }); - assert.strictEqual( - result.css.replaceAll(/\s/g, ""), - output.replaceAll(/\s/g, "") - ); - assert.strictEqual(result.warnings().length, 0); -} +const run = require("./common").createTestRunner(plugin); module.exports.tests = function tests() { return { @@ -46,7 +38,7 @@ module.exports.tests = function tests() { --foo-color--lighter-50: ${transformedColor.hex()}; } `; - await run( inputCSS, outputCSS, {}, assert); + await run( inputCSS, outputCSS, {derive}, assert); }, "derived variables work with alias": async (assert) => { @@ -66,7 +58,7 @@ module.exports.tests = function tests() { --my-alias--lighter-15: ${aliasLighter}; } `; - await run(inputCSS, outputCSS, { }, assert); + await run(inputCSS, outputCSS, {derive}, assert); }, "derived variable throws if base not present in config": async (assert) => { @@ -94,7 +86,7 @@ module.exports.tests = function tests() { --foo-color--darker-20: ${transformedColor2.hex()}; } `; - await run( inputCSS, outputCSS, { }, assert); + await run( inputCSS, outputCSS, {derive}, assert); }, "multiple aliased-derived variable in single declaration is parsed correctly": async (assert) => { diff --git a/scripts/postcss/tests/css-url-to-variables.test.js b/scripts/postcss/tests/css-url-to-variables.test.js index 645b1775..0369995b 100644 --- a/scripts/postcss/tests/css-url-to-variables.test.js +++ b/scripts/postcss/tests/css-url-to-variables.test.js @@ -14,17 +14,8 @@ See the License for the specific language governing permissions and limitations under the License. */ -const postcss = require("postcss"); const plugin = require("../css-url-to-variables"); - -async function run(input, output, opts = {}, assert) { - let result = await postcss([plugin(opts)]).process(input, { from: undefined, }); - assert.strictEqual( - result.css.replaceAll(/\s/g, ""), - output.replaceAll(/\s/g, "") - ); - assert.strictEqual(result.warnings().length, 0); -} +const run = require("./common").createTestRunner(plugin); module.exports.tests = function tests() { return { From 97ade0659cdcad78514c5dc42deacb11170ba3ca Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Mar 2022 11:40:21 +0530 Subject: [PATCH 05/18] Add explaining comment --- scripts/postcss/css-url-to-variables.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index a1a47971..07d524c9 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -15,6 +15,10 @@ limitations under the License. */ const valueParser = require("postcss-value-parser"); +/** + * This plugin extracts content inside url() into css variables. + * The extracted css variables are added to the :root section. + */ let counter; const urlVariables = new Map(); const idToPrepend = "icon-url"; From 6b4bb762aa830b19e69b6160ec57169d73484cf2 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Mar 2022 11:40:35 +0530 Subject: [PATCH 06/18] Remove unused variable --- scripts/postcss/css-url-to-variables.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 07d524c9..79814cb2 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -26,7 +26,6 @@ const idToPrepend = "icon-url"; function extractUrl(decl) { const value = decl.value; const parsed = valueParser(value); - const variables = []; parsed.walk(node => { if (node.type !== "function" || node.value !== "url") { return; @@ -43,7 +42,6 @@ function extractUrl(decl) { node.nodes[0] = varNode; }); decl.assign({prop: decl.prop, value: parsed.toString()}) - return variables; } function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { From 2d4ec5380e9cf578e2d0f186e0e895f50b130bf3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Mar 2022 11:46:48 +0530 Subject: [PATCH 07/18] Initialize variables later --- scripts/postcss/css-url-to-variables.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 79814cb2..902e3e9d 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -15,12 +15,13 @@ limitations under the License. */ const valueParser = require("postcss-value-parser"); + /** * This plugin extracts content inside url() into css variables. * The extracted css variables are added to the :root section. */ let counter; -const urlVariables = new Map(); +let urlVariables; const idToPrepend = "icon-url"; function extractUrl(decl) { @@ -58,6 +59,7 @@ function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { * @type {import('postcss').PluginCreator} */ module.exports = (opts = {}) => { + urlVariables = new Map(); counter = 0; return { postcssPlugin: "postcss-url-to-variable", From f07a3ea5b5b05ca6afd9ee4df6ecbb457f60127d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Mar 2022 15:48:32 +0530 Subject: [PATCH 08/18] Remove css specific syntax from map --- scripts/postcss/css-url-to-variables.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 902e3e9d..dff72264 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -33,7 +33,7 @@ function extractUrl(decl) { } const urlStringNode = node.nodes[0]; const variableName = `${idToPrepend}-${counter++}`; - urlVariables.set(variableName, `"${urlStringNode.value}"`); + urlVariables.set(variableName, urlStringNode.value); const varNode = { type: "function", value: "var", @@ -49,7 +49,7 @@ function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { const newRule = new Rule({ selector: ":root", source: root.source }); // Add derived css variables to :root urlVariables.forEach((value, key) => { - const declaration = new Declaration({ prop: `--${key}`, value }); + const declaration = new Declaration({ prop: `--${key}`, value: `"${value}"`}); newRule.append(declaration); }); root.append(newRule); From 0a186dd11bc8fb7d14a76d7ad4a4efb753eb345b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Mar 2022 16:06:40 +0530 Subject: [PATCH 09/18] Fix css logic --- scripts/postcss/css-url-to-variables.js | 11 +++-------- scripts/postcss/tests/css-url-to-variables.test.js | 8 ++++---- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index dff72264..34d21bcc 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -34,13 +34,8 @@ function extractUrl(decl) { const urlStringNode = node.nodes[0]; const variableName = `${idToPrepend}-${counter++}`; urlVariables.set(variableName, urlStringNode.value); - const varNode = { - type: "function", - value: "var", - nodes: [{ type: "word", value: `--${variableName}` }], - }; - // replace the url-string node with this var-node - node.nodes[0] = varNode; + node.value = "var"; + node.nodes = [{ type: "word", value: `--${variableName}` }]; }); decl.assign({prop: decl.prop, value: parsed.toString()}) } @@ -49,7 +44,7 @@ function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { const newRule = new Rule({ selector: ":root", source: root.source }); // Add derived css variables to :root urlVariables.forEach((value, key) => { - const declaration = new Declaration({ prop: `--${key}`, value: `"${value}"`}); + const declaration = new Declaration({ prop: `--${key}`, value: `url("${value}")`}); newRule.append(declaration); }); root.append(newRule); diff --git a/scripts/postcss/tests/css-url-to-variables.test.js b/scripts/postcss/tests/css-url-to-variables.test.js index 0369995b..fe4d4865 100644 --- a/scripts/postcss/tests/css-url-to-variables.test.js +++ b/scripts/postcss/tests/css-url-to-variables.test.js @@ -28,15 +28,15 @@ module.exports.tests = function tests() { }`; const outputCSS = `div { - background: no-repeat center/80% url(var(--icon-url-0)); + background: no-repeat center/80% var(--icon-url-0); } button { - background: url(var(--icon-url-1)); + background: var(--icon-url-1); }`+ ` :root { - --icon-url-0: "../img/image.png"; - --icon-url-1: "/home/foo/bar/cool.jpg"; + --icon-url-0: url("../img/image.png"); + --icon-url-1: url("/home/foo/bar/cool.jpg"); } `; await run( inputCSS, outputCSS, { }, assert); From b7a47ae901c148ced1f166aba0becda5bf7db596 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Mar 2022 16:08:15 +0530 Subject: [PATCH 10/18] Give function better name --- scripts/postcss/css-url-to-variables.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 34d21bcc..aff8eef9 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -24,7 +24,7 @@ let counter; let urlVariables; const idToPrepend = "icon-url"; -function extractUrl(decl) { +function findAndReplaceUrl(decl) { const value = decl.value; const parsed = valueParser(value); parsed.walk(node => { @@ -60,7 +60,7 @@ module.exports = (opts = {}) => { postcssPlugin: "postcss-url-to-variable", Once(root, { Rule, Declaration }) { - root.walkDecls(decl => extractUrl(decl)); + root.walkDecls(decl => findAndReplaceUrl(decl)); addResolvedVariablesToRootSelector(root, { Rule, Declaration }); }, }; From 1a50effd861fdf773578f231e3ee668a01fb1744 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Fri, 25 Mar 2022 18:21:03 +0530 Subject: [PATCH 11/18] Only extract into variables if file is svg --- scripts/postcss/css-url-to-variables.js | 11 ++++++++--- .../postcss/tests/css-url-to-variables.test.js | 16 +++++++++++----- 2 files changed, 19 insertions(+), 8 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index aff8eef9..2a2937c0 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -31,9 +31,12 @@ function findAndReplaceUrl(decl) { if (node.type !== "function" || node.value !== "url") { return; } - const urlStringNode = node.nodes[0]; + const url = node.nodes[0].value; + if (!url.match(/\.svg\?primary=.+/)) { + return; + } const variableName = `${idToPrepend}-${counter++}`; - urlVariables.set(variableName, urlStringNode.value); + urlVariables.set(variableName, url); node.value = "var"; node.nodes = [{ type: "word", value: `--${variableName}` }]; }); @@ -61,7 +64,9 @@ module.exports = (opts = {}) => { Once(root, { Rule, Declaration }) { root.walkDecls(decl => findAndReplaceUrl(decl)); - addResolvedVariablesToRootSelector(root, { Rule, Declaration }); + if (urlVariables.size) { + addResolvedVariablesToRootSelector(root, { Rule, Declaration }); + } }, }; }; diff --git a/scripts/postcss/tests/css-url-to-variables.test.js b/scripts/postcss/tests/css-url-to-variables.test.js index fe4d4865..cc7d9cd2 100644 --- a/scripts/postcss/tests/css-url-to-variables.test.js +++ b/scripts/postcss/tests/css-url-to-variables.test.js @@ -21,10 +21,10 @@ module.exports.tests = function tests() { return { "url is replaced with variable": async (assert) => { const inputCSS = `div { - background: no-repeat center/80% url("../img/image.png"); + background: no-repeat center/80% url("../img/image.svg?primary=main-color--darker-20"); } button { - background: url("/home/foo/bar/cool.jpg"); + background: url("/home/foo/bar/cool.svg?primary=blue&secondary=green"); }`; const outputCSS = `div { @@ -35,12 +35,18 @@ module.exports.tests = function tests() { }`+ ` :root { - --icon-url-0: url("../img/image.png"); - --icon-url-1: url("/home/foo/bar/cool.jpg"); + --icon-url-0: url("../img/image.svg?primary=main-color--darker-20"); + --icon-url-1: url("/home/foo/bar/cool.svg?primary=blue&secondary=green"); } `; - await run( inputCSS, outputCSS, { }, assert); + await run(inputCSS, outputCSS, { }, assert); }, + "non svg urls without query params are not replaced": async (assert) => { + const inputCSS = `div { + background: no-repeat url("./img/foo/bar/image.png"); + }`; + await run(inputCSS, inputCSS, {}, assert); + } }; }; From cd4fce0c6ff94b53b58d820f16c8b46597535fe3 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sat, 2 Apr 2022 23:09:20 +0530 Subject: [PATCH 12/18] Populate shared map with collected icons --- scripts/postcss/css-url-to-variables.js | 18 ++++++++++++++++++ .../postcss/tests/css-url-to-variables.test.js | 16 ++++++++++++++++ 2 files changed, 34 insertions(+) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 2a2937c0..ddc65bed 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -53,6 +53,19 @@ function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { root.append(newRule); } +function populateMapWithDerivedVariables(map, cssFileLocation) { + const location = cssFileLocation.match(/(.+)\/.+\.css/)?.[1]; + if (map.has(location)) { + /** + * This postcss plugin is going to run on all theme variants of a single theme. + * But we only really need to populate the map once since theme variants only differ + * by the values of the base-variables and we don't care about values here. + */ + return; + } + map.set(location, { "icon": Object.fromEntries(urlVariables) }); +} + /* * * @type {import('postcss').PluginCreator} */ @@ -67,6 +80,11 @@ module.exports = (opts = {}) => { if (urlVariables.size) { addResolvedVariablesToRootSelector(root, { Rule, Declaration }); } + if (opts.compiledVariables){ + const cssFileLocation = root.source.input.from; + populateMapWithDerivedVariables(opts.compiledVariables, cssFileLocation); + } + console.log(opts.compiledVariables); }, }; }; diff --git a/scripts/postcss/tests/css-url-to-variables.test.js b/scripts/postcss/tests/css-url-to-variables.test.js index cc7d9cd2..e298599d 100644 --- a/scripts/postcss/tests/css-url-to-variables.test.js +++ b/scripts/postcss/tests/css-url-to-variables.test.js @@ -16,6 +16,7 @@ limitations under the License. const plugin = require("../css-url-to-variables"); const run = require("./common").createTestRunner(plugin); +const postcss = require("postcss"); module.exports.tests = function tests() { return { @@ -46,6 +47,21 @@ module.exports.tests = function tests() { background: no-repeat url("./img/foo/bar/image.png"); }`; await run(inputCSS, inputCSS, {}, assert); + }, + "map is populated with icons": async (assert) => { + const compiledVariables = new Map(); + const inputCSS = `div { + background: no-repeat center/80% url("../img/image.svg?primary=main-color--darker-20"); + } + button { + background: url("/home/foo/bar/cool.svg?primary=blue&secondary=green"); + }`; + const expectedObject = { + "icon-url-0": "../img/image.svg?primary=main-color--darker-20", + "icon-url-1": "/home/foo/bar/cool.svg?primary=blue&secondary=green", + }; + await postcss([plugin({compiledVariables})]).process(inputCSS, { from: "/foo/bar/test.css", }); + assert.deepEqual(expectedObject, compiledVariables.get("/foo/bar")["icon"]); } }; }; From 5e702171cebb11737a0128747bf855e3fe190b5f Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 3 Apr 2022 16:44:50 +0530 Subject: [PATCH 13/18] Remove console.log --- scripts/postcss/css-url-to-variables.js | 1 - 1 file changed, 1 deletion(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index ddc65bed..6c58b093 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -84,7 +84,6 @@ module.exports = (opts = {}) => { const cssFileLocation = root.source.input.from; populateMapWithDerivedVariables(opts.compiledVariables, cssFileLocation); } - console.log(opts.compiledVariables); }, }; }; From 545ff2ec32f8cd654f7676fe1c7052700dbbd3af Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Sun, 3 Apr 2022 16:46:26 +0530 Subject: [PATCH 14/18] Add explaining comment --- scripts/postcss/css-url-to-variables.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 6c58b093..7e9f5759 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -17,8 +17,8 @@ limitations under the License. const valueParser = require("postcss-value-parser"); /** - * This plugin extracts content inside url() into css variables. - * The extracted css variables are added to the :root section. + * This plugin extracts content inside url() into css variables and adds the variables to the root section. + * This plugin is used in conjunction with css-url-processor plugin to colorize svg icons. */ let counter; let urlVariables; From 9a96112146a86655a04f2b3ba9b695870ce3984d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 4 Apr 2022 12:02:59 +0530 Subject: [PATCH 15/18] Rename function name --- scripts/postcss/css-url-to-variables.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 7e9f5759..598ac973 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -53,7 +53,7 @@ function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { root.append(newRule); } -function populateMapWithDerivedVariables(map, cssFileLocation) { +function populateMapWithIcons(map, cssFileLocation) { const location = cssFileLocation.match(/(.+)\/.+\.css/)?.[1]; if (map.has(location)) { /** @@ -82,7 +82,7 @@ module.exports = (opts = {}) => { } if (opts.compiledVariables){ const cssFileLocation = root.source.input.from; - populateMapWithDerivedVariables(opts.compiledVariables, cssFileLocation); + populateMapWithIcons(opts.compiledVariables, cssFileLocation); } }, }; From 2dd655cd9ab9b4aef111061eff6ca1a3270b839b Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Mon, 4 Apr 2022 12:10:54 +0530 Subject: [PATCH 16/18] Check if icon is in shared var --- scripts/postcss/css-url-to-variables.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 598ac973..4480a2b8 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -55,7 +55,8 @@ function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { function populateMapWithIcons(map, cssFileLocation) { const location = cssFileLocation.match(/(.+)\/.+\.css/)?.[1]; - if (map.has(location)) { + const sharedObject = map.get(location); + if (sharedObject?.["icon"]) { /** * This postcss plugin is going to run on all theme variants of a single theme. * But we only really need to populate the map once since theme variants only differ @@ -63,7 +64,7 @@ function populateMapWithIcons(map, cssFileLocation) { */ return; } - map.set(location, { "icon": Object.fromEntries(urlVariables) }); + map.set(location, { ...sharedObject, "icon": Object.fromEntries(urlVariables) }); } /* * From 6d724e27e70cd547e5d87cde06a8165d77765ad9 Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Tue, 5 Apr 2022 15:26:00 +0530 Subject: [PATCH 17/18] No need to check if icons are already written --- scripts/postcss/css-url-to-variables.js | 10 +--------- scripts/postcss/tests/css-url-to-variables.test.js | 5 ++++- 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/scripts/postcss/css-url-to-variables.js b/scripts/postcss/css-url-to-variables.js index 4480a2b8..1d4666f4 100644 --- a/scripts/postcss/css-url-to-variables.js +++ b/scripts/postcss/css-url-to-variables.js @@ -56,15 +56,7 @@ function addResolvedVariablesToRootSelector(root, { Rule, Declaration }) { function populateMapWithIcons(map, cssFileLocation) { const location = cssFileLocation.match(/(.+)\/.+\.css/)?.[1]; const sharedObject = map.get(location); - if (sharedObject?.["icon"]) { - /** - * This postcss plugin is going to run on all theme variants of a single theme. - * But we only really need to populate the map once since theme variants only differ - * by the values of the base-variables and we don't care about values here. - */ - return; - } - map.set(location, { ...sharedObject, "icon": Object.fromEntries(urlVariables) }); + sharedObject["icon"] = Object.fromEntries(urlVariables); } /* * diff --git a/scripts/postcss/tests/css-url-to-variables.test.js b/scripts/postcss/tests/css-url-to-variables.test.js index e298599d..f406a38a 100644 --- a/scripts/postcss/tests/css-url-to-variables.test.js +++ b/scripts/postcss/tests/css-url-to-variables.test.js @@ -50,6 +50,7 @@ module.exports.tests = function tests() { }, "map is populated with icons": async (assert) => { const compiledVariables = new Map(); + compiledVariables.set("/foo/bar", { "derived-variables": ["background-color--darker-20", "accent-color--lighter-15"] }); const inputCSS = `div { background: no-repeat center/80% url("../img/image.svg?primary=main-color--darker-20"); } @@ -61,7 +62,9 @@ module.exports.tests = function tests() { "icon-url-1": "/home/foo/bar/cool.svg?primary=blue&secondary=green", }; await postcss([plugin({compiledVariables})]).process(inputCSS, { from: "/foo/bar/test.css", }); - assert.deepEqual(expectedObject, compiledVariables.get("/foo/bar")["icon"]); + const sharedVariable = compiledVariables.get("/foo/bar"); + assert.deepEqual(["background-color--darker-20", "accent-color--lighter-15"], sharedVariable["derived-variables"]); + assert.deepEqual(expectedObject, sharedVariable["icon"]); } }; }; From bfd73ae52a9b6cad00d7b9b4e34343495ede798d Mon Sep 17 00:00:00 2001 From: RMidhunSuresh Date: Thu, 7 Apr 2022 11:37:20 +0530 Subject: [PATCH 18/18] Pass derive function as argument --- scripts/postcss/tests/css-compile-variables.test.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/postcss/tests/css-compile-variables.test.js b/scripts/postcss/tests/css-compile-variables.test.js index e20e195f..e40751db 100644 --- a/scripts/postcss/tests/css-compile-variables.test.js +++ b/scripts/postcss/tests/css-compile-variables.test.js @@ -108,7 +108,7 @@ module.exports.tests = function tests() { --my-alias--darker-20: ${transformedColor2.hex()}; } `; - await run( inputCSS, outputCSS, { }, assert); + await run( inputCSS, outputCSS, {derive}, assert); }, "compiledVariables map is populated": async (assert) => { @@ -150,7 +150,7 @@ module.exports.tests = function tests() { --foo-color--darker-5: ${transformedColorDarker.hex()}; } `; - await run( inputCSS, outputCSS, {}, assert); + await run( inputCSS, outputCSS, {derive}, assert); } }; };