css-loader 5.2.7 → 6.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/utils.js CHANGED
@@ -23,14 +23,14 @@ exports.isUrlRequestable = isUrlRequestable;
23
23
  exports.sort = sort;
24
24
  exports.combineRequests = combineRequests;
25
25
  exports.camelCase = camelCase;
26
+ exports.stringifyRequest = stringifyRequest;
27
+ exports.isDataUrl = isDataUrl;
26
28
  exports.WEBPACK_IGNORE_COMMENT_REGEXP = void 0;
27
29
 
28
30
  var _url = require("url");
29
31
 
30
32
  var _path = _interopRequireDefault(require("path"));
31
33
 
32
- var _loaderUtils = require("loader-utils");
33
-
34
34
  var _postcssModulesValues = _interopRequireDefault(require("postcss-modules-values"));
35
35
 
36
36
  var _postcssModulesLocalByDefault = _interopRequireDefault(require("postcss-modules-local-by-default"));
@@ -45,9 +45,78 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
45
45
  MIT License http://www.opensource.org/licenses/mit-license.php
46
46
  Author Tobias Koppers @sokra
47
47
  */
48
- const WEBPACK_IGNORE_COMMENT_REGEXP = /webpackIgnore:(\s+)?(true|false)/; // eslint-disable-next-line no-useless-escape
49
-
48
+ const WEBPACK_IGNORE_COMMENT_REGEXP = /webpackIgnore:(\s+)?(true|false)/;
50
49
  exports.WEBPACK_IGNORE_COMMENT_REGEXP = WEBPACK_IGNORE_COMMENT_REGEXP;
50
+ const matchRelativePath = /^\.\.?[/\\]/;
51
+
52
+ function isAbsolutePath(str) {
53
+ return _path.default.posix.isAbsolute(str) || _path.default.win32.isAbsolute(str);
54
+ }
55
+
56
+ function isRelativePath(str) {
57
+ return matchRelativePath.test(str);
58
+ }
59
+
60
+ function stringifyRequest(loaderContext, request) {
61
+ const splitted = request.split("!");
62
+ const {
63
+ context
64
+ } = loaderContext;
65
+ return JSON.stringify(splitted.map(part => {
66
+ // First, separate singlePath from query, because the query might contain paths again
67
+ const splittedPart = part.match(/^(.*?)(\?.*)/);
68
+ const query = splittedPart ? splittedPart[2] : "";
69
+ let singlePath = splittedPart ? splittedPart[1] : part;
70
+
71
+ if (isAbsolutePath(singlePath) && context) {
72
+ singlePath = _path.default.relative(context, singlePath);
73
+
74
+ if (isAbsolutePath(singlePath)) {
75
+ // If singlePath still matches an absolute path, singlePath was on a different drive than context.
76
+ // In this case, we leave the path platform-specific without replacing any separators.
77
+ // @see https://github.com/webpack/loader-utils/pull/14
78
+ return singlePath + query;
79
+ }
80
+
81
+ if (isRelativePath(singlePath) === false) {
82
+ // Ensure that the relative path starts at least with ./ otherwise it would be a request into the modules directory (like node_modules).
83
+ singlePath = `./${singlePath}`;
84
+ }
85
+ }
86
+
87
+ return singlePath.replace(/\\/g, "/") + query;
88
+ }).join("!"));
89
+ } // We can't use path.win32.isAbsolute because it also matches paths starting with a forward slash
90
+
91
+
92
+ const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
93
+ const IS_MODULE_REQUEST = /^[^?]*~/;
94
+
95
+ function urlToRequest(url, root) {
96
+ let request;
97
+
98
+ if (IS_NATIVE_WIN32_PATH.test(url)) {
99
+ // absolute windows path, keep it
100
+ request = url;
101
+ } else if (typeof root !== "undefined" && /^\//.test(url)) {
102
+ request = root + url;
103
+ } else if (/^\.\.?\//.test(url)) {
104
+ // A relative url stays
105
+ request = url;
106
+ } else {
107
+ // every other url is threaded like a relative url
108
+ request = `./${url}`;
109
+ } // A `~` makes the url an module
110
+
111
+
112
+ if (IS_MODULE_REQUEST.test(request)) {
113
+ request = request.replace(IS_MODULE_REQUEST, "");
114
+ }
115
+
116
+ return request;
117
+ } // eslint-disable-next-line no-useless-escape
118
+
119
+
51
120
  const regexSingleEscape = /[ -,.\/:-@[\]\^`{-~]/;
52
121
  const regexExcessiveSpaces = /(^|\\+)?(\\[A-F0-9]{1,6})\x20(?![a-fA-F0-9\x20])/g;
53
122
 
@@ -244,17 +313,108 @@ function escapeLocalIdent(localident) {
244
313
  }
245
314
 
246
315
  function defaultGetLocalIdent(loaderContext, localIdentName, localName, options) {
247
- let relativeMatchResource = ""; // eslint-disable-next-line no-underscore-dangle
316
+ let relativeMatchResource = "";
317
+ const {
318
+ context
319
+ } = options;
320
+ const {
321
+ resourcePath
322
+ } = loaderContext; // eslint-disable-next-line no-underscore-dangle
248
323
 
249
324
  if (loaderContext._module && loaderContext._module.matchResource) {
250
325
  relativeMatchResource = `${normalizePath( // eslint-disable-next-line no-underscore-dangle
251
- _path.default.relative(options.context, loaderContext._module.matchResource))}\x00`;
326
+ _path.default.relative(context, loaderContext._module.matchResource))}\x00`;
327
+ }
328
+
329
+ const relativeResourcePath = normalizePath(_path.default.relative(context, resourcePath)); // eslint-disable-next-line no-param-reassign
330
+
331
+ options.content = `${relativeMatchResource}${relativeResourcePath}\x00${localName}`;
332
+ let {
333
+ hashFunction,
334
+ hashDigest,
335
+ hashDigestLength
336
+ } = options;
337
+ const matches = localIdentName.match(/\[(?:([^:\]]+):)?(?:(hash|contenthash|fullhash))(?::([a-z]+\d*))?(?::(\d+))?\]/i);
338
+
339
+ if (matches) {
340
+ const hashName = matches[2] || hashFunction;
341
+ hashFunction = matches[1] || hashFunction;
342
+ hashDigest = matches[3] || hashDigest;
343
+ hashDigestLength = matches[4] || hashDigestLength; // `hash` and `contenthash` are same in `loader-utils` context
344
+ // let's keep `hash` for backward compatibility
345
+ // eslint-disable-next-line no-param-reassign
346
+
347
+ localIdentName = localIdentName.replace(/\[(?:([^:\]]+):)?(?:hash|contenthash|fullhash)(?::([a-z]+\d*))?(?::(\d+))?\]/gi, () => hashName === "fullhash" ? "[fullhash]" : "[contenthash]");
348
+ } // eslint-disable-next-line no-underscore-dangle
349
+
350
+
351
+ const hash = loaderContext._compiler.webpack.util.createHash(hashFunction);
352
+
353
+ const {
354
+ hashSalt
355
+ } = options;
356
+
357
+ if (hashSalt) {
358
+ hash.update(hashSalt);
252
359
  }
253
360
 
254
- const relativeResourcePath = normalizePath(_path.default.relative(options.context, loaderContext.resourcePath)); // eslint-disable-next-line no-param-reassign
361
+ hash.update(options.content);
362
+ const localIdentHash = hash.digest(hashDigest).slice(0, hashDigestLength).replace(/[/+]/g, "_").replace(/^\d/g, "_"); // TODO need improve on webpack side, we should allow to pass hash/contentHash without chunk property, also `data` for `getPath` should be looks good without chunk property
363
+
364
+ const ext = _path.default.extname(resourcePath);
365
+
366
+ const base = _path.default.basename(resourcePath);
367
+
368
+ const name = base.slice(0, base.length - ext.length);
369
+ const data = {
370
+ filename: _path.default.relative(context, resourcePath),
371
+ contentHash: localIdentHash,
372
+ chunk: {
373
+ name,
374
+ hash: localIdentHash,
375
+ contentHash: localIdentHash
376
+ }
377
+ }; // eslint-disable-next-line no-underscore-dangle
378
+
379
+ let result = loaderContext._compilation.getPath(localIdentName, data);
380
+
381
+ if (/\[folder\]/gi.test(result)) {
382
+ const dirname = _path.default.dirname(resourcePath);
383
+
384
+ let directory = normalizePath(_path.default.relative(context, `${dirname + _path.default.sep}_`));
385
+ directory = directory.substr(0, directory.length - 1);
386
+ let folder = "";
387
+
388
+ if (directory.length > 1) {
389
+ folder = _path.default.basename(directory);
390
+ }
391
+
392
+ result = result.replace(/\[folder\]/gi, () => folder);
393
+ }
255
394
 
256
- options.content = `${options.hashPrefix}${relativeMatchResource}${relativeResourcePath}\x00${localName}`;
257
- return (0, _loaderUtils.interpolateName)(loaderContext, localIdentName, options);
395
+ if (options.regExp) {
396
+ const match = resourcePath.match(options.regExp);
397
+
398
+ if (match) {
399
+ match.forEach((matched, i) => {
400
+ result = result.replace(new RegExp(`\\[${i}\\]`, "ig"), matched);
401
+ });
402
+ }
403
+ }
404
+
405
+ return result;
406
+ }
407
+
408
+ function fixedEncodeURIComponent(str) {
409
+ return str.replace(/[!'()*]/g, c => `%${c.charCodeAt(0).toString(16)}`);
410
+ }
411
+
412
+ function isDataUrl(url) {
413
+ if (/^data:/i.test(url)) {
414
+ return true;
415
+ }
416
+
417
+ return false;
258
418
  }
259
419
 
260
420
  const NATIVE_WIN32_PATH = /^[A-Z]:[/\\]|^\\\\/i;
@@ -277,6 +437,11 @@ function normalizeUrl(url, isStringValue) {
277
437
 
278
438
  normalizedUrl = unescape(normalizedUrl);
279
439
 
440
+ if (isDataUrl(url)) {
441
+ // Todo fixedEncodeURIComponent is workaround. Webpack resolver shouldn't handle "!" in dataURL
442
+ return fixedEncodeURIComponent(normalizedUrl);
443
+ }
444
+
280
445
  try {
281
446
  normalizedUrl = decodeURI(normalizedUrl);
282
447
  } catch (error) {// Ignore
@@ -285,12 +450,25 @@ function normalizeUrl(url, isStringValue) {
285
450
  return normalizedUrl;
286
451
  }
287
452
 
288
- function requestify(url, rootContext) {
289
- if (/^file:/i.test(url)) {
290
- return (0, _url.fileURLToPath)(url);
453
+ function requestify(url, rootContext, needToResolveURL = true) {
454
+ if (needToResolveURL) {
455
+ if (/^file:/i.test(url)) {
456
+ return (0, _url.fileURLToPath)(url);
457
+ }
458
+
459
+ return url.charAt(0) === "/" ? urlToRequest(url, rootContext) : urlToRequest(url);
291
460
  }
292
461
 
293
- return url.charAt(0) === "/" ? (0, _loaderUtils.urlToRequest)(url, rootContext) : (0, _loaderUtils.urlToRequest)(url);
462
+ if (url.charAt(0) === "/" || /^file:/i.test(url)) {
463
+ return url;
464
+ } // A `~` makes the url an module
465
+
466
+
467
+ if (IS_MODULE_REQUEST.test(url)) {
468
+ return url.replace(IS_MODULE_REQUEST, "");
469
+ }
470
+
471
+ return url;
294
472
  }
295
473
 
296
474
  function getFilter(filter, resourcePath) {
@@ -304,116 +482,164 @@ function getFilter(filter, resourcePath) {
304
482
  }
305
483
 
306
484
  function getValidLocalName(localName, exportLocalsConvention) {
307
- if (exportLocalsConvention === "dashesOnly") {
308
- return dashesCamelCase(localName);
309
- }
310
-
311
- return camelCase(localName);
485
+ const result = exportLocalsConvention(localName);
486
+ return Array.isArray(result) ? result[0] : result;
312
487
  }
313
488
 
314
- const moduleRegExp = /\.module(s)?\.\w+$/i;
315
- const icssRegExp = /\.icss\.\w+$/i;
489
+ const IS_MODULES = /\.module(s)?\.\w+$/i;
490
+ const IS_ICSS = /\.icss\.\w+$/i;
491
+
492
+ function getModulesOptions(rawOptions, exportType, loaderContext) {
493
+ if (typeof rawOptions.modules === "boolean" && rawOptions.modules === false) {
494
+ return false;
495
+ }
316
496
 
317
- function getModulesOptions(rawOptions, loaderContext) {
318
497
  const resourcePath = // eslint-disable-next-line no-underscore-dangle
319
498
  loaderContext._module && loaderContext._module.matchResource || loaderContext.resourcePath;
320
- let isIcss;
499
+ let auto;
500
+ let rawModulesOptions;
321
501
 
322
502
  if (typeof rawOptions.modules === "undefined") {
323
- const isModules = moduleRegExp.test(resourcePath);
324
-
325
- if (!isModules) {
326
- isIcss = icssRegExp.test(resourcePath);
327
- }
503
+ rawModulesOptions = {};
504
+ auto = true;
505
+ } else if (typeof rawOptions.modules === "boolean") {
506
+ rawModulesOptions = {};
507
+ } else if (typeof rawOptions.modules === "string") {
508
+ rawModulesOptions = {
509
+ mode: rawOptions.modules
510
+ };
511
+ } else {
512
+ rawModulesOptions = rawOptions.modules;
513
+ ({
514
+ auto
515
+ } = rawModulesOptions);
516
+ } // eslint-disable-next-line no-underscore-dangle
328
517
 
329
- if (!isModules && !isIcss) {
330
- return false;
331
- }
332
- } else if (typeof rawOptions.modules === "boolean" && rawOptions.modules === false) {
333
- return false;
334
- }
335
518
 
336
- let modulesOptions = {
337
- compileType: isIcss ? "icss" : "module",
338
- auto: true,
519
+ const {
520
+ outputOptions
521
+ } = loaderContext._compilation;
522
+ const needNamedExport = exportType === "css-style-sheet" || exportType === "string";
523
+ const modulesOptions = {
524
+ auto,
339
525
  mode: "local",
340
526
  exportGlobals: false,
341
527
  localIdentName: "[hash:base64]",
342
528
  localIdentContext: loaderContext.rootContext,
343
- localIdentHashPrefix: "",
529
+ localIdentHashSalt: outputOptions.hashSalt,
530
+ localIdentHashFunction: outputOptions.hashFunction,
531
+ localIdentHashDigest: outputOptions.hashDigest,
532
+ localIdentHashDigestLength: outputOptions.hashDigestLength,
344
533
  // eslint-disable-next-line no-undefined
345
534
  localIdentRegExp: undefined,
346
535
  // eslint-disable-next-line no-undefined
347
536
  getLocalIdent: undefined,
348
- namedExport: false,
349
- exportLocalsConvention: "asIs",
350
- exportOnlyLocals: false
537
+ namedExport: needNamedExport || false,
538
+ exportLocalsConvention: (rawModulesOptions.namedExport === true || needNamedExport) && typeof rawModulesOptions.exportLocalsConvention === "undefined" ? "camelCaseOnly" : "asIs",
539
+ exportOnlyLocals: false,
540
+ ...rawModulesOptions
351
541
  };
542
+ let exportLocalsConventionType;
352
543
 
353
- if (typeof rawOptions.modules === "boolean" || typeof rawOptions.modules === "string") {
354
- modulesOptions.mode = typeof rawOptions.modules === "string" ? rawOptions.modules : "local";
355
- } else {
356
- if (rawOptions.modules) {
357
- if (typeof rawOptions.modules.auto === "boolean") {
358
- const isModules = rawOptions.modules.auto && moduleRegExp.test(resourcePath);
544
+ if (typeof modulesOptions.exportLocalsConvention === "string") {
545
+ exportLocalsConventionType = modulesOptions.exportLocalsConvention;
359
546
 
360
- if (!isModules) {
361
- return false;
362
- }
363
- } else if (rawOptions.modules.auto instanceof RegExp) {
364
- const isModules = rawOptions.modules.auto.test(resourcePath);
547
+ modulesOptions.exportLocalsConvention = name => {
548
+ switch (exportLocalsConventionType) {
549
+ case "camelCase":
550
+ {
551
+ return [name, camelCase(name)];
552
+ }
365
553
 
366
- if (!isModules) {
367
- return false;
368
- }
369
- } else if (typeof rawOptions.modules.auto === "function") {
370
- const isModule = rawOptions.modules.auto(resourcePath);
554
+ case "camelCaseOnly":
555
+ {
556
+ return camelCase(name);
557
+ }
371
558
 
372
- if (!isModule) {
373
- return false;
374
- }
559
+ case "dashes":
560
+ {
561
+ return [name, dashesCamelCase(name)];
562
+ }
563
+
564
+ case "dashesOnly":
565
+ {
566
+ return dashesCamelCase(name);
567
+ }
568
+
569
+ case "asIs":
570
+ default:
571
+ return name;
375
572
  }
573
+ };
574
+ }
575
+
576
+ if (typeof modulesOptions.auto === "boolean") {
577
+ const isModules = modulesOptions.auto && IS_MODULES.test(resourcePath);
578
+ let isIcss;
376
579
 
377
- if (rawOptions.modules.namedExport === true && typeof rawOptions.modules.exportLocalsConvention === "undefined") {
378
- modulesOptions.exportLocalsConvention = "camelCaseOnly";
580
+ if (!isModules) {
581
+ isIcss = IS_ICSS.test(resourcePath);
582
+
583
+ if (isIcss) {
584
+ modulesOptions.mode = "icss";
379
585
  }
380
586
  }
381
587
 
382
- modulesOptions = { ...modulesOptions,
383
- ...(rawOptions.modules || {})
384
- };
588
+ if (!isModules && !isIcss) {
589
+ return false;
590
+ }
591
+ } else if (modulesOptions.auto instanceof RegExp) {
592
+ const isModules = modulesOptions.auto.test(resourcePath);
593
+
594
+ if (!isModules) {
595
+ return false;
596
+ }
597
+ } else if (typeof modulesOptions.auto === "function") {
598
+ const isModule = modulesOptions.auto(resourcePath);
599
+
600
+ if (!isModule) {
601
+ return false;
602
+ }
385
603
  }
386
604
 
387
605
  if (typeof modulesOptions.mode === "function") {
388
606
  modulesOptions.mode = modulesOptions.mode(loaderContext.resourcePath);
389
607
  }
390
608
 
391
- if (modulesOptions.namedExport === true) {
609
+ if (needNamedExport) {
392
610
  if (rawOptions.esModule === false) {
393
- throw new Error('The "modules.namedExport" option requires the "esModules" option to be enabled');
611
+ throw new Error("The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'esModules' option to be enabled");
394
612
  }
395
613
 
396
- if (modulesOptions.exportLocalsConvention !== "camelCaseOnly" && modulesOptions.exportLocalsConvention !== "dashesOnly") {
397
- throw new Error('The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "camelCaseOnly" or "dashesOnly"');
614
+ if (modulesOptions.namedExport === false) {
615
+ throw new Error("The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'modules.namedExport' option to be enabled");
398
616
  }
399
617
  }
400
618
 
401
- if (/\[emoji(?::(\d+))?\]/i.test(modulesOptions.localIdentName)) {
402
- loaderContext.emitWarning("Emoji is deprecated and will be removed in next major release.");
619
+ if (modulesOptions.namedExport === true) {
620
+ if (rawOptions.esModule === false) {
621
+ throw new Error("The 'modules.namedExport' option requires the 'esModules' option to be enabled");
622
+ }
623
+
624
+ if (typeof exportLocalsConventionType === "string" && exportLocalsConventionType !== "camelCaseOnly" && exportLocalsConventionType !== "dashesOnly") {
625
+ throw new Error('The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "camelCaseOnly" or "dashesOnly"');
626
+ }
403
627
  }
404
628
 
405
629
  return modulesOptions;
406
630
  }
407
631
 
408
632
  function normalizeOptions(rawOptions, loaderContext) {
409
- const modulesOptions = getModulesOptions(rawOptions, loaderContext);
633
+ const exportType = typeof rawOptions.exportType === "undefined" ? "array" : rawOptions.exportType;
634
+ const modulesOptions = getModulesOptions(rawOptions, exportType, loaderContext);
410
635
  return {
411
636
  url: typeof rawOptions.url === "undefined" ? true : rawOptions.url,
412
637
  import: typeof rawOptions.import === "undefined" ? true : rawOptions.import,
413
638
  modules: modulesOptions,
414
639
  sourceMap: typeof rawOptions.sourceMap === "boolean" ? rawOptions.sourceMap : loaderContext.sourceMap,
415
640
  importLoaders: typeof rawOptions.importLoaders === "string" ? parseInt(rawOptions.importLoaders, 10) : rawOptions.importLoaders,
416
- esModule: typeof rawOptions.esModule === "undefined" ? true : rawOptions.esModule
641
+ esModule: typeof rawOptions.esModule === "undefined" ? true : rawOptions.esModule,
642
+ exportType
417
643
  };
418
644
  }
419
645
 
@@ -442,11 +668,15 @@ function shouldUseURLPlugin(options) {
442
668
  }
443
669
 
444
670
  function shouldUseModulesPlugins(options) {
445
- return options.modules.compileType === "module";
671
+ if (typeof options.modules === "boolean" && options.modules === false) {
672
+ return false;
673
+ }
674
+
675
+ return options.modules.mode !== "icss";
446
676
  }
447
677
 
448
678
  function shouldUseIcssPlugin(options) {
449
- return options.icss === true || Boolean(options.modules);
679
+ return Boolean(options.modules);
450
680
  }
451
681
 
452
682
  function getModulesPlugins(options, loaderContext) {
@@ -455,7 +685,10 @@ function getModulesPlugins(options, loaderContext) {
455
685
  getLocalIdent,
456
686
  localIdentName,
457
687
  localIdentContext,
458
- localIdentHashPrefix,
688
+ localIdentHashSalt,
689
+ localIdentHashFunction,
690
+ localIdentHashDigest,
691
+ localIdentHashDigestLength,
459
692
  localIdentRegExp
460
693
  } = options.modules;
461
694
  let plugins = [];
@@ -470,7 +703,10 @@ function getModulesPlugins(options, loaderContext) {
470
703
  if (typeof getLocalIdent !== "undefined") {
471
704
  localIdent = getLocalIdent(loaderContext, localIdentName, unescape(exportName), {
472
705
  context: localIdentContext,
473
- hashPrefix: localIdentHashPrefix,
706
+ hashSalt: localIdentHashSalt,
707
+ hashFunction: localIdentHashFunction,
708
+ hashDigest: localIdentHashDigest,
709
+ hashDigestLength: localIdentHashDigestLength,
474
710
  regExp: localIdentRegExp
475
711
  });
476
712
  } // A null/undefined value signals that we should invoke the default
@@ -480,7 +716,10 @@ function getModulesPlugins(options, loaderContext) {
480
716
  if (typeof localIdent === "undefined" || localIdent === null) {
481
717
  localIdent = defaultGetLocalIdent(loaderContext, localIdentName, unescape(exportName), {
482
718
  context: localIdentContext,
483
- hashPrefix: localIdentHashPrefix,
719
+ hashSalt: localIdentHashSalt,
720
+ hashFunction: localIdentHashFunction,
721
+ hashDigest: localIdentHashDigest,
722
+ hashDigestLength: localIdentHashDigestLength,
484
723
  regExp: localIdentRegExp
485
724
  });
486
725
  return escapeLocalIdent(localIdent).replace(/\\\[local\\]/gi, exportName);
@@ -498,7 +737,6 @@ function getModulesPlugins(options, loaderContext) {
498
737
  return plugins;
499
738
  }
500
739
 
501
- const IS_NATIVE_WIN32_PATH = /^[a-z]:[/\\]|^\\\\/i;
502
740
  const ABSOLUTE_SCHEME = /^[a-z0-9+\-.]+:/i;
503
741
 
504
742
  function getURLType(source) {
@@ -582,14 +820,15 @@ function getImportCode(imports, options) {
582
820
  const {
583
821
  importName,
584
822
  url,
585
- icss
823
+ icss,
824
+ type
586
825
  } = item;
587
826
 
588
827
  if (options.esModule) {
589
828
  if (icss && options.modules.namedExport) {
590
829
  code += `import ${options.modules.exportOnlyLocals ? "" : `${importName}, `}* as ${importName}_NAMED___ from ${url};\n`;
591
830
  } else {
592
- code += `import ${importName} from ${url};\n`;
831
+ code += type === "url" ? `var ${importName} = new URL(${url}, import.meta.url);\n` : `import ${importName} from ${url};\n`;
593
832
  }
594
833
  } else {
595
834
  code += `var ${importName} = require(${url});\n`;
@@ -629,6 +868,34 @@ function normalizeSourceMapForRuntime(map, loaderContext) {
629
868
  return JSON.stringify(resultMap);
630
869
  }
631
870
 
871
+ function printParams(media, dedupe, supports, layer) {
872
+ let result = "";
873
+
874
+ if (typeof layer !== "undefined") {
875
+ result = `, ${JSON.stringify(layer)}`;
876
+ }
877
+
878
+ if (typeof supports !== "undefined") {
879
+ result = `, ${JSON.stringify(supports)}${result}`;
880
+ } else if (result.length > 0) {
881
+ result = `, undefined${result}`;
882
+ }
883
+
884
+ if (dedupe) {
885
+ result = `, true${result}`;
886
+ } else if (result.length > 0) {
887
+ result = `, false${result}`;
888
+ }
889
+
890
+ if (media) {
891
+ result = `${JSON.stringify(media)}${result}`;
892
+ } else if (result.length > 0) {
893
+ result = `""${result}`;
894
+ }
895
+
896
+ return result;
897
+ }
898
+
632
899
  function getModuleCode(result, api, replacements, options, loaderContext) {
633
900
  if (options.modules.exportOnlyLocals === true) {
634
901
  return "";
@@ -636,15 +903,25 @@ function getModuleCode(result, api, replacements, options, loaderContext) {
636
903
 
637
904
  const sourceMapValue = options.sourceMap ? `,${normalizeSourceMapForRuntime(result.map, loaderContext)}` : "";
638
905
  let code = JSON.stringify(result.css);
639
- let beforeCode = `var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(${options.sourceMap ? "___CSS_LOADER_API_SOURCEMAP_IMPORT___" : "function(i){return i[1]}"});\n`;
906
+ let beforeCode = `var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(${options.sourceMap ? "___CSS_LOADER_API_SOURCEMAP_IMPORT___" : "___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___"});\n`;
640
907
 
641
908
  for (const item of api) {
642
909
  const {
643
910
  url,
911
+ layer,
912
+ supports,
644
913
  media,
645
914
  dedupe
646
915
  } = item;
647
- beforeCode += url ? `___CSS_LOADER_EXPORT___.push([module.id, ${JSON.stringify(`@import url(${url});`)}${media ? `, ${JSON.stringify(media)}` : ""}]);\n` : `___CSS_LOADER_EXPORT___.i(${item.importName}${media ? `, ${JSON.stringify(media)}` : dedupe ? ', ""' : ""}${dedupe ? ", true" : ""});\n`;
916
+
917
+ if (url) {
918
+ // eslint-disable-next-line no-undefined
919
+ const printedParam = printParams(media, undefined, supports, layer);
920
+ beforeCode += `___CSS_LOADER_EXPORT___.push([module.id, ${JSON.stringify(`@import url(${url});`)}${printedParam.length > 0 ? `, ${printedParam}` : ""}]);\n`;
921
+ } else {
922
+ const printedParam = printParams(media, dedupe, supports, layer);
923
+ beforeCode += `___CSS_LOADER_EXPORT___.i(${item.importName}${printedParam.length > 0 ? `, ${printedParam}` : ""});\n`;
924
+ }
648
925
  }
649
926
 
650
927
  for (const item of replacements) {
@@ -666,7 +943,14 @@ function getModuleCode(result, api, replacements, options, loaderContext) {
666
943
  beforeCode += `var ${replacementName} = ___CSS_LOADER_GET_URL_IMPORT___(${importName}${preparedOptions});\n`;
667
944
  code = code.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`);
668
945
  }
669
- }
946
+ } // Indexes description:
947
+ // 0 - module id
948
+ // 1 - CSS code
949
+ // 2 - media
950
+ // 3 - source map
951
+ // 4 - supports
952
+ // 5 - layer
953
+
670
954
 
671
955
  return `${beforeCode}// Module\n___CSS_LOADER_EXPORT___.push([module.id, ${code}, ""${sourceMapValue}]);\n`;
672
956
  }
@@ -675,107 +959,92 @@ function dashesCamelCase(str) {
675
959
  return str.replace(/-+(\w)/g, (match, firstLetter) => firstLetter.toUpperCase());
676
960
  }
677
961
 
678
- function getExportCode(exports, replacements, needToUseIcssPlugin, options) {
962
+ function getExportCode(exports, replacements, icssPluginUsed, options) {
679
963
  let code = "// Exports\n";
680
964
 
681
- if (!needToUseIcssPlugin) {
682
- code += `${options.esModule ? "export default" : "module.exports ="} ___CSS_LOADER_EXPORT___;\n`;
683
- return code;
684
- }
685
-
686
- let localsCode = "";
687
-
688
- const addExportToLocalsCode = (name, value) => {
689
- if (options.modules.namedExport) {
690
- localsCode += `export var ${name} = ${JSON.stringify(value)};\n`;
691
- } else {
692
- if (localsCode) {
693
- localsCode += `,\n`;
694
- }
965
+ if (icssPluginUsed) {
966
+ let localsCode = "";
695
967
 
696
- localsCode += `\t${JSON.stringify(name)}: ${JSON.stringify(value)}`;
697
- }
698
- };
968
+ const addExportToLocalsCode = (names, value) => {
969
+ const normalizedNames = Array.isArray(names) ? new Set(names) : new Set([names]);
699
970
 
700
- for (const {
701
- name,
702
- value
703
- } of exports) {
704
- switch (options.modules.exportLocalsConvention) {
705
- case "camelCase":
706
- {
707
- addExportToLocalsCode(name, value);
708
- const modifiedName = camelCase(name);
709
-
710
- if (modifiedName !== name) {
711
- addExportToLocalsCode(modifiedName, value);
971
+ for (const name of normalizedNames) {
972
+ if (options.modules.namedExport) {
973
+ localsCode += `export var ${name} = ${JSON.stringify(value)};\n`;
974
+ } else {
975
+ if (localsCode) {
976
+ localsCode += `,\n`;
712
977
  }
713
978
 
714
- break;
979
+ localsCode += `\t${JSON.stringify(name)}: ${JSON.stringify(value)}`;
715
980
  }
981
+ }
982
+ };
716
983
 
717
- case "camelCaseOnly":
718
- {
719
- addExportToLocalsCode(camelCase(name), value);
720
- break;
721
- }
984
+ for (const {
985
+ name,
986
+ value
987
+ } of exports) {
988
+ addExportToLocalsCode(options.modules.exportLocalsConvention(name), value);
989
+ }
722
990
 
723
- case "dashes":
724
- {
725
- addExportToLocalsCode(name, value);
726
- const modifiedName = dashesCamelCase(name);
991
+ for (const item of replacements) {
992
+ const {
993
+ replacementName,
994
+ localName
995
+ } = item;
727
996
 
728
- if (modifiedName !== name) {
729
- addExportToLocalsCode(modifiedName, value);
997
+ if (localName) {
998
+ const {
999
+ importName
1000
+ } = item;
1001
+ localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => {
1002
+ if (options.modules.namedExport) {
1003
+ return `" + ${importName}_NAMED___[${JSON.stringify(getValidLocalName(localName, options.modules.exportLocalsConvention))}] + "`;
1004
+ } else if (options.modules.exportOnlyLocals) {
1005
+ return `" + ${importName}[${JSON.stringify(localName)}] + "`;
730
1006
  }
731
1007
 
732
- break;
733
- }
734
-
735
- case "dashesOnly":
736
- {
737
- addExportToLocalsCode(dashesCamelCase(name), value);
738
- break;
739
- }
1008
+ return `" + ${importName}.locals[${JSON.stringify(localName)}] + "`;
1009
+ });
1010
+ } else {
1011
+ localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`);
1012
+ }
1013
+ }
740
1014
 
741
- case "asIs":
742
- default:
743
- addExportToLocalsCode(name, value);
744
- break;
1015
+ if (options.modules.exportOnlyLocals) {
1016
+ code += options.modules.namedExport ? localsCode : `${options.esModule ? "export default" : "module.exports ="} {\n${localsCode}\n};\n`;
1017
+ return code;
745
1018
  }
746
- }
747
1019
 
748
- for (const item of replacements) {
749
- const {
750
- replacementName,
751
- localName
752
- } = item;
1020
+ code += options.modules.namedExport ? localsCode : `___CSS_LOADER_EXPORT___.locals = {${localsCode ? `\n${localsCode}\n` : ""}};\n`;
1021
+ }
753
1022
 
754
- if (localName) {
755
- const {
756
- importName
757
- } = item;
758
- localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => {
759
- if (options.modules.namedExport) {
760
- return `" + ${importName}_NAMED___[${JSON.stringify(getValidLocalName(localName, options.modules.exportLocalsConvention))}] + "`;
761
- } else if (options.modules.exportOnlyLocals) {
762
- return `" + ${importName}[${JSON.stringify(localName)}] + "`;
763
- }
1023
+ const isCSSStyleSheetExport = options.exportType === "css-style-sheet";
764
1024
 
765
- return `" + ${importName}.locals[${JSON.stringify(localName)}] + "`;
766
- });
767
- } else {
768
- localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`);
769
- }
1025
+ if (isCSSStyleSheetExport) {
1026
+ code += "var ___CSS_LOADER_STYLE_SHEET___ = new CSSStyleSheet();\n";
1027
+ code += "___CSS_LOADER_STYLE_SHEET___.replaceSync(___CSS_LOADER_EXPORT___.toString());\n";
770
1028
  }
771
1029
 
772
- if (options.modules.exportOnlyLocals) {
773
- code += options.modules.namedExport ? localsCode : `${options.esModule ? "export default" : "module.exports ="} {\n${localsCode}\n};\n`;
774
- return code;
1030
+ let finalExport;
1031
+
1032
+ switch (options.exportType) {
1033
+ case "string":
1034
+ finalExport = "___CSS_LOADER_EXPORT___.toString()";
1035
+ break;
1036
+
1037
+ case "css-style-sheet":
1038
+ finalExport = "___CSS_LOADER_STYLE_SHEET___";
1039
+ break;
1040
+
1041
+ default:
1042
+ case "array":
1043
+ finalExport = "___CSS_LOADER_EXPORT___";
1044
+ break;
775
1045
  }
776
1046
 
777
- code += options.modules.namedExport ? localsCode : `___CSS_LOADER_EXPORT___.locals = {${localsCode ? `\n${localsCode}\n` : ""}};\n`;
778
- code += `${options.esModule ? "export default" : "module.exports ="} ___CSS_LOADER_EXPORT___;\n`;
1047
+ code += `${options.esModule ? "export default" : "module.exports ="} ${finalExport};\n`;
779
1048
  return code;
780
1049
  }
781
1050