forked from vuejs/vueify
/
style-rewriter.js
97 lines (89 loc) · 2.64 KB
/
style-rewriter.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
var postcss = require('postcss')
var selectorParser = require('postcss-selector-parser')
var cache = require('lru-cache')(100)
var assign = require('object-assign')
var currentId
var addId = postcss.plugin('add-id', function () {
return function (root) {
root.each(function rewriteSelector (node) {
if (!node.selector) {
// handle media queries
if (node.type === 'atrule' && node.name === 'media') {
node.each(rewriteSelector)
}
return
}
node.selector = selectorParser(function (selectors) {
selectors.each(function (selector) {
var node = null
selector.each(function (n) {
if (n.type === "combinator" && n.value === ">>>") {
n.value = " "
n.spaces.before = n.spaces.after = ""
return false
}
if (n.type === "tag" && n.value === "/deep/") {
var next = n.next()
if (next.type === "combinator" && next.value === " ") {
next.remove()
}
n.remove()
return false
}
if (n.type !== 'pseudo' && n.type !== "combinator") node = n
})
selector.insertAfter(node, selectorParser.attribute({
attribute: currentId
}))
})
}).process(node.selector).result
})
}
})
/**
* Add attribute selector to css
*
* @param {String} id
* @param {String} css
* @param {Boolean} scoped
* @param {Object} options
* @return {Promise}
*/
module.exports = function (id, css, scoped, options) {
var key = id + '!!' + scoped + '!!' + css
var val = cache.get(key)
if (val) {
return Promise.resolve(val)
} else {
var plugins = []
var opts = {}
if (options.postcss instanceof Array) {
plugins = options.postcss.slice()
} else if (options.postcss instanceof Object) {
plugins = options.postcss.plugins || []
opts = options.postcss.options
}
// scoped css rewrite
// make sure the addId plugin is only pushed once
if (scoped && plugins.indexOf(addId) === -1) {
plugins.push(addId)
}
// remove the addId plugin if the style block is not scoped
if (!scoped && plugins.indexOf(addId) !== -1) {
plugins.splice(plugins.indexOf(addId), 1)
}
// minification
if (process.env.NODE_ENV === 'production') {
plugins.push(require('cssnano')(assign({
safe: true
}, options.cssnano)))
}
currentId = id
return postcss(plugins)
.process(css, opts)
.then(function (res) {
cache.set(key, res.css)
return res.css
})
}
}