Skip to content

Commit d2f6bd2

Browse files
refactor: getLocalIdent function (#1121)
BREAKING CHANGE: the `getLocalIndent` option should be always `Function` and should always return `String` value
1 parent 069dbb0 commit d2f6bd2

8 files changed

+1261
-1396
lines changed

src/options.json

+1-8
Original file line numberDiff line numberDiff line change
@@ -86,14 +86,7 @@
8686
]
8787
},
8888
"getLocalIdent": {
89-
"anyOf": [
90-
{
91-
"type": "boolean"
92-
},
93-
{
94-
"instanceof": "Function"
95-
}
96-
]
89+
"instanceof": "Function"
9790
},
9891
"namedExport": {
9992
"description": "Use the named export ES modules.",

src/utils.js

+29-41
Original file line numberDiff line numberDiff line change
@@ -46,18 +46,22 @@ function unescape(str) {
4646
}
4747

4848
// eslint-disable-next-line no-control-regex
49-
const filenameReservedRegex = /[<>:"/\\|?*\x00-\x1F]/g;
49+
const filenameReservedRegex = /[<>:"/\\|?*]/g;
5050
// eslint-disable-next-line no-control-regex
5151
const reControlChars = /[\u0000-\u001f\u0080-\u009f]/g;
52-
const reRelativePath = /^\.+/;
5352

54-
function getLocalIdent(loaderContext, localIdentName, localName, options) {
55-
const request = normalizePath(
56-
path.relative(options.context, loaderContext.resourcePath)
57-
);
53+
function defaultGetLocalIdent(
54+
loaderContext,
55+
localIdentName,
56+
localName,
57+
options
58+
) {
59+
const { context, hashPrefix } = options;
60+
const { resourcePath } = loaderContext;
61+
const request = normalizePath(path.relative(context, resourcePath));
5862

5963
// eslint-disable-next-line no-param-reassign
60-
options.content = `${options.hashPrefix + request}+${unescape(localName)}`;
64+
options.content = `${hashPrefix + request}\x00${unescape(localName)}`;
6165

6266
// Using `[path]` placeholder outputs `/` we need escape their
6367
// Also directories can contains invalid characters for css we need escape their too
@@ -67,10 +71,9 @@ function getLocalIdent(loaderContext, localIdentName, localName, options) {
6771
.replace(/^((-?[0-9])|--)/, '_$1')
6872
.replace(filenameReservedRegex, '-')
6973
.replace(reControlChars, '-')
70-
.replace(reRelativePath, '-')
7174
.replace(/\./g, '-'),
7275
{ isIdentifier: true }
73-
).replace(/\\\[local\\\]/gi, localName);
76+
).replace(/\\\[local\\]/gi, localName);
7477
}
7578

7679
function normalizeUrl(url, isStringValue) {
@@ -126,7 +129,7 @@ function getModulesOptions(rawOptions, loaderContext) {
126129
localIdentHashPrefix: '',
127130
// eslint-disable-next-line no-undefined
128131
localIdentRegExp: undefined,
129-
getLocalIdent,
132+
getLocalIdent: defaultGetLocalIdent,
130133
namedExport: false,
131134
exportLocalsConvention: 'asIs',
132135
exportOnlyLocals: false,
@@ -224,44 +227,29 @@ function shouldUseModulesPlugins(options) {
224227
}
225228

226229
function getModulesPlugins(options, loaderContext) {
230+
const {
231+
mode,
232+
getLocalIdent,
233+
localIdentName,
234+
localIdentContext,
235+
localIdentHashPrefix,
236+
localIdentRegExp,
237+
} = options.modules;
238+
227239
let plugins = [];
228240

229241
try {
230242
plugins = [
231243
modulesValues,
232-
localByDefault({ mode: options.modules.mode }),
244+
localByDefault({ mode }),
233245
extractImports(),
234246
modulesScope({
235-
generateScopedName: function generateScopedName(exportName) {
236-
let localIdent;
237-
238-
if (options.modules.getLocalIdent) {
239-
localIdent = options.modules.getLocalIdent(
240-
loaderContext,
241-
options.modules.localIdentName,
242-
exportName,
243-
{
244-
context: options.modules.localIdentContext,
245-
hashPrefix: options.modules.localIdentHashPrefix,
246-
regExp: options.modules.localIdentRegExp,
247-
}
248-
);
249-
}
250-
251-
if (!localIdent) {
252-
localIdent = getLocalIdent(
253-
loaderContext,
254-
options.modules.localIdentName,
255-
exportName,
256-
{
257-
context: options.modules.localIdentContext,
258-
hashPrefix: options.modules.localIdentHashPrefix,
259-
regExp: options.modules.localIdentRegExp,
260-
}
261-
);
262-
}
263-
264-
return localIdent;
247+
generateScopedName(exportName) {
248+
return getLocalIdent(loaderContext, localIdentName, exportName, {
249+
context: localIdentContext,
250+
hashPrefix: localIdentHashPrefix,
251+
regExp: localIdentRegExp,
252+
});
265253
},
266254
exportGlobals: options.modules.exportGlobals,
267255
}),

test/__snapshots__/esModule-option.test.js.snap

+38-38
Original file line numberDiff line numberDiff line change
@@ -118,10 +118,10 @@ import ___CSS_LOADER_ICSS_IMPORT_0___, * as ___CSS_LOADER_ICSS_IMPORT_0____NAMED
118118
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
119119
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_ICSS_IMPORT_0___, \\"\\", true);
120120
// Module
121-
___CSS_LOADER_EXPORT___.push([module.id, \\".lOpALu8t_iv2-GccTMbIq {\\\\n color: \\" + ___CSS_LOADER_ICSS_IMPORT_0____NAMED___[\\"vDef\\"] + \\";\\\\n}\\\\n\\", \\"\\"]);
121+
___CSS_LOADER_EXPORT___.push([module.id, \\"._1yYSY3W2VgnkKdMmuxCIL1 {\\\\n color: \\" + ___CSS_LOADER_ICSS_IMPORT_0____NAMED___[\\"vDef\\"] + \\";\\\\n}\\\\n\\", \\"\\"]);
122122
// Exports
123123
export const vDef = \\"\\" + ___CSS_LOADER_ICSS_IMPORT_0____NAMED___[\\"vDef\\"] + \\"\\";
124-
export const ghi = \\"lOpALu8t_iv2-GccTMbIq\\";
124+
export const ghi = \\"_1yYSY3W2VgnkKdMmuxCIL1\\";
125125
126126
export default ___CSS_LOADER_EXPORT___;
127127
"
@@ -137,7 +137,7 @@ Array [
137137
],
138138
Array [
139139
"./es-module/named/nested/index.css",
140-
".lOpALu8t_iv2-GccTMbIq {
140+
"._1yYSY3W2VgnkKdMmuxCIL1 {
141141
color: red;
142142
}
143143
",
@@ -155,9 +155,9 @@ exports[`"esModule" option should work with "namedExport" option: module 1`] = `
155155
import ___CSS_LOADER_API_IMPORT___ from \\"../../../../../src/runtime/api.js\\";
156156
var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
157157
// Module
158-
___CSS_LOADER_EXPORT___.push([module.id, \\".jSf5EjnYI1bvqKHBrOPz6 {\\\\n color: red;\\\\n}\\\\n\\\\n.bar {\\\\n color: red;\\\\n}\\\\n\\", \\"\\"]);
158+
___CSS_LOADER_EXPORT___.push([module.id, \\"._3yAjbn27wJ9GVH2M-pj-hs {\\\\n color: red;\\\\n}\\\\n\\\\n.bar {\\\\n color: red;\\\\n}\\\\n\\", \\"\\"]);
159159
// Exports
160-
export const barBaz = \\"jSf5EjnYI1bvqKHBrOPz6\\";
160+
export const barBaz = \\"_3yAjbn27wJ9GVH2M-pj-hs\\";
161161
162162
export default ___CSS_LOADER_EXPORT___;
163163
"
@@ -167,7 +167,7 @@ exports[`"esModule" option should work with "namedExport" option: result 1`] = `
167167
Array [
168168
Array [
169169
"./es-module/named/base/index.css",
170-
".jSf5EjnYI1bvqKHBrOPz6 {
170+
"._3yAjbn27wJ9GVH2M-pj-hs {
171171
color: red;
172172
}
173173
@@ -286,10 +286,10 @@ var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
286286
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
287287
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
288288
// Module
289-
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n._2uMy1nigdepJE7b3T1Visj {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
289+
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.oFwPvuANP2XsfGir7HPVz {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
290290
// Exports
291291
___CSS_LOADER_EXPORT___.locals = {
292-
\\"class\\": \\"_2uMy1nigdepJE7b3T1Visj\\"
292+
\\"class\\": \\"oFwPvuANP2XsfGir7HPVz\\"
293293
};
294294
export default ___CSS_LOADER_EXPORT___;
295295
"
@@ -299,7 +299,7 @@ exports[`"esModule" option should work with a value equal to "true" and the "mod
299299
Array [
300300
Array [
301301
"../../src/index.js?[ident]!./es-module/imported.css",
302-
"._3zJoIAkhorFsUbhn0phThb {
302+
"._2sn2s-Iv44Mnv3FmSmFVuI {
303303
color: red;
304304
}
305305
",
@@ -311,7 +311,7 @@ Array [
311311
312312
/* Comment */
313313
314-
._2uMy1nigdepJE7b3T1Visj {
314+
.oFwPvuANP2XsfGir7HPVz {
315315
color: red;
316316
background: url(/webpack/public/path/img.png);
317317
}
@@ -335,10 +335,10 @@ var ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(false);
335335
___CSS_LOADER_EXPORT___.i(___CSS_LOADER_AT_RULE_IMPORT_0___);
336336
var ___CSS_LOADER_URL_REPLACEMENT_0___ = ___CSS_LOADER_GET_URL_IMPORT___(___CSS_LOADER_URL_IMPORT_0___);
337337
// Module
338-
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n._2uMy1nigdepJE7b3T1Visj {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
338+
___CSS_LOADER_EXPORT___.push([module.id, \\"@charset \\\\\\"UTF-8\\\\\\";\\\\n\\\\n/* Comment */\\\\n\\\\n.oFwPvuANP2XsfGir7HPVz {\\\\n color: red;\\\\n background: url(\\" + ___CSS_LOADER_URL_REPLACEMENT_0___ + \\");\\\\n}\\\\n\\", \\"\\"]);
339339
// Exports
340340
___CSS_LOADER_EXPORT___.locals = {
341-
\\"class\\": \\"_2uMy1nigdepJE7b3T1Visj\\"
341+
\\"class\\": \\"oFwPvuANP2XsfGir7HPVz\\"
342342
};
343343
export default ___CSS_LOADER_EXPORT___;
344344
"
@@ -348,7 +348,7 @@ exports[`"esModule" option should work with a value equal to "true" and the "mod
348348
Array [
349349
Array [
350350
"../../src/index.js?[ident]!./es-module/imported.css",
351-
"._3zJoIAkhorFsUbhn0phThb {
351+
"._2sn2s-Iv44Mnv3FmSmFVuI {
352352
color: red;
353353
}
354354
",
@@ -360,7 +360,7 @@ Array [
360360
361361
/* Comment */
362362
363-
._2uMy1nigdepJE7b3T1Visj {
363+
.oFwPvuANP2XsfGir7HPVz {
364364
color: red;
365365
background: url(/webpack/public/path/img.png);
366366
}
@@ -429,14 +429,14 @@ exports[`"esModule" option should work with commonjs css-loader + commonjs style
429429
exports[`"esModule" option should work with commonjs css-loader + commonjs style-loader: result 1`] = `
430430
Object {
431431
"css": Object {
432-
"body": "uTw0Zyl5UXHez5t_lWCWm",
433-
"footer": "_2QW_-wZzF9G9_VrEnlztAG",
434-
"header-baz": "_24LP0msVwbV2gDQs7MsBEI",
432+
"body": "BwpsNB5_0Pze7vq8KQOAN",
433+
"footer": "_10gZ0Ke9A0uqq8u0Z2eRKA",
434+
"header-baz": "_2n-RuEOd5cLXo65ILWgtue",
435435
},
436436
"html": "
437-
<div class=\\"_24LP0msVwbV2gDQs7MsBEI\\">
438-
<div class=\\"uTw0Zyl5UXHez5t_lWCWm\\">
439-
<div class=\\"_2QW_-wZzF9G9_VrEnlztAG\\">
437+
<div class=\\"_2n-RuEOd5cLXo65ILWgtue\\">
438+
<div class=\\"BwpsNB5_0Pze7vq8KQOAN\\">
439+
<div class=\\"_10gZ0Ke9A0uqq8u0Z2eRKA\\">
440440
",
441441
}
442442
`;
@@ -454,14 +454,14 @@ exports[`"esModule" option should work with commonjs css-loader + esModule style
454454
exports[`"esModule" option should work with commonjs css-loader + esModule style-loader: result 1`] = `
455455
Object {
456456
"css": Object {
457-
"body": "uTw0Zyl5UXHez5t_lWCWm",
458-
"footer": "_2QW_-wZzF9G9_VrEnlztAG",
459-
"header-baz": "_24LP0msVwbV2gDQs7MsBEI",
457+
"body": "BwpsNB5_0Pze7vq8KQOAN",
458+
"footer": "_10gZ0Ke9A0uqq8u0Z2eRKA",
459+
"header-baz": "_2n-RuEOd5cLXo65ILWgtue",
460460
},
461461
"html": "
462-
<div class=\\"_24LP0msVwbV2gDQs7MsBEI\\">
463-
<div class=\\"uTw0Zyl5UXHez5t_lWCWm\\">
464-
<div class=\\"_2QW_-wZzF9G9_VrEnlztAG\\">
462+
<div class=\\"_2n-RuEOd5cLXo65ILWgtue\\">
463+
<div class=\\"BwpsNB5_0Pze7vq8KQOAN\\">
464+
<div class=\\"_10gZ0Ke9A0uqq8u0Z2eRKA\\">
465465
",
466466
}
467467
`;
@@ -479,14 +479,14 @@ exports[`"esModule" option should work with esModule css-loader + commonjs style
479479
exports[`"esModule" option should work with esModule css-loader + commonjs style-loader: result 1`] = `
480480
Object {
481481
"css": Object {
482-
"body": "uTw0Zyl5UXHez5t_lWCWm",
483-
"footer": "_2QW_-wZzF9G9_VrEnlztAG",
484-
"header-baz": "_24LP0msVwbV2gDQs7MsBEI",
482+
"body": "BwpsNB5_0Pze7vq8KQOAN",
483+
"footer": "_10gZ0Ke9A0uqq8u0Z2eRKA",
484+
"header-baz": "_2n-RuEOd5cLXo65ILWgtue",
485485
},
486486
"html": "
487-
<div class=\\"_24LP0msVwbV2gDQs7MsBEI\\">
488-
<div class=\\"uTw0Zyl5UXHez5t_lWCWm\\">
489-
<div class=\\"_2QW_-wZzF9G9_VrEnlztAG\\">
487+
<div class=\\"_2n-RuEOd5cLXo65ILWgtue\\">
488+
<div class=\\"BwpsNB5_0Pze7vq8KQOAN\\">
489+
<div class=\\"_10gZ0Ke9A0uqq8u0Z2eRKA\\">
490490
",
491491
}
492492
`;
@@ -504,14 +504,14 @@ exports[`"esModule" option should work with esModule css-loader + esModule style
504504
exports[`"esModule" option should work with esModule css-loader + esModule style-loader: result 1`] = `
505505
Object {
506506
"css": Object {
507-
"body": "uTw0Zyl5UXHez5t_lWCWm",
508-
"footer": "_2QW_-wZzF9G9_VrEnlztAG",
509-
"header-baz": "_24LP0msVwbV2gDQs7MsBEI",
507+
"body": "BwpsNB5_0Pze7vq8KQOAN",
508+
"footer": "_10gZ0Ke9A0uqq8u0Z2eRKA",
509+
"header-baz": "_2n-RuEOd5cLXo65ILWgtue",
510510
},
511511
"html": "
512-
<div class=\\"_24LP0msVwbV2gDQs7MsBEI\\">
513-
<div class=\\"uTw0Zyl5UXHez5t_lWCWm\\">
514-
<div class=\\"_2QW_-wZzF9G9_VrEnlztAG\\">
512+
<div class=\\"_2n-RuEOd5cLXo65ILWgtue\\">
513+
<div class=\\"BwpsNB5_0Pze7vq8KQOAN\\">
514+
<div class=\\"_10gZ0Ke9A0uqq8u0Z2eRKA\\">
515515
",
516516
}
517517
`;

test/__snapshots__/loader.test.js.snap

+2-2
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ exports[`loader should work with the "modules.auto" option and the "importLoader
634634
color: #333;
635635
}
636636
/* CSS modules */
637-
._3ZewTmcU5fqs585BjdQt_0 {
637+
._1IwxFskZk1cbjNkH0QoBiv {
638638
overflow-x: hidden;
639639
overflow-y: auto;
640640
overflow: hidden auto;
@@ -651,7 +651,7 @@ exports[`loader should work with the "modules.auto" option and the "importLoader
651651
overflow-y: auto;
652652
overflow: hidden auto;
653653
}
654-
.irHrhsl3WEJVKUxOmS7dC {
654+
._2on1B_I_5ZLmD6I3yY37jX {
655655
color: #333;
656656
overflow-x: hidden;
657657
overflow-y: auto;

0 commit comments

Comments
 (0)