@@ -6,7 +6,7 @@ import loaderUtils from 'loader-utils';
66import parse from './parse' ;
77
88export default function loader ( source , map ) {
9- const options = loaderUtils . getOptions ( this ) ;
9+ const options = loaderUtils . getOptions ( this ) || { } ;
1010 const remainingRequest = loaderUtils . getRemainingRequest ( this ) ;
1111 const parseResult = parse ( source ) ;
1212
@@ -19,7 +19,96 @@ export default function loader(source, map) {
1919 replacer = new ReplaceSource ( new RawSource ( source ) , remainingRequest ) ;
2020 }
2121
22+ const includedStylesheets = new Set ( ) ;
23+ const includedStylesheetsMediaQuery = new Map ( ) ;
24+
25+ parseResult . atImports . forEach ( ( imp ) => {
26+ if ( loaderUtils . isUrlRequest ( imp . url , options . root ) ) {
27+ const request = loaderUtils . urlToRequest ( imp . url , options . root ) ;
28+ replacer . replace ( imp . start , imp . end , '' ) ;
29+ includedStylesheets . add ( request ) ;
30+ includedStylesheetsMediaQuery . set ( request , imp . mediaQuery . join ( ' ' ) ) ;
31+ }
32+ } ) ;
33+
34+ let columns = true ;
35+ const importedNames = new Map ( ) ;
36+
37+ parseResult . imports . forEach ( ( imp ) => {
38+ importedNames . set ( imp . alias , imp ) ;
39+ } ) ;
40+
41+ const declarations = [ ] ;
42+ const importReplacements = new Map ( ) ;
43+
44+ let id = 0 ;
45+ for ( const pair of importedNames ) {
46+ const internalName = `cssLoaderImport${ id } _${ pair [ 1 ] . importName } ` ;
47+ id += 1 ;
48+ importReplacements . set ( pair [ 0 ] , internalName ) ;
49+ declarations . push ( `import { ${ pair [ 1 ] . importName } as ${ internalName } } from ${ JSON . stringify ( pair [ 1 ] . from ) } ;` ) ;
50+ includedStylesheets . add ( pair [ 1 ] . from ) ;
51+ }
52+
53+ for ( const pair of importReplacements ) {
54+ const identifier = parseResult . identifiers . get ( pair [ 0 ] ) ;
55+ if ( identifier ) {
56+ columns = false ;
57+ const length = identifier . name . length ;
58+ identifier . locations . forEach ( ( loc ) => {
59+ replacer . replace ( loc , loc + length - 1 , `$CSS$LOADER$\{${ pair [ 1 ] } }` ) ;
60+ } ) ;
61+ }
62+ }
63+
2264 parseResult . metablocks . forEach ( ( block ) => {
2365 replacer . replace ( block . start , block . end , '' ) ;
2466 } ) ;
67+
68+ const includedStylesheetsArray = [ ] ;
69+ for ( const include of includedStylesheets ) {
70+ const internalName = `cssLoaderImport${ id } ` ;
71+ id += 1 ;
72+ declarations . push ( `import ${ internalName } from ${ loaderUtils . stringifyRequest ( this , include ) } ;` ) ;
73+ includedStylesheetsArray . push ( {
74+ name : internalName ,
75+ mediaQuery : includedStylesheetsMediaQuery . get ( include ) || ''
76+ } ) ;
77+ }
78+
79+ let css ;
80+ let sourceMap ;
81+ if ( options . sourceMap ) {
82+ const sourceAndMap = replacer . sourceAndMap ( typeof options . sourceMap === 'object' ? options . sourceMap : {
83+ columns : columns
84+ } ) ;
85+ css = sourceAndMap . code ;
86+ sourceMap = sourceAndMap . map ;
87+ } else {
88+ css = replacer . source ( ) ;
89+ sourceMap = null ;
90+ }
91+
92+ const cssJs = JSON . stringify ( css ) . replace ( / \$ C S S \$ L O A D E R \$ \{ ( [ ^ } ] + ) \} / g, ( match , identifer ) => `" + ${ identifer } + "` ) ;
93+
94+ return [
95+ '// css runtime' ,
96+ `import * as runtime from ${ loaderUtils . stringifyRequest ( this , require . resolve ( "../runtime" ) ) } ;` ,
97+ '' ,
98+ '// declarations' ,
99+ declarations . join ( '\n' ) ,
100+ '' ,
101+ '// CSS' ,
102+ 'export default runtime.a([' ,
103+ ] . concat (
104+ includedStylesheetsArray . map ( ( include ) => {
105+ if ( ! include . mediaQuery ) return ` ${ include . name } ,` ;
106+ return ` runtime.d(${ include . name } , ${ JSON . stringify ( include . mediaQuery ) } ,` ;
107+ } )
108+ ) . concat ( [
109+ sourceMap ?
110+ ` runtime.b(module.id, ${ cssJs } , ${ sourceMap } )` :
111+ ` runtime.c(module.id, ${ cssJs } )` ,
112+ ']);'
113+ ] ) . join ( '\n' ) ;
25114}
0 commit comments