Skip to content

Commit 2c66669

Browse files
authored
use postcss-value-parser for light-dark (#32)
* use postcss-value-parser for light-dark * replace var with let * fix lint errors
1 parent 470b5f9 commit 2c66669

4 files changed

Lines changed: 1247 additions & 1513 deletions

File tree

index.js

Lines changed: 23 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
1+
let valueParser = require('postcss-value-parser');
2+
13
const PREFERS_COLOR_ONLY = /^\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)$/
24
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
65

76
function escapeRegExp(string) {
87
return string.replace(/[$()*+.?[\\\]^{|}-]/g, '\\$&')
@@ -35,17 +34,24 @@ function addColorSchemeMedia(isDark, propValue, declaration, postcss) {
3534
declaration.parent.after(mediaQuery)
3635
}
3736

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+
})
4955
}
5056

5157
module.exports = (opts = {}) => {
@@ -151,25 +157,9 @@ module.exports = (opts = {}) => {
151157
DeclarationExit: (declaration, { postcss }) => {
152158
if (!declaration.value.includes('light-dark')) return
153159

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)
173163

174164
addColorSchemeMedia(false, lightValue, declaration, postcss)
175165
addColorSchemeMedia(true, darkValue, declaration, postcss)

index.test.js

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -701,3 +701,27 @@ body:where(.is-light) {
701701
{ rootSelector: 'body' }
702702
)
703703
})
704+
705+
test('transforms complex nested light-dark()', () => {
706+
run(
707+
`.light-dark-function-mix-a {
708+
color: light-dark(color-mix(in oklch, red, light-dark(cyan, rgb(0, 0, 0))), blue);
709+
}`,
710+
`@media (prefers-color-scheme:dark) {
711+
:where(html:not(.is-light)) .light-dark-function-mix-a {
712+
color: blue
713+
}
714+
}
715+
:where(html.is-dark) .light-dark-function-mix-a {
716+
color: blue
717+
}
718+
@media (prefers-color-scheme:light) {
719+
:where(html:not(.is-dark)) .light-dark-function-mix-a {
720+
color: color-mix(in oklch, red, cyan)
721+
}
722+
}
723+
:where(html.is-light) .light-dark-function-mix-a {
724+
color: color-mix(in oklch, red, cyan)
725+
}`
726+
)
727+
})

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,8 @@
6565
},
6666
"clean-publish": {
6767
"cleanDocs": true
68+
},
69+
"dependencies": {
70+
"postcss-value-parser": "^4.2.0"
6871
}
6972
}

0 commit comments

Comments
 (0)