From 77c71c5e34ac33f88f038e44a687b0289058c067 Mon Sep 17 00:00:00 2001 From: Cameron Moon Date: Tue, 3 Jun 2025 11:56:34 +1000 Subject: [PATCH] Fix bug with transitive values containing spaces --- index.js | 21 +++++++-------------- index.test.js | 18 ++++++++++++++---- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/index.js b/index.js index b236de3..16d079e 100644 --- a/index.js +++ b/index.js @@ -8,7 +8,7 @@ const { urlToRequest } = require('loader-utils'); const ICSSUtils = require('icss-utils'); const matchImports = /^(.+?|\([\s\S]+?\))\s+from\s+("[^"]*"|'[^']*'|[\w-]+)$/; -const matchValueDefinition = /(?:\s+|^)([\w-]+)(:?\s+)(.+?)(\s*)$/g; +const matchValueDefinition = /(?:\s+|^)([\w-]+)(:?\s+)(.+?)(\s*)$/; const matchImport = /^([\w-]+)(?:\s+as\s+([\w-]+))?/; const matchPath = /"[^"]*"|'[^']*'/; @@ -38,22 +38,15 @@ const replaceValueSymbols = (valueString, replacements) => { }; const getDefinition = (atRule, existingDefinitions, requiredDefinitions) => { - let matches; - const definition = {}; + const [/* match */, name, middle, value, end] = matchValueDefinition.exec(atRule.params); + const valueWithReplacements = replaceValueSymbols(value, existingDefinitions); - // eslint-disable-next-line no-cond-assign - while (matches = matchValueDefinition.exec(atRule.params)) { - const [/* match */, requiredName, middle, value, end] = matches; - // Add to the definitions, knowing that values can refer to each other - definition[requiredName] = replaceValueSymbols(value, existingDefinitions); - - if (!requiredDefinitions) { - // eslint-disable-next-line no-param-reassign - atRule.params = requiredName + middle + definition[requiredName] + end; - } + if (!requiredDefinitions) { + // eslint-disable-next-line no-param-reassign + atRule.params = name + middle + valueWithReplacements + end; } - return definition; + return { [name]: valueWithReplacements }; }; const getImports = (aliases) => { diff --git a/index.test.js b/index.test.js index 74b5204..9e1ab6a 100644 --- a/index.test.js +++ b/index.test.js @@ -255,6 +255,16 @@ test('should allow transitive values within calc without spaces', async (t) => { ); }); +test('should allow transitive values containing spaces, like CSS relative colors', async (t) => { + await run( + t, + '@value mixedColor: color-mix(in hsl, hsl(200 50 80), coral 80%);\n' + + '@value mixedColorA90: hsl(from mixedColor h s l / 90%);', + '@value mixedColor: color-mix(in hsl, hsl(200 50 80), coral 80%);\n' + + '@value mixedColorA90: hsl(from color-mix(in hsl, hsl(200 50 80), coral 80%) h s l / 90%);', + ); +}); + test('should replace inside custom properties', async (t) => { await run( t, @@ -300,10 +310,10 @@ test('should allow custom-property-style names', async (t) => { test('should allow all colour types', async (t) => { await run( t, - '@value named: red; @value hex3char #0f0; @value hex6char #00ff00; @value rgba rgba(34, 12, 64, 0.3); @value hsla hsla(220, 13.0%, 18.0%, 1);\n' - + '.foo { color: named; background-color: hex3char; border-top-color: hex6char; border-bottom-color: rgba; outline-color: hsla; }', - '@value named: red; @value hex3char #0f0; @value hex6char #00ff00; @value rgba rgba(34, 12, 64, 0.3); @value hsla hsla(220, 13.0%, 18.0%, 1);\n' - + '.foo { color: red; background-color: #0f0; border-top-color: #00ff00; border-bottom-color: rgba(34, 12, 64, 0.3); outline-color: hsla(220, 13.0%, 18.0%, 1); }', + '@value named: red; @value hex3char #0f0; @value hex6char #00ff00; @value rgba rgba(34, 12, 64, 0.3); @value hsla hsla(220, 13.0%, 18.0%, 1); @value hsl hsl(264 100% 62% / 70%);\n' + + '.foo { color: named; background-color: hex3char; border-top-color: hex6char; border-bottom-color: rgba; outline-color: hsla; border-left-color: hsl; }', + '@value named: red; @value hex3char #0f0; @value hex6char #00ff00; @value rgba rgba(34, 12, 64, 0.3); @value hsla hsla(220, 13.0%, 18.0%, 1); @value hsl hsl(264 100% 62% / 70%);\n' + + '.foo { color: red; background-color: #0f0; border-top-color: #00ff00; border-bottom-color: rgba(34, 12, 64, 0.3); outline-color: hsla(220, 13.0%, 18.0%, 1); border-left-color: hsl(264 100% 62% / 70%); }', ); });