-
-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathprefers-color-scheme.js
78 lines (63 loc) · 2.17 KB
/
prefers-color-scheme.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
const postcss = require('postcss');
/**
* Docusaurus theming depends on JavaScript by default. This drops that in
* favor of `prefers-color-scheme`.
*
* Doesn't work for components styled with Prism like code blocks.
*
* @param {Object} context
* @returns {Object}
*/
function prefersColorScheme(context) {
const themeConfig = context.siteConfig.themeConfig;
const { colorMode } = themeConfig;
return {
name: 'prefers-color-scheme',
configurePostCss(postCssOptions) {
if (colorMode.disableSwitch && colorMode.respectPrefersColorScheme) {
/** @type {postcss.Plugin} */
const plugin = {
postcssPlugin: 'PrefersColorSchemePlugin',
Rule(rule) {
if (!rule.parent) {
return;
}
const pattern = /\[data-theme=(["']|)([^"']+)\1\]/;
const newSelectors = [];
for (const selector of rule.selectors) {
const match = pattern.exec(selector);
if (!match) {
newSelectors.push(selector);
continue;
}
const [fullMatch, , theme] = match;
// Replace attribute selector ([data-theme]) with an always
// matching selector of equal specificity (0, 1, 0)
const trimmed = selector.replace(fullMatch, '');
const newSelector =
trimmed.length > 0 ? `${trimmed}:not(._)` : ':root';
const newRule = rule.clone();
newRule.selector = newSelector;
newRule.selectors = [newSelector];
const media = new postcss.AtRule({
name: 'media',
params: `(prefers-color-scheme: ${theme})`,
nodes: [newRule],
});
rule.parent.insertBefore(rule, media);
}
if (newSelectors.length === 0) {
rule.remove();
return;
}
rule.selector = newSelectors.join(',');
rule.selectors = newSelectors;
},
};
postCssOptions.plugins.push(plugin);
}
return postCssOptions;
},
};
}
module.exports = prefersColorScheme;