@@ -7,9 +7,8 @@ import postcss from 'postcss';
7
7
8
8
import Warning from './Warning' ;
9
9
import SyntaxError from './Error' ;
10
- import parseOptions from './options' ;
11
10
import schema from './options.json' ;
12
- import { exec , loadConfig } from './utils' ;
11
+ import { exec , loadConfig , getArrayPlugins } from './utils' ;
13
12
14
13
/**
15
14
* **PostCSS Loader**
@@ -34,30 +33,13 @@ export default async function loader(content, sourceMap, meta = {}) {
34
33
35
34
const callback = this . async ( ) ;
36
35
const file = this . resourcePath ;
37
- let config ;
38
-
39
- const { length } = Object . keys ( options ) . filter ( ( option ) => {
40
- switch ( option ) {
41
- // case 'exec':
42
- case 'ident' :
43
- case 'config' :
44
- case 'sourceMap' :
45
- return false ;
46
- default :
47
- return option ;
48
- }
49
- } ) ;
36
+ let loadedConfig = { } ;
50
37
51
- if ( length ) {
52
- try {
53
- config = await parseOptions . call ( this , options ) ;
54
- } catch ( error ) {
55
- callback ( error ) ;
38
+ const configOptions =
39
+ typeof options . config === 'undefined' ? true : options . config ;
56
40
57
- return ;
58
- }
59
- } else {
60
- const rc = {
41
+ if ( configOptions ) {
42
+ const dataForLoadConfig = {
61
43
path : path . dirname ( file ) ,
62
44
ctx : {
63
45
file : {
@@ -69,58 +51,62 @@ export default async function loader(content, sourceMap, meta = {}) {
69
51
} ,
70
52
} ;
71
53
72
- if ( options . config ) {
73
- if ( options . config . path ) {
74
- rc . path = path . resolve ( options . config . path ) ;
75
- }
54
+ if ( typeof configOptions . path !== 'undefined' ) {
55
+ dataForLoadConfig . path = path . resolve ( configOptions . path ) ;
56
+ }
76
57
77
- if ( options . config . ctx ) {
78
- rc . ctx . options = options . config . ctx ;
79
- }
58
+ if ( typeof configOptions . ctx !== 'undefined' ) {
59
+ dataForLoadConfig . ctx . options = configOptions . ctx ;
80
60
}
81
61
82
- rc . ctx . webpack = this ;
62
+ dataForLoadConfig . ctx . webpack = this ;
83
63
84
64
try {
85
- config = await loadConfig ( options . config , rc . ctx , rc . path , this . fs ) ;
65
+ loadedConfig = await loadConfig (
66
+ configOptions ,
67
+ dataForLoadConfig . ctx ,
68
+ dataForLoadConfig . path ,
69
+ this
70
+ ) ;
86
71
} catch ( error ) {
87
72
callback ( error ) ;
88
73
89
74
return ;
90
75
}
91
76
}
92
77
93
- if ( typeof config === 'undefined' ) {
94
- config = { } ;
95
- }
78
+ let plugins ;
96
79
97
- if ( config . file ) {
98
- this . addDependency ( config . file ) ;
80
+ try {
81
+ plugins = [
82
+ ...getArrayPlugins ( loadedConfig . plugins , file ) ,
83
+ ...getArrayPlugins ( options . plugins , file ) ,
84
+ ] ;
85
+ } catch ( error ) {
86
+ this . emitError ( error ) ;
99
87
}
100
88
101
- if ( typeof config . options !== 'undefined' ) {
102
- if ( typeof config . options . to !== 'undefined' ) {
103
- delete config . options . to ;
104
- }
89
+ const mergedOptions = {
90
+ ...loadedConfig ,
91
+ ...options ,
92
+ plugins,
93
+ } ;
105
94
106
- if ( typeof config . options . from !== 'undefined' ) {
107
- delete config . options . from ;
108
- }
109
- }
95
+ const resultPlugins = mergedOptions . plugins ;
110
96
111
- const plugins = config . plugins || [ ] ;
97
+ const { parser , syntax , stringifier } = mergedOptions ;
112
98
113
- const postcssOptions = Object . assign (
114
- {
115
- from : file ,
116
- map : options . sourceMap
117
- ? options . sourceMap === ' inline'
118
- ? { inline : true , annotation : false }
119
- : { inline : false , annotation : false }
120
- : false ,
121
- } ,
122
- config . options
123
- ) ;
99
+ const postcssOptions = {
100
+ from : file ,
101
+ map : options . sourceMap
102
+ ? options . sourceMap === 'inline'
103
+ ? { inline : true , annotation : false }
104
+ : { inline : false , annotation : false }
105
+ : false ,
106
+ parser ,
107
+ syntax ,
108
+ stringifier ,
109
+ } ;
124
110
125
111
// Loader Exec (Deprecated)
126
112
// https://webpack.js.org/api/loaders/#deprecated-context-properties
@@ -130,23 +116,41 @@ export default async function loader(content, sourceMap, meta = {}) {
130
116
}
131
117
132
118
if ( typeof postcssOptions . parser === 'string' ) {
133
- // eslint-disable-next-line import/no-dynamic-require,global-require
134
- postcssOptions . parser = require ( postcssOptions . parser ) ;
119
+ try {
120
+ // eslint-disable-next-line import/no-dynamic-require,global-require
121
+ postcssOptions . parser = require ( postcssOptions . parser ) ;
122
+ } catch ( error ) {
123
+ this . emitError (
124
+ `Loading PostCSS Parser failed: ${ error . message } \n\n(@${ file } )`
125
+ ) ;
126
+ }
135
127
}
136
128
137
129
if ( typeof postcssOptions . syntax === 'string' ) {
138
- // eslint-disable-next-line import/no-dynamic-require,global-require
139
- postcssOptions . syntax = require ( postcssOptions . syntax ) ;
130
+ try {
131
+ // eslint-disable-next-line import/no-dynamic-require,global-require
132
+ postcssOptions . syntax = require ( postcssOptions . syntax ) ;
133
+ } catch ( error ) {
134
+ this . emitError (
135
+ `Loading PostCSS Syntax failed: ${ error . message } \n\n(@${ file } )`
136
+ ) ;
137
+ }
140
138
}
141
139
142
140
if ( typeof postcssOptions . stringifier === 'string' ) {
143
- // eslint-disable-next-line import/no-dynamic-require,global-require
144
- postcssOptions . stringifier = require ( postcssOptions . stringifier ) ;
141
+ try {
142
+ // eslint-disable-next-line import/no-dynamic-require,global-require
143
+ postcssOptions . stringifier = require ( postcssOptions . stringifier ) ;
144
+ } catch ( error ) {
145
+ this . emitError (
146
+ `Loading PostCSS Stringifier failed: ${ error . message } \n\n(@${ file } )`
147
+ ) ;
148
+ }
145
149
}
146
150
147
151
// Loader API Exec (Deprecated)
148
152
// https://webpack.js.org/api/loaders/#deprecated-context-properties
149
- if ( config . exec ) {
153
+ if ( mergedOptions . exec ) {
150
154
// eslint-disable-next-line no-param-reassign
151
155
content = exec ( content , this ) ;
152
156
}
@@ -163,7 +167,7 @@ export default async function loader(content, sourceMap, meta = {}) {
163
167
let result ;
164
168
165
169
try {
166
- result = await postcss ( plugins ) . process ( content , postcssOptions ) ;
170
+ result = await postcss ( resultPlugins ) . process ( content , postcssOptions ) ;
167
171
} catch ( error ) {
168
172
if ( error . file ) {
169
173
this . addDependency ( error . file ) ;
@@ -231,9 +235,7 @@ export default async function loader(content, sourceMap, meta = {}) {
231
235
* @requires schema-utils
232
236
*
233
237
* @requires postcss
234
- * @requires postcss-load-config
235
238
*
236
- * @requires ./options.js
237
239
* @requires ./Warning.js
238
240
* @requires ./SyntaxError.js
239
241
*/
0 commit comments