11import postcss from 'postcss'
2+ import postcssLoadConfig from './postcss'
23import modules from 'postcss-modules'
34import selectorParser from 'postcss-selector-parser'
45import camelcase from 'camelcase'
@@ -21,7 +22,7 @@ function isInvalidTag (tag) {
2122 }
2223}
2324
24- const addScopeID = postcss . plugin ( 'add-scope-id' , options => {
25+ const addScopeID = postcss . plugin ( 'add-scope-id' , ( { scopeID } ) => {
2526 const selectorTransformer = selectorParser ( selectors => {
2627 selectors . each ( selector => {
2728 let target = null
@@ -55,7 +56,7 @@ const addScopeID = postcss.plugin('add-scope-id', options => {
5556 /* eslint-enable complexity */
5657
5758 target && selector . insertAfter ( target , selectorParser . attribute ( {
58- attribute : options . scopeID
59+ attribute : scopeID
5960 } ) )
6061 } )
6162 } )
@@ -78,25 +79,9 @@ function compileModule (code, map, source, options) {
7879 } ,
7980 ...options . cssModules
8081 } )
81- ] ) . process ( code , { map : { inline : false , prev : map } , from : source . id , to : source . id } )
82- . then (
83- result => ( { code : result . css , map : result . map . toString ( ) , module : style } ) ,
84- error => {
85- throw error
86- }
87- )
88- }
89-
90- function compileScopedCSS ( code , map , source , options ) {
91- debug ( `Scoped CSS: ${ source . id } ` )
92-
93- return postcss ( [
94- addScopeID ( {
95- scopeID : genScopeID ( source . id )
96- } )
9782 ] ) . process ( code , { map : { inline : false , prev : map } , from : source . id , to : source . id } )
9883 . then (
99- result => ( { code : result . css , map : result . map . toString ( ) } ) ,
84+ result => ( { code : result . css , map : result . map . toString ( ) , module : style } ) ,
10085 error => {
10186 throw error
10287 }
@@ -110,62 +95,72 @@ function escapeRegExp (str) {
11095export default async function ( promise , options ) {
11196 const style = await promise
11297 debug ( `CSS: ${ style . id } ` )
113- const { code, map } = ( '$compiled' in style ) ? style . $compiled : style
114-
115- if ( style . module === true ) {
116- return compileModule ( code , map , style , options ) . then ( compiled => {
117- if ( style . $compiled ) {
118- compiled . $prev = style . $compiled
119-
120- const classes = Object . keys ( compiled . module )
121- const cssModule = { }
122-
123- if ( classes . length ) {
124- // Apply CSS modules to actual source.
125- // TODO: Update source map.
126- // const original = style.code
127-
128- style . code = classes . reduce (
129- ( result , original ) => {
130- const transformed = compiled . module [ original ]
131- cssModule [ camelcase ( original ) ] = transformed
132- cssModule [ original ] = transformed
133-
134- return result . replace ( new RegExp ( escapeRegExp ( `.${ original } ` ) , 'g' ) , `.${ transformed } ` )
135- } ,
136- style . code
137- )
138- // style.map = (new MagicString(original))
139-
140- compiled . module = (
141- typeof ( style . module ) === 'string' && style . attrs . module . length
142- ) ? { [ style . module ] : cssModule } : cssModule
143- }
144- }
145-
146- style . $compiled = compiled
147-
148- return style
149- } ) . catch ( error => debug ( error ) )
98+ const { code, map} = ( '$compiled' in style ) ? style . $compiled : style
99+ const initPostcssOptions = { map : { inline : false , prev : map } , from : style . id , to : style . id }
100+ const hasModule = style . module === true
101+ const hasScope = style . scoped === true
102+ const postcssConfig = await postcssLoadConfig ( options . postcss )
103+ const plugins = postcssConfig . plugins || [ ]
104+ let processPromise = Promise . resolve ( )
105+
106+ if ( hasScope ) {
107+ debug ( `Scoped CSS: ${ style . id } ` )
108+ plugins . push ( addScopeID ( {
109+ scopeID : genScopeID ( style . id )
110+ } ) )
150111 }
151112
152- if ( style . scoped === true ) {
153- return compileScopedCSS ( code , map , style , options ) . then ( compiled => {
154- if ( style . $compiled ) {
155- compiled . $prev = style . $compiled
156- }
157-
158- style . $compiled = compiled
159-
160- return style
161- } )
113+ if ( hasModule ) {
114+ // TODO: I found this plugin makes all postcss plugin run twice.
115+ processPromise = compileModule ( code , map , style , options )
162116 }
163117
164- const output = { code , map , lang : 'css' }
118+ const curOptions = Object . assign ( { } , postcssConfig . options , initPostcssOptions )
165119
166- if ( style . $compiled ) output . $prev = style . $compiled
120+ return processPromise . then ( firstResult => {
121+ const moduleNames = firstResult && firstResult . module
122+ return postcss ( plugins )
123+ . process ( firstResult ? firstResult . code : code , curOptions )
124+ . then ( result => {
125+ const compiled = {
126+ code : result . css ,
127+ map : result . map . toString ( )
128+ }
129+ if ( style . $compiled ) {
130+ compiled . $prev = style . $compiled
131+ }
167132
168- style . $compiled = output
133+ if ( hasModule ) {
134+ const classes = Object . keys ( moduleNames )
135+ const cssModule = { }
136+
137+ if ( classes . length ) {
138+ // Apply CSS modules to actual source.
139+ // TODO: Update source map.
140+ // const original = style.code
141+
142+ style . code = classes . reduce (
143+ ( result , original ) => {
144+ const transformed = moduleNames [ original ]
145+ cssModule [ camelcase ( original ) ] = transformed
146+ cssModule [ original ] = transformed
147+
148+ return result . replace ( new RegExp ( escapeRegExp ( `.${ original } ` ) , 'g' ) , `.${ transformed } ` )
149+ } ,
150+ style . code
151+ )
152+ // style.map = (new MagicString(original))
153+
154+ compiled . module = (
155+ typeof ( style . module ) === 'string' && style . attrs . module . length
156+ ) ? { [ style . module ] : cssModule } : cssModule
157+ }
158+ }
159+
160+ style . $compiled = compiled
169161
170- return style
162+ return style
163+ } )
164+ . catch ( error => debug ( error ) )
165+ } )
171166}
0 commit comments