/
removeInlinedSelectors.js
81 lines (65 loc) · 2.54 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
73
74
75
76
77
78
79
80
81
const postcss = require('postcss')
const posthtml = require('posthtml')
const {get, merge, has, remove} = require('lodash')
const parseAttrs = require('posthtml-attrs-parser')
const matchHelper = require('posthtml-match-helper')
const defaultConfig = require('../generators/posthtml/defaultConfig')
module.exports = async (html, config = {}) => {
if (get(config, 'removeInlinedClasses') === false) {
return html
}
const posthtmlOptions = merge(defaultConfig, get(config, 'build.posthtml.options', {}))
return posthtml([plugin(posthtmlOptions)]).process(html, posthtmlOptions).then(result => result.html)
}
const plugin = posthtmlOptions => 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()
// Fix issue with .compose() automatically quoting attributes with no values
Object.entries(n.attrs).forEach(([name, value]) => {
if (value === '' && get(posthtmlOptions, 'recognizeNoValueAttribute') === true) {
n.attrs[name] = true
}
})
return n
})
} catch {}
})
node.content = root.toString()
}
return node
}
return tree.walk(process)
}