Skip to content

Commit 0bdf9b7

Browse files
authoredNov 27, 2018
fix: inconsistent generate class names on difference os (#812)
1 parent d54216b commit 0bdf9b7

File tree

5 files changed

+514
-3
lines changed

5 files changed

+514
-3
lines changed
 

‎lib/utils.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,8 @@ function getLocalIdent(loaderContext, localIdentName, localName, options) {
9696
}
9797
const request = path.relative(options.context, loaderContext.resourcePath);
9898
// eslint-disable-next-line no-param-reassign
99-
options.content = `${options.hashPrefix + request}+${localName}`;
99+
options.content = `${options.hashPrefix +
100+
request.replace(/\\/g, '/')}+${localName}`;
100101
// eslint-disable-next-line no-param-reassign
101102
localIdentName = localIdentName.replace(/\[local\]/gi, localName);
102103
const hash = loaderUtils.interpolateName(
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,365 @@
1+
// Jest Snapshot v1, https://goo.gl/fbAQLP
2+
3+
exports[`localIdentName option basic: errors 1`] = `Array []`;
4+
5+
exports[`localIdentName option basic: locals 1`] = `
6+
Object {
7+
"-a0-34a___f": "_2nJ5XVdGAwkzTI324zw6Pg",
8+
"_test": "_23te_4QsMe8I6hzxjH0MUx",
9+
"className": "_1E8Hx67EIx_tltp58vyNJ0",
10+
"someId": "_3w7JetWWlr8Zm4sxZ-ANzU",
11+
"subClass": "_3lo0JvMLLK_gjw1mbsomb3",
12+
"test": "NW9YAb4ijHq-3lCxF5vFu",
13+
}
14+
`;
15+
16+
exports[`localIdentName option basic: module (evaluated) 1`] = `
17+
Array [
18+
Array [
19+
1,
20+
".NW9YAb4ijHq-3lCxF5vFu {
21+
background: red;
22+
}
23+
24+
._23te_4QsMe8I6hzxjH0MUx {
25+
background: blue;
26+
}
27+
28+
._1E8Hx67EIx_tltp58vyNJ0 {
29+
background: red;
30+
}
31+
32+
#_3w7JetWWlr8Zm4sxZ-ANzU {
33+
background: green;
34+
}
35+
36+
._1E8Hx67EIx_tltp58vyNJ0 ._3lo0JvMLLK_gjw1mbsomb3 {
37+
color: green;
38+
}
39+
40+
#_3w7JetWWlr8Zm4sxZ-ANzU ._3lo0JvMLLK_gjw1mbsomb3 {
41+
color: blue;
42+
}
43+
44+
._2nJ5XVdGAwkzTI324zw6Pg {
45+
color: red;
46+
}
47+
",
48+
"",
49+
],
50+
]
51+
`;
52+
53+
exports[`localIdentName option basic: warnings 1`] = `Array []`;
54+
55+
exports[`localIdentName option should have hash: errors 1`] = `Array []`;
56+
57+
exports[`localIdentName option should have hash: locals 1`] = `
58+
Object {
59+
"-a0-34a___f": "localIdentName---a0-34a___f--3RHUZ",
60+
"_test": "localIdentName--_test--3Q--B",
61+
"className": "localIdentName--className--3wBIH",
62+
"someId": "localIdentName--someId--mxosG",
63+
"subClass": "localIdentName--subClass--3jIM-",
64+
"test": "localIdentName--test--1Os7J",
65+
}
66+
`;
67+
68+
exports[`localIdentName option should have hash: module (evaluated) 1`] = `
69+
Array [
70+
Array [
71+
1,
72+
".localIdentName--test--1Os7J {
73+
background: red;
74+
}
75+
76+
.localIdentName--_test--3Q--B {
77+
background: blue;
78+
}
79+
80+
.localIdentName--className--3wBIH {
81+
background: red;
82+
}
83+
84+
#localIdentName--someId--mxosG {
85+
background: green;
86+
}
87+
88+
.localIdentName--className--3wBIH .localIdentName--subClass--3jIM- {
89+
color: green;
90+
}
91+
92+
#localIdentName--someId--mxosG .localIdentName--subClass--3jIM- {
93+
color: blue;
94+
}
95+
96+
.localIdentName---a0-34a___f--3RHUZ {
97+
color: red;
98+
}
99+
",
100+
"",
101+
],
102+
]
103+
`;
104+
105+
exports[`localIdentName option should have hash: warnings 1`] = `Array []`;
106+
107+
exports[`localIdentName option should have path naming with context: errors 1`] = `Array []`;
108+
109+
exports[`localIdentName option should have path naming with context: locals 1`] = `
110+
Object {
111+
"-a0-34a___f": "fixtures-modules--localIdentName---a0-34a___f",
112+
"_test": "fixtures-modules--localIdentName--_test",
113+
"className": "fixtures-modules--localIdentName--className",
114+
"someId": "fixtures-modules--localIdentName--someId",
115+
"subClass": "fixtures-modules--localIdentName--subClass",
116+
"test": "fixtures-modules--localIdentName--test",
117+
}
118+
`;
119+
120+
exports[`localIdentName option should have path naming with context: module (evaluated) 1`] = `
121+
Array [
122+
Array [
123+
1,
124+
".fixtures-modules--localIdentName--test {
125+
background: red;
126+
}
127+
128+
.fixtures-modules--localIdentName--_test {
129+
background: blue;
130+
}
131+
132+
.fixtures-modules--localIdentName--className {
133+
background: red;
134+
}
135+
136+
#fixtures-modules--localIdentName--someId {
137+
background: green;
138+
}
139+
140+
.fixtures-modules--localIdentName--className .fixtures-modules--localIdentName--subClass {
141+
color: green;
142+
}
143+
144+
#fixtures-modules--localIdentName--someId .fixtures-modules--localIdentName--subClass {
145+
color: blue;
146+
}
147+
148+
.fixtures-modules--localIdentName---a0-34a___f {
149+
color: red;
150+
}
151+
",
152+
"",
153+
],
154+
]
155+
`;
156+
157+
exports[`localIdentName option should have path naming with context: warnings 1`] = `Array []`;
158+
159+
exports[`localIdentName option should prefixes leading hyphen + digit with underscore: errors 1`] = `Array []`;
160+
161+
exports[`localIdentName option should prefixes leading hyphen + digit with underscore: locals 1`] = `
162+
Object {
163+
"-a0-34a___f": "_-1-a0-34a___f",
164+
"_test": "_-1_test",
165+
"className": "_-1className",
166+
"someId": "_-1someId",
167+
"subClass": "_-1subClass",
168+
"test": "_-1test",
169+
}
170+
`;
171+
172+
exports[`localIdentName option should prefixes leading hyphen + digit with underscore: module (evaluated) 1`] = `
173+
Array [
174+
Array [
175+
1,
176+
"._-1test {
177+
background: red;
178+
}
179+
180+
._-1_test {
181+
background: blue;
182+
}
183+
184+
._-1className {
185+
background: red;
186+
}
187+
188+
#_-1someId {
189+
background: green;
190+
}
191+
192+
._-1className ._-1subClass {
193+
color: green;
194+
}
195+
196+
#_-1someId ._-1subClass {
197+
color: blue;
198+
}
199+
200+
._-1-a0-34a___f {
201+
color: red;
202+
}
203+
",
204+
"",
205+
],
206+
]
207+
`;
208+
209+
exports[`localIdentName option should prefixes leading hyphen + digit with underscore: warnings 1`] = `Array []`;
210+
211+
exports[`localIdentName option should prefixes two leading hyphens with underscore: errors 1`] = `Array []`;
212+
213+
exports[`localIdentName option should prefixes two leading hyphens with underscore: locals 1`] = `
214+
Object {
215+
"-a0-34a___f": "_---a0-34a___f",
216+
"_test": "_--_test",
217+
"className": "_--className",
218+
"someId": "_--someId",
219+
"subClass": "_--subClass",
220+
"test": "_--test",
221+
}
222+
`;
223+
224+
exports[`localIdentName option should prefixes two leading hyphens with underscore: module (evaluated) 1`] = `
225+
Array [
226+
Array [
227+
1,
228+
"._--test {
229+
background: red;
230+
}
231+
232+
._--_test {
233+
background: blue;
234+
}
235+
236+
._--className {
237+
background: red;
238+
}
239+
240+
#_--someId {
241+
background: green;
242+
}
243+
244+
._--className ._--subClass {
245+
color: green;
246+
}
247+
248+
#_--someId ._--subClass {
249+
color: blue;
250+
}
251+
252+
._---a0-34a___f {
253+
color: red;
254+
}
255+
",
256+
"",
257+
],
258+
]
259+
`;
260+
261+
exports[`localIdentName option should prefixes two leading hyphens with underscore: warnings 1`] = `Array []`;
262+
263+
exports[`localIdentName option should saves underscore prefix in exported class names: errors 1`] = `Array []`;
264+
265+
exports[`localIdentName option should saves underscore prefix in exported class names: locals 1`] = `
266+
Object {
267+
"-a0-34a___f": "-a0-34a___f",
268+
"_test": "_test",
269+
"className": "className",
270+
"someId": "someId",
271+
"subClass": "subClass",
272+
"test": "test",
273+
}
274+
`;
275+
276+
exports[`localIdentName option should saves underscore prefix in exported class names: module (evaluated) 1`] = `
277+
Array [
278+
Array [
279+
1,
280+
".test {
281+
background: red;
282+
}
283+
284+
._test {
285+
background: blue;
286+
}
287+
288+
.className {
289+
background: red;
290+
}
291+
292+
#someId {
293+
background: green;
294+
}
295+
296+
.className .subClass {
297+
color: green;
298+
}
299+
300+
#someId .subClass {
301+
color: blue;
302+
}
303+
304+
.-a0-34a___f {
305+
color: red;
306+
}
307+
",
308+
"",
309+
],
310+
]
311+
`;
312+
313+
exports[`localIdentName option should saves underscore prefix in exported class names: warnings 1`] = `Array []`;
314+
315+
exports[`localIdentName option should use hash prefix: errors 1`] = `Array []`;
316+
317+
exports[`localIdentName option should use hash prefix: locals 1`] = `
318+
Object {
319+
"-a0-34a___f": "-a0-34a___f--e99d667fe0ceff9363b011302ac3f508",
320+
"_test": "_test--d745495d407559ef605c9072243801fd",
321+
"className": "className--eab624d1bc6b9c6b6a4278d1030dd690",
322+
"someId": "someId--a0ce220cc9bbb1ee0e85cc0d1f0c6aa9",
323+
"subClass": "subClass--2c82998be8a2b2e94ad7be56c9e685cd",
324+
"test": "test--307c32aa793aaec9aecded85a9fdd448",
325+
}
326+
`;
327+
328+
exports[`localIdentName option should use hash prefix: module (evaluated) 1`] = `
329+
Array [
330+
Array [
331+
1,
332+
".test--307c32aa793aaec9aecded85a9fdd448 {
333+
background: red;
334+
}
335+
336+
._test--d745495d407559ef605c9072243801fd {
337+
background: blue;
338+
}
339+
340+
.className--eab624d1bc6b9c6b6a4278d1030dd690 {
341+
background: red;
342+
}
343+
344+
#someId--a0ce220cc9bbb1ee0e85cc0d1f0c6aa9 {
345+
background: green;
346+
}
347+
348+
.className--eab624d1bc6b9c6b6a4278d1030dd690 .subClass--2c82998be8a2b2e94ad7be56c9e685cd {
349+
color: green;
350+
}
351+
352+
#someId--a0ce220cc9bbb1ee0e85cc0d1f0c6aa9 .subClass--2c82998be8a2b2e94ad7be56c9e685cd {
353+
color: blue;
354+
}
355+
356+
.-a0-34a___f--e99d667fe0ceff9363b011302ac3f508 {
357+
color: red;
358+
}
359+
",
360+
"",
361+
],
362+
]
363+
`;
364+
365+
exports[`localIdentName option should use hash prefix: warnings 1`] = `Array []`;
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
:local(.test) {
2+
background: red;
3+
}
4+
5+
:local(._test) {
6+
background: blue;
7+
}
8+
9+
:local(.className) {
10+
background: red;
11+
}
12+
13+
:local(#someId) {
14+
background: green;
15+
}
16+
17+
:local(.className .subClass) {
18+
color: green;
19+
}
20+
21+
:local(#someId .subClass) {
22+
color: blue;
23+
}
24+
25+
:local(.-a0-34a___f) {
26+
color: red;
27+
}

‎test/localIdentName-option.test.js

+120
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
const path = require('path');
2+
3+
const { webpack, evaluated } = require('./helpers');
4+
5+
describe('localIdentName option', () => {
6+
it('basic', async () => {
7+
const testId = './modules/localIdentName.css';
8+
const stats = await webpack(testId);
9+
const { modules } = stats.toJson();
10+
const module = modules.find((m) => m.id === testId);
11+
const evaluatedModule = evaluated(module.source, modules);
12+
13+
expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
14+
expect(evaluatedModule.locals).toMatchSnapshot('locals');
15+
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
16+
expect(stats.compilation.errors).toMatchSnapshot('errors');
17+
});
18+
19+
it('should have hash', async () => {
20+
const config = {
21+
loader: {
22+
options: {
23+
localIdentName: '[name]--[local]--[hash:base64:5]',
24+
context: path.resolve(__dirname),
25+
},
26+
},
27+
};
28+
const testId = './modules/localIdentName.css';
29+
const stats = await webpack(testId, config);
30+
const { modules } = stats.toJson();
31+
const module = modules.find((m) => m.id === testId);
32+
const evaluatedModule = evaluated(module.source, modules);
33+
34+
expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
35+
expect(evaluatedModule.locals).toMatchSnapshot('locals');
36+
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
37+
expect(stats.compilation.errors).toMatchSnapshot('errors');
38+
});
39+
40+
it('should have path naming with context', async () => {
41+
const config = {
42+
loader: {
43+
options: {
44+
localIdentName: '[path]-[name]--[local]',
45+
context: path.resolve(__dirname),
46+
},
47+
},
48+
};
49+
const testId = './modules/localIdentName.css';
50+
const stats = await webpack(testId, config);
51+
const { modules } = stats.toJson();
52+
const module = modules.find((m) => m.id === testId);
53+
const evaluatedModule = evaluated(module.source, modules);
54+
55+
expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
56+
expect(evaluatedModule.locals).toMatchSnapshot('locals');
57+
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
58+
expect(stats.compilation.errors).toMatchSnapshot('errors');
59+
});
60+
61+
it('should use hash prefix', async () => {
62+
const config = {
63+
loader: {
64+
options: { localIdentName: '[local]--[hash]', hashPrefix: 'x' },
65+
},
66+
};
67+
const testId = './modules/localIdentName.css';
68+
const stats = await webpack(testId, config);
69+
const { modules } = stats.toJson();
70+
const module = modules.find((m) => m.id === testId);
71+
const evaluatedModule = evaluated(module.source, modules);
72+
73+
expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
74+
expect(evaluatedModule.locals).toMatchSnapshot('locals');
75+
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
76+
expect(stats.compilation.errors).toMatchSnapshot('errors');
77+
});
78+
79+
it('should prefixes leading hyphen + digit with underscore', async () => {
80+
const config = { loader: { options: { localIdentName: '-1[local]' } } };
81+
const testId = './modules/localIdentName.css';
82+
const stats = await webpack(testId, config);
83+
const { modules } = stats.toJson();
84+
const module = modules.find((m) => m.id === testId);
85+
const evaluatedModule = evaluated(module.source, modules);
86+
87+
expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
88+
expect(evaluatedModule.locals).toMatchSnapshot('locals');
89+
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
90+
expect(stats.compilation.errors).toMatchSnapshot('errors');
91+
});
92+
93+
it('should prefixes two leading hyphens with underscore', async () => {
94+
const config = { loader: { options: { localIdentName: '--[local]' } } };
95+
const testId = './modules/localIdentName.css';
96+
const stats = await webpack(testId, config);
97+
const { modules } = stats.toJson();
98+
const module = modules.find((m) => m.id === testId);
99+
const evaluatedModule = evaluated(module.source, modules);
100+
101+
expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
102+
expect(evaluatedModule.locals).toMatchSnapshot('locals');
103+
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
104+
expect(stats.compilation.errors).toMatchSnapshot('errors');
105+
});
106+
107+
it('should saves underscore prefix in exported class names', async () => {
108+
const config = { loader: { options: { localIdentName: '[local]' } } };
109+
const testId = './modules/localIdentName.css';
110+
const stats = await webpack(testId, config);
111+
const { modules } = stats.toJson();
112+
const module = modules.find((m) => m.id === testId);
113+
const evaluatedModule = evaluated(module.source, modules);
114+
115+
expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
116+
expect(evaluatedModule.locals).toMatchSnapshot('locals');
117+
expect(stats.compilation.warnings).toMatchSnapshot('warnings');
118+
expect(stats.compilation.errors).toMatchSnapshot('errors');
119+
});
120+
});

‎test/modules-option.test.js

-2
Original file line numberDiff line numberDiff line change
@@ -21,8 +21,6 @@ describe('modules option', () => {
2121
const module = modules.find((m) => m.id === testId);
2222
const evaluatedModule = evaluated(module.source, modules);
2323

24-
// console.log(module)
25-
2624
expect(evaluatedModule).toMatchSnapshot('module (evaluated)');
2725
expect(evaluatedModule.locals).toMatchSnapshot('locals');
2826
expect(stats.compilation.warnings).toMatchSnapshot('warnings');

0 commit comments

Comments
 (0)
Please sign in to comment.