@@ -7,9 +7,8 @@ import postcss from 'postcss';
77
88import Warning from './Warning' ;
99import SyntaxError from './Error' ;
10- import parseOptions from './options' ;
1110import schema from './options.json' ;
12- import { exec , loadConfig } from './utils' ;
11+ import { exec , loadConfig , getArrayPlugins } from './utils' ;
1312
1413/**
1514 * **PostCSS Loader**
@@ -34,30 +33,13 @@ export default async function loader(content, sourceMap, meta = {}) {
3433
3534 const callback = this . async ( ) ;
3635 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 = { } ;
5037
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 ;
5640
57- return ;
58- }
59- } else {
60- const rc = {
41+ if ( configOptions ) {
42+ const dataForLoadConfig = {
6143 path : path . dirname ( file ) ,
6244 ctx : {
6345 file : {
@@ -69,58 +51,62 @@ export default async function loader(content, sourceMap, meta = {}) {
6951 } ,
7052 } ;
7153
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+ }
7657
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 ;
8060 }
8161
82- rc . ctx . webpack = this ;
62+ dataForLoadConfig . ctx . webpack = this ;
8363
8464 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+ ) ;
8671 } catch ( error ) {
8772 callback ( error ) ;
8873
8974 return ;
9075 }
9176 }
9277
93- if ( typeof config === 'undefined' ) {
94- config = { } ;
95- }
78+ let plugins ;
9679
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 ) ;
9987 }
10088
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+ } ;
10594
106- if ( typeof config . options . from !== 'undefined' ) {
107- delete config . options . from ;
108- }
109- }
95+ const resultPlugins = mergedOptions . plugins ;
11096
111- const plugins = config . plugins || [ ] ;
97+ const { parser , syntax , stringifier } = mergedOptions ;
11298
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+ } ;
124110
125111 // Loader Exec (Deprecated)
126112 // https://webpack.js.org/api/loaders/#deprecated-context-properties
@@ -130,23 +116,41 @@ export default async function loader(content, sourceMap, meta = {}) {
130116 }
131117
132118 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+ }
135127 }
136128
137129 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+ }
140138 }
141139
142140 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+ }
145149 }
146150
147151 // Loader API Exec (Deprecated)
148152 // https://webpack.js.org/api/loaders/#deprecated-context-properties
149- if ( config . exec ) {
153+ if ( mergedOptions . exec ) {
150154 // eslint-disable-next-line no-param-reassign
151155 content = exec ( content , this ) ;
152156 }
@@ -163,7 +167,7 @@ export default async function loader(content, sourceMap, meta = {}) {
163167 let result ;
164168
165169 try {
166- result = await postcss ( plugins ) . process ( content , postcssOptions ) ;
170+ result = await postcss ( resultPlugins ) . process ( content , postcssOptions ) ;
167171 } catch ( error ) {
168172 if ( error . file ) {
169173 this . addDependency ( error . file ) ;
@@ -231,9 +235,7 @@ export default async function loader(content, sourceMap, meta = {}) {
231235 * @requires schema-utils
232236 *
233237 * @requires postcss
234- * @requires postcss-load-config
235238 *
236- * @requires ./options.js
237239 * @requires ./Warning.js
238240 * @requires ./SyntaxError.js
239241 */
0 commit comments