Skip to content

Commit 70879f1

Browse files
committed
add support for checking a11y for themes with light-dark(...) colors to tools/checkTheme.js
1 parent 6e69825 commit 70879f1

File tree

2 files changed

+90
-8
lines changed

2 files changed

+90
-8
lines changed

CHANGES.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,10 @@ Core Grammars:
2828
- fix(css) `unicode-range` parsing, issue #4253 [Kerry Shetline][]
2929
- fix(csharp) Support digit separators [te-ing][]
3030

31+
Developer Tools:
32+
33+
- add support for checking a11y for themes with `light-dark(...)` colors to `tools/checkTheme.js`
34+
3135
Documentation:
3236

3337
- alphabetized languages + upper-cased BASIC in SUPPORTED_LANGUAGES.md [Adam Lui][]

tools/checkTheme.js

Lines changed: 86 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,19 @@ function check_group(group, rules) {
187187
}
188188
}
189189

190+
function is_light_dark(value) {
191+
return typeof value === "string" && value.startsWith("light-dark");
192+
}
193+
194+
function get_colors_from_light_dark(light_dark_value) {
195+
light_dark_value = light_dark_value.trim();
196+
light_dark_value = light_dark_value.substring(11, light_dark_value.length - 1);
197+
let [light, dark] = light_dark_value.split(",");
198+
light = light.trim();
199+
dark = dark.trim();
200+
return [light, dark];
201+
}
202+
190203
const round2 = (x) => Math.round(x*100)/100;
191204

192205
class CSSRule {
@@ -199,38 +212,85 @@ class CSSRule {
199212
}
200213
this.fg = rule.declarations.find(x => x.property =="color")?.value;
201214

215+
if (is_light_dark(this.bg)) {
216+
[this.bg, this.bg_dark] = get_colors_from_light_dark(this.bg);
217+
}
218+
if (is_light_dark(this.fg)) {
219+
[this.fg, this.fg_dark] = get_colors_from_light_dark(this.fg);
220+
}
221+
202222
if (this.bg) {
203223
this.bg = csscolors[this.bg] || this.bg;
204224
}
205225
if (this.fg) {
206226
this.fg = csscolors[this.fg] || this.fg;
207227
}
228+
if (this.bg_dark) {
229+
this.bg_dark = csscolors[this.bg_dark] || this.bg_dark;
230+
}
231+
if (this.fg_dark) {
232+
this.fg_dark = csscolors[this.fg_dark] || this.fg_dark;
233+
}
208234

209235
// inherit from body if we're missing fg or bg
210236
if (this.hasColor) {
211237
if (!this.bg) this.bg = body.background;
212238
if (!this.fg) this.fg = body.foreground;
239+
if (body?.hasLightDark) {
240+
if (!this.bg_dark) this.bg_dark = body.backgroundDark;
241+
if (!this.fg_dark) this.fg_dark = body.foregroundDark;
242+
}
213243
}
214244
}
215245
}
246+
216247
get background() {
217248
return this.bg
218249
}
219250

220251
get foreground() {
221252
return this.fg
222253
}
254+
255+
get backgroundDark() {
256+
return this.bg_dark;
257+
}
258+
259+
get foregroundDark() {
260+
return this.fg_dark;
261+
}
262+
223263
get hasColor() {
224264
if (!this.rule.declarations) return false;
225265
return this.fg || this.bg;
226266
}
267+
268+
get hasLightDark() {
269+
if (!this.rule.declarations) return false;
270+
return this.fg_dark || this.bg_dark;
271+
}
272+
227273
toString() {
274+
if (this.hasLightDark) {
275+
return ` light: ${this.foreground} on ${this.background}, dark: ${this.foregroundDark} on ${this.backgroundDark}`;
276+
}
228277
return ` ${this.foreground} on ${this.background}`
229278
}
230279

231280
contrastRatio() {
232281
if (!this.foreground) return "unknown (no fg)"
233282
if (!this.background) return "unknown (no bg)"
283+
if (this.hasLightDark) {
284+
const lightRatio = round2(wcagContrast.hex(this.foreground, this.background));
285+
286+
let darkRatio = "unknown";
287+
if (!this.foregroundDark) darkRatio = "unknown (no fg)";
288+
else if (!this.backgroundDark) darkRatio = "unknown (no bg)";
289+
else darkRatio = round2(wcagContrast.hex(this.foregroundDark, this.backgroundDark));
290+
291+
return [lightRatio, darkRatio];
292+
}
293+
234294
return round2(wcagContrast.hex(this.foreground, this.background));
235295
}
236296
}
@@ -240,10 +300,17 @@ function contrast_report(rules) {
240300

241301
var hljs = rules.find (x => x.selectors && x.selectors.includes(".hljs"));
242302
var body = new CSSRule(hljs);
303+
const head = body.hasLightDark
304+
? ['ratio light', 'ratio dark', 'selector', 'fg light', 'bg light', 'fg dark', 'bg dark']
305+
: ['ratio', 'selector', 'fg', 'bg'];
306+
const colWidths = body.hasLightDark
307+
? [13, 12, 40, 10, 10, 10, 10]
308+
: [7, 40, 10, 10];
309+
243310
const table = new Table({
244311
chars: {'mid': '', 'left-mid': '', 'mid-mid': '', 'right-mid': ''},
245-
head: ['ratio', 'selector', 'fg', 'bg'],
246-
colWidths: [7, 40, 10, 10],
312+
head,
313+
colWidths,
247314
style: {
248315
head: ['grey']
249316
}
@@ -252,12 +319,23 @@ function contrast_report(rules) {
252319
rules.forEach(rule => {
253320
var color = new CSSRule(rule, body);
254321
if (!color.hasColor) return;
255-
table.push([
256-
color.contrastRatio(),
257-
rule.selectors,
258-
color.foreground,
259-
color.background
260-
])
322+
if (color.hasLightDark) {
323+
table.push([
324+
...color.contrastRatio(),
325+
rule.selectors,
326+
color.foreground,
327+
color.background,
328+
color.foregroundDark,
329+
color.backgroundDark
330+
]);
331+
} else {
332+
table.push([
333+
color.contrastRatio(),
334+
rule.selectors,
335+
color.foreground,
336+
color.background
337+
]);
338+
}
261339
// console.log(r.selectors[0], color.contrastRatio(), color.toString());
262340
})
263341
console.log(table.toString())

0 commit comments

Comments
 (0)