@@ -2,6 +2,7 @@ import path from 'path';
22
33import Module from 'module' ;
44
5+ import postcssPkg from 'postcss/package.json' ;
56import { cosmiconfig } from 'cosmiconfig' ;
67
78const parentModule = module ;
@@ -31,6 +32,26 @@ const createContext = (context) => {
3132 return result ;
3233} ;
3334
35+ const load = ( plugin , options , file ) => {
36+ try {
37+ if (
38+ options === null ||
39+ typeof options === 'undefined' ||
40+ Object . keys ( options ) . length === 0
41+ ) {
42+ // eslint-disable-next-line global-require,import/no-dynamic-require
43+ return require ( plugin ) ;
44+ }
45+
46+ // eslint-disable-next-line global-require,import/no-dynamic-require
47+ return require ( plugin ) ( options ) ;
48+ } catch ( err ) {
49+ throw new Error (
50+ `Loading PostCSS Plugin failed: ${ err . message } \n\n(@${ file } )`
51+ ) ;
52+ }
53+ } ;
54+
3455const loadOptions = ( config , file ) => {
3556 const result = { } ;
3657
@@ -70,6 +91,54 @@ const loadOptions = (config, file) => {
7091 return { ...config , ...result } ;
7192} ;
7293
94+ function loadPlugins ( pluginEntry , file ) {
95+ let plugins = [ ] ;
96+
97+ if ( Array . isArray ( pluginEntry ) ) {
98+ plugins = pluginEntry . filter ( Boolean ) ;
99+ } else {
100+ plugins = Object . entries ( pluginEntry ) . filter ( ( i ) => {
101+ const [ , options ] = i ;
102+
103+ return options !== false ? pluginEntry : '' ;
104+ } ) ;
105+ }
106+
107+ plugins = plugins . map ( ( plugin ) => {
108+ const [ pluginName , pluginOptions ] = plugin ;
109+
110+ return load ( pluginName , pluginOptions , file ) ;
111+ } ) ;
112+
113+ if ( plugins . length && plugins . length > 0 ) {
114+ plugins . forEach ( ( plugin , i ) => {
115+ if ( plugin . postcss ) {
116+ // eslint-disable-next-line no-param-reassign
117+ plugin = plugin . postcss ;
118+ }
119+
120+ if ( plugin . default ) {
121+ // eslint-disable-next-line no-param-reassign
122+ plugin = plugin . default ;
123+ }
124+
125+ if (
126+ // eslint-disable-next-line
127+ ! (
128+ ( typeof plugin === 'object' && Array . isArray ( plugin . plugins ) ) ||
129+ typeof plugin === 'function'
130+ )
131+ ) {
132+ throw new TypeError (
133+ `Invalid PostCSS Plugin found at: plugins[${ i } ]\n\n(@${ file } )`
134+ ) ;
135+ }
136+ } ) ;
137+ }
138+
139+ return plugins ;
140+ }
141+
73142function exec ( code , loaderContext ) {
74143 const { resource, context } = loaderContext ;
75144
@@ -137,4 +206,45 @@ async function loadConfig(config, context, configPath, inputFileSystem) {
137206 return { ...resultConfig , ...options } ;
138207}
139208
140- export { exec , loadConfig } ;
209+ function createPostCssPlugins ( items , file ) {
210+ function iterator ( plugins , plugin , acc ) {
211+ if ( typeof plugin === 'undefined' ) {
212+ return acc ;
213+ }
214+
215+ if ( plugin === false ) {
216+ return iterator ( plugins , plugins . pop ( ) , acc ) ;
217+ }
218+
219+ if ( plugin . postcssVersion === postcssPkg . version ) {
220+ acc . push ( plugin ) ;
221+ return iterator ( plugins , plugins . pop ( ) , acc ) ;
222+ }
223+
224+ if ( typeof plugin === 'function' ) {
225+ const postcssPlugin = plugin . call ( this , this ) ;
226+
227+ if ( Array . isArray ( postcssPlugin ) ) {
228+ acc . concat ( postcssPlugin ) ;
229+ } else {
230+ acc . push ( postcssPlugin ) ;
231+ }
232+
233+ return iterator ( plugins , plugins . pop ( ) , acc ) ;
234+ }
235+
236+ if ( Object . keys ( plugin ) . length === 0 ) {
237+ return iterator ( plugins , plugins . pop ( ) , acc ) ;
238+ }
239+
240+ const concatPlugins = [ ...plugins , ...loadPlugins ( plugin , file ) ] ;
241+
242+ return iterator ( concatPlugins , concatPlugins . pop ( ) , acc ) ;
243+ }
244+
245+ const pl = [ ...items ] ;
246+
247+ return iterator ( pl , pl . pop ( ) , [ ] ) ;
248+ }
249+
250+ export { exec , loadConfig , loadPlugins , createPostCssPlugins } ;
0 commit comments