css-loader 6.2.0 → 6.5.1

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
@@ -3,29 +3,29 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
- exports.normalizeOptions = normalizeOptions;
7
- exports.shouldUseModulesPlugins = shouldUseModulesPlugins;
8
- exports.shouldUseImportPlugin = shouldUseImportPlugin;
9
- exports.shouldUseURLPlugin = shouldUseURLPlugin;
10
- exports.shouldUseIcssPlugin = shouldUseIcssPlugin;
11
- exports.normalizeUrl = normalizeUrl;
12
- exports.requestify = requestify;
6
+ exports.WEBPACK_IGNORE_COMMENT_REGEXP = void 0;
7
+ exports.camelCase = camelCase;
8
+ exports.combineRequests = combineRequests;
9
+ exports.getExportCode = getExportCode;
13
10
  exports.getFilter = getFilter;
11
+ exports.getImportCode = getImportCode;
12
+ exports.getModuleCode = getModuleCode;
14
13
  exports.getModulesOptions = getModulesOptions;
15
14
  exports.getModulesPlugins = getModulesPlugins;
16
- exports.normalizeSourceMap = normalizeSourceMap;
17
15
  exports.getPreRequester = getPreRequester;
18
- exports.getImportCode = getImportCode;
19
- exports.getModuleCode = getModuleCode;
20
- exports.getExportCode = getExportCode;
16
+ exports.isDataUrl = isDataUrl;
17
+ exports.isURLRequestable = isURLRequestable;
18
+ exports.normalizeOptions = normalizeOptions;
19
+ exports.normalizeSourceMap = normalizeSourceMap;
20
+ exports.normalizeUrl = normalizeUrl;
21
+ exports.requestify = requestify;
21
22
  exports.resolveRequests = resolveRequests;
22
- exports.isUrlRequestable = isUrlRequestable;
23
+ exports.shouldUseIcssPlugin = shouldUseIcssPlugin;
24
+ exports.shouldUseImportPlugin = shouldUseImportPlugin;
25
+ exports.shouldUseModulesPlugins = shouldUseModulesPlugins;
26
+ exports.shouldUseURLPlugin = shouldUseURLPlugin;
23
27
  exports.sort = sort;
24
- exports.combineRequests = combineRequests;
25
- exports.camelCase = camelCase;
26
28
  exports.stringifyRequest = stringifyRequest;
27
- exports.isDataUrl = isDataUrl;
28
- exports.WEBPACK_IGNORE_COMMENT_REGEXP = void 0;
29
29
 
30
30
  var _url = require("url");
31
31
 
@@ -55,9 +55,14 @@ function isAbsolutePath(str) {
55
55
 
56
56
  function isRelativePath(str) {
57
57
  return matchRelativePath.test(str);
58
- }
58
+ } // TODO simplify for the next major release
59
+
59
60
 
60
61
  function stringifyRequest(loaderContext, request) {
62
+ if (typeof loaderContext.utils !== "undefined" && typeof loaderContext.utils.contextify === "function") {
63
+ return JSON.stringify(loaderContext.utils.contextify(loaderContext.context || loaderContext.rootContext, request));
64
+ }
65
+
61
66
  const splitted = request.split("!");
62
67
  const {
63
68
  context
@@ -313,55 +318,64 @@ function escapeLocalIdent(localident) {
313
318
  }
314
319
 
315
320
  function defaultGetLocalIdent(loaderContext, localIdentName, localName, options) {
316
- let relativeMatchResource = ""; // eslint-disable-next-line no-underscore-dangle
317
-
318
- if (loaderContext._module && loaderContext._module.matchResource) {
319
- relativeMatchResource = `${normalizePath( // eslint-disable-next-line no-underscore-dangle
320
- _path.default.relative(options.context, loaderContext._module.matchResource))}\x00`;
321
- }
322
-
323
- const relativeResourcePath = normalizePath(_path.default.relative(options.context, loaderContext.resourcePath)); // eslint-disable-next-line no-param-reassign
321
+ const {
322
+ context,
323
+ hashSalt
324
+ } = options;
325
+ const {
326
+ resourcePath
327
+ } = loaderContext;
328
+ const relativeResourcePath = normalizePath(_path.default.relative(context, resourcePath)); // eslint-disable-next-line no-param-reassign
324
329
 
325
- options.content = `${relativeMatchResource}${relativeResourcePath}\x00${localName}`;
330
+ options.content = `${relativeResourcePath}\x00${localName}`;
326
331
  let {
327
332
  hashFunction,
328
333
  hashDigest,
329
334
  hashDigestLength
330
335
  } = options;
331
- const mathes = localIdentName.match(/\[(?:([^:\]]+):)?(?:(hash|contenthash|fullhash))(?::([a-z]+\d*))?(?::(\d+))?\]/i);
336
+ const matches = localIdentName.match(/\[(?:([^:\]]+):)?(?:(hash|contenthash|fullhash))(?::([a-z]+\d*))?(?::(\d+))?\]/i);
332
337
 
333
- if (mathes) {
334
- const hashName = mathes[2] || hashFunction;
335
- hashFunction = mathes[1] || hashFunction;
336
- hashDigest = mathes[3] || hashDigest;
337
- hashDigestLength = mathes[4] || hashDigestLength; // `hash` and `contenthash` are same in `loader-utils` context
338
+ if (matches) {
339
+ const hashName = matches[2] || hashFunction;
340
+ hashFunction = matches[1] || hashFunction;
341
+ hashDigest = matches[3] || hashDigest;
342
+ hashDigestLength = matches[4] || hashDigestLength; // `hash` and `contenthash` are same in `loader-utils` context
338
343
  // let's keep `hash` for backward compatibility
339
344
  // eslint-disable-next-line no-param-reassign
340
345
 
341
346
  localIdentName = localIdentName.replace(/\[(?:([^:\]]+):)?(?:hash|contenthash|fullhash)(?::([a-z]+\d*))?(?::(\d+))?\]/gi, () => hashName === "fullhash" ? "[fullhash]" : "[contenthash]");
342
- } // eslint-disable-next-line no-underscore-dangle
347
+ }
343
348
 
349
+ let localIdentHash = "";
344
350
 
345
- const hash = loaderContext._compiler.webpack.util.createHash(hashFunction);
351
+ for (let tier = 0; localIdentHash.length < hashDigestLength; tier++) {
352
+ // TODO remove this in the next major release
353
+ const hash = loaderContext.utils && typeof loaderContext.utils.createHash === "function" ? loaderContext.utils.createHash(hashFunction) : // eslint-disable-next-line no-underscore-dangle
354
+ loaderContext._compiler.webpack.util.createHash(hashFunction);
346
355
 
347
- const {
348
- hashSalt
349
- } = options;
356
+ if (hashSalt) {
357
+ hash.update(hashSalt);
358
+ }
350
359
 
351
- if (hashSalt) {
352
- hash.update(hashSalt);
353
- }
360
+ const tierSalt = Buffer.allocUnsafe(4);
361
+ tierSalt.writeUInt32LE(tier);
362
+ hash.update(tierSalt); // TODO: bug in webpack with unicode characters with strings
354
363
 
355
- hash.update(options.content);
356
- 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
364
+ hash.update(Buffer.from(options.content, "utf8"));
365
+ localIdentHash = (localIdentHash + hash.digest(hashDigest) // Remove all leading digits
366
+ ).replace(/^\d+/, "") // Replace all slashes with underscores (same as in base64url)
367
+ .replace(/\//g, "_") // Remove everything that is not an alphanumeric or underscore
368
+ .replace(/[^A-Za-z0-9_]+/g, "").slice(0, hashDigestLength);
369
+ } // 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
357
370
 
358
- const ext = _path.default.extname(loaderContext.resourcePath);
359
371
 
360
- const base = _path.default.basename(loaderContext.resourcePath);
372
+ const ext = _path.default.extname(resourcePath);
373
+
374
+ const base = _path.default.basename(resourcePath);
361
375
 
362
376
  const name = base.slice(0, base.length - ext.length);
363
377
  const data = {
364
- filename: _path.default.relative(options.context, loaderContext.resourcePath),
378
+ filename: _path.default.relative(context, resourcePath),
365
379
  contentHash: localIdentHash,
366
380
  chunk: {
367
381
  name,
@@ -372,8 +386,22 @@ function defaultGetLocalIdent(loaderContext, localIdentName, localName, options)
372
386
 
373
387
  let result = loaderContext._compilation.getPath(localIdentName, data);
374
388
 
389
+ if (/\[folder\]/gi.test(result)) {
390
+ const dirname = _path.default.dirname(resourcePath);
391
+
392
+ let directory = normalizePath(_path.default.relative(context, `${dirname + _path.default.sep}_`));
393
+ directory = directory.substr(0, directory.length - 1);
394
+ let folder = "";
395
+
396
+ if (directory.length > 1) {
397
+ folder = _path.default.basename(directory);
398
+ }
399
+
400
+ result = result.replace(/\[folder\]/gi, () => folder);
401
+ }
402
+
375
403
  if (options.regExp) {
376
- const match = loaderContext.resourcePath.match(options.regExp);
404
+ const match = resourcePath.match(options.regExp);
377
405
 
378
406
  if (match) {
379
407
  match.forEach((matched, i) => {
@@ -462,22 +490,14 @@ function getFilter(filter, resourcePath) {
462
490
  }
463
491
 
464
492
  function getValidLocalName(localName, exportLocalsConvention) {
465
- if (typeof exportLocalsConvention === "function") {
466
- const result = exportLocalsConvention(localName);
467
- return Array.isArray(result) ? result[0] : result;
468
- }
469
-
470
- if (exportLocalsConvention === "dashesOnly") {
471
- return dashesCamelCase(localName);
472
- }
473
-
474
- return camelCase(localName);
493
+ const result = exportLocalsConvention(localName);
494
+ return Array.isArray(result) ? result[0] : result;
475
495
  }
476
496
 
477
497
  const IS_MODULES = /\.module(s)?\.\w+$/i;
478
498
  const IS_ICSS = /\.icss\.\w+$/i;
479
499
 
480
- function getModulesOptions(rawOptions, loaderContext) {
500
+ function getModulesOptions(rawOptions, exportType, loaderContext) {
481
501
  if (typeof rawOptions.modules === "boolean" && rawOptions.modules === false) {
482
502
  return false;
483
503
  }
@@ -507,6 +527,7 @@ function getModulesOptions(rawOptions, loaderContext) {
507
527
  const {
508
528
  outputOptions
509
529
  } = loaderContext._compilation;
530
+ const needNamedExport = exportType === "css-style-sheet" || exportType === "string";
510
531
  const modulesOptions = {
511
532
  auto,
512
533
  mode: "local",
@@ -521,11 +542,44 @@ function getModulesOptions(rawOptions, loaderContext) {
521
542
  localIdentRegExp: undefined,
522
543
  // eslint-disable-next-line no-undefined
523
544
  getLocalIdent: undefined,
524
- namedExport: false,
525
- exportLocalsConvention: rawModulesOptions.namedExport === true && typeof rawModulesOptions.exportLocalsConvention === "undefined" ? "camelCaseOnly" : "asIs",
545
+ namedExport: needNamedExport || false,
546
+ exportLocalsConvention: (rawModulesOptions.namedExport === true || needNamedExport) && typeof rawModulesOptions.exportLocalsConvention === "undefined" ? "camelCaseOnly" : "asIs",
526
547
  exportOnlyLocals: false,
527
548
  ...rawModulesOptions
528
549
  };
550
+ let exportLocalsConventionType;
551
+
552
+ if (typeof modulesOptions.exportLocalsConvention === "string") {
553
+ exportLocalsConventionType = modulesOptions.exportLocalsConvention;
554
+
555
+ modulesOptions.exportLocalsConvention = name => {
556
+ switch (exportLocalsConventionType) {
557
+ case "camelCase":
558
+ {
559
+ return [name, camelCase(name)];
560
+ }
561
+
562
+ case "camelCaseOnly":
563
+ {
564
+ return camelCase(name);
565
+ }
566
+
567
+ case "dashes":
568
+ {
569
+ return [name, dashesCamelCase(name)];
570
+ }
571
+
572
+ case "dashesOnly":
573
+ {
574
+ return dashesCamelCase(name);
575
+ }
576
+
577
+ case "asIs":
578
+ default:
579
+ return name;
580
+ }
581
+ };
582
+ }
529
583
 
530
584
  if (typeof modulesOptions.auto === "boolean") {
531
585
  const isModules = modulesOptions.auto && IS_MODULES.test(resourcePath);
@@ -560,12 +614,22 @@ function getModulesOptions(rawOptions, loaderContext) {
560
614
  modulesOptions.mode = modulesOptions.mode(loaderContext.resourcePath);
561
615
  }
562
616
 
617
+ if (needNamedExport) {
618
+ if (rawOptions.esModule === false) {
619
+ throw new Error("The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'esModules' option to be enabled");
620
+ }
621
+
622
+ if (modulesOptions.namedExport === false) {
623
+ throw new Error("The 'exportType' option with the 'css-style-sheet' or 'string' value requires the 'modules.namedExport' option to be enabled");
624
+ }
625
+ }
626
+
563
627
  if (modulesOptions.namedExport === true) {
564
628
  if (rawOptions.esModule === false) {
565
- throw new Error('The "modules.namedExport" option requires the "esModules" option to be enabled');
629
+ throw new Error("The 'modules.namedExport' option requires the 'esModules' option to be enabled");
566
630
  }
567
631
 
568
- if (typeof modulesOptions.exportLocalsConvention === "string" && modulesOptions.exportLocalsConvention !== "camelCaseOnly" && modulesOptions.exportLocalsConvention !== "dashesOnly") {
632
+ if (typeof exportLocalsConventionType === "string" && exportLocalsConventionType !== "camelCaseOnly" && exportLocalsConventionType !== "dashesOnly") {
569
633
  throw new Error('The "modules.namedExport" option requires the "modules.exportLocalsConvention" option to be "camelCaseOnly" or "dashesOnly"');
570
634
  }
571
635
  }
@@ -574,14 +638,16 @@ function getModulesOptions(rawOptions, loaderContext) {
574
638
  }
575
639
 
576
640
  function normalizeOptions(rawOptions, loaderContext) {
577
- const modulesOptions = getModulesOptions(rawOptions, loaderContext);
641
+ const exportType = typeof rawOptions.exportType === "undefined" ? "array" : rawOptions.exportType;
642
+ const modulesOptions = getModulesOptions(rawOptions, exportType, loaderContext);
578
643
  return {
579
644
  url: typeof rawOptions.url === "undefined" ? true : rawOptions.url,
580
645
  import: typeof rawOptions.import === "undefined" ? true : rawOptions.import,
581
646
  modules: modulesOptions,
582
647
  sourceMap: typeof rawOptions.sourceMap === "boolean" ? rawOptions.sourceMap : loaderContext.sourceMap,
583
648
  importLoaders: typeof rawOptions.importLoaders === "string" ? parseInt(rawOptions.importLoaders, 10) : rawOptions.importLoaders,
584
- esModule: typeof rawOptions.esModule === "undefined" ? true : rawOptions.esModule
649
+ esModule: typeof rawOptions.esModule === "undefined" ? true : rawOptions.esModule,
650
+ exportType
585
651
  };
586
652
  }
587
653
 
@@ -785,6 +851,13 @@ function normalizeSourceMapForRuntime(map, loaderContext) {
785
851
 
786
852
  if (resultMap) {
787
853
  delete resultMap.file;
854
+ /* eslint-disable no-underscore-dangle */
855
+
856
+ if (loaderContext._compilation && loaderContext._compilation.options && loaderContext._compilation.options.devtool && loaderContext._compilation.options.devtool.includes("nosources")) {
857
+ /* eslint-enable no-underscore-dangle */
858
+ delete resultMap.sourcesContent;
859
+ }
860
+
788
861
  resultMap.sourceRoot = "";
789
862
  resultMap.sources = resultMap.sources.map(source => {
790
863
  // Non-standard syntax from `postcss`
@@ -810,22 +883,66 @@ function normalizeSourceMapForRuntime(map, loaderContext) {
810
883
  return JSON.stringify(resultMap);
811
884
  }
812
885
 
886
+ function printParams(media, dedupe, supports, layer) {
887
+ let result = "";
888
+
889
+ if (typeof layer !== "undefined") {
890
+ result = `, ${JSON.stringify(layer)}`;
891
+ }
892
+
893
+ if (typeof supports !== "undefined") {
894
+ result = `, ${JSON.stringify(supports)}${result}`;
895
+ } else if (result.length > 0) {
896
+ result = `, undefined${result}`;
897
+ }
898
+
899
+ if (dedupe) {
900
+ result = `, true${result}`;
901
+ } else if (result.length > 0) {
902
+ result = `, false${result}`;
903
+ }
904
+
905
+ if (media) {
906
+ result = `${JSON.stringify(media)}${result}`;
907
+ } else if (result.length > 0) {
908
+ result = `""${result}`;
909
+ }
910
+
911
+ return result;
912
+ }
913
+
813
914
  function getModuleCode(result, api, replacements, options, loaderContext) {
814
915
  if (options.modules.exportOnlyLocals === true) {
815
916
  return "";
816
917
  }
817
918
 
818
- const sourceMapValue = options.sourceMap ? `,${normalizeSourceMapForRuntime(result.map, loaderContext)}` : "";
919
+ let sourceMapValue = "";
920
+
921
+ if (options.sourceMap) {
922
+ const sourceMap = result.map;
923
+ sourceMapValue = `,${normalizeSourceMapForRuntime(sourceMap, loaderContext)}`;
924
+ }
925
+
819
926
  let code = JSON.stringify(result.css);
820
- let beforeCode = `var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(${options.sourceMap ? "___CSS_LOADER_API_SOURCEMAP_IMPORT___" : "function(i){return i[1]}"});\n`;
927
+ let beforeCode = `var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(${options.sourceMap ? "___CSS_LOADER_API_SOURCEMAP_IMPORT___" : "___CSS_LOADER_API_NO_SOURCEMAP_IMPORT___"});\n`;
821
928
 
822
929
  for (const item of api) {
823
930
  const {
824
931
  url,
932
+ layer,
933
+ supports,
825
934
  media,
826
935
  dedupe
827
936
  } = item;
828
- 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`;
937
+
938
+ if (url) {
939
+ // eslint-disable-next-line no-undefined
940
+ const printedParam = printParams(media, undefined, supports, layer);
941
+ beforeCode += `___CSS_LOADER_EXPORT___.push([module.id, ${JSON.stringify(`@import url(${url});`)}${printedParam.length > 0 ? `, ${printedParam}` : ""}]);\n`;
942
+ } else {
943
+ const printedParam = printParams(media, dedupe, supports, layer);
944
+ beforeCode += `___CSS_LOADER_EXPORT___.i(${item.importName}${printedParam.length > 0 ? `, ${printedParam}` : ""});\n`;
945
+ }
829
946
  }
830
947
 
831
948
  for (const item of replacements) {
@@ -847,7 +964,14 @@ function getModuleCode(result, api, replacements, options, loaderContext) {
847
964
  beforeCode += `var ${replacementName} = ___CSS_LOADER_GET_URL_IMPORT___(${importName}${preparedOptions});\n`;
848
965
  code = code.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`);
849
966
  }
850
- }
967
+ } // Indexes description:
968
+ // 0 - module id
969
+ // 1 - CSS code
970
+ // 2 - media
971
+ // 3 - source map
972
+ // 4 - supports
973
+ // 5 - layer
974
+
851
975
 
852
976
  return `${beforeCode}// Module\n___CSS_LOADER_EXPORT___.push([module.id, ${code}, ""${sourceMapValue}]);\n`;
853
977
  }
@@ -856,107 +980,92 @@ function dashesCamelCase(str) {
856
980
  return str.replace(/-+(\w)/g, (match, firstLetter) => firstLetter.toUpperCase());
857
981
  }
858
982
 
859
- function getExportCode(exports, replacements, needToUseIcssPlugin, options) {
983
+ function getExportCode(exports, replacements, icssPluginUsed, options) {
860
984
  let code = "// Exports\n";
861
985
 
862
- if (!needToUseIcssPlugin) {
863
- code += `${options.esModule ? "export default" : "module.exports ="} ___CSS_LOADER_EXPORT___;\n`;
864
- return code;
865
- }
986
+ if (icssPluginUsed) {
987
+ let localsCode = "";
866
988
 
867
- let localsCode = "";
989
+ const addExportToLocalsCode = (names, value) => {
990
+ const normalizedNames = Array.isArray(names) ? new Set(names) : new Set([names]);
868
991
 
869
- const addExportToLocalsCode = (names, value) => {
870
- const normalizedNames = Array.isArray(names) ? new Set(names) : new Set([names]);
992
+ for (const name of normalizedNames) {
993
+ if (options.modules.namedExport) {
994
+ localsCode += `export var ${name} = ${JSON.stringify(value)};\n`;
995
+ } else {
996
+ if (localsCode) {
997
+ localsCode += `,\n`;
998
+ }
871
999
 
872
- for (const name of normalizedNames) {
873
- if (options.modules.namedExport) {
874
- localsCode += `export var ${name} = ${JSON.stringify(value)};\n`;
875
- } else {
876
- if (localsCode) {
877
- localsCode += `,\n`;
1000
+ localsCode += `\t${JSON.stringify(name)}: ${JSON.stringify(value)}`;
878
1001
  }
879
-
880
- localsCode += `\t${JSON.stringify(name)}: ${JSON.stringify(value)}`;
881
1002
  }
1003
+ };
1004
+
1005
+ for (const {
1006
+ name,
1007
+ value
1008
+ } of exports) {
1009
+ addExportToLocalsCode(options.modules.exportLocalsConvention(name), value);
882
1010
  }
883
- };
884
1011
 
885
- for (const {
886
- name,
887
- value
888
- } of exports) {
889
- if (typeof options.modules.exportLocalsConvention === "function") {
890
- addExportToLocalsCode(options.modules.exportLocalsConvention(name), value); // eslint-disable-next-line no-continue
1012
+ for (const item of replacements) {
1013
+ const {
1014
+ replacementName,
1015
+ localName
1016
+ } = item;
891
1017
 
892
- continue;
1018
+ if (localName) {
1019
+ const {
1020
+ importName
1021
+ } = item;
1022
+ localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => {
1023
+ if (options.modules.namedExport) {
1024
+ return `" + ${importName}_NAMED___[${JSON.stringify(getValidLocalName(localName, options.modules.exportLocalsConvention))}] + "`;
1025
+ } else if (options.modules.exportOnlyLocals) {
1026
+ return `" + ${importName}[${JSON.stringify(localName)}] + "`;
1027
+ }
1028
+
1029
+ return `" + ${importName}.locals[${JSON.stringify(localName)}] + "`;
1030
+ });
1031
+ } else {
1032
+ localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`);
1033
+ }
893
1034
  }
894
1035
 
895
- switch (options.modules.exportLocalsConvention) {
896
- case "camelCase":
897
- {
898
- const modifiedName = camelCase(name);
899
- addExportToLocalsCode([name, modifiedName], value);
900
- break;
901
- }
902
-
903
- case "camelCaseOnly":
904
- {
905
- addExportToLocalsCode(camelCase(name), value);
906
- break;
907
- }
1036
+ if (options.modules.exportOnlyLocals) {
1037
+ code += options.modules.namedExport ? localsCode : `${options.esModule ? "export default" : "module.exports ="} {\n${localsCode}\n};\n`;
1038
+ return code;
1039
+ }
908
1040
 
909
- case "dashes":
910
- {
911
- const modifiedName = dashesCamelCase(name);
912
- addExportToLocalsCode([name, modifiedName], value);
913
- break;
914
- }
1041
+ code += options.modules.namedExport ? localsCode : `___CSS_LOADER_EXPORT___.locals = {${localsCode ? `\n${localsCode}\n` : ""}};\n`;
1042
+ }
915
1043
 
916
- case "dashesOnly":
917
- {
918
- addExportToLocalsCode(dashesCamelCase(name), value);
919
- break;
920
- }
1044
+ const isCSSStyleSheetExport = options.exportType === "css-style-sheet";
921
1045
 
922
- case "asIs":
923
- default:
924
- addExportToLocalsCode(name, value);
925
- break;
926
- }
1046
+ if (isCSSStyleSheetExport) {
1047
+ code += "var ___CSS_LOADER_STYLE_SHEET___ = new CSSStyleSheet();\n";
1048
+ code += "___CSS_LOADER_STYLE_SHEET___.replaceSync(___CSS_LOADER_EXPORT___.toString());\n";
927
1049
  }
928
1050
 
929
- for (const item of replacements) {
930
- const {
931
- replacementName,
932
- localName
933
- } = item;
1051
+ let finalExport;
934
1052
 
935
- if (localName) {
936
- const {
937
- importName
938
- } = item;
939
- localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => {
940
- if (options.modules.namedExport) {
941
- return `" + ${importName}_NAMED___[${JSON.stringify(getValidLocalName(localName, options.modules.exportLocalsConvention))}] + "`;
942
- } else if (options.modules.exportOnlyLocals) {
943
- return `" + ${importName}[${JSON.stringify(localName)}] + "`;
944
- }
1053
+ switch (options.exportType) {
1054
+ case "string":
1055
+ finalExport = "___CSS_LOADER_EXPORT___.toString()";
1056
+ break;
945
1057
 
946
- return `" + ${importName}.locals[${JSON.stringify(localName)}] + "`;
947
- });
948
- } else {
949
- localsCode = localsCode.replace(new RegExp(replacementName, "g"), () => `" + ${replacementName} + "`);
950
- }
951
- }
1058
+ case "css-style-sheet":
1059
+ finalExport = "___CSS_LOADER_STYLE_SHEET___";
1060
+ break;
952
1061
 
953
- if (options.modules.exportOnlyLocals) {
954
- code += options.modules.namedExport ? localsCode : `${options.esModule ? "export default" : "module.exports ="} {\n${localsCode}\n};\n`;
955
- return code;
1062
+ default:
1063
+ case "array":
1064
+ finalExport = "___CSS_LOADER_EXPORT___";
1065
+ break;
956
1066
  }
957
1067
 
958
- code += options.modules.namedExport ? localsCode : `___CSS_LOADER_EXPORT___.locals = {${localsCode ? `\n${localsCode}\n` : ""}};\n`;
959
- code += `${options.esModule ? "export default" : "module.exports ="} ___CSS_LOADER_EXPORT___;\n`;
1068
+ code += `${options.esModule ? "export default" : "module.exports ="} ${finalExport};\n`;
960
1069
  return code;
961
1070
  }
962
1071
 
@@ -972,28 +1081,67 @@ async function resolveRequests(resolve, context, possibleRequests) {
972
1081
  });
973
1082
  }
974
1083
 
975
- function isUrlRequestable(url) {
1084
+ function isURLRequestable(url, options = {}) {
976
1085
  // Protocol-relative URLs
977
1086
  if (/^\/\//.test(url)) {
978
- return false;
1087
+ return {
1088
+ requestable: false,
1089
+ needResolve: false
1090
+ };
1091
+ } // `#` URLs
1092
+
1093
+
1094
+ if (/^#/.test(url)) {
1095
+ return {
1096
+ requestable: false,
1097
+ needResolve: false
1098
+ };
1099
+ } // Data URI
1100
+
1101
+
1102
+ if (isDataUrl(url) && options.isSupportDataURL) {
1103
+ try {
1104
+ decodeURIComponent(url);
1105
+ } catch (ignoreError) {
1106
+ return {
1107
+ requestable: false,
1108
+ needResolve: false
1109
+ };
1110
+ }
1111
+
1112
+ return {
1113
+ requestable: true,
1114
+ needResolve: false
1115
+ };
979
1116
  } // `file:` protocol
980
1117
 
981
1118
 
982
1119
  if (/^file:/i.test(url)) {
983
- return true;
1120
+ return {
1121
+ requestable: true,
1122
+ needResolve: true
1123
+ };
984
1124
  } // Absolute URLs
985
1125
 
986
1126
 
987
1127
  if (/^[a-z][a-z0-9+.-]*:/i.test(url) && !NATIVE_WIN32_PATH.test(url)) {
988
- return false;
989
- } // `#` URLs
990
-
1128
+ if (options.isSupportAbsoluteURL && /^https?:/i.test(url)) {
1129
+ return {
1130
+ requestable: true,
1131
+ needResolve: false
1132
+ };
1133
+ }
991
1134
 
992
- if (/^#/.test(url)) {
993
- return false;
1135
+ return {
1136
+ requestable: false,
1137
+ needResolve: false
1138
+ };
994
1139
  }
995
1140
 
996
- return true;
1141
+ return {
1142
+ requestable: true,
1143
+ needResolve: true
1144
+ };
997
1145
  }
998
1146
 
999
1147
  function sort(a, b) {