This repository has been archived by the owner on May 12, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
index.js
125 lines (109 loc) · 3.85 KB
/
index.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
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
import browserslist from 'browserslist'
const plugin = opts => {
return {
postcssPlugin: 'postcss-browser-comments',
Once(root) {
// client browserslist
const clientBrowserList = browserslist(
Object(opts).browsers || null,
{ path: root.source && root.source.input && root.source.input.file }
)
// root children references
const references = root.nodes.slice(0)
// for each child node of the root children references
for (const node of references) {
// if the node is a comment browser comment node
if (isBrowserCommentNode(node)) {
// rule following the browser comment
const rule = node.next()
// browser data
const browserdata = getBrowserData(node.text)
if (browserdata.isNumbered) {
rule.nodes.filter(isBrowserReferenceCommentNode).map(
comment => {
const browserdataIndex = parseFloat(comment.text) - 1
const browserslistPart = browserdata.browserslist[browserdataIndex]
// whether to remove the rule if the comment browserslist does not match the client browserslist
const removeRule = !clientBrowserList.some(
clientBrowser => browserslist(browserslistPart).some(
commentBrowser => commentBrowser === clientBrowser
)
)
// conditionally remove the declaration and reference comment
if (removeRule) {
comment.prev().remove()
comment.remove()
}
}
)
// conditionally remove the empty rule and comment
if (!rule.nodes.length) {
rule.remove()
node.remove()
}
} else {
// whether to remove the rule if the comment browserslist does not match the client browserslist
const removeRule = !clientBrowserList.some(
clientBrowser => browserslist(browserdata.browserslist).some(
commentBrowser => commentBrowser === clientBrowser
)
)
// conditionally remove the rule and comment
if (removeRule) {
rule.remove()
node.remove()
}
}
}
}
}
}
}
plugin.postcss = true
export default plugin
// returns whether a node is a browser comment
const isBrowserCommentNode = node => node.type === 'comment' && isBrowserCommentNodeRegExp.test(node.text) && node.next().type === 'rule'
const isBrowserCommentNodeRegExp = /^\*\n * /
// returns whether a node is a browser reference comment
const isBrowserReferenceCommentNode = node => node.type === 'comment' && isBrowserReferenceCommentNodeRegExp.test(node.text)
const isBrowserReferenceCommentNodeRegExp = /^\d+$/
// returns browser data from comment text
const getBrowserData = text => {
const browserDataNumbered = text.match(browserDataMutliRegExp)
const isNumbered = Boolean(browserDataNumbered)
return {
browserslist: isNumbered
? browserDataNumbered.map(
browserslistPart => getBrowsersList(browserslistPart.replace(browserDataNumberedNewlineRegExp, '$1'))
)
: getBrowsersList(
text.replace(browserDataNewlineRegExp, '')
),
isNumbered
}
}
const browserDataMutliRegExp = /(\n \* \d+\. (?:[^\n]+|\n \* {4,})+)/g
const browserDataNewlineRegExp = /^\*\n \* ?|\n \*/g
const browserDataNumberedNewlineRegExp = /\n \* (?:( )\s*)?/g
// returns a browserlist from comment text
const getBrowsersList = text => text.split(getBrowsersListInSplitRegExp).slice(1).map(
part => part.split(getBrowsersListAndSplitRegExp).filter(part2 => part2)
).reduce(
(acc, val) => acc.concat(val), [])
.map(
part => part.replace(
getBrowsersListQueryRegExp,
($0, browser, query) => browser === 'all'
? '> 0%'
: `${browser}${
query
? /^((?:\d*\.)?\d+)-$/.test(query)
? ` <= ${query.slice(0, -1)}`
: ` ${query}`
: ' > 0'
}`
).toLowerCase()
)
const getBrowsersListInSplitRegExp = /\s+in\s+/
const getBrowsersListAndSplitRegExp = /(?: and|, and|,)/
const getBrowsersListQueryRegExp = /^\s*(\w+)(?: ((?:(?:\d*\.)?\d+-)?(?:\d*\.)?\d+[+-]?))?.*$/