css-loader 2.0.2 → 3.1.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.
@@ -9,112 +9,167 @@ var _postcss = _interopRequireDefault(require("postcss"));
9
9
 
10
10
  var _postcssValueParser = _interopRequireDefault(require("postcss-value-parser"));
11
11
 
12
+ var _utils = require("../utils");
13
+
12
14
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
15
 
14
16
  const pluginName = 'postcss-url-parser';
17
+ const isUrlFunc = /url/i;
18
+ const isImageSetFunc = /^(?:-webkit-)?image-set$/i;
19
+ const needParseDecl = /(?:url|(?:-webkit-)?image-set)\(/i;
20
+
21
+ function getNodeFromUrlFunc(node) {
22
+ return node.nodes && node.nodes[0];
23
+ }
15
24
 
16
- function getArg(nodes) {
17
- return nodes.length !== 0 && nodes[0].type === 'string' ? nodes[0].value : _postcssValueParser.default.stringify(nodes);
25
+ function getUrlFromUrlFunc(node) {
26
+ return node.nodes.length !== 0 && node.nodes[0].type === 'string' ? node.nodes[0].value : _postcssValueParser.default.stringify(node.nodes);
18
27
  }
19
28
 
20
29
  function walkUrls(parsed, callback) {
21
30
  parsed.walk(node => {
22
- if (node.type !== 'function' || node.value.toLowerCase() !== 'url') {
31
+ if (node.type !== 'function') {
23
32
  return;
24
33
  }
25
- /* eslint-disable */
26
34
 
35
+ if (isUrlFunc.test(node.value)) {
36
+ callback(getNodeFromUrlFunc(node), getUrlFromUrlFunc(node), false); // Do not traverse inside `url`
37
+ // eslint-disable-next-line consistent-return
27
38
 
28
- node.before = '';
29
- node.after = '';
30
- /* eslint-enable */
39
+ return false;
40
+ }
41
+
42
+ if (isImageSetFunc.test(node.value)) {
43
+ node.nodes.forEach(nNode => {
44
+ if (nNode.type === 'function' && isUrlFunc.test(nNode.value)) {
45
+ callback(getNodeFromUrlFunc(nNode), getUrlFromUrlFunc(nNode), false);
46
+ }
31
47
 
32
- callback(node, getArg(node.nodes)); // Do not traverse inside url
33
- // eslint-disable-next-line consistent-return
48
+ if (nNode.type === 'string') {
49
+ callback(nNode, nNode.value, true);
50
+ }
51
+ }); // Do not traverse inside `image-set`
52
+ // eslint-disable-next-line consistent-return
34
53
 
35
- return false;
54
+ return false;
55
+ }
36
56
  });
37
57
  }
38
58
 
39
- function walkDeclsWithUrl(css, result, filter) {
40
- const items = [];
41
- css.walkDecls(decl => {
42
- if (!/url\(/i.test(decl.value)) {
59
+ function getUrlsFromValue(value, result, filter, decl = null) {
60
+ if (!needParseDecl.test(value)) {
61
+ return;
62
+ }
63
+
64
+ const parsed = (0, _postcssValueParser.default)(value);
65
+ const urls = [];
66
+ walkUrls(parsed, (node, url, needQuotes) => {
67
+ if (url.trim().replace(/\\[\r\n]/g, '').length === 0) {
68
+ result.warn(`Unable to find uri in '${decl ? decl.toString() : value}'`, decl ? {
69
+ node: decl
70
+ } : {});
43
71
  return;
44
72
  }
45
73
 
46
- const parsed = (0, _postcssValueParser.default)(decl.value);
47
- const urls = [];
48
- walkUrls(parsed, (node, url) => {
49
- if (url.trim().replace(/\\[\r\n]/g, '').length === 0) {
50
- result.warn(`Unable to find uri in '${decl.toString()}'`, {
51
- node: decl
52
- });
53
- return;
54
- }
55
-
56
- if (filter && !filter(url)) {
57
- return;
58
- }
74
+ if (filter && !filter(url)) {
75
+ return;
76
+ }
59
77
 
60
- urls.push(url);
78
+ urls.push({
79
+ url,
80
+ needQuotes
61
81
  });
82
+ }); // eslint-disable-next-line consistent-return
83
+
84
+ return {
85
+ parsed,
86
+ urls
87
+ };
88
+ }
62
89
 
63
- if (urls.length === 0) {
90
+ function walkDeclsWithUrl(css, result, filter) {
91
+ const items = [];
92
+ css.walkDecls(decl => {
93
+ const item = getUrlsFromValue(decl.value, result, filter, decl);
94
+
95
+ if (!item) {
96
+ return;
97
+ }
98
+
99
+ if (item.urls.length === 0) {
64
100
  return;
65
101
  }
66
102
 
67
103
  items.push({
68
104
  decl,
69
- parsed,
70
- urls
105
+ parsed: item.parsed,
106
+ urls: item.urls
71
107
  });
72
108
  });
73
109
  return items;
74
110
  }
75
111
 
76
- function flatten(array) {
77
- return array.reduce((acc, d) => [...acc, ...d], []);
78
- }
79
-
80
- function uniq(array) {
81
- return array.reduce((acc, d) => acc.indexOf(d) === -1 ? [...acc, d] : acc, []);
82
- }
83
-
84
112
  var _default = _postcss.default.plugin(pluginName, (options = {}) => function process(css, result) {
85
113
  const traversed = walkDeclsWithUrl(css, result, options.filter);
86
- const paths = uniq(flatten(traversed.map(item => item.urls)));
114
+ const paths = (0, _utils.uniqWith)((0, _utils.flatten)(traversed.map(item => item.urls)), (value, other) => value.url === other.url && value.needQuotes === other.needQuotes);
87
115
 
88
116
  if (paths.length === 0) {
89
117
  return;
90
118
  }
91
119
 
92
- const urls = {};
120
+ const placeholders = [];
121
+ let hasUrlHelper = false;
93
122
  paths.forEach((path, index) => {
123
+ const {
124
+ loaderContext
125
+ } = options;
94
126
  const placeholder = `___CSS_LOADER_URL___${index}___`;
95
- urls[path] = placeholder;
127
+ const {
128
+ url,
129
+ needQuotes
130
+ } = path;
131
+ placeholders.push({
132
+ placeholder,
133
+ path
134
+ });
135
+
136
+ if (!hasUrlHelper) {
137
+ result.messages.push({
138
+ pluginName,
139
+ type: 'import',
140
+ import: (0, _utils.getUrlHelperCode)(loaderContext)
141
+ }); // eslint-disable-next-line no-param-reassign
142
+
143
+ hasUrlHelper = true;
144
+ }
145
+
96
146
  result.messages.push({
97
147
  pluginName,
98
- type: 'url',
99
- item: {
100
- url: path,
101
- placeholder
102
- }
148
+ type: 'import',
149
+ import: (0, _utils.getUrlItemCode)({
150
+ url,
151
+ placeholder,
152
+ needQuotes
153
+ }, loaderContext),
154
+ importType: 'url',
155
+ placeholder
103
156
  });
104
157
  });
105
158
  traversed.forEach(item => {
106
- walkUrls(item.parsed, (node, url) => {
107
- const value = urls[url];
159
+ walkUrls(item.parsed, (node, url, needQuotes) => {
160
+ const value = placeholders.find(placeholder => placeholder.path.url === url && placeholder.path.needQuotes === needQuotes);
108
161
 
109
162
  if (!value) {
110
163
  return;
111
- } // eslint-disable-next-line no-param-reassign
164
+ }
165
+
166
+ const {
167
+ placeholder
168
+ } = value; // eslint-disable-next-line no-param-reassign
112
169
 
170
+ node.type = 'word'; // eslint-disable-next-line no-param-reassign
113
171
 
114
- node.nodes = [{
115
- type: 'word',
116
- value
117
- }];
172
+ node.value = placeholder;
118
173
  }); // eslint-disable-next-line no-param-reassign
119
174
 
120
175
  item.decl.value = item.parsed.toString();
@@ -5,6 +5,7 @@
5
5
  Author Tobias Koppers @sokra
6
6
  */
7
7
  // css base code, injected by the css-loader
8
+ // eslint-disable-next-line func-names
8
9
  module.exports = function (useSourceMap) {
9
10
  var list = []; // return the list of modules as css string
10
11
 
@@ -13,22 +14,25 @@ module.exports = function (useSourceMap) {
13
14
  var content = cssWithMappingToString(item, useSourceMap);
14
15
 
15
16
  if (item[2]) {
16
- return '@media ' + item[2] + '{' + content + '}';
17
- } else {
18
- return content;
17
+ return "@media ".concat(item[2], "{").concat(content, "}");
19
18
  }
19
+
20
+ return content;
20
21
  }).join('');
21
22
  }; // import a list of modules into the list
23
+ // eslint-disable-next-line func-names
22
24
 
23
25
 
24
26
  list.i = function (modules, mediaQuery) {
25
27
  if (typeof modules === 'string') {
28
+ // eslint-disable-next-line no-param-reassign
26
29
  modules = [[null, modules, '']];
27
30
  }
28
31
 
29
32
  var alreadyImportedModules = {};
30
33
 
31
34
  for (var i = 0; i < this.length; i++) {
35
+ // eslint-disable-next-line prefer-destructuring
32
36
  var id = this[i][0];
33
37
 
34
38
  if (id != null) {
@@ -36,8 +40,8 @@ module.exports = function (useSourceMap) {
36
40
  }
37
41
  }
38
42
 
39
- for (i = 0; i < modules.length; i++) {
40
- var item = modules[i]; // skip already imported module
43
+ for (var _i = 0; _i < modules.length; _i++) {
44
+ var item = modules[_i]; // skip already imported module
41
45
  // this implementation is not 100% perfect for weird media query combinations
42
46
  // when a module is imported multiple times with different media queries.
43
47
  // I hope this will never occur (Hey this way we have smaller bundles)
@@ -46,7 +50,7 @@ module.exports = function (useSourceMap) {
46
50
  if (mediaQuery && !item[2]) {
47
51
  item[2] = mediaQuery;
48
52
  } else if (mediaQuery) {
49
- item[2] = '(' + item[2] + ') and (' + mediaQuery + ')';
53
+ item[2] = "(".concat(item[2], ") and (").concat(mediaQuery, ")");
50
54
  }
51
55
 
52
56
  list.push(item);
@@ -58,7 +62,8 @@ module.exports = function (useSourceMap) {
58
62
  };
59
63
 
60
64
  function cssWithMappingToString(item, useSourceMap) {
61
- var content = item[1] || '';
65
+ var content = item[1] || ''; // eslint-disable-next-line prefer-destructuring
66
+
62
67
  var cssMapping = item[3];
63
68
 
64
69
  if (!cssMapping) {
@@ -68,7 +73,7 @@ function cssWithMappingToString(item, useSourceMap) {
68
73
  if (useSourceMap && typeof btoa === 'function') {
69
74
  var sourceMapping = toComment(cssMapping);
70
75
  var sourceURLs = cssMapping.sources.map(function (source) {
71
- return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */';
76
+ return "/*# sourceURL=".concat(cssMapping.sourceRoot).concat(source, " */");
72
77
  });
73
78
  return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
74
79
  }
@@ -80,6 +85,6 @@ function cssWithMappingToString(item, useSourceMap) {
80
85
  function toComment(sourceMap) {
81
86
  // eslint-disable-next-line no-undef
82
87
  var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
83
- var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
84
- return '/*# ' + data + ' */';
88
+ var data = "sourceMappingURL=data:application/json;charset=utf-8;base64,".concat(base64);
89
+ return "/*# ".concat(data, " */");
85
90
  }
@@ -1,19 +1,20 @@
1
1
  "use strict";
2
2
 
3
- module.exports = function escape(url) {
3
+ module.exports = function (url, needQuotes) {
4
4
  if (typeof url !== 'string') {
5
5
  return url;
6
6
  } // If url is already wrapped in quotes, remove them
7
7
 
8
8
 
9
9
  if (/^['"].*['"]$/.test(url)) {
10
+ // eslint-disable-next-line no-param-reassign
10
11
  url = url.slice(1, -1);
11
12
  } // Should url be wrapped?
12
13
  // See https://drafts.csswg.org/css-values-3/#urls
13
14
 
14
15
 
15
- if (/["'() \t\n]/.test(url)) {
16
- return '"' + url.replace(/"/g, '\\"').replace(/\n/g, '\\n') + '"';
16
+ if (/["'() \t\n]/.test(url) || needQuotes) {
17
+ return "\"".concat(url.replace(/"/g, '\\"').replace(/\n/g, '\\n'), "\"");
17
18
  }
18
19
 
19
20
  return url;
package/dist/utils.js CHANGED
@@ -3,15 +3,43 @@
3
3
  Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
+ exports.uniqWith = uniqWith;
7
+ exports.flatten = flatten;
8
+ exports.dashesCamelCase = dashesCamelCase;
6
9
  exports.getImportPrefix = getImportPrefix;
7
10
  exports.getLocalIdent = getLocalIdent;
8
- exports.dashesCamelCase = dashesCamelCase;
9
11
  exports.getFilter = getFilter;
10
- exports.placholderRegExps = void 0;
12
+ exports.getModulesPlugins = getModulesPlugins;
13
+ exports.normalizeSourceMap = normalizeSourceMap;
14
+ exports.getImportItemCode = getImportItemCode;
15
+ exports.getUrlHelperCode = getUrlHelperCode;
16
+ exports.getUrlItemCode = getUrlItemCode;
17
+ exports.getApiCode = getApiCode;
18
+ exports.getImportCode = getImportCode;
19
+ exports.getModuleCode = getModuleCode;
20
+ exports.getExportItemCode = getExportItemCode;
21
+ exports.getExportCode = getExportCode;
22
+ exports.prepareCode = prepareCode;
11
23
 
12
24
  var _path = _interopRequireDefault(require("path"));
13
25
 
14
- var _loaderUtils = _interopRequireDefault(require("loader-utils"));
26
+ var _loaderUtils = _interopRequireWildcard(require("loader-utils"));
27
+
28
+ var _normalizePath = _interopRequireDefault(require("normalize-path"));
29
+
30
+ var _cssesc = _interopRequireDefault(require("cssesc"));
31
+
32
+ var _postcssModulesValues = _interopRequireDefault(require("postcss-modules-values"));
33
+
34
+ var _postcssModulesLocalByDefault = _interopRequireDefault(require("postcss-modules-local-by-default"));
35
+
36
+ var _postcssModulesExtractImports = _interopRequireDefault(require("postcss-modules-extract-imports"));
37
+
38
+ var _postcssModulesScope = _interopRequireDefault(require("postcss-modules-scope"));
39
+
40
+ var _camelcase = _interopRequireDefault(require("camelcase"));
41
+
42
+ function _interopRequireWildcard(obj) { if (obj && obj.__esModule) { return obj; } else { var newObj = {}; if (obj != null) { for (var key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { var desc = Object.defineProperty && Object.getOwnPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : {}; if (desc.get || desc.set) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } } newObj.default = obj; return newObj; } }
15
43
 
16
44
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
17
45
 
@@ -19,11 +47,17 @@ function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { de
19
47
  MIT License http://www.opensource.org/licenses/mit-license.php
20
48
  Author Tobias Koppers @sokra
21
49
  */
22
- const placholderRegExps = {
23
- importItemG: /___CSS_LOADER_IMPORT___([0-9]+)___/g,
24
- importItem: /___CSS_LOADER_IMPORT___([0-9]+)___/
25
- };
26
- exports.placholderRegExps = placholderRegExps;
50
+ function uniqWith(array, comparator) {
51
+ return array.reduce((acc, d) => !acc.some(item => comparator(d, item)) ? [...acc, d] : acc, []);
52
+ }
53
+
54
+ function flatten(array) {
55
+ return array.reduce((a, b) => a.concat(b), []);
56
+ }
57
+
58
+ function dashesCamelCase(str) {
59
+ return str.replace(/-+(\w)/g, (match, firstLetter) => firstLetter.toUpperCase());
60
+ }
27
61
 
28
62
  function getImportPrefix(loaderContext, importLoaders) {
29
63
  if (importLoaders === false) {
@@ -35,9 +69,30 @@ function getImportPrefix(loaderContext, importLoaders) {
35
69
  return `-!${loadersRequest}!`;
36
70
  }
37
71
 
38
- function dashesCamelCase(str) {
39
- return str.replace(/-+(\w)/g, (match, firstLetter) => firstLetter.toUpperCase());
40
- }
72
+ const whitespace = '[\\x20\\t\\r\\n\\f]';
73
+ const unescapeRegExp = new RegExp(`\\\\([\\da-f]{1,6}${whitespace}?|(${whitespace})|.)`, 'ig');
74
+
75
+ function unescape(str) {
76
+ return str.replace(unescapeRegExp, (_, escaped, escapedWhitespace) => {
77
+ const high = `0x${escaped}` - 0x10000;
78
+ /* eslint-disable line-comment-position */
79
+ // NaN means non-codepoint
80
+ // Workaround erroneous numeric interpretation of +"0x"
81
+ // eslint-disable-next-line no-self-compare
82
+
83
+ return high !== high || escapedWhitespace ? escaped : high < 0 ? // BMP codepoint
84
+ String.fromCharCode(high + 0x10000) : // Supplemental Plane codepoint (surrogate pair)
85
+ // eslint-disable-next-line no-bitwise
86
+ String.fromCharCode(high >> 10 | 0xd800, high & 0x3ff | 0xdc00);
87
+ /* eslint-enable line-comment-position */
88
+ });
89
+ } // eslint-disable-next-line no-control-regex
90
+
91
+
92
+ const filenameReservedRegex = /[<>:"/\\|?*\x00-\x1F]/g; // eslint-disable-next-line no-control-regex
93
+
94
+ const reControlChars = /[\u0000-\u001f\u0080-\u009f]/g;
95
+ const reRelativePath = /^\.+/;
41
96
 
42
97
  function getLocalIdent(loaderContext, localIdentName, localName, options) {
43
98
  if (!options.context) {
@@ -45,28 +100,246 @@ function getLocalIdent(loaderContext, localIdentName, localName, options) {
45
100
  options.context = loaderContext.rootContext;
46
101
  }
47
102
 
48
- const request = _path.default.relative(options.context, loaderContext.resourcePath).replace(/\\/g, '/'); // eslint-disable-next-line no-param-reassign
49
-
103
+ const request = (0, _normalizePath.default)(_path.default.relative(options.context || '', loaderContext.resourcePath)); // eslint-disable-next-line no-param-reassign
50
104
 
51
- options.content = `${options.hashPrefix + request}+${localName}`; // eslint-disable-next-line no-param-reassign
105
+ options.content = `${options.hashPrefix + request}+${unescape(localName)}`; // Using `[path]` placeholder outputs `/` we need escape their
106
+ // Also directories can contains invalid characters for css we need escape their too
52
107
 
53
- localIdentName = localIdentName.replace(/\[local\]/gi, localName);
54
-
55
- const hash = _loaderUtils.default.interpolateName(loaderContext, localIdentName, options);
56
-
57
- return hash.replace(new RegExp('[^a-zA-Z0-9\\-_\u00A0-\uFFFF]', 'g'), '-').replace(/^((-?[0-9])|--)/, '_$1');
108
+ return (0, _cssesc.default)(_loaderUtils.default.interpolateName(loaderContext, localIdentName, options) // For `[hash]` placeholder
109
+ .replace(/^((-?[0-9])|--)/, '_$1').replace(filenameReservedRegex, '-').replace(reControlChars, '-').replace(reRelativePath, '-'), {
110
+ isIdentifier: true
111
+ }).replace(/\\\[local\\\]/gi, localName);
58
112
  }
59
113
 
60
114
  function getFilter(filter, resourcePath, defaultFilter = null) {
61
- return content => {
62
- if (defaultFilter && !defaultFilter(content)) {
115
+ return item => {
116
+ if (defaultFilter && !defaultFilter(item)) {
63
117
  return false;
64
118
  }
65
119
 
66
120
  if (typeof filter === 'function') {
67
- return !filter(content, resourcePath);
121
+ return filter(item, resourcePath);
68
122
  }
69
123
 
70
124
  return true;
71
125
  };
126
+ }
127
+
128
+ function getModulesPlugins(options, loaderContext) {
129
+ let modulesOptions = {
130
+ mode: 'local',
131
+ localIdentName: '[hash:base64]',
132
+ getLocalIdent,
133
+ hashPrefix: '',
134
+ localIdentRegExp: null
135
+ };
136
+
137
+ if (typeof options.modules === 'boolean' || typeof options.modules === 'string') {
138
+ modulesOptions.mode = typeof options.modules === 'string' ? options.modules : 'local';
139
+ } else {
140
+ modulesOptions = Object.assign({}, modulesOptions, options.modules);
141
+ }
142
+
143
+ return [_postcssModulesValues.default, (0, _postcssModulesLocalByDefault.default)({
144
+ mode: modulesOptions.mode
145
+ }), (0, _postcssModulesExtractImports.default)(), (0, _postcssModulesScope.default)({
146
+ generateScopedName: function generateScopedName(exportName) {
147
+ let localIdent = modulesOptions.getLocalIdent(loaderContext, modulesOptions.localIdentName, exportName, {
148
+ context: modulesOptions.context,
149
+ hashPrefix: modulesOptions.hashPrefix,
150
+ regExp: modulesOptions.localIdentRegExp
151
+ });
152
+
153
+ if (!localIdent) {
154
+ localIdent = getLocalIdent(loaderContext, modulesOptions.localIdentName, exportName, {
155
+ context: modulesOptions.context,
156
+ hashPrefix: modulesOptions.hashPrefix,
157
+ regExp: modulesOptions.localIdentRegExp
158
+ });
159
+ }
160
+
161
+ return localIdent;
162
+ }
163
+ })];
164
+ }
165
+
166
+ function normalizeSourceMap(map) {
167
+ let newMap = map; // Some loader emit source map as string
168
+ // Strip any JSON XSSI avoidance prefix from the string (as documented in the source maps specification), and then parse the string as JSON.
169
+
170
+ if (typeof newMap === 'string') {
171
+ newMap = JSON.parse(newMap.replace(/^\)]}'[^\n]*\n/, ''));
172
+ } // Source maps should use forward slash because it is URLs (https://github.com/mozilla/source-map/issues/91)
173
+ // We should normalize path because previous loaders like `sass-loader` using backslash when generate source map
174
+
175
+
176
+ if (newMap.file) {
177
+ newMap.file = (0, _normalizePath.default)(newMap.file);
178
+ }
179
+
180
+ if (newMap.sourceRoot) {
181
+ newMap.sourceRoot = (0, _normalizePath.default)(newMap.sourceRoot);
182
+ }
183
+
184
+ if (newMap.sources) {
185
+ newMap.sources = newMap.sources.map(source => (0, _normalizePath.default)(source));
186
+ }
187
+
188
+ return newMap;
189
+ }
190
+
191
+ function getImportItemCode(item, loaderContext, importPrefix) {
192
+ const {
193
+ url
194
+ } = item;
195
+ const media = item.media || '';
196
+
197
+ if (!(0, _loaderUtils.isUrlRequest)(url)) {
198
+ return `exports.push([module.id, ${JSON.stringify(`@import url(${url});`)}, ${JSON.stringify(media)}]);`;
199
+ }
200
+
201
+ const importUrl = importPrefix + (0, _loaderUtils.urlToRequest)(url);
202
+ return `exports.i(require(${(0, _loaderUtils.stringifyRequest)(loaderContext, importUrl)}), ${JSON.stringify(media)});`;
203
+ }
204
+
205
+ function getUrlHelperCode(loaderContext) {
206
+ return `var getUrl = require(${(0, _loaderUtils.stringifyRequest)(loaderContext, require.resolve('./runtime/getUrl.js'))});`;
207
+ }
208
+
209
+ function getUrlItemCode(item, loaderContext) {
210
+ const {
211
+ url,
212
+ placeholder,
213
+ needQuotes
214
+ } = item; // Remove `#hash` and `?#hash` from `require`
215
+
216
+ const [normalizedUrl, singleQuery, hashValue] = url.split(/(\?)?#/);
217
+ const hash = singleQuery || hashValue ? `"${singleQuery ? '?' : ''}${hashValue ? `#${hashValue}` : ''}"` : '';
218
+ return `var ${placeholder} = getUrl(require(${(0, _loaderUtils.stringifyRequest)(loaderContext, (0, _loaderUtils.urlToRequest)(normalizedUrl))})${hash ? ` + ${hash}` : ''}${needQuotes ? ', true' : ''});`;
219
+ }
220
+
221
+ function getApiCode(loaderContext, sourceMap, onlyLocals) {
222
+ if (onlyLocals) {
223
+ return '';
224
+ }
225
+
226
+ return `exports = module.exports = require(${(0, _loaderUtils.stringifyRequest)(loaderContext, require.resolve('./runtime/api'))})(${sourceMap});\n`;
227
+ }
228
+
229
+ function getImportCode(importItems, onlyLocals) {
230
+ if (importItems.length === 0 || onlyLocals) {
231
+ return '';
232
+ }
233
+
234
+ return `// Imports\n${importItems.join('\n')}\n`;
235
+ }
236
+
237
+ function getModuleCode(result, sourceMap, onlyLocals) {
238
+ if (onlyLocals) {
239
+ return '';
240
+ }
241
+
242
+ return `// Module\nexports.push([module.id, ${JSON.stringify(result.css)}, ""${sourceMap && result.map ? `,${result.map}` : ''}]);\n`;
243
+ }
244
+
245
+ function getExportItemCode(key, value, localsConvention) {
246
+ let targetKey;
247
+ const items = [];
248
+
249
+ function addEntry(k) {
250
+ items.push(`\t${JSON.stringify(k)}: ${JSON.stringify(value)}`);
251
+ }
252
+
253
+ switch (localsConvention) {
254
+ case 'camelCase':
255
+ addEntry(key);
256
+ targetKey = (0, _camelcase.default)(key);
257
+
258
+ if (targetKey !== key) {
259
+ addEntry(targetKey);
260
+ }
261
+
262
+ break;
263
+
264
+ case 'camelCaseOnly':
265
+ addEntry((0, _camelcase.default)(key));
266
+ break;
267
+
268
+ case 'dashes':
269
+ addEntry(key);
270
+ targetKey = dashesCamelCase(key);
271
+
272
+ if (targetKey !== key) {
273
+ addEntry(targetKey);
274
+ }
275
+
276
+ break;
277
+
278
+ case 'dashesOnly':
279
+ addEntry(dashesCamelCase(key));
280
+ break;
281
+
282
+ case 'asIs':
283
+ default:
284
+ addEntry(key);
285
+ break;
286
+ }
287
+
288
+ return items.join(',\n');
289
+ }
290
+
291
+ function getExportCode(exportItems, onlyLocals) {
292
+ if (exportItems.length === 0) {
293
+ return '';
294
+ }
295
+
296
+ return `// Exports\n${onlyLocals ? 'module.exports' : 'exports.locals'} = {\n${exportItems.join(',\n')}\n};`;
297
+ }
298
+
299
+ function getIcssReplacer(item, loaderContext, importPrefix, onlyLocals) {
300
+ const importUrl = importPrefix + (0, _loaderUtils.urlToRequest)(item.url);
301
+ return () => onlyLocals ? `" + require(${(0, _loaderUtils.stringifyRequest)(loaderContext, importUrl)})[${JSON.stringify(item.export)}] + "` : `" + require(${(0, _loaderUtils.stringifyRequest)(loaderContext, importUrl)}).locals[${JSON.stringify(item.export)}] + "`;
302
+ }
303
+
304
+ function prepareCode(file, messages, loaderContext, importPrefix, onlyLocals) {
305
+ const {
306
+ apiCode,
307
+ importCode
308
+ } = file;
309
+ let {
310
+ moduleCode,
311
+ exportCode
312
+ } = file;
313
+ messages.filter(message => message.type === 'icss-import' || message.type === 'import' && message.importType === 'url').forEach(message => {
314
+ // Replace all urls on `require`
315
+ if (message.type === 'import') {
316
+ const {
317
+ placeholder
318
+ } = message;
319
+
320
+ if (moduleCode) {
321
+ // eslint-disable-next-line no-param-reassign
322
+ moduleCode = moduleCode.replace(new RegExp(placeholder, 'g'), () => `" + ${placeholder} + "`);
323
+ }
324
+ } // Replace external ICSS import on `require`
325
+
326
+
327
+ if (message.type === 'icss-import') {
328
+ const {
329
+ item
330
+ } = message;
331
+ const replacer = getIcssReplacer(item, loaderContext, importPrefix, onlyLocals);
332
+
333
+ if (moduleCode) {
334
+ // eslint-disable-next-line no-param-reassign
335
+ moduleCode = moduleCode.replace(new RegExp(`___CSS_LOADER_IMPORT___(${item.index})___`, 'g'), replacer);
336
+ }
337
+
338
+ if (exportCode) {
339
+ // eslint-disable-next-line no-param-reassign
340
+ exportCode = exportCode.replace(new RegExp(`___CSS_LOADER_IMPORT___(${item.index})___`, 'g'), replacer);
341
+ }
342
+ }
343
+ });
344
+ return [apiCode, importCode, moduleCode, exportCode].filter(Boolean).join('');
72
345
  }