2
2
MIT License http://www.opensource.org/licenses/mit-license.php
3
3
Author Tobias Koppers @sokra
4
4
*/
5
+ const postcss = require ( 'postcss' ) ;
6
+ const localByDefault = require ( 'postcss-modules-local-by-default' ) ;
7
+ const extractImports = require ( 'postcss-modules-extract-imports' ) ;
8
+ const modulesScope = require ( 'postcss-modules-scope' ) ;
9
+ const modulesValues = require ( 'postcss-modules-values' ) ;
5
10
const loaderUtils = require ( 'loader-utils' ) ;
6
11
7
- const processCss = require ( './processCss ' ) ;
12
+ const { importParser , icssParser , urlParser } = require ( './plugins ' ) ;
8
13
const {
14
+ getLocalIdent,
9
15
getImportPrefix,
10
16
placeholderImportItemReplacer,
11
17
compileExports,
18
+ placholderRegExps,
12
19
} = require ( './utils' ) ;
20
+ const Warning = require ( './Warning' ) ;
21
+ const CssSyntaxError = require ( './CssSyntaxError' ) ;
13
22
14
23
module . exports = function loader ( content , map ) {
15
24
const callback = this . async ( ) ;
@@ -34,27 +43,92 @@ module.exports = function loader(content, map) {
34
43
}
35
44
/* eslint-enable no-param-reassign */
36
45
37
- processCss (
38
- content ,
39
- map ,
40
- {
41
- loaderContext : this ,
42
- loaderOptions : options ,
43
- sourceMap,
44
- } ,
45
- ( err , result ) => {
46
- if ( err ) {
47
- return callback ( err ) ;
48
- }
46
+ const loaderContext = this ;
47
+ const localIdentName = options . localIdentName || '[hash:base64]' ;
48
+ const customGetLocalIdent = options . getLocalIdent || getLocalIdent ;
49
+
50
+ const parserOptions = {
51
+ url : options . url !== false ,
52
+ import : options . import !== false ,
53
+ } ;
54
+
55
+ const plugins = [
56
+ modulesValues ,
57
+ localByDefault ( {
58
+ mode : options . modules ? 'local' : 'global' ,
59
+ rewriteUrl ( global , url ) {
60
+ if ( parserOptions . url ) {
61
+ // eslint-disable-next-line no-param-reassign
62
+ url = url . trim ( ) ;
63
+
64
+ if (
65
+ ! url . replace ( / \s / g, '' ) . length ||
66
+ ! loaderUtils . isUrlRequest ( url )
67
+ ) {
68
+ return url ;
69
+ }
70
+ if ( global ) {
71
+ return loaderUtils . urlToRequest ( url ) ;
72
+ }
73
+ }
74
+ return url ;
75
+ } ,
76
+ } ) ,
77
+ extractImports ( ) ,
78
+ modulesScope ( {
79
+ generateScopedName : function generateScopedName ( exportName ) {
80
+ return customGetLocalIdent ( loaderContext , localIdentName , exportName , {
81
+ regExp : options . localIdentRegExp ,
82
+ hashPrefix : options . hashPrefix || '' ,
83
+ context : options . context ,
84
+ } ) ;
85
+ } ,
86
+ } ) ,
87
+ ] ;
88
+
89
+ if ( options . import !== false ) {
90
+ plugins . push ( importParser ( parserOptions ) ) ;
91
+ }
92
+
93
+ if ( options . url !== false ) {
94
+ plugins . push ( urlParser ( parserOptions ) ) ;
95
+ }
96
+
97
+ plugins . push ( icssParser ( parserOptions ) ) ;
98
+
99
+ postcss ( plugins )
100
+ . process ( content , {
101
+ // we need a prefix to avoid path rewriting of PostCSS
102
+ from : `/css-loader!${ loaderUtils
103
+ . getRemainingRequest ( this )
104
+ . split ( '!' )
105
+ . pop ( ) } `,
106
+ to : loaderUtils
107
+ . getCurrentRequest ( this )
108
+ . split ( '!' )
109
+ . pop ( ) ,
110
+ map : options . sourceMap
111
+ ? {
112
+ prev : map ,
113
+ sourcesContent : true ,
114
+ inline : false ,
115
+ annotation : false ,
116
+ }
117
+ : null ,
118
+ } )
119
+ . then ( ( result ) => {
120
+ result
121
+ . warnings ( )
122
+ . forEach ( ( warning ) => this . emitWarning ( new Warning ( warning ) ) ) ;
49
123
50
124
// for importing CSS
51
125
const importUrlPrefix = getImportPrefix ( this , options ) ;
52
126
53
127
let exportJs = compileExports (
54
- result ,
128
+ parserOptions . exports ,
55
129
placeholderImportItemReplacer (
56
130
this ,
57
- result ,
131
+ parserOptions . importItems ,
58
132
importUrlPrefix ,
59
133
options . exportOnlyLocals
60
134
) ,
@@ -69,10 +143,10 @@ module.exports = function loader(content, map) {
69
143
return callback ( null , exportJs ) ;
70
144
}
71
145
72
- let cssAsString = JSON . stringify ( result . source ) ;
146
+ let cssAsString = JSON . stringify ( result . css ) ;
73
147
74
148
const alreadyImported = { } ;
75
- const importJs = result . importItems
149
+ const importJs = parserOptions . importItems
76
150
. filter ( ( imp ) => {
77
151
if ( ! imp . media ) {
78
152
if ( alreadyImported [ imp . url ] ) {
@@ -102,48 +176,61 @@ module.exports = function loader(content, map) {
102
176
. join ( '\n' ) ;
103
177
104
178
cssAsString = cssAsString . replace (
105
- result . importItemRegExpG ,
106
- placeholderImportItemReplacer ( this , result , importUrlPrefix )
179
+ placholderRegExps . importItemG ,
180
+ placeholderImportItemReplacer (
181
+ this ,
182
+ parserOptions . importItems ,
183
+ importUrlPrefix
184
+ )
107
185
) ;
108
186
109
187
// helper for ensuring valid CSS strings from requires
110
188
let urlEscapeHelper = '' ;
111
189
112
190
if (
113
191
options . url !== false &&
114
- result . urlItems &&
115
- result . urlItems . length > 0
192
+ parserOptions . urlItems &&
193
+ parserOptions . urlItems . length > 0
116
194
) {
117
195
urlEscapeHelper = `var escape = require(${ loaderUtils . stringifyRequest (
118
196
this ,
119
197
require . resolve ( './runtime/escape.js' )
120
198
) } );\n`;
121
199
122
- cssAsString = cssAsString . replace ( result . urlItemRegExpG , ( item ) => {
123
- const match = result . urlItemRegExp . exec ( item ) ;
124
- let idx = + match [ 1 ] ;
125
- const urlItem = result . urlItems [ idx ] ;
126
- const { url } = urlItem ;
127
- idx = url . indexOf ( '?#' ) ;
128
- if ( idx < 0 ) {
129
- idx = url . indexOf ( '#' ) ;
130
- }
131
- let urlRequest ;
132
- if ( idx > 0 ) {
133
- // idx === 0 is catched by isUrlRequest
134
- // in cases like url('webfont.eot?#iefix')
135
- urlRequest = url . substr ( 0 , idx ) ;
200
+ cssAsString = cssAsString . replace (
201
+ placholderRegExps . urlItemG ,
202
+ ( item ) => {
203
+ const match = placholderRegExps . urlItem . exec ( item ) ;
204
+ let idx = + match [ 1 ] ;
205
+ const urlItem = parserOptions . urlItems [ idx ] ;
206
+ const { url } = urlItem ;
207
+
208
+ idx = url . indexOf ( '?#' ) ;
209
+
210
+ if ( idx < 0 ) {
211
+ idx = url . indexOf ( '#' ) ;
212
+ }
213
+
214
+ let urlRequest ;
215
+
216
+ if ( idx > 0 ) {
217
+ // idx === 0 is catched by isUrlRequest
218
+ // in cases like url('webfont.eot?#iefix')
219
+ urlRequest = url . substr ( 0 , idx ) ;
220
+ return `" + escape(require(${ loaderUtils . stringifyRequest (
221
+ this ,
222
+ urlRequest
223
+ ) } ) + "${ url . substr ( idx ) } ") + "`;
224
+ }
225
+
226
+ urlRequest = url ;
227
+
136
228
return `" + escape(require(${ loaderUtils . stringifyRequest (
137
229
this ,
138
230
urlRequest
139
- ) } ) + " ${ url . substr ( idx ) } " ) + "`;
231
+ ) } )) + "`;
140
232
}
141
- urlRequest = url ;
142
- return `" + escape(require(${ loaderUtils . stringifyRequest (
143
- this ,
144
- urlRequest
145
- ) } )) + "`;
146
- } ) ;
233
+ ) ;
147
234
}
148
235
149
236
if ( exportJs ) {
@@ -154,7 +241,8 @@ module.exports = function loader(content, map) {
154
241
if ( sourceMap && result . map ) {
155
242
/* eslint-disable no-param-reassign */
156
243
// Add a SourceMap
157
- ( { map } = result ) ;
244
+ map = result . map . toJSON ( ) ;
245
+
158
246
if ( map . sources ) {
159
247
map . sources = map . sources . map (
160
248
( source ) =>
@@ -166,12 +254,14 @@ module.exports = function loader(content, map) {
166
254
) ;
167
255
map . sourceRoot = '' ;
168
256
}
257
+
169
258
map . file = map . file
170
259
. split ( '!' )
171
260
. pop ( )
172
261
. replace ( / \\ / g, '/' ) ;
173
262
map = JSON . stringify ( map ) ;
174
263
/* eslint-enable no-param-reassign */
264
+
175
265
moduleJs = `exports.push([module.id, ${ cssAsString } , "", ${ map } ]);` ;
176
266
} else {
177
267
moduleJs = `exports.push([module.id, ${ cssAsString } , ""]);` ;
@@ -188,6 +278,10 @@ module.exports = function loader(content, map) {
188
278
`// module\n${ moduleJs } \n\n` +
189
279
`// exports\n${ exportJs } `
190
280
) ;
191
- }
192
- ) ;
281
+ } )
282
+ . catch ( ( error ) => {
283
+ callback (
284
+ error . name === 'CssSyntaxError' ? new CssSyntaxError ( error ) : error
285
+ ) ;
286
+ } ) ;
193
287
} ;
0 commit comments