Skip to content

Commit

Permalink
Fix light-dark (#27)
Browse files Browse the repository at this point in the history
* update light-dark regex to support different color syntax

* handle nested light-dark
  • Loading branch information
VladBrok authored Feb 14, 2024
1 parent 08d3d43 commit e486e28
Show file tree
Hide file tree
Showing 2 changed files with 92 additions and 6 deletions.
21 changes: 15 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
const PREFERS_COLOR_ONLY = /^\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)$/
const PREFERS_COLOR = /\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)/g
const LIGHT_DARK = /light-dark\(\s*(.+?)\s*,\s*(.+?)\s*\)/g
const LIGHT_DARK =
/light-dark\(\s*((?:[^(),]|\(.+\))+?)\s*,\s*((?:[^(),]|\(.+\))+?)\s*\)/gs
const STRING = /"(?:\\.|[^"\\])*"|'(?:\\.|[^'\\])*'/dg

function escapeRegExp(string) {
Expand Down Expand Up @@ -30,15 +31,15 @@ function addColorSchemeMedia(isDark, propValue, declaration, postcss) {
declaration.parent.after(mediaQuery)
}

function replaceLightDark(isDark, declaration, stringBoundaries) {
return declaration.value.replaceAll(
function replaceLightDark(isDark, declarationValue, stringBoundaries) {
return declarationValue.replaceAll(
LIGHT_DARK,
(match, lightColor, darkColor, offset) => {
let isInsideString = stringBoundaries.some(
boundary => offset > boundary[0] && offset < boundary[1]
)
if (isInsideString) return match
return isDark ? darkColor : lightColor
return replaceLightDark(isDark, isDark ? darkColor : lightColor, [])
}
)
}
Expand Down Expand Up @@ -154,9 +155,17 @@ module.exports = (opts = {}) => {
match = STRING.exec(value)
}

let lightValue = replaceLightDark(false, declaration, stringBoundaries)
let lightValue = replaceLightDark(
false,
declaration.value,
stringBoundaries
)
if (declaration.value === lightValue) return
let darkValue = replaceLightDark(true, declaration, stringBoundaries)
let darkValue = replaceLightDark(
true,
declaration.value,
stringBoundaries
)

addColorSchemeMedia(false, lightValue, declaration, postcss)
addColorSchemeMedia(true, darkValue, declaration, postcss)
Expand Down
77 changes: 77 additions & 0 deletions index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -407,6 +407,83 @@ html:where(.is-light) {
)
})

test('transforms nested light-dark()', () => {
run(
`html {
border: 1px solid light-dark(light-dark(white, red), light-dark(blue, light-dark(gray, rgb(255 122 127 / .2))))
}`,
`@media (prefers-color-scheme:dark) {
html:where(:not(.is-light)) {
border: 1px solid rgb(255 122 127 / .2)
}
}
html:where(.is-dark) {
border: 1px solid rgb(255 122 127 / .2)
}
@media (prefers-color-scheme:light) {
html:where(:not(.is-dark)) {
border: 1px solid white
}
}
html:where(.is-light) {
border: 1px solid white
}`
)
})

test('transforms light-dark() with various color formats', () => {
run(
`html {
border: 1px solid light-dark(rgb(0, 0, 0), var(--color));
color: light-dark( hsla(120, 100%, 50%, 0.3) , hsl(
var(--red-hue)
var(--red-sat)
calc(var(--red-lit) - 20%)
));
}`,
`@media (prefers-color-scheme:dark) {
html:where(:not(.is-light)) {
color: hsl(
var(--red-hue)
var(--red-sat)
calc(var(--red-lit) - 20%)
)
}
}
html:where(.is-dark) {
color: hsl(
var(--red-hue)
var(--red-sat)
calc(var(--red-lit) - 20%)
)
}
@media (prefers-color-scheme:light) {
html:where(:not(.is-dark)) {
color: hsla(120, 100%, 50%, 0.3)
}
}
html:where(.is-light) {
color: hsla(120, 100%, 50%, 0.3)
}
@media (prefers-color-scheme:dark) {
html:where(:not(.is-light)) {
border: 1px solid var(--color)
}
}
html:where(.is-dark) {
border: 1px solid var(--color)
}
@media (prefers-color-scheme:light) {
html:where(:not(.is-dark)) {
border: 1px solid rgb(0, 0, 0)
}
}
html:where(.is-light) {
border: 1px solid rgb(0, 0, 0)
}`
)
})

test('does not transform light-dark() inside strings', () => {
run(
`html {
Expand Down

0 comments on commit e486e28

Please sign in to comment.