/
removeInlinedSelectors.js
72 lines (58 loc) · 2.1 KB
/
removeInlinedSelectors.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
const {get, has, remove} = require('lodash')
const postcss = require('postcss')
const posthtml = require('posthtml')
const parseAttrs = require('posthtml-attrs-parser')
const matchHelper = require('posthtml-match-helper')
module.exports = async (html, config = {}) => {
if (get(config, 'removeInlinedClasses') === false) {
return html
}
const posthtmlOptions = get(config, 'build.posthtml.options', {})
return posthtml([plugin()]).process(html, posthtmlOptions).then(result => result.html)
}
const plugin = () => tree => {
const process = node => {
// For each style tag...
if (node.tag === 'style') {
const {root} = postcss().process(node.content)
root.walkRules(rule => {
// Skip media queries and such...
if (rule.parent.type === 'atrule') {
return
}
const {selector} = rule
const prop = get(rule.nodes[0], 'prop')
try {
// If we find the selector in the HTML...
tree.match(matchHelper(selector), n => {
const parsedAttrs = parseAttrs(n.attrs)
const classAttr = get(parsedAttrs, 'class', [])
const styleAttr = get(parsedAttrs, 'style', {})
// If the class is in the style attribute (inlined), remove it
if (has(styleAttr, prop)) {
// Remove the class attribute
remove(classAttr, s => selector.includes(s))
// Remove the rule in the <style> tag
rule.remove()
}
/**
* Remove from <style> selectors that were used to create shorthand declarations
* like `margin: 0 0 0 16px` (transformed with mergeLonghand when inlining).
*/
Object.keys(styleAttr).forEach(key => {
if (prop && prop.includes(key)) {
rule.remove()
remove(classAttr, s => selector.includes(s))
}
})
n.attrs = parsedAttrs.compose()
return n
})
} catch {}
})
node.content = root.toString()
}
return node
}
return tree.walk(process)
}