@@ -17,14 +17,15 @@ import {
1717 getCurrentRequest ,
1818 stringifyRequest ,
1919} from 'loader-utils' ;
20+ import camelCase from 'lodash/camelCase' ;
2021
2122import schema from './options.json' ;
2223import { importParser , icssParser , urlParser } from './plugins' ;
2324import {
2425 getLocalIdent ,
2526 getImportPrefix ,
26- compileExports ,
2727 placholderRegExps ,
28+ dashesCamelCase ,
2829} from './utils' ;
2930import Warning from './Warning' ;
3031import CssSyntaxError from './CssSyntaxError' ;
@@ -137,10 +138,9 @@ export default function loader(content, map, meta) {
137138 . forEach ( ( warning ) => this . emitWarning ( new Warning ( warning ) ) ) ;
138139
139140 const messages = result . messages || [ ] ;
140- const { camelCase, exportOnlyLocals, importLoaders } = options ;
141141
142142 // Run other loader (`postcss-loader`, `sass-loader` and etc) for importing CSS
143- const importUrlPrefix = getImportPrefix ( this , importLoaders ) ;
143+ const importUrlPrefix = getImportPrefix ( this , options . importLoaders ) ;
144144
145145 // Prepare replacer to change from `___CSS_LOADER_IMPORT___INDEX___` to `require('./file.css').locals`
146146 const importItemReplacer = ( placeholder ) => {
@@ -162,7 +162,7 @@ export default function loader(content, map, meta) {
162162 const { item } = message ;
163163 const importUrl = importUrlPrefix + urlToRequest ( item . url ) ;
164164
165- if ( exportOnlyLocals ) {
165+ if ( options . exportOnlyLocals ) {
166166 return `" + require(${ stringifyRequest (
167167 this ,
168168 importUrl
@@ -175,18 +175,65 @@ export default function loader(content, map, meta) {
175175 ) } ).locals[${ JSON . stringify ( item . export ) } ] + "`;
176176 } ;
177177
178- let exportCode = compileExports ( messages , camelCase , ( valueAsString ) =>
179- valueAsString . replace ( placholderRegExps . importItemG , importItemReplacer )
180- ) ;
178+ const exports = messages
179+ . filter ( ( message ) => message . type === 'export' )
180+ . reduce ( ( accumulator , message ) => {
181+ const { key, value } = message . item ;
182+
183+ let valueAsString = JSON . stringify ( value ) ;
184+
185+ valueAsString = valueAsString . replace (
186+ placholderRegExps . importItemG ,
187+ importItemReplacer
188+ ) ;
189+
190+ function addEntry ( k ) {
191+ accumulator . push ( `\t${ JSON . stringify ( k ) } : ${ valueAsString } ` ) ;
192+ }
193+
194+ let targetKey ;
195+
196+ switch ( options . camelCase ) {
197+ case true :
198+ addEntry ( key ) ;
199+ targetKey = camelCase ( key ) ;
200+
201+ if ( targetKey !== key ) {
202+ addEntry ( targetKey ) ;
203+ }
204+ break ;
205+ case 'dashes' :
206+ addEntry ( key ) ;
207+ targetKey = dashesCamelCase ( key ) ;
208+
209+ if ( targetKey !== key ) {
210+ addEntry ( targetKey ) ;
211+ }
212+ break ;
213+ case 'only' :
214+ addEntry ( camelCase ( key ) ) ;
215+ break ;
216+ case 'dashesOnly' :
217+ addEntry ( dashesCamelCase ( key ) ) ;
218+ break ;
219+ default :
220+ addEntry ( key ) ;
221+ break ;
222+ }
223+
224+ return accumulator ;
225+ } , [ ] ) ;
181226
182- if ( exportOnlyLocals ) {
227+ if ( options . exportOnlyLocals ) {
183228 return callback (
184229 null ,
185- exportCode ? `module.exports = ${ exportCode } ;` : exportCode
230+ exports . length > 0
231+ ? `module.exports = {\n${ exports . join ( ',\n' ) } \n};`
232+ : ''
186233 ) ;
187234 }
188235
189- const importCode = messages
236+ const imports = messages
190237 . filter ( ( message ) => message . type === 'import' )
191238 . map ( ( message ) => {
192239 const { url } = message . item ;
@@ -204,56 +251,52 @@ export default function loader(content, map, meta) {
204251 this ,
205252 importUrl
206253 ) } ), ${ JSON . stringify ( media ) } );`;
207- } , this )
208- . join ( '\n' ) ;
254+ } , this ) ;
209255
210256 let cssAsString = JSON . stringify ( result . css ) . replace (
211257 placholderRegExps . importItemG ,
212258 importItemReplacer
213259 ) ;
214260
215- // helper for ensuring valid CSS strings from requires
216- let urlEscapeHelperCode = '' ;
261+ // Helper for ensuring valid CSS strings from requires
262+ let hasUrlEscapeHelper = false ;
217263
218264 messages
219265 . filter ( ( message ) => message . type === 'url' )
220266 . forEach ( ( message ) => {
221- if ( ! urlEscapeHelperCode ) {
222- urlEscapeHelperCode = `var escape = require(${ stringifyRequest (
223- this ,
224- require . resolve ( './runtime/escape.js' )
225- ) } );\n`;
267+ if ( ! hasUrlEscapeHelper ) {
268+ imports . push (
269+ `var urlEscape = require(${ stringifyRequest (
270+ this ,
271+ require . resolve ( './runtime/url-escape.js' )
272+ ) } );`
273+ ) ;
274+
275+ hasUrlEscapeHelper = true ;
226276 }
227277
228278 const { item } = message ;
229279 const { url, placeholder } = item ;
280+ // Remove `#hash` and `?#hash` from `require`
281+ const [ normalizedUrl , singleQuery , hashValue ] = url . split ( / ( \? ) ? # / ) ;
282+ const hash =
283+ singleQuery || hashValue
284+ ? `"${ singleQuery ? '?' : '' } ${ hashValue ? `#${ hashValue } ` : '' } "`
285+ : '' ;
286+
287+ imports . push (
288+ `var ${ placeholder } = urlEscape(require(${ stringifyRequest (
289+ this ,
290+ urlToRequest ( normalizedUrl )
291+ ) } )${ hash ? ` + ${ hash } ` : '' } );`
292+ ) ;
230293
231294 cssAsString = cssAsString . replace (
232295 new RegExp ( placeholder , 'g' ) ,
233- ( ) => {
234- // Remove `#hash` and `?#hash` from `require`
235- const [ normalizedUrl , singleQuery , hashValue ] = url . split (
236- / ( \? ) ? # /
237- ) ;
238- const hash =
239- singleQuery || hashValue
240- ? `"${ singleQuery ? '?' : '' } ${
241- hashValue ? `#${ hashValue } ` : ''
242- } "`
243- : '' ;
244-
245- return `" + escape(require(${ stringifyRequest (
246- this ,
247- urlToRequest ( normalizedUrl )
248- ) } )${ hash ? ` + ${ hash } ` : '' } ) + "`;
249- }
296+ ( ) => `" + ${ placeholder } + "`
250297 ) ;
251298 } ) ;
252299
253- if ( exportCode ) {
254- exportCode = `exports.locals = ${ exportCode } ;` ;
255- }
256-
257300 let newMap = result . map ;
258301
259302 if ( sourceMap && newMap ) {
@@ -282,18 +325,21 @@ export default function loader(content, map, meta) {
282325 const runtimeCode = `exports = module.exports = require(${ stringifyRequest (
283326 this ,
284327 require . resolve ( './runtime/api' )
285- ) } )(${ ! ! sourceMap } );`;
286- const moduleCode = `exports.push([module.id, ${ cssAsString } , ""${
328+ ) } )(${ ! ! sourceMap } );\n`;
329+ const importCode =
330+ imports . length > 0 ? `// Imports\n${ imports . join ( '\n' ) } \n\n` : '' ;
331+ const moduleCode = `// Module\nexports.push([module.id, ${ cssAsString } , ""${
287332 newMap ? `,${ newMap } ` : ''
288- } ]);`;
333+ } ]);\n\n`;
334+ const exportsCode =
335+ exports . length > 0
336+ ? `// Exports\nexports.locals = {\n${ exports . join ( ',\n' ) } \n};`
337+ : '' ;
289338
290339 // Embed runtime
291340 return callback (
292341 null ,
293- `${ urlEscapeHelperCode } ${ runtimeCode } \n` +
294- `// imports\n${ importCode } \n\n` +
295- `// module\n${ moduleCode } \n\n` +
296- `// exports\n${ exportCode } `
342+ runtimeCode + importCode + moduleCode + exportsCode
297343 ) ;
298344 } )
299345 . catch ( ( error ) => {
0 commit comments