Skip to content

Commit 71927bc

Browse files
Add preferred-color-scheme: light support (#23)
* add light color scheme support * fix README * separate tests for light scheme * remove an example for the light scheme from README
1 parent 13e818f commit 71927bc

2 files changed

Lines changed: 176 additions & 17 deletions

File tree

index.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
const PREFERS_COLOR_ONLY = /^\(\s*prefers-color-scheme\s*:\s*dark\s*\)$/
2-
const PREFERS_COLOR = /\(\s*prefers-color-scheme\s*:\s*dark\s*\)/g
1+
const PREFERS_COLOR_ONLY = /^\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)$/
2+
const PREFERS_COLOR = /\(\s*prefers-color-scheme\s*:\s*(dark|light)\s*\)/g
33

44
function escapeRegExp(string) {
55
return string.replace(/[$()*+.?[\\\]^{|}-]/g, '\\$&')
@@ -11,7 +11,7 @@ function replaceAll(string, find, replace) {
1111

1212
module.exports = (opts = {}) => {
1313
let dark = opts.darkSelector || '.is-dark'
14-
let light = `:not(${opts.lightSelector || '.is-light'})`
14+
let light = opts.lightSelector || '.is-light'
1515

1616
let roots = opts.rootSelector || ['html', ':root']
1717
if (!Array.isArray(roots)) roots = [roots]
@@ -64,22 +64,26 @@ module.exports = (opts = {}) => {
6464
return {
6565
AtRuleExit: {
6666
media: atrule => {
67-
if (!atrule.params.includes('dark')) return
67+
if (!atrule.params.includes('dark') && !atrule.params.includes('light')) return
68+
6869
let params = atrule.params
70+
let fixedSelector = params.includes('dark') ? dark : light
71+
let nodeSelector = `:not(${params.includes('dark') ? light : dark})`
72+
6973
if (PREFERS_COLOR_ONLY.test(params)) {
7074
let last = atrule
7175
atrule.each(node => {
7276
let fixed
7377
if (node.type === 'atrule') {
7478
fixed = node.clone()
75-
processNodes(fixed, dark)
76-
processNodes(node, light)
79+
processNodes(fixed, fixedSelector)
80+
processNodes(node, nodeSelector)
7781
} else if (node.type === 'rule') {
78-
if (!node.selector.includes(light)) {
82+
if (!node.selector.includes(nodeSelector)) {
7983
fixed = node.clone({
80-
selectors: processSelectors(node.selectors, dark)
84+
selectors: processSelectors(node.selectors, fixedSelector)
8185
})
82-
node.selectors = processSelectors(node.selectors, light)
86+
node.selectors = processSelectors(node.selectors, nodeSelector)
8387
}
8488
} else if (node.type === 'comment') {
8589
fixed = node.clone()
@@ -99,8 +103,8 @@ module.exports = (opts = {}) => {
99103
.replace(/\s+and\s*$/i, '')
100104
})
101105
atrule.after(fixed)
102-
processNodes(fixed, dark)
103-
processNodes(atrule, light)
106+
processNodes(fixed, fixedSelector)
107+
processNodes(atrule, nodeSelector)
104108
}
105109
}
106110
}

index.test.js

Lines changed: 161 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ function run(input, output, opts) {
1010
equal(result.warnings().length, 0)
1111
}
1212

13-
test('replaces selectors', () => {
13+
test('replaces selectors - dark scheme', () => {
1414
run(
1515
`@media (prefers-color-scheme:dark) {
1616
html.is-a,
@@ -31,7 +31,65 @@ test('replaces selectors', () => {
3131
)
3232
})
3333

34-
test('disables :where() of request', () => {
34+
test('replaces selectors - light scheme', () => {
35+
run(
36+
`@media (prefers-color-scheme:light) {
37+
html.is-a,
38+
html,
39+
:root,
40+
a { }
41+
}`,
42+
`@media (prefers-color-scheme:light) {
43+
html:where(:not(.is-dark)).is-a,
44+
html:where(:not(.is-dark)),
45+
:root:where(:not(.is-dark)),
46+
:where(html:not(.is-dark)) a { }
47+
}
48+
html:where(.is-light).is-a,
49+
html:where(.is-light),
50+
:root:where(.is-light),
51+
:where(html.is-light) a { }`
52+
)
53+
})
54+
55+
test('replaces selectors - dark and light schemes', () => {
56+
run(
57+
`@media (prefers-color-scheme:dark) {
58+
html.is-a,
59+
html,
60+
:root,
61+
a { }
62+
}
63+
@media (prefers-color-scheme:light) {
64+
html.is-a,
65+
html,
66+
:root,
67+
a { }
68+
}`,
69+
`@media (prefers-color-scheme:dark) {
70+
html:where(:not(.is-light)).is-a,
71+
html:where(:not(.is-light)),
72+
:root:where(:not(.is-light)),
73+
:where(html:not(.is-light)) a { }
74+
}
75+
html:where(.is-dark).is-a,
76+
html:where(.is-dark),
77+
:root:where(.is-dark),
78+
:where(html.is-dark) a { }
79+
@media (prefers-color-scheme:light) {
80+
html:where(:not(.is-dark)).is-a,
81+
html:where(:not(.is-dark)),
82+
:root:where(:not(.is-dark)),
83+
:where(html:not(.is-dark)) a { }
84+
}
85+
html:where(.is-light).is-a,
86+
html:where(.is-light),
87+
:root:where(.is-light),
88+
:where(html.is-light) a { }`
89+
)
90+
})
91+
92+
test('disables :where() of request - dark scheme', () => {
3593
run(
3694
`@media (prefers-color-scheme:dark) {
3795
html.is-a,
@@ -53,7 +111,29 @@ test('disables :where() of request', () => {
53111
)
54112
})
55113

56-
test('processes inner at-rules', () => {
114+
test('disables :where() of request - light scheme', () => {
115+
run(
116+
`@media (prefers-color-scheme:light) {
117+
html.is-a,
118+
html,
119+
:root,
120+
a { }
121+
}`,
122+
`@media (prefers-color-scheme:light) {
123+
html:not(.is-dark).is-a,
124+
html:not(.is-dark),
125+
:root:not(.is-dark),
126+
html:not(.is-dark) a { }
127+
}
128+
html.is-light.is-a,
129+
html.is-light,
130+
:root.is-light,
131+
html.is-light a { }`,
132+
{ useWhere: false }
133+
)
134+
})
135+
136+
test('processes inner at-rules - dark scheme', () => {
57137
run(
58138
`@media (prefers-color-scheme: dark) {
59139
@media (min-width: 500px) {
@@ -86,6 +166,39 @@ test('processes inner at-rules', () => {
86166
)
87167
})
88168

169+
test('processes inner at-rules - light scheme', () => {
170+
run(
171+
`@media (prefers-color-scheme: light) {
172+
@media (min-width: 500px) {
173+
a { }
174+
}
175+
@media (min-width: 500px) {
176+
@media (print) {
177+
a { }
178+
}
179+
}
180+
}`,
181+
`@media (prefers-color-scheme: light) {
182+
@media (min-width: 500px) {
183+
:where(html:not(.is-dark)) a { }
184+
}
185+
@media (min-width: 500px) {
186+
@media (print) {
187+
:where(html:not(.is-dark)) a { }
188+
}
189+
}
190+
}
191+
@media (min-width: 500px) {
192+
:where(html.is-light) a { }
193+
}
194+
@media (min-width: 500px) {
195+
@media (print) {
196+
:where(html.is-light) a { }
197+
}
198+
}`
199+
)
200+
})
201+
89202
test('checks media params deeply', () => {
90203
run(
91204
`@media (x-dark: true) {
@@ -133,7 +246,7 @@ test('reserve comments', () => {
133246
)
134247
})
135248

136-
test('supports combined queries', () => {
249+
test('supports combined queries - dark scheme', () => {
137250
run(
138251
`@media (min-width: 60px) and (prefers-color-scheme: dark) {
139252
a { color: white }
@@ -146,7 +259,20 @@ test('supports combined queries', () => {
146259
)
147260
})
148261

149-
test('supports combined queries in the middle', () => {
262+
test('supports combined queries - light scheme', () => {
263+
run(
264+
`@media (min-width: 60px) and (prefers-color-scheme: light) {
265+
a { color: white }
266+
}`,
267+
`@media (min-width: 60px) and (prefers-color-scheme: light) {
268+
:where(html:not(.is-dark)) a { color: white }
269+
}@media (min-width: 60px) {
270+
:where(html.is-light) a { color: white }
271+
}`
272+
)
273+
})
274+
275+
test('supports combined queries in the middle - dark scheme', () => {
150276
run(
151277
`@media (width > 0) and (prefers-color-scheme: dark) and (width > 0) {
152278
a { color: white }
@@ -159,6 +285,19 @@ test('supports combined queries in the middle', () => {
159285
)
160286
})
161287

288+
test('supports combined queries in the middle - light scheme', () => {
289+
run(
290+
`@media (width > 0) and (prefers-color-scheme: light) and (width > 0) {
291+
a { color: white }
292+
}`,
293+
`@media (width > 0) and (prefers-color-scheme: light) and (width > 0) {
294+
:where(html:not(.is-dark)) a { color: white }
295+
}@media (width > 0) and (width > 0) {
296+
:where(html.is-light) a { color: white }
297+
}`
298+
)
299+
})
300+
162301
test('allows to change class', () => {
163302
run(
164303
`@media (prefers-color-scheme: dark) {
@@ -212,7 +351,7 @@ test('changes root selector', () => {
212351
)
213352
})
214353

215-
test('ignores already transformed rules', () => {
354+
test('ignores already transformed rules - dark scheme', () => {
216355
run(
217356
`@media (prefers-color-scheme: dark) {
218357
:root:not(.is-light) { --bg: black }
@@ -228,4 +367,20 @@ test('ignores already transformed rules', () => {
228367
)
229368
})
230369

370+
test('ignores already transformed rules - light scheme', () => {
371+
run(
372+
`@media (prefers-color-scheme: light) {
373+
:root:not(.is-dark) { --bg: black }
374+
p { color: white }
375+
}
376+
:root { --bg: white }`,
377+
`@media (prefers-color-scheme: light) {
378+
:root:not(.is-dark) { --bg: black }
379+
:where(html:not(.is-dark)) p { color: white }
380+
}
381+
:where(html.is-light) p { color: white }
382+
:root { --bg: white }`
383+
)
384+
})
385+
231386
test.run()

0 commit comments

Comments
 (0)