forked from hplush/slowreader
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy paththeme-classes.cjs
More file actions
98 lines (92 loc) · 2.49 KB
/
Copy paththeme-classes.cjs
File metadata and controls
98 lines (92 loc) · 2.49 KB
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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// PostCSS plugin to allow enabling @media prefers-color-scheme: dark/light
// by changing classes (is-dark-theme, is-light-theme) in the HTML.
// It is like postcss-dark-theme-class but solved our unique case.
const IS_DARK = /^\(prefers-color-scheme:\s*dark\)$/
const IS_LIGHT = /^\(prefers-color-scheme:\s*light\)$/
/**
* @param {import('postcss').Node} node
* @param {(node: import('postcss').Node) => boolean} cb
* @returns {import('postcss').Node}
*/
function findNext(node, cb) {
if (node.next()) node = node.next()
while (!cb(node) && node.next()) {
node = node.next()
}
return node
}
/**
* @param {string} selector
* @param {string} modifier
* @returns string
*/
function wrapSelector(selector, modifier) {
if (selector.includes('.is-slow-theme')) {
return `:where(${modifier}) ${selector}, ${selector}:where(${modifier})`
} else {
return `:where(${modifier}) ${selector}`
}
}
/**
* @param {typeof import('postcss').Rule} Rule
* @param {import('postcss').AtRule} atrule
* @param {string} selector
*/
function cloneToRule(Rule, atrule, selector) {
/**
* @type {import('postcss').Rule | import('postcss').Rule[]}
*/
let copy
if (
atrule.parent.type === 'root' &&
atrule.every(n => n.type === 'rule' && n.selector !== ':root')
) {
copy = []
for (let child of atrule.nodes) {
let childCopy = child.clone()
if (childCopy.type === 'rule') {
childCopy.selectors = childCopy.selectors.map(i => {
return wrapSelector(i, selector)
})
}
copy.push(childCopy)
}
} else {
if (atrule.parent.type === 'rule' && atrule.parent.selector !== ':root') {
selector = atrule.parent.selectors
.map(i => wrapSelector(i, selector))
.join(',')
}
copy = new Rule({
selector,
source: atrule.source
})
for (let child of atrule.nodes) {
if (child.selector === ':root') {
copy.append(child.clone().nodes)
} else {
copy.append(child.clone())
}
}
}
if (atrule.parent.type === 'rule') {
atrule.parent.after(copy)
} else {
findNext(atrule, node => node.name !== 'media').after(copy)
}
}
/**
* @type {import('postcss').Plugin}
*/
module.exports = {
AtRule: {
media(atrule, { Rule }) {
if (IS_DARK.test(atrule.params)) {
cloneToRule(Rule, atrule, '.is-dark-theme')
} else if (IS_LIGHT.test(atrule.params)) {
cloneToRule(Rule, atrule, '.is-light-theme')
}
}
},
postcssPlugin: 'theme-classes'
}