Skip to content

Commit e486e28

Browse files
authored
Fix light-dark (#27)
* update light-dark regex to support different color syntax * handle nested light-dark
1 parent 08d3d43 commit e486e28

File tree

2 files changed

+92
-6
lines changed

2 files changed

+92
-6
lines changed

index.js

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
const PREFERS_COLOR_ONLY = /^\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)$/
22
const PREFERS_COLOR = /\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)/g
3-
const LIGHT_DARK = /light-dark\(\s*(.+?)\s*,\s*(.+?)\s*\)/g
3+
const LIGHT_DARK =
4+
/light-dark\(\s*((?:[^(),]|\(.+\))+?)\s*,\s*((?:[^(),]|\(.+\))+?)\s*\)/gs
45
const STRING = /"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/dg
56

67
function escapeRegExp(string) {
@@ -30,15 +31,15 @@ function addColorSchemeMedia(isDark, propValue, declaration, postcss) {
3031
declaration.parent.after(mediaQuery)
3132
}
3233

33-
function replaceLightDark(isDark, declaration, stringBoundaries) {
34-
return declaration.value.replaceAll(
34+
function replaceLightDark(isDark, declarationValue, stringBoundaries) {
35+
return declarationValue.replaceAll(
3536
LIGHT_DARK,
3637
(match, lightColor, darkColor, offset) => {
3738
let isInsideString = stringBoundaries.some(
3839
boundary => offset > boundary[0] && offset < boundary[1]
3940
)
4041
if (isInsideString) return match
41-
return isDark ? darkColor : lightColor
42+
return replaceLightDark(isDark, isDark ? darkColor : lightColor, [])
4243
}
4344
)
4445
}
@@ -154,9 +155,17 @@ module.exports = (opts = {}) => {
154155
match = STRING.exec(value)
155156
}
156157

157-
let lightValue = replaceLightDark(false, declaration, stringBoundaries)
158+
let lightValue = replaceLightDark(
159+
false,
160+
declaration.value,
161+
stringBoundaries
162+
)
158163
if (declaration.value === lightValue) return
159-
let darkValue = replaceLightDark(true, declaration, stringBoundaries)
164+
let darkValue = replaceLightDark(
165+
true,
166+
declaration.value,
167+
stringBoundaries
168+
)
160169

161170
addColorSchemeMedia(false, lightValue, declaration, postcss)
162171
addColorSchemeMedia(true, darkValue, declaration, postcss)

index.test.js

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,83 @@ html:where(.is-light) {
407407
)
408408
})
409409

410+
test('transforms nested light-dark()', () => {
411+
run(
412+
`html {
413+
border: 1px solid light-dark(light-dark(white, red), light-dark(blue, light-dark(gray, rgb(255 122 127 / .2))))
414+
}`,
415+
`@media (prefers-color-scheme:dark) {
416+
html:where(:not(.is-light)) {
417+
border: 1px solid rgb(255 122 127 / .2)
418+
}
419+
}
420+
html:where(.is-dark) {
421+
border: 1px solid rgb(255 122 127 / .2)
422+
}
423+
@media (prefers-color-scheme:light) {
424+
html:where(:not(.is-dark)) {
425+
border: 1px solid white
426+
}
427+
}
428+
html:where(.is-light) {
429+
border: 1px solid white
430+
}`
431+
)
432+
})
433+
434+
test('transforms light-dark() with various color formats', () => {
435+
run(
436+
`html {
437+
border: 1px solid light-dark(rgb(0, 0, 0), var(--color));
438+
color: light-dark( hsla(120, 100%, 50%, 0.3) , hsl(
439+
var(--red-hue)
440+
var(--red-sat)
441+
calc(var(--red-lit) - 20%)
442+
));
443+
}`,
444+
`@media (prefers-color-scheme:dark) {
445+
html:where(:not(.is-light)) {
446+
color: hsl(
447+
var(--red-hue)
448+
var(--red-sat)
449+
calc(var(--red-lit) - 20%)
450+
)
451+
}
452+
}
453+
html:where(.is-dark) {
454+
color: hsl(
455+
var(--red-hue)
456+
var(--red-sat)
457+
calc(var(--red-lit) - 20%)
458+
)
459+
}
460+
@media (prefers-color-scheme:light) {
461+
html:where(:not(.is-dark)) {
462+
color: hsla(120, 100%, 50%, 0.3)
463+
}
464+
}
465+
html:where(.is-light) {
466+
color: hsla(120, 100%, 50%, 0.3)
467+
}
468+
@media (prefers-color-scheme:dark) {
469+
html:where(:not(.is-light)) {
470+
border: 1px solid var(--color)
471+
}
472+
}
473+
html:where(.is-dark) {
474+
border: 1px solid var(--color)
475+
}
476+
@media (prefers-color-scheme:light) {
477+
html:where(:not(.is-dark)) {
478+
border: 1px solid rgb(0, 0, 0)
479+
}
480+
}
481+
html:where(.is-light) {
482+
border: 1px solid rgb(0, 0, 0)
483+
}`
484+
)
485+
})
486+
410487
test('does not transform light-dark() inside strings', () => {
411488
run(
412489
`html {

0 commit comments

Comments
 (0)