style-rewriter.js
3.72 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
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
126
127
128
129
130
131
132
var postcss = require('postcss')
var loaderUtils = require('loader-utils')
var loadPostcssConfig = require('postcss-load-config')
var selectorParser = require('postcss-selector-parser')
var addId = postcss.plugin('add-id', function (opts) {
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 !== 'pseudo') node = n
})
selector.insertAfter(node, selectorParser.attribute({
attribute: opts.id
}))
})
}).process(node.selector).result
})
}
})
var trim = postcss.plugin('trim', function (opts) {
return function (css) {
css.walk(function (node) {
if (node.type === 'rule' || node.type === 'atrule') {
node.raws.before = node.raws.after = '\n'
}
})
}
})
module.exports = function (css, map) {
this.cacheable()
var cb = this.async()
var query = loaderUtils.parseQuery(this.query)
var vueOptions = this.options.__vueOptions__
if (!vueOptions) {
if (query.hasInlineConfig) {
this.emitError(
`\n [vue-loader] It seems you are using HappyPack with inline postcss ` +
`options for vue-loader. This is not supported because loaders running ` +
`in different threads cannot share non-serializable options. ` +
`It is recommended to use a postcss config file instead.\n` +
`\n See http://vue-loader.vuejs.org/en/features/postcss.html#using-a-config-file for more details.\n`
)
}
vueOptions = Object.assign({}, this.options.vue, this.vue)
}
// use the same config loading interface as postcss-loader
loadPostcssConfig({ webpack: this }, null, { argv: false }).catch(() => {
// postcss-load-config throws error when no config file is found,
// but for us it's optional.
}).then(config => {
var plugins
var options
// inline postcss options for vue-loader
var rawInlineOptions = vueOptions.postcss
if (typeof rawInlineOptions === 'function') {
rawInlineOptions = rawInlineOptions.call(this, this)
}
if (Array.isArray(rawInlineOptions)) {
plugins = rawInlineOptions
} else if (isObject(rawInlineOptions)) {
plugins = rawInlineOptions.plugins
options = rawInlineOptions.options
}
plugins = [trim].concat(plugins || [])
options = Object.assign({
to: this.resourcePath,
from: this.resourcePath,
map: false
}, options)
// merge postcss config file
if (config && config.plugins) {
plugins = plugins.concat(config.plugins)
}
if (config && config.options) {
options = Object.assign({}, config.options, options)
}
// add plugin for vue-loader scoped css rewrite
if (query.scoped) {
plugins.push(addId({ id: query.id }))
}
// source map
if (
this.sourceMap &&
!this.minimize &&
vueOptions.cssSourceMap !== false &&
process.env.NODE_ENV !== 'production' &&
!options.map
) {
options.map = {
inline: false,
annotation: false,
prev: map
}
}
postcss(plugins)
.process(css, options)
.then(function (result) {
var map = result.map && result.map.toJSON()
cb(null, result.css, map)
return null // silence bluebird warning
})
.catch(function (e) {
console.log(e)
cb(e)
})
})
}
function isObject (val) {
return val && typeof val === 'object'
}