happy-css-modules 0.2.1 → 0.4.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/README.md +15 -18
- package/dist/cli.js +15 -4
- package/dist/cli.js.map +1 -1
- package/dist/cli.test.js +10 -0
- package/dist/cli.test.js.map +1 -1
- package/dist/emitter/dts.js +3 -4
- package/dist/emitter/dts.js.map +1 -1
- package/dist/integration-test/go-to-definition.test.js +9 -8
- package/dist/integration-test/go-to-definition.test.js.map +1 -1
- package/dist/loader/index.js +6 -10
- package/dist/loader/index.js.map +1 -1
- package/dist/loader/index.test.js +22 -3
- package/dist/loader/index.test.js.map +1 -1
- package/dist/resolver/index.d.ts +3 -1
- package/dist/resolver/index.js +17 -14
- package/dist/resolver/index.js.map +1 -1
- package/dist/resolver/webpack-resolver.d.ts +13 -1
- package/dist/resolver/webpack-resolver.js +73 -59
- package/dist/resolver/webpack-resolver.js.map +1 -1
- package/dist/resolver/webpack-resolver.test.js +34 -7
- package/dist/resolver/webpack-resolver.test.js.map +1 -1
- package/dist/runner.d.ts +12 -0
- package/dist/runner.js +16 -14
- package/dist/runner.js.map +1 -1
- package/dist/runner.test.js +41 -11
- package/dist/runner.test.js.map +1 -1
- package/dist/test/tsserver.d.ts +10 -6
- package/dist/test/tsserver.js +94 -85
- package/dist/test/tsserver.js.map +1 -1
- package/dist/test/util.js +9 -12
- package/dist/test/util.js.map +1 -1
- package/dist/transformer/index.js +11 -9
- package/dist/transformer/index.js.map +1 -1
- package/dist/transformer/less-transformer.js +7 -5
- package/dist/transformer/less-transformer.js.map +1 -1
- package/dist/transformer/less-transformer.test.js +11 -6
- package/dist/transformer/less-transformer.test.js.map +1 -1
- package/dist/transformer/scss-transformer.js +1 -48
- package/dist/transformer/scss-transformer.js.map +1 -1
- package/dist/transformer/scss-transformer.test.js +11 -5
- package/dist/transformer/scss-transformer.test.js.map +1 -1
- package/package.json +3 -3
- package/src/cli.test.ts +14 -0
- package/src/cli.ts +15 -4
- package/src/integration-test/go-to-definition.test.ts +10 -8
- package/src/loader/index.test.ts +22 -3
- package/src/loader/index.ts +3 -4
- package/src/resolver/index.ts +21 -12
- package/src/resolver/webpack-resolver.test.ts +44 -8
- package/src/resolver/webpack-resolver.ts +90 -57
- package/src/runner.test.ts +45 -12
- package/src/runner.ts +29 -10
- package/src/test/tsserver.ts +106 -129
- package/src/transformer/index.ts +10 -8
- package/src/transformer/less-transformer.test.ts +12 -6
- package/src/transformer/less-transformer.ts +6 -4
- package/src/transformer/scss-transformer.test.ts +12 -5
- package/src/transformer/scss-transformer.ts +0 -51
package/src/test/tsserver.ts
CHANGED
|
@@ -1,11 +1,21 @@
|
|
|
1
1
|
import { readFileSync } from 'fs';
|
|
2
|
+
import { mkdir, writeFile as nativeWriteFile } from 'fs/promises';
|
|
3
|
+
import { dirname } from 'path';
|
|
2
4
|
import { fileURLToPath } from 'url';
|
|
5
|
+
import { promisify } from 'util';
|
|
3
6
|
import serverHarness from '@typescript/server-harness';
|
|
7
|
+
import _glob from 'glob';
|
|
4
8
|
import { resolve } from 'import-meta-resolve';
|
|
5
9
|
import lineColumn from 'line-column';
|
|
10
|
+
import type { UpdateOpenRequest, DefinitionResponse, DefinitionRequest } from 'typescript/lib/protocol.js';
|
|
6
11
|
import { getFixturePath } from './util.js';
|
|
7
12
|
|
|
8
|
-
|
|
13
|
+
const glob = promisify(_glob);
|
|
14
|
+
|
|
15
|
+
async function writeFile(path: string, content: string): Promise<void> {
|
|
16
|
+
await mkdir(dirname(path), { recursive: true });
|
|
17
|
+
return nativeWriteFile(path, content, 'utf8');
|
|
18
|
+
}
|
|
9
19
|
|
|
10
20
|
type Definition = {
|
|
11
21
|
/** The path of the destination file */
|
|
@@ -28,42 +38,7 @@ type Definition = {
|
|
|
28
38
|
};
|
|
29
39
|
};
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
seq: number;
|
|
33
|
-
type: 'response';
|
|
34
|
-
command: 'definition';
|
|
35
|
-
success: boolean;
|
|
36
|
-
body: [
|
|
37
|
-
{
|
|
38
|
-
/** The path of the destination file */
|
|
39
|
-
file: string;
|
|
40
|
-
/** inclusive */
|
|
41
|
-
start: {
|
|
42
|
-
/** line, 1-based */
|
|
43
|
-
line: number;
|
|
44
|
-
/** column, 1-based */
|
|
45
|
-
offset: number;
|
|
46
|
-
};
|
|
47
|
-
/** exclusive */
|
|
48
|
-
end: {
|
|
49
|
-
/** line, 1-based */
|
|
50
|
-
line: number;
|
|
51
|
-
/** column, 1-based */
|
|
52
|
-
offset: number;
|
|
53
|
-
};
|
|
54
|
-
},
|
|
55
|
-
];
|
|
56
|
-
};
|
|
57
|
-
|
|
58
|
-
export async function getIdentifierDefinitions(filePath: string, identifier: string): Promise<Definition[]> {
|
|
59
|
-
const results = await getMultipleIdentifierDefinitions(filePath, [identifier]);
|
|
60
|
-
return results[0]!.definitions;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
export async function getMultipleIdentifierDefinitions(
|
|
64
|
-
filePath: string,
|
|
65
|
-
identifiers: string[],
|
|
66
|
-
): Promise<{ identifier: string; definitions: Definition[] }[]> {
|
|
41
|
+
export async function createTSServer() {
|
|
67
42
|
const server = serverHarness.launchServer(
|
|
68
43
|
fileURLToPath(await resolve('typescript/lib/tsserver.js', import.meta.url)),
|
|
69
44
|
[
|
|
@@ -72,105 +47,107 @@ export async function getMultipleIdentifierDefinitions(
|
|
|
72
47
|
],
|
|
73
48
|
);
|
|
74
49
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
].join('\n');
|
|
80
|
-
|
|
81
|
-
await server.message({
|
|
82
|
-
type: 'request',
|
|
83
|
-
command: 'updateOpen',
|
|
84
|
-
arguments: {
|
|
85
|
-
changedFiles: [],
|
|
86
|
-
closedFiles: [],
|
|
87
|
-
openFiles: [
|
|
88
|
-
{
|
|
89
|
-
file: tmpFilePath,
|
|
90
|
-
fileContent: tmpFileContent,
|
|
91
|
-
projectRootPath: getFixturePath('/server-harness'),
|
|
92
|
-
scriptKindName: 'TS', // It's easy to get this wrong when copy-pasting
|
|
93
|
-
},
|
|
94
|
-
],
|
|
50
|
+
return {
|
|
51
|
+
async getIdentifierDefinitions(filePath: string, identifier: string): Promise<Definition[]> {
|
|
52
|
+
const results = await this.getMultipleIdentifierDefinitions(filePath, [identifier]);
|
|
53
|
+
return results[0]!.definitions;
|
|
95
54
|
},
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
55
|
+
async getMultipleIdentifierDefinitions(
|
|
56
|
+
filePath: string,
|
|
57
|
+
identifiers: string[],
|
|
58
|
+
): Promise<{ identifier: string; definitions: Definition[] }[]> {
|
|
59
|
+
const tmpFilePath = getFixturePath('/server-harness/tmp.ts');
|
|
60
|
+
const tmpFileContent = [
|
|
61
|
+
`import styles from '${filePath}';`,
|
|
62
|
+
...identifiers.map((identifier) => `styles.${identifier};`),
|
|
63
|
+
].join('\n');
|
|
64
|
+
await writeFile(tmpFilePath, tmpFileContent);
|
|
65
|
+
|
|
66
|
+
await this.refreshCache();
|
|
67
|
+
|
|
68
|
+
const results: { identifier: string; definitions: Definition[] }[] = [];
|
|
69
|
+
|
|
70
|
+
for (let i = 0; i < identifiers.length; i++) {
|
|
71
|
+
const response: DefinitionResponse = await server.message({
|
|
72
|
+
seq: 0,
|
|
73
|
+
type: 'request',
|
|
74
|
+
command: 'definition',
|
|
75
|
+
arguments: {
|
|
76
|
+
file: tmpFilePath,
|
|
77
|
+
line: i + 2, // line, 1-based
|
|
78
|
+
offset: 8, // column, 1-based
|
|
79
|
+
},
|
|
80
|
+
} as DefinitionRequest);
|
|
81
|
+
const definitions: Definition[] = response.body!.map((definition) => {
|
|
82
|
+
const { file, start, end } = definition;
|
|
83
|
+
const fileContent = readFileSync(file, 'utf-8');
|
|
84
|
+
const startIndex = lineColumn(fileContent).toIndex(start.line, start.offset);
|
|
85
|
+
const endIndex = lineColumn(fileContent).toIndex(end.line, end.offset);
|
|
86
|
+
const text = fileContent.slice(startIndex, endIndex);
|
|
87
|
+
return { file, text, start, end };
|
|
88
|
+
});
|
|
89
|
+
results.push({ identifier: identifiers[i]!, definitions });
|
|
90
|
+
}
|
|
91
|
+
return results;
|
|
92
|
+
},
|
|
93
|
+
async getModuleDefinitions(filePath: string): Promise<Definition[]> {
|
|
94
|
+
await this.refreshCache();
|
|
122
95
|
|
|
123
|
-
|
|
124
|
-
}
|
|
96
|
+
const tmpFilePath = getFixturePath('/server-harness/tmp.ts');
|
|
97
|
+
const tmpFileContent = `import styles from '${filePath}';`;
|
|
125
98
|
|
|
126
|
-
|
|
127
|
-
const server = serverHarness.launchServer(
|
|
128
|
-
fileURLToPath(await resolve('typescript/lib/tsserver.js', import.meta.url)),
|
|
129
|
-
[
|
|
130
|
-
// ATA generates some extra network traffic and isn't usually relevant when profiling
|
|
131
|
-
'--disableAutomaticTypingAcquisition',
|
|
132
|
-
],
|
|
133
|
-
);
|
|
99
|
+
await writeFile(tmpFilePath, tmpFileContent);
|
|
134
100
|
|
|
135
|
-
|
|
136
|
-
const tmpFileContent = `import styles from '${filePath}';`;
|
|
101
|
+
await this.refreshCache();
|
|
137
102
|
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
closedFiles: [],
|
|
144
|
-
openFiles: [
|
|
145
|
-
{
|
|
103
|
+
const response: DefinitionResponse = await server.message({
|
|
104
|
+
seq: 0,
|
|
105
|
+
type: 'request',
|
|
106
|
+
command: 'definition',
|
|
107
|
+
arguments: {
|
|
146
108
|
file: tmpFilePath,
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
scriptKindName: 'TS', // It's easy to get this wrong when copy-pasting
|
|
109
|
+
line: 1, // line, 1-based
|
|
110
|
+
offset: 20, // column, 1-based
|
|
150
111
|
},
|
|
151
|
-
|
|
112
|
+
} as DefinitionRequest);
|
|
113
|
+
const definitions: Definition[] = response.body!.map((definition) => {
|
|
114
|
+
const { file, start, end } = definition;
|
|
115
|
+
const fileContent = readFileSync(file, 'utf-8');
|
|
116
|
+
const startIndex = lineColumn(fileContent).toIndex(start.line, start.offset);
|
|
117
|
+
const endIndex = lineColumn(fileContent).toIndex(end.line, end.offset);
|
|
118
|
+
const text = fileContent.slice(startIndex, endIndex);
|
|
119
|
+
return { file, text, start, end };
|
|
120
|
+
});
|
|
121
|
+
return definitions;
|
|
152
122
|
},
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
123
|
+
async refreshCache() {
|
|
124
|
+
// tsserver caches the contents of opened files.
|
|
125
|
+
// When a file is updated, its cache remains with the old content.
|
|
126
|
+
// Therefore we need to overwrite the cache with the latest content.
|
|
127
|
+
|
|
128
|
+
const fixtureFilePaths = await glob(getFixturePath('/**/*.ts'), { dot: true });
|
|
129
|
+
// latest contents
|
|
130
|
+
const openFiles: UpdateOpenRequest['arguments']['openFiles'] = fixtureFilePaths.map((filePath) => ({
|
|
131
|
+
file: filePath,
|
|
132
|
+
fileContent: readFileSync(filePath, 'utf-8'),
|
|
133
|
+
projectRootPath: getFixturePath('/server-harness'),
|
|
134
|
+
scriptKindName: 'TS', // It's easy to get this wrong when copy-pasting
|
|
135
|
+
}));
|
|
136
|
+
|
|
137
|
+
// override the cache
|
|
138
|
+
await server.message({
|
|
139
|
+
seq: 0,
|
|
140
|
+
type: 'request',
|
|
141
|
+
command: 'updateOpen',
|
|
142
|
+
arguments: {
|
|
143
|
+
changedFiles: [],
|
|
144
|
+
closedFiles: [],
|
|
145
|
+
openFiles,
|
|
146
|
+
},
|
|
147
|
+
} as UpdateOpenRequest);
|
|
162
148
|
},
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
const startIndex = lineColumn(fileContent).toIndex(start.line, start.offset);
|
|
168
|
-
const endIndex = lineColumn(fileContent).toIndex(end.line, end.offset);
|
|
169
|
-
const text = fileContent.slice(startIndex, endIndex);
|
|
170
|
-
return { file, text, start, end };
|
|
171
|
-
});
|
|
172
|
-
|
|
173
|
-
await server.message({ command: 'exit' });
|
|
174
|
-
|
|
175
|
-
return definitions;
|
|
149
|
+
exit: async () => {
|
|
150
|
+
await server.message({ command: 'exit' });
|
|
151
|
+
},
|
|
152
|
+
};
|
|
176
153
|
}
|
package/src/transformer/index.ts
CHANGED
|
@@ -36,14 +36,16 @@ export const handleImportError = (packageName: string) => (e: unknown) => {
|
|
|
36
36
|
throw e;
|
|
37
37
|
};
|
|
38
38
|
|
|
39
|
-
export const createDefaultTransformer: () => Transformer = () =>
|
|
39
|
+
export const createDefaultTransformer: () => Transformer = () => {
|
|
40
40
|
const scssTransformer = createScssTransformer();
|
|
41
41
|
const lessTransformer = createLessTransformer();
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
42
|
+
return async (source, options) => {
|
|
43
|
+
if (options.from.endsWith('.scss')) {
|
|
44
|
+
return scssTransformer(source, options);
|
|
45
|
+
} else if (options.from.endsWith('.less')) {
|
|
46
|
+
return lessTransformer(source, options);
|
|
47
|
+
}
|
|
48
|
+
// TODO: support postcss
|
|
49
|
+
return false;
|
|
50
|
+
};
|
|
49
51
|
};
|
|
@@ -117,12 +117,6 @@ test('resolves specifier using resolver', async () => {
|
|
|
117
117
|
'/test/1.less': dedent`
|
|
118
118
|
@import 'package-1';
|
|
119
119
|
@import 'package-2';
|
|
120
|
-
// NOTE: less does not resolve files that are http(s) protocol.
|
|
121
|
-
// Therefore, the resolver will not be called for those files,
|
|
122
|
-
// and they will not be included in result.dependencies.
|
|
123
|
-
@import url('https://mizdra.net/css/index.css');
|
|
124
|
-
// However, if Content-Type is set to text/css, less will try to resolve it and inline it.
|
|
125
|
-
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,900;1,900&display=swap');
|
|
126
120
|
`,
|
|
127
121
|
'/node_modules/package-1/index.css': `.a {}`,
|
|
128
122
|
'/node_modules/package-2/index.less': `.a {}`,
|
|
@@ -134,3 +128,15 @@ test('resolves specifier using resolver', async () => {
|
|
|
134
128
|
[getFixturePath('/node_modules/package-1/index.css'), getFixturePath('/node_modules/package-2/index.less')].sort(),
|
|
135
129
|
);
|
|
136
130
|
});
|
|
131
|
+
|
|
132
|
+
test('ignores http(s) protocol file', async () => {
|
|
133
|
+
createFixtures({
|
|
134
|
+
'/test/1.less': dedent`
|
|
135
|
+
@import 'http://example.com/path/http.css';
|
|
136
|
+
@import 'https://example.com/path/https.css';
|
|
137
|
+
@import 'https://example.com/path/less.less';
|
|
138
|
+
`,
|
|
139
|
+
});
|
|
140
|
+
const result = await loader.load(getFixturePath('/test/1.less'));
|
|
141
|
+
expect(result.dependencies).toStrictEqual([]);
|
|
142
|
+
});
|
|
@@ -2,7 +2,7 @@ import type { Transformer } from '../index.js';
|
|
|
2
2
|
import type { TransformerOptions } from './index.js';
|
|
3
3
|
import { handleImportError } from './index.js';
|
|
4
4
|
|
|
5
|
-
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
6
6
|
function createLessPluginResolver(Less: typeof import('less'), options: TransformerOptions): Less.Plugin {
|
|
7
7
|
class ResolverFileManager extends Less.FileManager {
|
|
8
8
|
options: TransformerOptions;
|
|
@@ -10,8 +10,8 @@ function createLessPluginResolver(Less: typeof import('less'), options: Transfor
|
|
|
10
10
|
super();
|
|
11
11
|
this.options = options;
|
|
12
12
|
}
|
|
13
|
-
public override supports(
|
|
14
|
-
return
|
|
13
|
+
public override supports(): boolean {
|
|
14
|
+
return true;
|
|
15
15
|
}
|
|
16
16
|
public override async loadFile(
|
|
17
17
|
filename: string,
|
|
@@ -19,6 +19,9 @@ function createLessPluginResolver(Less: typeof import('less'), options: Transfor
|
|
|
19
19
|
options: Less.LoadFileOptions,
|
|
20
20
|
environment: Less.Environment,
|
|
21
21
|
): Promise<Less.FileLoadResult> {
|
|
22
|
+
// The http/https file is treated as an empty file.
|
|
23
|
+
if (this.options.isIgnoredSpecifier(filename)) return { contents: '', filename };
|
|
24
|
+
|
|
22
25
|
const resolved = await this.options.resolver(filename, { request: currentDirectory });
|
|
23
26
|
return super.loadFile(resolved, currentDirectory, options, environment);
|
|
24
27
|
}
|
|
@@ -39,7 +42,6 @@ function createLessPluginResolver(Less: typeof import('less'), options: Transfor
|
|
|
39
42
|
}
|
|
40
43
|
|
|
41
44
|
export const createLessTransformer: () => Transformer = () => {
|
|
42
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
43
45
|
let less: typeof import('less');
|
|
44
46
|
return async (source, options) => {
|
|
45
47
|
less ??= (await import('less').catch(handleImportError('less'))).default;
|
|
@@ -126,11 +126,6 @@ test('resolves specifier using resolver', async () => {
|
|
|
126
126
|
'/test/1.scss': dedent`
|
|
127
127
|
@import 'package-1';
|
|
128
128
|
@import 'package-2';
|
|
129
|
-
// NOTE: sass does not resolve files that are http(s) protocol.
|
|
130
|
-
// Therefore, the resolver will not be called for those files,
|
|
131
|
-
// and they will not be included in result.dependencies.
|
|
132
|
-
@import 'http://example.com/path/1.css';
|
|
133
|
-
@import 'https://example.com/path/1.css';
|
|
134
129
|
`,
|
|
135
130
|
'/node_modules/package-1/index.css': `.a {}`,
|
|
136
131
|
'/node_modules/package-2/index.scss': `.a {}`,
|
|
@@ -140,3 +135,15 @@ test('resolves specifier using resolver', async () => {
|
|
|
140
135
|
['/node_modules/package-1/index.css', '/node_modules/package-2/index.scss'].map(getFixturePath),
|
|
141
136
|
);
|
|
142
137
|
});
|
|
138
|
+
|
|
139
|
+
test('ignores http(s) protocol file', async () => {
|
|
140
|
+
createFixtures({
|
|
141
|
+
'/test/1.scss': dedent`
|
|
142
|
+
@import 'http://example.com/path/http.css';
|
|
143
|
+
@import 'https://example.com/path/https.css';
|
|
144
|
+
@import 'https://example.com/path/scss.scss';
|
|
145
|
+
`,
|
|
146
|
+
});
|
|
147
|
+
const result = await loader.load(getFixturePath('/test/1.scss'));
|
|
148
|
+
expect(result.dependencies).toStrictEqual([]);
|
|
149
|
+
});
|
|
@@ -7,48 +7,6 @@ import type { LegacyResult } from 'sass';
|
|
|
7
7
|
import type { Transformer, TransformerOptions } from './index.js';
|
|
8
8
|
import { handleImportError } from './index.js';
|
|
9
9
|
|
|
10
|
-
// const IS_JEST_ENVIRONMENT = process.env.JEST_WORKER_ID !== undefined;
|
|
11
|
-
|
|
12
|
-
// function verifyJestEnvironment() {
|
|
13
|
-
// if (
|
|
14
|
-
// !(
|
|
15
|
-
// 'window' in global &&
|
|
16
|
-
// 'location' in global &&
|
|
17
|
-
// // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
18
|
-
// 'href' in (global as any).location &&
|
|
19
|
-
// // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
20
|
-
// typeof (global as any).location.href === 'string' &&
|
|
21
|
-
// // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
22
|
-
// (global as any).location.href.startsWith('http://')
|
|
23
|
-
// )
|
|
24
|
-
// ) {
|
|
25
|
-
// throw new Error(
|
|
26
|
-
// 'To use dart-sass with jest, dummy `global.window` and `global.location.href` must be set. See https://github.com/sass/dart-sass/issues/1692#issuecomment-1229219993 .',
|
|
27
|
-
// );
|
|
28
|
-
// }
|
|
29
|
-
// }
|
|
30
|
-
|
|
31
|
-
// const createImporterForJest: (from: string) => Importer<'async'> = (from) => ({
|
|
32
|
-
// canonicalize(url) {
|
|
33
|
-
// // NOTE: The format of `url` changes depending on the import source.
|
|
34
|
-
// //
|
|
35
|
-
// // - When `from === '/test/1.scss'` and `@import './2.scss'` in `/test/1.scss` is resolved, `url === '2.scss'`.
|
|
36
|
-
// // - When `from === '/test/1.scss'` and `@import './3.scss'` in `/test/2.scss` is resolved, `url === 'file:///test/3.scss'`.
|
|
37
|
-
// //
|
|
38
|
-
// // That is, the paths of @import statements written to the `from` file is passed through unresolved,
|
|
39
|
-
// // but paths written to other files is passed through resolved to absolute paths.
|
|
40
|
-
// return new URL(url, pathToFileURL(from));
|
|
41
|
-
// },
|
|
42
|
-
// async load(canonicalUrl) {
|
|
43
|
-
// return {
|
|
44
|
-
// contents: await readFile(fileURLToPath(canonicalUrl.href), 'utf8'),
|
|
45
|
-
// syntax: 'scss',
|
|
46
|
-
// sourceMapUrl: canonicalUrl,
|
|
47
|
-
// };
|
|
48
|
-
// },
|
|
49
|
-
// });
|
|
50
|
-
|
|
51
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
52
10
|
async function renderSass(sass: typeof import('sass'), source: string, options: TransformerOptions) {
|
|
53
11
|
return new Promise<LegacyResult>((resolve, reject) => {
|
|
54
12
|
sass.render(
|
|
@@ -76,19 +34,10 @@ async function renderSass(sass: typeof import('sass'), source: string, options:
|
|
|
76
34
|
}
|
|
77
35
|
|
|
78
36
|
export const createScssTransformer: () => Transformer = () => {
|
|
79
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-imports
|
|
80
37
|
let sass: typeof import('sass');
|
|
81
38
|
return async (source, options) => {
|
|
82
39
|
sass ??= (await import('sass').catch(handleImportError('sass'))).default;
|
|
83
40
|
const result = await renderSass(sass, source, options);
|
|
84
41
|
return { css: result.css.toString(), map: result.map!.toString(), dependencies: result.stats.includedFiles };
|
|
85
|
-
|
|
86
|
-
// if (IS_JEST_ENVIRONMENT) verifyJestEnvironment();
|
|
87
|
-
// const result = await sass.default.compileStringAsync(source, {
|
|
88
|
-
// url: pathToFileURL(from),
|
|
89
|
-
// sourceMap: true,
|
|
90
|
-
// importers: IS_JEST_ENVIRONMENT ? [createImporterForJest(from)] : [],
|
|
91
|
-
// });
|
|
92
|
-
// return { css: result.css, map: result.sourceMap!, dependencies: result.loadedUrls };
|
|
93
42
|
};
|
|
94
43
|
};
|