happy-css-modules 3.0.0 → 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.
- package/package.json +1 -1
- package/src/emitter/dts.test.ts +3 -3
- package/src/emitter/dts.ts +59 -37
- package/src/emitter/index.test.ts +3 -3
- package/src/integration-test/go-to-definition.test.ts +0 -35
- package/src/locator/index.test.ts +152 -158
- package/src/locator/index.ts +44 -37
- package/src/locator/postcss.test.ts +118 -76
- package/src/locator/postcss.ts +116 -73
- package/src/test-util/util.ts +24 -23
- package/src/transformer/less-transformer.test.ts +26 -24
- package/src/transformer/postcss-transformer.test.ts +5 -3
- package/src/transformer/scss-transformer.test.ts +39 -28
- package/src/util.ts +1 -1
- package/dist/cli.d.ts +0 -6
- package/dist/cli.js +0 -121
- package/dist/cli.js.map +0 -1
- package/dist/cli.test.d.ts +0 -1
- package/dist/cli.test.js +0 -66
- package/dist/cli.test.js.map +0 -1
- package/dist/config.d.ts +0 -1
- package/dist/config.js +0 -2
- package/dist/config.js.map +0 -1
- package/dist/emitter/dts.d.ts +0 -14
- package/dist/emitter/dts.js +0 -111
- package/dist/emitter/dts.js.map +0 -1
- package/dist/emitter/dts.test.d.ts +0 -1
- package/dist/emitter/dts.test.js +0 -205
- package/dist/emitter/dts.test.js.map +0 -1
- package/dist/emitter/file-system.d.ts +0 -6
- package/dist/emitter/file-system.js +0 -26
- package/dist/emitter/file-system.js.map +0 -1
- package/dist/emitter/file-system.test.d.ts +0 -1
- package/dist/emitter/file-system.test.js +0 -34
- package/dist/emitter/file-system.test.js.map +0 -1
- package/dist/emitter/index.d.ts +0 -34
- package/dist/emitter/index.js +0 -49
- package/dist/emitter/index.js.map +0 -1
- package/dist/emitter/index.test.d.ts +0 -1
- package/dist/emitter/index.test.js +0 -68
- package/dist/emitter/index.test.js.map +0 -1
- package/dist/emitter/source-map.d.ts +0 -8
- package/dist/emitter/source-map.js +0 -16
- package/dist/emitter/source-map.js.map +0 -1
- package/dist/emitter/source-map.test.d.ts +0 -1
- package/dist/emitter/source-map.test.js +0 -13
- package/dist/emitter/source-map.test.js.map +0 -1
- package/dist/index.d.ts +0 -5
- package/dist/index.js +0 -6
- package/dist/index.js.map +0 -1
- package/dist/integration-test/go-to-definition.test.d.ts +0 -1
- package/dist/integration-test/go-to-definition.test.js +0 -369
- package/dist/integration-test/go-to-definition.test.js.map +0 -1
- package/dist/library/source-map/index.d.ts +0 -8
- package/dist/library/source-map/index.js +0 -5
- package/dist/library/source-map/index.js.map +0 -1
- package/dist/locator/index.d.ts +0 -44
- package/dist/locator/index.js +0 -162
- package/dist/locator/index.js.map +0 -1
- package/dist/locator/index.test.d.ts +0 -1
- package/dist/locator/index.test.js +0 -395
- package/dist/locator/index.test.js.map +0 -1
- package/dist/locator/postcss.d.ts +0 -64
- package/dist/locator/postcss.js +0 -208
- package/dist/locator/postcss.js.map +0 -1
- package/dist/locator/postcss.test.d.ts +0 -1
- package/dist/locator/postcss.test.js +0 -242
- package/dist/locator/postcss.test.js.map +0 -1
- package/dist/logger.d.ts +0 -9
- package/dist/logger.js +0 -28
- package/dist/logger.js.map +0 -1
- package/dist/regression-test/issue-168.test.d.ts +0 -1
- package/dist/regression-test/issue-168.test.js +0 -30
- package/dist/regression-test/issue-168.test.js.map +0 -1
- package/dist/resolver/index.d.ts +0 -22
- package/dist/resolver/index.js +0 -44
- package/dist/resolver/index.js.map +0 -1
- package/dist/resolver/index.test.d.ts +0 -1
- package/dist/resolver/index.test.js +0 -16
- package/dist/resolver/index.test.js.map +0 -1
- package/dist/resolver/node-resolver.d.ts +0 -2
- package/dist/resolver/node-resolver.js +0 -6
- package/dist/resolver/node-resolver.js.map +0 -1
- package/dist/resolver/node-resolver.test.d.ts +0 -1
- package/dist/resolver/node-resolver.test.js +0 -25
- package/dist/resolver/node-resolver.test.js.map +0 -1
- package/dist/resolver/relative-resolver.d.ts +0 -2
- package/dist/resolver/relative-resolver.js +0 -5
- package/dist/resolver/relative-resolver.js.map +0 -1
- package/dist/resolver/relative-resolver.test.d.ts +0 -1
- package/dist/resolver/relative-resolver.test.js +0 -12
- package/dist/resolver/relative-resolver.test.js.map +0 -1
- package/dist/resolver/webpack-resolver.d.ts +0 -24
- package/dist/resolver/webpack-resolver.js +0 -91
- package/dist/resolver/webpack-resolver.js.map +0 -1
- package/dist/resolver/webpack-resolver.test.d.ts +0 -1
- package/dist/resolver/webpack-resolver.test.js +0 -89
- package/dist/resolver/webpack-resolver.test.js.map +0 -1
- package/dist/runner.d.ts +0 -76
- package/dist/runner.js +0 -120
- package/dist/runner.js.map +0 -1
- package/dist/runner.test.d.ts +0 -1
- package/dist/runner.test.js +0 -287
- package/dist/runner.test.js.map +0 -1
- package/dist/test-util/jest/resolver.cjs +0 -31
- package/dist/test-util/jest/resolver.cjs.map +0 -1
- package/dist/test-util/jest/resolver.d.cts +0 -16
- package/dist/test-util/tsserver.d.ts +0 -31
- package/dist/test-util/tsserver.js +0 -112
- package/dist/test-util/tsserver.js.map +0 -1
- package/dist/test-util/util.d.ts +0 -29
- package/dist/test-util/util.js +0 -84
- package/dist/test-util/util.js.map +0 -1
- package/dist/transformer/index.d.ts +0 -30
- package/dist/transformer/index.js +0 -25
- package/dist/transformer/index.js.map +0 -1
- package/dist/transformer/index.test.d.ts +0 -1
- package/dist/transformer/index.test.js +0 -66
- package/dist/transformer/index.test.js.map +0 -1
- package/dist/transformer/less-transformer.d.ts +0 -2
- package/dist/transformer/less-transformer.js +0 -45
- package/dist/transformer/less-transformer.js.map +0 -1
- package/dist/transformer/less-transformer.test.d.ts +0 -1
- package/dist/transformer/less-transformer.test.js +0 -132
- package/dist/transformer/less-transformer.test.js.map +0 -1
- package/dist/transformer/postcss-transformer.d.ts +0 -12
- package/dist/transformer/postcss-transformer.js +0 -32
- package/dist/transformer/postcss-transformer.js.map +0 -1
- package/dist/transformer/postcss-transformer.test.d.ts +0 -1
- package/dist/transformer/postcss-transformer.test.js +0 -176
- package/dist/transformer/postcss-transformer.test.js.map +0 -1
- package/dist/transformer/scss-transformer.d.ts +0 -2
- package/dist/transformer/scss-transformer.js +0 -40
- package/dist/transformer/scss-transformer.js.map +0 -1
- package/dist/transformer/scss-transformer.test.d.ts +0 -1
- package/dist/transformer/scss-transformer.test.js +0 -138
- package/dist/transformer/scss-transformer.test.js.map +0 -1
- package/dist/util.d.ts +0 -21
- package/dist/util.js +0 -72
- package/dist/util.js.map +0 -1
- package/dist/util.test.d.ts +0 -1
- package/dist/util.test.js +0 -74
- package/dist/util.test.js.map +0 -1
|
@@ -1,395 +0,0 @@
|
|
|
1
|
-
import fs, { readFile, writeFile } from 'fs/promises';
|
|
2
|
-
import { randomUUID } from 'node:crypto';
|
|
3
|
-
import { jest } from '@jest/globals';
|
|
4
|
-
import dedent from 'dedent';
|
|
5
|
-
import { createDefaultTransformer } from '../index.js';
|
|
6
|
-
import { createFixtures, FIXTURE_DIR_PATH, getFixturePath } from '../test-util/util.js';
|
|
7
|
-
import { sleepSync } from '../util.js';
|
|
8
|
-
const readFileSpy = jest.spyOn(fs, 'readFile');
|
|
9
|
-
// In ESM, for some reason, we need to explicitly mock module
|
|
10
|
-
jest.unstable_mockModule('fs/promises', () => ({
|
|
11
|
-
...fs, // Inherit native functions (e.g., fs.stat)
|
|
12
|
-
readFile: readFileSpy,
|
|
13
|
-
}));
|
|
14
|
-
// After the mock of fs/promises is complete, . /index.js after the mock of fs/promises is complete.
|
|
15
|
-
// ref: https://www.coolcomputerclub.com/posts/jest-hoist-await/
|
|
16
|
-
const { Locator } = await import('./index.js');
|
|
17
|
-
// NOTE: ../test/util.js depends on . /index.js, so it must also be imported dynamically...
|
|
18
|
-
const locator = new Locator();
|
|
19
|
-
afterEach(() => {
|
|
20
|
-
readFileSpy.mockClear();
|
|
21
|
-
});
|
|
22
|
-
test('basic', async () => {
|
|
23
|
-
createFixtures({
|
|
24
|
-
'/test/1.css': dedent `
|
|
25
|
-
.a {}
|
|
26
|
-
.b {}
|
|
27
|
-
`,
|
|
28
|
-
});
|
|
29
|
-
const result = await locator.load(getFixturePath('/test/1.css'));
|
|
30
|
-
expect(result).toMatchInlineSnapshot(`
|
|
31
|
-
{
|
|
32
|
-
dependencies: [],
|
|
33
|
-
tokens: [
|
|
34
|
-
{
|
|
35
|
-
name: "a",
|
|
36
|
-
originalLocations: [
|
|
37
|
-
{ filePath: "<fixtures>/test/1.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
38
|
-
],
|
|
39
|
-
},
|
|
40
|
-
{
|
|
41
|
-
name: "b",
|
|
42
|
-
originalLocations: [
|
|
43
|
-
{ filePath: "<fixtures>/test/1.css", start: { line: 2, column: 1 }, end: { line: 2, column: 2 } },
|
|
44
|
-
],
|
|
45
|
-
},
|
|
46
|
-
],
|
|
47
|
-
}
|
|
48
|
-
`);
|
|
49
|
-
});
|
|
50
|
-
test('tracks other files when `@import` is present', async () => {
|
|
51
|
-
createFixtures({
|
|
52
|
-
'/test/1.css': dedent `
|
|
53
|
-
@import './2.css';
|
|
54
|
-
@import '3.css';
|
|
55
|
-
@import '${getFixturePath('/test/4.css')}';
|
|
56
|
-
@import './5.css';
|
|
57
|
-
`,
|
|
58
|
-
'/test/2.css': dedent `
|
|
59
|
-
.a {}
|
|
60
|
-
`,
|
|
61
|
-
'/test/3.css': dedent `
|
|
62
|
-
.b {}
|
|
63
|
-
`,
|
|
64
|
-
'/test/4.css': dedent `
|
|
65
|
-
.c {}
|
|
66
|
-
`,
|
|
67
|
-
'/test/5.css': dedent `
|
|
68
|
-
@import './5-recursive.css';
|
|
69
|
-
`,
|
|
70
|
-
'/test/5-recursive.css': dedent `
|
|
71
|
-
.d {}
|
|
72
|
-
`,
|
|
73
|
-
});
|
|
74
|
-
const result = await locator.load(getFixturePath('/test/1.css'));
|
|
75
|
-
expect(result).toMatchInlineSnapshot(`
|
|
76
|
-
{
|
|
77
|
-
dependencies: [
|
|
78
|
-
"<fixtures>/test/2.css",
|
|
79
|
-
"<fixtures>/test/3.css",
|
|
80
|
-
"<fixtures>/test/4.css",
|
|
81
|
-
"<fixtures>/test/5.css",
|
|
82
|
-
"<fixtures>/test/5-recursive.css",
|
|
83
|
-
],
|
|
84
|
-
tokens: [
|
|
85
|
-
{
|
|
86
|
-
name: "a",
|
|
87
|
-
originalLocations: [
|
|
88
|
-
{ filePath: "<fixtures>/test/2.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
89
|
-
],
|
|
90
|
-
},
|
|
91
|
-
{
|
|
92
|
-
name: "b",
|
|
93
|
-
originalLocations: [
|
|
94
|
-
{ filePath: "<fixtures>/test/3.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
95
|
-
],
|
|
96
|
-
},
|
|
97
|
-
{
|
|
98
|
-
name: "c",
|
|
99
|
-
originalLocations: [
|
|
100
|
-
{ filePath: "<fixtures>/test/4.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
101
|
-
],
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
name: "d",
|
|
105
|
-
originalLocations: [
|
|
106
|
-
{ filePath: "<fixtures>/test/5-recursive.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
107
|
-
],
|
|
108
|
-
},
|
|
109
|
-
],
|
|
110
|
-
}
|
|
111
|
-
`);
|
|
112
|
-
});
|
|
113
|
-
test('tracks other files when `composes` is present', async () => {
|
|
114
|
-
createFixtures({
|
|
115
|
-
'/test/1.css': dedent `
|
|
116
|
-
.a {
|
|
117
|
-
composes: b from './2.css';
|
|
118
|
-
composes: c d from './3.css';
|
|
119
|
-
composes: e from '${getFixturePath('/test/4.css')}';
|
|
120
|
-
}
|
|
121
|
-
`,
|
|
122
|
-
'/test/2.css': dedent `
|
|
123
|
-
.b {}
|
|
124
|
-
`,
|
|
125
|
-
'/test/3.css': dedent `
|
|
126
|
-
.c {}
|
|
127
|
-
.d {}
|
|
128
|
-
`,
|
|
129
|
-
'/test/4.css': dedent `
|
|
130
|
-
.e {}
|
|
131
|
-
`,
|
|
132
|
-
});
|
|
133
|
-
const result = await locator.load(getFixturePath('/test/1.css'));
|
|
134
|
-
expect(result).toMatchInlineSnapshot(`
|
|
135
|
-
{
|
|
136
|
-
dependencies: ["<fixtures>/test/2.css", "<fixtures>/test/3.css", "<fixtures>/test/4.css"],
|
|
137
|
-
tokens: [
|
|
138
|
-
{
|
|
139
|
-
name: "a",
|
|
140
|
-
originalLocations: [
|
|
141
|
-
{ filePath: "<fixtures>/test/1.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
142
|
-
],
|
|
143
|
-
},
|
|
144
|
-
{
|
|
145
|
-
name: "b",
|
|
146
|
-
originalLocations: [
|
|
147
|
-
{ filePath: "<fixtures>/test/2.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
148
|
-
],
|
|
149
|
-
},
|
|
150
|
-
{
|
|
151
|
-
name: "c",
|
|
152
|
-
originalLocations: [
|
|
153
|
-
{ filePath: "<fixtures>/test/3.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
154
|
-
],
|
|
155
|
-
},
|
|
156
|
-
{
|
|
157
|
-
name: "d",
|
|
158
|
-
originalLocations: [
|
|
159
|
-
{ filePath: "<fixtures>/test/3.css", start: { line: 2, column: 1 }, end: { line: 2, column: 2 } },
|
|
160
|
-
],
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
name: "e",
|
|
164
|
-
originalLocations: [
|
|
165
|
-
{ filePath: "<fixtures>/test/4.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
166
|
-
],
|
|
167
|
-
},
|
|
168
|
-
],
|
|
169
|
-
}
|
|
170
|
-
`);
|
|
171
|
-
});
|
|
172
|
-
test('normalizes tokens', async () => {
|
|
173
|
-
createFixtures({
|
|
174
|
-
'/test/1.css': dedent `
|
|
175
|
-
/* duplicate import */
|
|
176
|
-
@import './2.css';
|
|
177
|
-
@import '2.css';
|
|
178
|
-
.a {
|
|
179
|
-
/* duplicate composes */
|
|
180
|
-
composes: c from './3.css';
|
|
181
|
-
composes: c from '3.css';
|
|
182
|
-
composes: c c from './3.css';
|
|
183
|
-
/* duplicate import and composes */
|
|
184
|
-
composes: b from './2.css';
|
|
185
|
-
}
|
|
186
|
-
.a {} /* duplicate class selector */
|
|
187
|
-
`,
|
|
188
|
-
'/test/2.css': dedent `
|
|
189
|
-
.a {} /* class selector that duplicates the import source */
|
|
190
|
-
.b {}
|
|
191
|
-
`,
|
|
192
|
-
'/test/3.css': dedent `
|
|
193
|
-
.c {}
|
|
194
|
-
`,
|
|
195
|
-
});
|
|
196
|
-
const result = await locator.load(getFixturePath('/test/1.css'));
|
|
197
|
-
expect(result).toMatchInlineSnapshot(`
|
|
198
|
-
{
|
|
199
|
-
dependencies: ["<fixtures>/test/2.css", "<fixtures>/test/3.css"],
|
|
200
|
-
tokens: [
|
|
201
|
-
{
|
|
202
|
-
name: "a",
|
|
203
|
-
originalLocations: [
|
|
204
|
-
{ filePath: "<fixtures>/test/2.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
205
|
-
{ filePath: "<fixtures>/test/1.css", start: { line: 4, column: 1 }, end: { line: 4, column: 2 } },
|
|
206
|
-
{ filePath: "<fixtures>/test/1.css", start: { line: 12, column: 1 }, end: { line: 12, column: 2 } },
|
|
207
|
-
],
|
|
208
|
-
},
|
|
209
|
-
{
|
|
210
|
-
name: "b",
|
|
211
|
-
originalLocations: [
|
|
212
|
-
{ filePath: "<fixtures>/test/2.css", start: { line: 2, column: 1 }, end: { line: 2, column: 2 } },
|
|
213
|
-
],
|
|
214
|
-
},
|
|
215
|
-
{
|
|
216
|
-
name: "c",
|
|
217
|
-
originalLocations: [
|
|
218
|
-
{ filePath: "<fixtures>/test/3.css", start: { line: 1, column: 1 }, end: { line: 1, column: 2 } },
|
|
219
|
-
],
|
|
220
|
-
},
|
|
221
|
-
],
|
|
222
|
-
}
|
|
223
|
-
`);
|
|
224
|
-
});
|
|
225
|
-
test.failing('returns the result from the cache when the file has not been modified', async () => {
|
|
226
|
-
createFixtures({
|
|
227
|
-
'/test/1.css': dedent `
|
|
228
|
-
@import './2.css';
|
|
229
|
-
@import './2.css';
|
|
230
|
-
.a {
|
|
231
|
-
composes: b from './2.css';
|
|
232
|
-
composes: c from './3.css';
|
|
233
|
-
composes: d from './3.css';
|
|
234
|
-
}
|
|
235
|
-
`,
|
|
236
|
-
'/test/2.css': dedent `
|
|
237
|
-
.b {}
|
|
238
|
-
`,
|
|
239
|
-
'/test/3.css': dedent `
|
|
240
|
-
.c {}
|
|
241
|
-
.d {}
|
|
242
|
-
`,
|
|
243
|
-
});
|
|
244
|
-
await locator.load(getFixturePath('/test/1.css'));
|
|
245
|
-
expect(readFileSpy).toHaveBeenCalledTimes(3);
|
|
246
|
-
expect(readFileSpy).toHaveBeenNthCalledWith(1, '/test/1.css', 'utf-8');
|
|
247
|
-
expect(readFileSpy).toHaveBeenNthCalledWith(2, '/test/2.css', 'utf-8');
|
|
248
|
-
expect(readFileSpy).toHaveBeenNthCalledWith(3, '/test/3.css', 'utf-8');
|
|
249
|
-
readFileSpy.mockClear();
|
|
250
|
-
// update `/test/2.css`
|
|
251
|
-
sleepSync(1); // wait for the file system to update the mtime
|
|
252
|
-
await writeFile(getFixturePath('/test/2.css'), await readFile(getFixturePath('/test/2.css'), 'utf-8'));
|
|
253
|
-
// `3.css` is not updated, so the cache is used. Therefore, `readFile` is not called.
|
|
254
|
-
await locator.load(getFixturePath('/test/3.css'));
|
|
255
|
-
expect(readFileSpy).toHaveBeenCalledTimes(0);
|
|
256
|
-
// `1.css` is not updated, but dependencies are updated, so the cache is used. Therefore, `readFile` is called.
|
|
257
|
-
await locator.load(getFixturePath('/test/1.css'));
|
|
258
|
-
expect(readFileSpy).toHaveBeenCalledTimes(2);
|
|
259
|
-
expect(readFileSpy).toHaveBeenNthCalledWith(1, '/test/1.css', 'utf-8');
|
|
260
|
-
expect(readFileSpy).toHaveBeenNthCalledWith(2, '/test/2.css', 'utf-8');
|
|
261
|
-
// ``2.css` is updated, but the cache is already available because it was updated in the previous step. Therefore, `readFile` is not called.
|
|
262
|
-
await locator.load(getFixturePath('/test/2.css'));
|
|
263
|
-
expect(readFileSpy).toHaveBeenCalledTimes(2);
|
|
264
|
-
});
|
|
265
|
-
test('ignores the composition of non-existent tokens', async () => {
|
|
266
|
-
// In css-loader and postcss-modules, compositions of non-existent tokens are simply ignored.
|
|
267
|
-
// Therefore, happy-css-modules follows suit.
|
|
268
|
-
// It may be preferable to warn rather than ignore, but for now, we will focus on compatibility.
|
|
269
|
-
// ref: https://github.com/css-modules/css-modules/issues/356
|
|
270
|
-
createFixtures({
|
|
271
|
-
'/test/1.css': dedent `
|
|
272
|
-
.a {
|
|
273
|
-
composes: b c from './2.css';
|
|
274
|
-
}
|
|
275
|
-
`,
|
|
276
|
-
'/test/2.css': dedent `
|
|
277
|
-
.b {}
|
|
278
|
-
`,
|
|
279
|
-
});
|
|
280
|
-
const result = await locator.load(getFixturePath('/test/1.css'));
|
|
281
|
-
expect(result.tokens.map((t) => t.name)).toStrictEqual(['a', 'b']);
|
|
282
|
-
});
|
|
283
|
-
test('throws error the composition of non-existent file', async () => {
|
|
284
|
-
// In postcss-modules, compositions of non-existent file are causes an error.
|
|
285
|
-
// Therefore, happy-css-modules follows suit.
|
|
286
|
-
createFixtures({
|
|
287
|
-
'/test/1.css': dedent `
|
|
288
|
-
.a {
|
|
289
|
-
composes: a from './2.css';
|
|
290
|
-
}
|
|
291
|
-
`,
|
|
292
|
-
});
|
|
293
|
-
await expect(async () => {
|
|
294
|
-
await locator.load(getFixturePath('/test/1.css')).catch((e) => {
|
|
295
|
-
e.message = e.message.replace(FIXTURE_DIR_PATH, '<fixtures>');
|
|
296
|
-
throw e;
|
|
297
|
-
});
|
|
298
|
-
}).rejects.toThrowError(`Could not resolve './2.css' in '<fixtures>/test/1.css'`);
|
|
299
|
-
});
|
|
300
|
-
describe('supports sourcemap', () => {
|
|
301
|
-
test('restores original locations from sourcemap', async () => {
|
|
302
|
-
const transformer = createDefaultTransformer();
|
|
303
|
-
const locator = new Locator({ transformer });
|
|
304
|
-
createFixtures({
|
|
305
|
-
'/test/1.scss': dedent `
|
|
306
|
-
.nesting {
|
|
307
|
-
dummy: '';
|
|
308
|
-
.nesting_child {
|
|
309
|
-
dummy: '';
|
|
310
|
-
}
|
|
311
|
-
}
|
|
312
|
-
`,
|
|
313
|
-
});
|
|
314
|
-
const result = await locator.load(getFixturePath('/test/1.scss'));
|
|
315
|
-
expect(result).toMatchInlineSnapshot(`
|
|
316
|
-
{
|
|
317
|
-
dependencies: [],
|
|
318
|
-
tokens: [
|
|
319
|
-
{
|
|
320
|
-
name: "nesting",
|
|
321
|
-
originalLocations: [
|
|
322
|
-
{ filePath: "<fixtures>/test/1.scss", start: { line: 1, column: 1 }, end: { line: 1, column: 8 } },
|
|
323
|
-
{ filePath: "<fixtures>/test/1.scss", start: { line: 3, column: 3 }, end: { line: 3, column: 10 } },
|
|
324
|
-
],
|
|
325
|
-
},
|
|
326
|
-
{
|
|
327
|
-
name: "nesting_child",
|
|
328
|
-
originalLocations: [
|
|
329
|
-
{ filePath: "<fixtures>/test/1.scss", start: { line: 3, column: 3 }, end: { line: 3, column: 16 } },
|
|
330
|
-
],
|
|
331
|
-
},
|
|
332
|
-
],
|
|
333
|
-
}
|
|
334
|
-
`);
|
|
335
|
-
});
|
|
336
|
-
test('treats originalLocation as empty if sourcemap is broken', async () => {
|
|
337
|
-
const uuid = randomUUID();
|
|
338
|
-
createFixtures({
|
|
339
|
-
[`/${uuid}/postcss.config.js`]: dedent `
|
|
340
|
-
module.exports = {
|
|
341
|
-
plugins: [],
|
|
342
|
-
};
|
|
343
|
-
`,
|
|
344
|
-
'/test/1.css': dedent `
|
|
345
|
-
.selector_list_a_1, .selector_list_a_2 {}
|
|
346
|
-
/* In postcss, including newlines in the selector list breaks the sourcemap. */
|
|
347
|
-
.selector_list_b_1,
|
|
348
|
-
.selector_list_b_2 {}
|
|
349
|
-
`,
|
|
350
|
-
});
|
|
351
|
-
const transformer = createDefaultTransformer({ postcssConfig: getFixturePath(`/${uuid}/postcss.config.js`) });
|
|
352
|
-
const locator = new Locator({ transformer });
|
|
353
|
-
const result = await locator.load(getFixturePath('/test/1.css'));
|
|
354
|
-
expect(result).toMatchInlineSnapshot(`
|
|
355
|
-
{
|
|
356
|
-
dependencies: [],
|
|
357
|
-
tokens: [
|
|
358
|
-
{
|
|
359
|
-
name: "selector_list_a_1",
|
|
360
|
-
originalLocations: [
|
|
361
|
-
{ filePath: "<fixtures>/test/1.css", start: { line: 1, column: 1 }, end: { line: 1, column: 18 } },
|
|
362
|
-
],
|
|
363
|
-
},
|
|
364
|
-
{
|
|
365
|
-
name: "selector_list_a_2",
|
|
366
|
-
originalLocations: [
|
|
367
|
-
{ filePath: "<fixtures>/test/1.css", start: { line: 1, column: 1 }, end: { line: 1, column: 18 } },
|
|
368
|
-
],
|
|
369
|
-
},
|
|
370
|
-
{ name: "selector_list_b_1", originalLocations: [{}] },
|
|
371
|
-
{ name: "selector_list_b_2", originalLocations: [{}] },
|
|
372
|
-
],
|
|
373
|
-
}
|
|
374
|
-
`);
|
|
375
|
-
});
|
|
376
|
-
});
|
|
377
|
-
test('ignores http(s) protocol file', async () => {
|
|
378
|
-
createFixtures({
|
|
379
|
-
'/test/1.css': dedent `
|
|
380
|
-
@import 'http://example.com/path/http.css';
|
|
381
|
-
@import 'https://example.com/path/https.css';
|
|
382
|
-
`,
|
|
383
|
-
});
|
|
384
|
-
const result = await locator.load(getFixturePath('/test/1.css'));
|
|
385
|
-
expect(result.dependencies).toStrictEqual([]);
|
|
386
|
-
});
|
|
387
|
-
test('block concurrent calls to load method', async () => {
|
|
388
|
-
createFixtures({
|
|
389
|
-
'/test/1.css': `.a {}`,
|
|
390
|
-
});
|
|
391
|
-
await expect(async () => {
|
|
392
|
-
await Promise.all([locator.load(getFixturePath('/test/1.css')), locator.load(getFixturePath('/test/1.css'))]);
|
|
393
|
-
}).rejects.toThrowError('Cannot call `Locator#load` concurrently.');
|
|
394
|
-
});
|
|
395
|
-
//# sourceMappingURL=index.test.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.test.js","sourceRoot":"","sources":["../../src/locator/index.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
import { type Rule, type AtRule, type Root, type Declaration } from 'postcss';
|
|
2
|
-
import { type ClassName } from 'postcss-selector-parser';
|
|
3
|
-
/** The pair of line number and column number. */
|
|
4
|
-
export type Position = {
|
|
5
|
-
/** The line number in the source file. It is 1-based (compatible with postcss). */
|
|
6
|
-
line: number;
|
|
7
|
-
/** The column number in the source file. It is 1-based (compatible with postcss). */
|
|
8
|
-
column: number;
|
|
9
|
-
};
|
|
10
|
-
/** The original location of class selector. If the original location is not found, all fields are `undefined`. */
|
|
11
|
-
export type Location = {
|
|
12
|
-
filePath: string;
|
|
13
|
-
/** The inclusive starting position of the node's source (compatible with postcss). */
|
|
14
|
-
start: Position;
|
|
15
|
-
/** The inclusive ending position of the node's source (compatible with postcss). */
|
|
16
|
-
end: Position;
|
|
17
|
-
} | {
|
|
18
|
-
filePath: undefined;
|
|
19
|
-
start: undefined;
|
|
20
|
-
end: undefined;
|
|
21
|
-
};
|
|
22
|
-
/**
|
|
23
|
-
* Traverses a local token from the AST and returns its name.
|
|
24
|
-
* @param ast The AST to traverse.
|
|
25
|
-
* @returns The name of the local token.
|
|
26
|
-
*/
|
|
27
|
-
export declare function generateLocalTokenNames(ast: Root): Promise<string[]>;
|
|
28
|
-
/**
|
|
29
|
-
* Get the token's location on the source file.
|
|
30
|
-
* @param rule The rule node that contains the token.
|
|
31
|
-
* @param classSelector The class selector node that contains the token.
|
|
32
|
-
* @returns The token's location on the source file.
|
|
33
|
-
*/
|
|
34
|
-
export declare function getOriginalLocation(rule: Rule, classSelector: ClassName): Location;
|
|
35
|
-
type CollectNodesResult = {
|
|
36
|
-
atImports: AtRule[];
|
|
37
|
-
classSelectors: {
|
|
38
|
-
rule: Rule;
|
|
39
|
-
classSelector: ClassName;
|
|
40
|
-
}[];
|
|
41
|
-
composesDeclarations: Declaration[];
|
|
42
|
-
};
|
|
43
|
-
/**
|
|
44
|
-
* Collect nodes from the AST.
|
|
45
|
-
* @param ast The AST.
|
|
46
|
-
*/
|
|
47
|
-
export declare function collectNodes(ast: Root): CollectNodesResult;
|
|
48
|
-
/**
|
|
49
|
-
* Parse the `@import` rule.
|
|
50
|
-
* @param atImport The `@import` rule to parse.
|
|
51
|
-
* @returns The imported sheet path.
|
|
52
|
-
*/
|
|
53
|
-
export declare function parseAtImport(atImport: AtRule): string | undefined;
|
|
54
|
-
/**
|
|
55
|
-
* Parse `composes` declaration with `from <url>`.
|
|
56
|
-
* If the declaration is not found or do not have `from <url>`, return `undefined`.
|
|
57
|
-
* @param composesDeclaration The `composes` declaration to parse.
|
|
58
|
-
* @returns The information of the declaration.
|
|
59
|
-
*/
|
|
60
|
-
export declare function parseComposesDeclarationWithFromUrl(composesDeclaration: Declaration): {
|
|
61
|
-
from: string;
|
|
62
|
-
tokenNames: string[];
|
|
63
|
-
} | undefined;
|
|
64
|
-
export {};
|
package/dist/locator/postcss.js
DELETED
|
@@ -1,208 +0,0 @@
|
|
|
1
|
-
import postcss from 'postcss';
|
|
2
|
-
import modules from 'postcss-modules';
|
|
3
|
-
import selectorParser from 'postcss-selector-parser';
|
|
4
|
-
import valueParser from 'postcss-value-parser';
|
|
5
|
-
function removeDependenciesPlugin() {
|
|
6
|
-
return {
|
|
7
|
-
postcssPlugin: 'remove-dependencies',
|
|
8
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
9
|
-
AtRule(atRule) {
|
|
10
|
-
if (isAtImportNode(atRule) || isAtValueNode(atRule)) {
|
|
11
|
-
atRule.remove();
|
|
12
|
-
}
|
|
13
|
-
},
|
|
14
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
15
|
-
Declaration(declaration) {
|
|
16
|
-
if (isComposesDeclaration(declaration)) {
|
|
17
|
-
declaration.remove();
|
|
18
|
-
}
|
|
19
|
-
},
|
|
20
|
-
};
|
|
21
|
-
}
|
|
22
|
-
/**
|
|
23
|
-
* Traverses a local token from the AST and returns its name.
|
|
24
|
-
* @param ast The AST to traverse.
|
|
25
|
-
* @returns The name of the local token.
|
|
26
|
-
*/
|
|
27
|
-
export async function generateLocalTokenNames(ast) {
|
|
28
|
-
return new Promise((resolve, reject) => {
|
|
29
|
-
postcss
|
|
30
|
-
.default()
|
|
31
|
-
// postcss-modules collects tokens (i.e., includes external tokens) by following
|
|
32
|
-
// the dependencies specified in the @import and composes properties.
|
|
33
|
-
// However, we do not want `generateLocalTokenNames` to return external tokens.
|
|
34
|
-
// So we remove the @import and composes properties beforehand.
|
|
35
|
-
.use(removeDependenciesPlugin())
|
|
36
|
-
.use(modules({
|
|
37
|
-
getJSON: (_cssFileName, json) => {
|
|
38
|
-
resolve(Object.keys(json));
|
|
39
|
-
},
|
|
40
|
-
}))
|
|
41
|
-
// NOTE: `process` modifies ast, so clone it.
|
|
42
|
-
.process(ast.clone())
|
|
43
|
-
.catch(reject);
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
/**
|
|
47
|
-
* Get the token's location on the source file.
|
|
48
|
-
* @param rule The rule node that contains the token.
|
|
49
|
-
* @param classSelector The class selector node that contains the token.
|
|
50
|
-
* @returns The token's location on the source file.
|
|
51
|
-
*/
|
|
52
|
-
export function getOriginalLocation(rule, classSelector) {
|
|
53
|
-
// The node derived from `postcss.parse` always has `source` property. Therefore, this line is unreachable.
|
|
54
|
-
if (rule.source === undefined || classSelector.source === undefined)
|
|
55
|
-
throw new Error('Node#source is undefined');
|
|
56
|
-
// The node derived from `postcss.parse` always has `start` and `end` property. Therefore, this line is unreachable.
|
|
57
|
-
if (rule.source.start === undefined || classSelector.source.start === undefined)
|
|
58
|
-
throw new Error('Node#start is undefined');
|
|
59
|
-
if (rule.source.end === undefined || classSelector.source.end === undefined)
|
|
60
|
-
throw new Error('Node#end is undefined');
|
|
61
|
-
if (rule.source.input.file === undefined)
|
|
62
|
-
throw new Error('Node#input.file is undefined');
|
|
63
|
-
const classSelectorStartPosition = {
|
|
64
|
-
// The line is 1-based.
|
|
65
|
-
line: rule.source.start.line + (classSelector.source.start.line - 1),
|
|
66
|
-
// The column is 1-based.
|
|
67
|
-
column: rule.source.start.column + (classSelector.source.start.column - 1),
|
|
68
|
-
};
|
|
69
|
-
const classSelectorEndPosition = {
|
|
70
|
-
line: classSelectorStartPosition.line,
|
|
71
|
-
// The column is inclusive.
|
|
72
|
-
column: classSelectorStartPosition.column + classSelector.value.length,
|
|
73
|
-
};
|
|
74
|
-
const classSelectorLocation = {
|
|
75
|
-
filePath: rule.source.input.file,
|
|
76
|
-
start: classSelectorStartPosition,
|
|
77
|
-
end: classSelectorEndPosition,
|
|
78
|
-
};
|
|
79
|
-
if (!rule.source.input.map)
|
|
80
|
-
return classSelectorLocation;
|
|
81
|
-
const classSelectorOrigin = rule.source.input.origin(classSelectorLocation.start.line,
|
|
82
|
-
// The column of `Input#origin` is 0-based. This behavior is undocumented and probably a postcss's bug.
|
|
83
|
-
// TODO: Open PR to postcss/postcss
|
|
84
|
-
classSelectorLocation.start.column - 1);
|
|
85
|
-
if (classSelectorOrigin === false || classSelectorOrigin.file === undefined) {
|
|
86
|
-
return { filePath: undefined, start: undefined, end: undefined };
|
|
87
|
-
}
|
|
88
|
-
return {
|
|
89
|
-
filePath: classSelectorOrigin.file,
|
|
90
|
-
start: {
|
|
91
|
-
line: classSelectorOrigin.line,
|
|
92
|
-
column: classSelectorOrigin.column + 1,
|
|
93
|
-
},
|
|
94
|
-
end: {
|
|
95
|
-
line: classSelectorOrigin.line,
|
|
96
|
-
column: classSelectorOrigin.column + classSelector.value.length + 1,
|
|
97
|
-
},
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
function isAtRuleNode(node) {
|
|
101
|
-
return node.type === 'atrule';
|
|
102
|
-
}
|
|
103
|
-
function isAtImportNode(node) {
|
|
104
|
-
return isAtRuleNode(node) && node.name === 'import';
|
|
105
|
-
}
|
|
106
|
-
function isAtValueNode(node) {
|
|
107
|
-
return isAtRuleNode(node) && node.name === 'value';
|
|
108
|
-
}
|
|
109
|
-
function isRuleNode(node) {
|
|
110
|
-
return node.type === 'rule';
|
|
111
|
-
}
|
|
112
|
-
function isDeclaration(node) {
|
|
113
|
-
return node.type === 'decl';
|
|
114
|
-
}
|
|
115
|
-
function isComposesDeclaration(node) {
|
|
116
|
-
return isDeclaration(node) && node.prop === 'composes';
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Collect nodes from the AST.
|
|
120
|
-
* @param ast The AST.
|
|
121
|
-
*/
|
|
122
|
-
export function collectNodes(ast) {
|
|
123
|
-
const atImports = [];
|
|
124
|
-
const classSelectors = [];
|
|
125
|
-
const composesDeclarations = [];
|
|
126
|
-
ast.walk((node) => {
|
|
127
|
-
if (isAtImportNode(node)) {
|
|
128
|
-
atImports.push(node);
|
|
129
|
-
}
|
|
130
|
-
else if (isRuleNode(node)) {
|
|
131
|
-
// In `rule.selector` comes the following string:
|
|
132
|
-
// 1. ".foo"
|
|
133
|
-
// 2. ".foo:hover"
|
|
134
|
-
// 3. ".foo, .bar"
|
|
135
|
-
selectorParser((selectors) => {
|
|
136
|
-
selectors.walk((selector) => {
|
|
137
|
-
if (selector.type === 'class') {
|
|
138
|
-
// In `selector.value` comes the following string:
|
|
139
|
-
// 1. "foo"
|
|
140
|
-
// 2. "bar"
|
|
141
|
-
classSelectors.push({ rule: node, classSelector: selector });
|
|
142
|
-
}
|
|
143
|
-
});
|
|
144
|
-
}).processSync(node);
|
|
145
|
-
}
|
|
146
|
-
else if (isComposesDeclaration(node)) {
|
|
147
|
-
composesDeclarations.push(node);
|
|
148
|
-
}
|
|
149
|
-
});
|
|
150
|
-
return { atImports, classSelectors, composesDeclarations };
|
|
151
|
-
}
|
|
152
|
-
/**
|
|
153
|
-
* Parse the `@import` rule.
|
|
154
|
-
* @param atImport The `@import` rule to parse.
|
|
155
|
-
* @returns The imported sheet path.
|
|
156
|
-
*/
|
|
157
|
-
export function parseAtImport(atImport) {
|
|
158
|
-
const firstNode = valueParser(atImport.params).nodes[0];
|
|
159
|
-
if (firstNode === undefined)
|
|
160
|
-
return undefined;
|
|
161
|
-
if (firstNode.type === 'string')
|
|
162
|
-
return firstNode.value;
|
|
163
|
-
if (firstNode.type === 'function' && firstNode.value === 'url') {
|
|
164
|
-
if (firstNode.nodes[0] === undefined)
|
|
165
|
-
return undefined;
|
|
166
|
-
if (firstNode.nodes[0].type === 'string')
|
|
167
|
-
return firstNode.nodes[0].value;
|
|
168
|
-
if (firstNode.nodes[0].type === 'word')
|
|
169
|
-
return firstNode.nodes[0].value;
|
|
170
|
-
}
|
|
171
|
-
return undefined;
|
|
172
|
-
}
|
|
173
|
-
/**
|
|
174
|
-
* Parse `composes` declaration with `from <url>`.
|
|
175
|
-
* If the declaration is not found or do not have `from <url>`, return `undefined`.
|
|
176
|
-
* @param composesDeclaration The `composes` declaration to parse.
|
|
177
|
-
* @returns The information of the declaration.
|
|
178
|
-
*/
|
|
179
|
-
export function parseComposesDeclarationWithFromUrl(composesDeclaration) {
|
|
180
|
-
// NOTE: `composes` property syntax is...
|
|
181
|
-
// - syntax: `composes: <class-name> [...<class-name>] [from <url>];`
|
|
182
|
-
// - variables:
|
|
183
|
-
// - `<class-name>`: `<sting>`
|
|
184
|
-
// - `<url>`: `<string>`
|
|
185
|
-
// - ref:
|
|
186
|
-
// - https://github.com/css-modules/css-modules#composition
|
|
187
|
-
// - https://github.com/css-modules/css-modules#composing-from-other-files
|
|
188
|
-
// - https://github.com/css-modules/postcss-modules-extract-imports#specification
|
|
189
|
-
const nodes = valueParser(composesDeclaration.value).nodes;
|
|
190
|
-
if (nodes.length < 5)
|
|
191
|
-
return undefined;
|
|
192
|
-
const classNamesOrSpaces = nodes.slice(0, -3);
|
|
193
|
-
const [from, , url] = nodes.slice(-3);
|
|
194
|
-
const classNames = classNamesOrSpaces.filter((node) => node.type === 'word');
|
|
195
|
-
// validate nodes
|
|
196
|
-
if (from === undefined)
|
|
197
|
-
return undefined;
|
|
198
|
-
if (from.type !== 'word' || from.value !== 'from')
|
|
199
|
-
return undefined;
|
|
200
|
-
if (url === undefined)
|
|
201
|
-
return undefined;
|
|
202
|
-
if (url.type !== 'string')
|
|
203
|
-
return undefined;
|
|
204
|
-
if (classNames.length === 0)
|
|
205
|
-
return undefined;
|
|
206
|
-
return { from: url.value, tokenNames: classNames.map((node) => node.value) };
|
|
207
|
-
}
|
|
208
|
-
//# sourceMappingURL=postcss.js.map
|