@@ -8,13 +8,13 @@ const plugin = require("./plugin");
8
8
const getImportPrefix = require ( "./getImportPrefix" ) ;
9
9
const SyntaxError = require ( "./SyntaxError" ) ;
10
10
11
- module . exports = function ( content , map ) {
11
+ module . exports = function ( content , map , meta ) {
12
12
const options = loaderUtils . getOptions ( this ) || { } ;
13
13
14
14
// Todo validate options
15
15
16
16
const cb = this . async ( ) ;
17
- const sourceMap = options . sourceMap ;
17
+ const sourceMap = options . sourceMap || false ;
18
18
19
19
if ( sourceMap && map ) {
20
20
if ( typeof map === "string" ) {
@@ -30,85 +30,95 @@ module.exports = function(content, map) {
30
30
map = null ;
31
31
}
32
32
33
- // We need a prefix to avoid path rewriting of PostCSS
34
- const from =
35
- "/css-loader!" +
36
- loaderUtils
37
- . getRemainingRequest ( this )
38
- . split ( "!" )
39
- . pop ( ) ;
40
- const to = loaderUtils
41
- . getCurrentRequest ( this )
42
- . split ( "!" )
43
- . pop ( ) ;
33
+ // Reuse CSS AST (PostCSS AST e.g 'postcss-loader') to avoid reparsing
34
+ if ( meta ) {
35
+ const { ast } = meta ;
36
+
37
+ if ( ast && ast . type === "postcss" ) {
38
+ content = ast . root ;
39
+ }
40
+ }
44
41
45
- postcss ( [
42
+ const plugins = [
46
43
plugin ( {
47
44
url : options . url !== false ,
48
45
import : options . import !== false
49
46
} )
50
- ] )
51
- . process ( content , {
52
- from,
53
- to,
54
- map : sourceMap
55
- ? {
56
- prev : map ,
57
- sourcesContent : true ,
58
- inline : false ,
59
- annotation : false
60
- }
61
- : null
62
- } )
47
+ ] ;
48
+
49
+ const postcssOptions = {
50
+ // We need a prefix to avoid path rewriting of PostCSS
51
+ from :
52
+ "/css-loader!" +
53
+ loaderUtils
54
+ . getRemainingRequest ( this )
55
+ . split ( "!" )
56
+ . pop ( ) ,
57
+ to : loaderUtils
58
+ . getCurrentRequest ( this )
59
+ . split ( "!" )
60
+ . pop ( ) ,
61
+ map : sourceMap
62
+ ? {
63
+ prev : map ,
64
+ sourcesContent : true ,
65
+ inline : false ,
66
+ annotation : false
67
+ }
68
+ : null
69
+ } ;
70
+
71
+ postcss ( plugins )
72
+ . process ( content , postcssOptions )
63
73
. then ( result => {
64
- var cssAsString = JSON . stringify ( result . css ) ;
74
+ let cssAsString = JSON . stringify ( result . css ) ;
75
+ let imports = "" ;
76
+ let exports = "" ;
77
+ let urlEscapeHelperCode = "" ;
65
78
66
79
if ( options . import !== false ) {
67
- var alreadyImported = { } ;
68
- var importJs = result . messages
80
+ const alreadyImported = { } ;
81
+ imports = result . messages
69
82
. filter ( message => message . type === "at-rule-import" )
70
- . filter ( imp => {
71
- if ( ! imp . mediaQuery ) {
72
- if ( alreadyImported [ imp . url ] ) {
83
+ . filter ( message => {
84
+ if ( ! message . mediaQuery ) {
85
+ if ( alreadyImported [ message . url ] ) {
73
86
return false ;
74
87
}
75
88
76
- alreadyImported [ imp . url ] = true ;
89
+ alreadyImported [ message . url ] = true ;
77
90
}
78
91
79
92
return true ;
80
93
} )
81
- . map ( imp => {
82
- if ( ! loaderUtils . isUrlRequest ( imp . url ) ) {
94
+ . map ( message => {
95
+ if ( ! loaderUtils . isUrlRequest ( message . url ) ) {
83
96
return (
84
97
"exports.push([module.id, " +
85
- JSON . stringify ( "@import url(" + imp . url + ");" ) +
98
+ JSON . stringify ( "@import url(" + message . url + ");" ) +
86
99
", " +
87
- JSON . stringify ( imp . mediaQuery ) +
100
+ JSON . stringify ( message . mediaQuery ) +
88
101
"]);"
89
102
) ;
90
103
}
91
104
92
105
// for importing CSS
93
106
var importUrlPrefix = getImportPrefix ( this , options ) ;
94
- var importUrl = importUrlPrefix + imp . url ;
107
+ var importUrl = importUrlPrefix + message . url ;
95
108
96
109
return (
97
110
"exports.i(require(" +
98
111
loaderUtils . stringifyRequest ( this , importUrl ) +
99
112
"), " +
100
- JSON . stringify ( imp . mediaQuery ) +
113
+ JSON . stringify ( message . mediaQuery ) +
101
114
");"
102
115
) ;
103
116
} )
104
117
. join ( "\n" ) ;
105
118
}
106
119
107
- // Helper for ensuring valid CSS strings from requires
108
- let urlEscapeHelper = "" ;
109
-
110
120
if ( options . url !== false ) {
111
- urlEscapeHelper =
121
+ urlEscapeHelperCode =
112
122
"var runtimeEscape = require(" +
113
123
loaderUtils . stringifyRequest (
114
124
this ,
@@ -117,7 +127,7 @@ module.exports = function(content, map) {
117
127
");\n" ;
118
128
119
129
result . messages
120
- . filter ( message => message . type === "css-loader-import -url" )
130
+ . filter ( message => message . type === "function -url" )
121
131
. forEach ( message => {
122
132
const { placeholder, url } = message ;
123
133
const splittedURL = url . split ( / ( \? ) ? # / ) ;
@@ -132,15 +142,6 @@ module.exports = function(content, map) {
132
142
} ) ;
133
143
}
134
144
135
- // Todo need save backward compatibility with old `style-loader`
136
- var exportJs = "" ;
137
-
138
- if ( exportJs ) {
139
- exportJs = "exports.locals = " + exportJs + ";" ;
140
- }
141
-
142
- var moduleJs ;
143
-
144
145
if ( sourceMap && result . map ) {
145
146
map = result . map . toJSON ( ) ;
146
147
@@ -159,34 +160,34 @@ module.exports = function(content, map) {
159
160
. pop ( )
160
161
. replace ( / \\ / g, "/" ) ;
161
162
map = JSON . stringify ( map ) ;
162
-
163
- moduleJs =
164
- "exports.push([module.id, " + cssAsString + ', "", ' + map + "]);" ;
165
- } else {
166
- moduleJs = "exports.push([module.id, " + cssAsString + ', ""]);' ;
167
163
}
168
164
169
- // embed runtime
165
+ const runtimeCode = `module.exports = exports = require(${ loaderUtils . stringifyRequest (
166
+ this ,
167
+ require . resolve ( "./runtime.js" )
168
+ ) } )(${ ! ! sourceMap } );\n`;
169
+ const moduleCode = `// CSS Module\nexports.push([module.id, ${ cssAsString } , ""${
170
+ map ? `,${ map } ` : ""
171
+ } ]);\n`;
172
+ const importsCode = imports ? `// CSS Imports\n${ imports } \n` : "" ;
173
+ // Todo need save backward compatibility with old `style-loader` and exports.locals
174
+ const exportsCode = exports ? `// CSS Exports\n${ exports } \n` : false ;
175
+
170
176
cb (
171
177
null ,
172
- urlEscapeHelper +
173
- "exports = module.exports = require(" +
174
- loaderUtils . stringifyRequest ( this , require . resolve ( "./runtime.js" ) ) +
175
- ")(" +
176
- sourceMap +
177
- ");\n" +
178
- "// imports\n" +
179
- importJs +
180
- "\n\n" +
181
- "// module\n" +
182
- moduleJs +
183
- "\n\n" +
184
- "// exports\n" +
185
- exportJs
178
+ [
179
+ urlEscapeHelperCode ,
180
+ runtimeCode ,
181
+ importsCode ,
182
+ moduleCode ,
183
+ exportsCode
184
+ ] . join ( "\n" )
186
185
) ;
187
186
} )
188
187
. catch ( err => {
189
- // Todo if (err.file) this.addDependency(err.file)
188
+ if ( err . file ) {
189
+ this . addDependency ( err . file ) ;
190
+ }
190
191
191
192
cb ( err . name === "CssSyntaxError" ? new SyntaxError ( err ) : err ) ;
192
193
} ) ;
0 commit comments