|
| 1 | +let valueParser = require('postcss-value-parser'); |
| 2 | + |
1 | 3 | const PREFERS_COLOR_ONLY = /^\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)$/ |
2 | 4 | const PREFERS_COLOR = /\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)/g |
3 | | -const LIGHT_DARK = |
4 | | - /light-dark\(\s*((?:[^(),]|\(.+\))+?)\s*,\s*((?:[^(),]|\(.+\))+?)\s*\)/gs |
5 | | -const STRING = /"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/dg |
6 | 5 |
|
7 | 6 | function escapeRegExp(string) { |
8 | 7 | return string.replace(/[$()*+.?[\\\]^{|}-]/g, '\\$&') |
@@ -35,17 +34,24 @@ function addColorSchemeMedia(isDark, propValue, declaration, postcss) { |
35 | 34 | declaration.parent.after(mediaQuery) |
36 | 35 | } |
37 | 36 |
|
38 | | -function replaceLightDark(isDark, declarationValue, stringBoundaries) { |
39 | | - return declarationValue.replaceAll( |
40 | | - LIGHT_DARK, |
41 | | - (match, lightColor, darkColor, offset) => { |
42 | | - let isInsideString = stringBoundaries.some( |
43 | | - boundary => offset > boundary[0] && offset < boundary[1] |
44 | | - ) |
45 | | - if (isInsideString) return match |
46 | | - return replaceLightDark(isDark, isDark ? darkColor : lightColor, []) |
47 | | - } |
48 | | - ) |
| 37 | +function extractLightDark(isDark, declarationValue) { |
| 38 | + let parsed = valueParser(declarationValue) |
| 39 | + mutateLightDarkRec(isDark, parsed) |
| 40 | + return valueParser.stringify(parsed) |
| 41 | +} |
| 42 | + |
| 43 | +function mutateLightDarkRec(isDark, parsed) { |
| 44 | + let wasMutated = false |
| 45 | + parsed.walk(node => { |
| 46 | + if (wasMutated || node.type !== 'function' || node.value !== 'light-dark') return |
| 47 | + |
| 48 | + let light = node.nodes[0] |
| 49 | + let dark = node.nodes.find((x, i) => i > 0 && (x.type === 'word' || x.type === 'function')) |
| 50 | + Object.assign(node, isDark ? dark : light) |
| 51 | + mutateLightDarkRec(isDark, parsed) |
| 52 | + wasMutated = true |
| 53 | + return false |
| 54 | + }) |
49 | 55 | } |
50 | 56 |
|
51 | 57 | module.exports = (opts = {}) => { |
@@ -151,25 +157,9 @@ module.exports = (opts = {}) => { |
151 | 157 | DeclarationExit: (declaration, { postcss }) => { |
152 | 158 | if (!declaration.value.includes('light-dark')) return |
153 | 159 |
|
154 | | - let stringBoundaries = [] |
155 | | - let value = declaration.value.slice() |
156 | | - let match = STRING.exec(value) |
157 | | - while (match) { |
158 | | - stringBoundaries.push(match.indices[0]) |
159 | | - match = STRING.exec(value) |
160 | | - } |
161 | | - |
162 | | - let lightValue = replaceLightDark( |
163 | | - false, |
164 | | - declaration.value, |
165 | | - stringBoundaries |
166 | | - ) |
167 | | - if (declaration.value === lightValue) return |
168 | | - let darkValue = replaceLightDark( |
169 | | - true, |
170 | | - declaration.value, |
171 | | - stringBoundaries |
172 | | - ) |
| 160 | + let lightValue = extractLightDark(false, declaration.value) |
| 161 | + if (lightValue === declaration.value) return |
| 162 | + let darkValue = extractLightDark(true, declaration.value) |
173 | 163 |
|
174 | 164 | addColorSchemeMedia(false, lightValue, declaration, postcss) |
175 | 165 | addColorSchemeMedia(true, darkValue, declaration, postcss) |
|
0 commit comments