@css-modules-kit/core 0.7.0 → 0.8.1
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/dist/checker.d.ts +9 -2
- package/dist/checker.d.ts.map +1 -1
- package/dist/checker.js +15 -14
- package/dist/checker.js.map +1 -1
- package/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +30 -24
- package/dist/config.js.map +1 -1
- package/dist/diagnostic.d.ts.map +1 -1
- package/dist/diagnostic.js +9 -15
- package/dist/diagnostic.js.map +1 -1
- package/dist/dts-generator.d.ts +2 -6
- package/dist/dts-generator.d.ts.map +1 -1
- package/dist/dts-generator.js +211 -63
- package/dist/dts-generator.js.map +1 -1
- package/dist/error.js +2 -7
- package/dist/error.js.map +1 -1
- package/dist/export-builder.js +1 -4
- package/dist/export-builder.js.map +1 -1
- package/dist/file.js +17 -30
- package/dist/file.js.map +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +12 -44
- package/dist/index.js.map +1 -1
- package/dist/parser/at-import-parser.js +3 -9
- package/dist/parser/at-import-parser.js.map +1 -1
- package/dist/parser/at-value-parser.js +1 -4
- package/dist/parser/at-value-parser.js.map +1 -1
- package/dist/parser/css-module-parser.js +15 -21
- package/dist/parser/css-module-parser.js.map +1 -1
- package/dist/parser/key-frame-parser.js +1 -4
- package/dist/parser/key-frame-parser.js.map +1 -1
- package/dist/parser/rule-parser.js +7 -13
- package/dist/parser/rule-parser.js.map +1 -1
- package/dist/path.d.ts +0 -1
- package/dist/path.d.ts.map +1 -1
- package/dist/path.js +16 -31
- package/dist/path.js.map +1 -1
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +13 -40
- package/dist/resolver.js.map +1 -1
- package/dist/type.d.ts +1 -1
- package/dist/type.d.ts.map +1 -1
- package/dist/type.js +1 -2
- package/dist/util.d.ts +1 -0
- package/dist/util.d.ts.map +1 -1
- package/dist/util.js +6 -8
- package/dist/util.js.map +1 -1
- package/package.json +2 -2
- package/src/checker.ts +19 -16
- package/src/config.ts +13 -0
- package/src/diagnostic.ts +2 -0
- package/src/dts-generator.ts +216 -66
- package/src/index.ts +3 -2
- package/src/path.ts +0 -3
- package/src/resolver.ts +7 -29
- package/src/type.ts +1 -1
- package/src/typing/typescript.d.ts +1 -1
- package/src/util.ts +4 -0
package/src/checker.ts
CHANGED
|
@@ -4,23 +4,24 @@ import type {
|
|
|
4
4
|
AtValueTokenImporterValue,
|
|
5
5
|
CSSModule,
|
|
6
6
|
Diagnostic,
|
|
7
|
-
|
|
7
|
+
ExportRecord,
|
|
8
8
|
Location,
|
|
9
9
|
MatchesPattern,
|
|
10
10
|
Resolver,
|
|
11
11
|
TokenImporter,
|
|
12
12
|
} from './type.js';
|
|
13
|
-
import { isValidAsJSIdentifier } from './util.js';
|
|
13
|
+
import { isURLSpecifier, isValidAsJSIdentifier } from './util.js';
|
|
14
14
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
cssModule: CSSModule
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
): Diagnostic[] {
|
|
15
|
+
export interface CheckerArgs {
|
|
16
|
+
config: CMKConfig;
|
|
17
|
+
getExportRecord: (cssModule: CSSModule) => ExportRecord;
|
|
18
|
+
matchesPattern: MatchesPattern;
|
|
19
|
+
resolver: Resolver;
|
|
20
|
+
getCSSModule: (path: string) => CSSModule | undefined;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
export function checkCSSModule(cssModule: CSSModule, args: CheckerArgs): Diagnostic[] {
|
|
24
|
+
const { config } = args;
|
|
24
25
|
const diagnostics: Diagnostic[] = [];
|
|
25
26
|
|
|
26
27
|
for (const token of cssModule.localTokens) {
|
|
@@ -37,16 +38,18 @@ export function checkCSSModule(
|
|
|
37
38
|
}
|
|
38
39
|
|
|
39
40
|
for (const tokenImporter of cssModule.tokenImporters) {
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
if (!imported) {
|
|
41
|
+
if (isURLSpecifier(tokenImporter.from)) continue;
|
|
42
|
+
const from = args.resolver(tokenImporter.from, { request: cssModule.fileName });
|
|
43
|
+
if (!from) {
|
|
44
44
|
diagnostics.push(createCannotImportModuleDiagnostic(cssModule, tokenImporter));
|
|
45
45
|
continue;
|
|
46
46
|
}
|
|
47
|
+
if (!args.matchesPattern(from)) continue;
|
|
48
|
+
const imported = args.getCSSModule(from);
|
|
49
|
+
if (!imported) throw new Error('unreachable: `imported` is undefined');
|
|
47
50
|
|
|
48
51
|
if (tokenImporter.type === 'value') {
|
|
49
|
-
const exportRecord =
|
|
52
|
+
const exportRecord = args.getExportRecord(imported);
|
|
50
53
|
for (const value of tokenImporter.values) {
|
|
51
54
|
if (!exportRecord.allTokens.includes(value.name)) {
|
|
52
55
|
diagnostics.push(createModuleHasNoExportedTokenDiagnostic(cssModule, tokenImporter, value));
|
package/src/config.ts
CHANGED
|
@@ -13,6 +13,7 @@ const DEFAULT_INCLUDE_SPEC = '**/*';
|
|
|
13
13
|
export interface CMKConfig {
|
|
14
14
|
includes: string[];
|
|
15
15
|
excludes: string[];
|
|
16
|
+
enabled: boolean | undefined;
|
|
16
17
|
dtsOutDir: string;
|
|
17
18
|
arbitraryExtensions: boolean;
|
|
18
19
|
namedExports: boolean;
|
|
@@ -71,6 +72,7 @@ export interface CMKConfig {
|
|
|
71
72
|
interface UnnormalizedRawConfig {
|
|
72
73
|
includes?: string[];
|
|
73
74
|
excludes?: string[];
|
|
75
|
+
enabled?: boolean;
|
|
74
76
|
dtsOutDir?: string;
|
|
75
77
|
arbitraryExtensions?: boolean;
|
|
76
78
|
namedExports?: boolean;
|
|
@@ -124,6 +126,16 @@ function parseRawData(raw: unknown, tsConfigSourceFile: ts.TsConfigSourceFile):
|
|
|
124
126
|
// MEMO: The errors for this option are reported by `tsc` or `tsserver`, so we don't need to report.
|
|
125
127
|
}
|
|
126
128
|
if ('cmkOptions' in raw && typeof raw.cmkOptions === 'object' && raw.cmkOptions !== null) {
|
|
129
|
+
if ('enabled' in raw.cmkOptions) {
|
|
130
|
+
if (typeof raw.cmkOptions.enabled === 'boolean') {
|
|
131
|
+
result.config.enabled = raw.cmkOptions.enabled;
|
|
132
|
+
} else {
|
|
133
|
+
result.diagnostics.push({
|
|
134
|
+
category: 'error',
|
|
135
|
+
text: `\`enabled\` in ${tsConfigSourceFile.fileName} must be a boolean.`,
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
}
|
|
127
139
|
if ('dtsOutDir' in raw.cmkOptions) {
|
|
128
140
|
if (typeof raw.cmkOptions.dtsOutDir === 'string') {
|
|
129
141
|
result.config.dtsOutDir = raw.cmkOptions.dtsOutDir;
|
|
@@ -255,6 +267,7 @@ export function readConfigFile(project: string): CMKConfig {
|
|
|
255
267
|
namedExports: parsedTsConfig.config.namedExports ?? false,
|
|
256
268
|
prioritizeNamedImports: parsedTsConfig.config.prioritizeNamedImports ?? false,
|
|
257
269
|
keyframes: parsedTsConfig.config.keyframes ?? true,
|
|
270
|
+
enabled: parsedTsConfig.config.enabled,
|
|
258
271
|
basePath,
|
|
259
272
|
configFileName,
|
|
260
273
|
compilerOptions: parsedTsConfig.compilerOptions,
|
package/src/diagnostic.ts
CHANGED
|
@@ -11,6 +11,8 @@ function convertErrorCategory(category: DiagnosticCategory): ts.DiagnosticCatego
|
|
|
11
11
|
switch (category) {
|
|
12
12
|
case 'error':
|
|
13
13
|
return ts.DiagnosticCategory.Error;
|
|
14
|
+
case 'warning':
|
|
15
|
+
return ts.DiagnosticCategory.Warning;
|
|
14
16
|
default:
|
|
15
17
|
throw new Error(`Unknown category: ${String(category)}`);
|
|
16
18
|
}
|
package/src/dts-generator.ts
CHANGED
|
@@ -1,13 +1,8 @@
|
|
|
1
|
-
import type { CSSModule,
|
|
2
|
-
import { isValidAsJSIdentifier } from './util.js';
|
|
1
|
+
import type { CSSModule, Token, TokenImporter } from './type.js';
|
|
2
|
+
import { isURLSpecifier, isValidAsJSIdentifier } from './util.js';
|
|
3
3
|
|
|
4
4
|
export const STYLES_EXPORT_NAME = 'styles';
|
|
5
5
|
|
|
6
|
-
export interface GenerateDtsHost {
|
|
7
|
-
resolver: Resolver;
|
|
8
|
-
matchesPattern: MatchesPattern;
|
|
9
|
-
}
|
|
10
|
-
|
|
11
6
|
export interface GenerateDtsOptions {
|
|
12
7
|
namedExports: boolean;
|
|
13
8
|
prioritizeNamedImports: boolean;
|
|
@@ -46,11 +41,7 @@ interface GenerateDtsResult {
|
|
|
46
41
|
/**
|
|
47
42
|
* Generate .d.ts from `CSSModule`.
|
|
48
43
|
*/
|
|
49
|
-
export function generateDts(
|
|
50
|
-
cssModule: CSSModule,
|
|
51
|
-
host: GenerateDtsHost,
|
|
52
|
-
options: GenerateDtsOptions,
|
|
53
|
-
): GenerateDtsResult {
|
|
44
|
+
export function generateDts(cssModule: CSSModule, options: GenerateDtsOptions): GenerateDtsResult {
|
|
54
45
|
// Exclude invalid tokens
|
|
55
46
|
const localTokens = cssModule.localTokens.filter((token) => isValidName(token.name, options));
|
|
56
47
|
const tokenImporters = cssModule.tokenImporters
|
|
@@ -69,10 +60,43 @@ export function generateDts(
|
|
|
69
60
|
return tokenImporter;
|
|
70
61
|
}
|
|
71
62
|
})
|
|
72
|
-
// Exclude token importers for external files
|
|
73
63
|
.filter((tokenImporter) => {
|
|
74
|
-
|
|
75
|
-
|
|
64
|
+
/**
|
|
65
|
+
* In principle, token importers with specifiers that cannot be resolved are still included in the type
|
|
66
|
+
* definitions. For example, consider the following:
|
|
67
|
+
*
|
|
68
|
+
* ```css
|
|
69
|
+
* // src/a.module.css
|
|
70
|
+
* @import './unresolved.module.css';
|
|
71
|
+
* @import './unmatched.css';
|
|
72
|
+
* .a_1 { color: red; }
|
|
73
|
+
* ```
|
|
74
|
+
*
|
|
75
|
+
* In this case, CSS Modules Kit generates the following type definitions:
|
|
76
|
+
*
|
|
77
|
+
* ```ts
|
|
78
|
+
* // generated/src/a.module.css.d.ts
|
|
79
|
+
* // @ts-nocheck
|
|
80
|
+
* declare const styles = {
|
|
81
|
+
* a_1: '' as readonly string,
|
|
82
|
+
* ...(await import('./unresolved.module.css')).default,
|
|
83
|
+
* ...(await import('./unmatched.css')).default,
|
|
84
|
+
* };
|
|
85
|
+
* ```
|
|
86
|
+
*
|
|
87
|
+
* Even if `./unresolved.module.css` or `./unmatched.css` does not exist, the same type definitions are
|
|
88
|
+
* generated. It is important that the generated type definitions do not change depending on whether the
|
|
89
|
+
* files exist. This provides the following benefits:
|
|
90
|
+
*
|
|
91
|
+
* - Simplifies the watch mode implementation
|
|
92
|
+
* - Only the type definitions for changed files need to be regenerated
|
|
93
|
+
* - Makes it easier to parallelize code generation
|
|
94
|
+
* - Type definitions can be generated independently per file
|
|
95
|
+
*
|
|
96
|
+
* However, as an exception, URL specifiers are not included in the type definitions, because URL
|
|
97
|
+
* specifiers are typically resolved at runtime.
|
|
98
|
+
*/
|
|
99
|
+
return !isURLSpecifier(tokenImporter.from);
|
|
76
100
|
});
|
|
77
101
|
|
|
78
102
|
if (options.namedExports) {
|
|
@@ -82,28 +106,7 @@ export function generateDts(
|
|
|
82
106
|
}
|
|
83
107
|
}
|
|
84
108
|
|
|
85
|
-
/**
|
|
86
|
-
* Generate a d.ts file with named exports.
|
|
87
|
-
* @example
|
|
88
|
-
* If the CSS module file is:
|
|
89
|
-
* ```css
|
|
90
|
-
* @import './a.module.css';
|
|
91
|
-
* @value local1: string;
|
|
92
|
-
* @value imported1, imported2 as aliasedImported2 from './b.module.css';
|
|
93
|
-
* .local2 { color: red }
|
|
94
|
-
* ```
|
|
95
|
-
* The d.ts file would be:
|
|
96
|
-
* ```ts
|
|
97
|
-
* // @ts-nocheck
|
|
98
|
-
* export var local1: string;
|
|
99
|
-
* export var local2: string;
|
|
100
|
-
* export * from './a.module.css';
|
|
101
|
-
* export {
|
|
102
|
-
* imported1,
|
|
103
|
-
* imported2 as aliasedImported2,
|
|
104
|
-
* } from './b.module.css';
|
|
105
|
-
* ```
|
|
106
|
-
*/
|
|
109
|
+
/** Generate a d.ts file with named exports. */
|
|
107
110
|
function generateNamedExportsDts(
|
|
108
111
|
localTokens: Token[],
|
|
109
112
|
tokenImporters: TokenImporter[],
|
|
@@ -125,6 +128,25 @@ function generateNamedExportsDts(
|
|
|
125
128
|
let text = `// @ts-nocheck\n`;
|
|
126
129
|
|
|
127
130
|
for (const token of localTokens) {
|
|
131
|
+
/**
|
|
132
|
+
* The mapping is created as follows:
|
|
133
|
+
* a.module.css:
|
|
134
|
+
* 1 | .a_1 { color: red; }
|
|
135
|
+
* | ^ mapping.sourceOffsets[0]
|
|
136
|
+
* |
|
|
137
|
+
* 2 | .a_2 { color: blue; }
|
|
138
|
+
* | ^ mapping.sourceOffsets[1]
|
|
139
|
+
* |
|
|
140
|
+
*
|
|
141
|
+
* a.module.css.d.ts:
|
|
142
|
+
* 1 | // @ts-nocheck
|
|
143
|
+
* 2 | export var a_1: string;
|
|
144
|
+
* | ^ mapping.generatedOffsets[0]
|
|
145
|
+
* |
|
|
146
|
+
* 3 | export var a_2: string;
|
|
147
|
+
* | ^ mapping.generatedOffsets[1]
|
|
148
|
+
*/
|
|
149
|
+
|
|
128
150
|
text += `export var `;
|
|
129
151
|
mapping.sourceOffsets.push(token.loc.start.offset);
|
|
130
152
|
mapping.generatedOffsets.push(text.length);
|
|
@@ -133,12 +155,71 @@ function generateNamedExportsDts(
|
|
|
133
155
|
}
|
|
134
156
|
for (const tokenImporter of tokenImporters) {
|
|
135
157
|
if (tokenImporter.type === 'import') {
|
|
158
|
+
/**
|
|
159
|
+
* The mapping is created as follows:
|
|
160
|
+
* a.module.css:
|
|
161
|
+
* 1 | @import './b.module.css';
|
|
162
|
+
* | ^ mapping.sourceOffsets[0]
|
|
163
|
+
* |
|
|
164
|
+
* 2 | @import './c.module.css';
|
|
165
|
+
* | ^ mapping.sourceOffsets[1]
|
|
166
|
+
* |
|
|
167
|
+
*
|
|
168
|
+
* a.module.css.d.ts:
|
|
169
|
+
* 1 | // @ts-nocheck
|
|
170
|
+
* 2 | export * from './b.module.css';
|
|
171
|
+
* | ^ mapping.generatedOffsets[0]
|
|
172
|
+
* |
|
|
173
|
+
* 3 | export * from './c.module.css';
|
|
174
|
+
* | ^ mapping.generatedOffsets[1]
|
|
175
|
+
*
|
|
176
|
+
* NOTE: Not only the specifier but also the surrounding quotes are included in the mapping.
|
|
177
|
+
*/
|
|
178
|
+
|
|
136
179
|
text += `export * from `;
|
|
137
180
|
mapping.sourceOffsets.push(tokenImporter.fromLoc.start.offset - 1);
|
|
138
181
|
mapping.lengths.push(tokenImporter.from.length + 2);
|
|
139
182
|
mapping.generatedOffsets.push(text.length);
|
|
140
183
|
text += `'${tokenImporter.from}';\n`;
|
|
141
184
|
} else {
|
|
185
|
+
/**
|
|
186
|
+
* The mapping is created as follows:
|
|
187
|
+
* a.module.css:
|
|
188
|
+
* 1 | @value b_1, b_2 from './b.module.css';
|
|
189
|
+
* | ^ ^ ^ mapping.sourceOffsets[2]
|
|
190
|
+
* | ^ ^ mapping.sourceOffsets[1]
|
|
191
|
+
* | ^ mapping.sourceOffsets[0]
|
|
192
|
+
* |
|
|
193
|
+
* 2 | @value c_1 as aliased_c_1 from './c.module.css';
|
|
194
|
+
* | ^ ^ ^ mapping.sourceOffsets[5]
|
|
195
|
+
* | ^ ^ mapping.sourceOffsets[4]
|
|
196
|
+
* | ^ mapping.sourceOffsets[3]
|
|
197
|
+
* |
|
|
198
|
+
*
|
|
199
|
+
* a.module.css.d.ts:
|
|
200
|
+
* 1 | // @ts-nocheck
|
|
201
|
+
* 2 | export {
|
|
202
|
+
* 3 | b_1,
|
|
203
|
+
* | ^ mapping.generatedOffsets[0]
|
|
204
|
+
* |
|
|
205
|
+
* 4 | b_2,
|
|
206
|
+
* | ^ mapping.generatedOffsets[1]
|
|
207
|
+
* |
|
|
208
|
+
* 5 | } from './b.module.css';
|
|
209
|
+
* | ^ mapping.generatedOffsets[2]
|
|
210
|
+
* |
|
|
211
|
+
* 6 | export {
|
|
212
|
+
* 7 | c_1 as aliased_c_1,
|
|
213
|
+
* | ^ ^ mapping.generatedOffsets[4], linkedCodeMapping.sourceOffsets[0]
|
|
214
|
+
* | ^ mapping.generatedOffsets[3], linkedCodeMapping.generatedOffsets[0]
|
|
215
|
+
* |
|
|
216
|
+
* 8 | } from './c.module.css';
|
|
217
|
+
* | ^ mapping.generatedOffsets[5]
|
|
218
|
+
*
|
|
219
|
+
* NOTE: Not only the specifier but also the surrounding quotes are included in the mapping.
|
|
220
|
+
* NOTE: linkedCodeMapping is only generated for tokens that have a `localName` (i.e., aliased tokens).
|
|
221
|
+
*/
|
|
222
|
+
|
|
142
223
|
text += `export {\n`;
|
|
143
224
|
// eslint-disable-next-line no-loop-func
|
|
144
225
|
tokenImporter.values.forEach((value) => {
|
|
@@ -179,29 +260,7 @@ function generateNamedExportsDts(
|
|
|
179
260
|
return { text, mapping, linkedCodeMapping };
|
|
180
261
|
}
|
|
181
262
|
|
|
182
|
-
/**
|
|
183
|
-
* Generate a d.ts file with a default export.
|
|
184
|
-
* @example
|
|
185
|
-
* If the CSS module file is:
|
|
186
|
-
* ```css
|
|
187
|
-
* @import './a.module.css';
|
|
188
|
-
* @value local1: string;
|
|
189
|
-
* @value imported1, imported2 as aliasedImported2 from './b.module.css';
|
|
190
|
-
* .local2 { color: red }
|
|
191
|
-
* ```
|
|
192
|
-
* The d.ts file would be:
|
|
193
|
-
* ```ts
|
|
194
|
-
* // @ts-nocheck
|
|
195
|
-
* const styles = {
|
|
196
|
-
* local1: '' as readonly string,
|
|
197
|
-
* local2: '' as readonly string,
|
|
198
|
-
* ...(await import('./a.module.css')).default,
|
|
199
|
-
* imported1: (await import('./b.module.css')).default.imported1,
|
|
200
|
-
* aliasedImported2: (await import('./b.module.css')).default.imported2,
|
|
201
|
-
* };
|
|
202
|
-
* export default styles;
|
|
203
|
-
* ```
|
|
204
|
-
*/
|
|
263
|
+
/** Generate a d.ts file with a default export. */
|
|
205
264
|
function generateDefaultExportDts(
|
|
206
265
|
localTokens: Token[],
|
|
207
266
|
tokenImporters: TokenImporter[],
|
|
@@ -219,9 +278,40 @@ function generateDefaultExportDts(
|
|
|
219
278
|
//
|
|
220
279
|
// If `--skipLibCheck` is false, those errors will be reported by `tsc`. However, these are negligible errors.
|
|
221
280
|
// Therefore, `@ts-nocheck` is added to the generated type definition file.
|
|
222
|
-
let text = `// @ts-nocheck\
|
|
281
|
+
let text = `// @ts-nocheck\n`;
|
|
223
282
|
|
|
283
|
+
// This is a workaround to avoid the issue described as a "Drawbacks" in https://github.com/mizdra/css-modules-kit/pull/302.
|
|
284
|
+
// It uses the technique from https://stackoverflow.com/a/55541672 to fall back from `any` to `{}`.
|
|
285
|
+
// However, the import type for an unresolvable specifier becomes a special `any` type called `errorType`.
|
|
286
|
+
// The technique from https://stackoverflow.com/a/55541672 does not work with `errorType`.
|
|
287
|
+
// Therefore, this combines it with the approach from https://github.com/microsoft/TypeScript/issues/62972.
|
|
288
|
+
if (tokenImporters.some((importer) => importer.type === 'import')) {
|
|
289
|
+
text += `function blockErrorType<T>(val: T): [0] extends [(1 & T)] ? {} : T;\n`;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
text += `declare const ${STYLES_EXPORT_NAME} = {\n`;
|
|
224
293
|
for (const token of localTokens) {
|
|
294
|
+
/**
|
|
295
|
+
* The mapping is created as follows:
|
|
296
|
+
* a.module.css:
|
|
297
|
+
* 1 | .a_1 { color: red; }
|
|
298
|
+
* | ^ mapping.sourceOffsets[0]
|
|
299
|
+
* |
|
|
300
|
+
* 2 | .a_2 { color: blue; }
|
|
301
|
+
* | ^ mapping.sourceOffsets[1]
|
|
302
|
+
* |
|
|
303
|
+
*
|
|
304
|
+
* a.module.css.d.ts:
|
|
305
|
+
* 1 | declare const styles = {
|
|
306
|
+
* 2 | a_1: '' as readonly string,
|
|
307
|
+
* | ^ mapping.generatedOffsets[0]
|
|
308
|
+
* |
|
|
309
|
+
* 3 | a_2: '' as readonly string,
|
|
310
|
+
* | ^ mapping.generatedOffsets[1]
|
|
311
|
+
* |
|
|
312
|
+
* 4 | };
|
|
313
|
+
*/
|
|
314
|
+
|
|
225
315
|
text += ` `;
|
|
226
316
|
mapping.sourceOffsets.push(token.loc.start.offset);
|
|
227
317
|
mapping.generatedOffsets.push(text.length);
|
|
@@ -230,12 +320,70 @@ function generateDefaultExportDts(
|
|
|
230
320
|
}
|
|
231
321
|
for (const tokenImporter of tokenImporters) {
|
|
232
322
|
if (tokenImporter.type === 'import') {
|
|
233
|
-
|
|
323
|
+
/**
|
|
324
|
+
* The mapping is created as follows:
|
|
325
|
+
* a.module.css:
|
|
326
|
+
* 1 | @import './b.module.css';
|
|
327
|
+
* | ^ mapping.sourceOffsets[0]
|
|
328
|
+
* |
|
|
329
|
+
* 2 | @import './c.module.css';
|
|
330
|
+
* | ^ mapping.sourceOffsets[1]
|
|
331
|
+
* |
|
|
332
|
+
*
|
|
333
|
+
* a.module.css.d.ts:
|
|
334
|
+
* 1 | declare const styles = {
|
|
335
|
+
* 2 | ...blockErrorType((await import('./b.module.css')).default),
|
|
336
|
+
* | ^ mapping.generatedOffsets[0]
|
|
337
|
+
* |
|
|
338
|
+
* 3 | ...blockErrorType((await import('./c.module.css')).default),
|
|
339
|
+
* | ^ mapping.generatedOffsets[1]
|
|
340
|
+
* |
|
|
341
|
+
* 4 | };
|
|
342
|
+
*
|
|
343
|
+
* NOTE: Not only the specifier but also the surrounding quotes are included in the mapping.
|
|
344
|
+
*/
|
|
345
|
+
|
|
346
|
+
text += ` ...blockErrorType((await import(`;
|
|
234
347
|
mapping.sourceOffsets.push(tokenImporter.fromLoc.start.offset - 1);
|
|
235
348
|
mapping.lengths.push(tokenImporter.from.length + 2);
|
|
236
349
|
mapping.generatedOffsets.push(text.length);
|
|
237
|
-
text += `'${tokenImporter.from}')).default,\n`;
|
|
350
|
+
text += `'${tokenImporter.from}')).default),\n`;
|
|
238
351
|
} else {
|
|
352
|
+
/**
|
|
353
|
+
* The mapping is created as follows:
|
|
354
|
+
* a.module.css:
|
|
355
|
+
* 1 | @value b_1, b_2 from './b.module.css';
|
|
356
|
+
* | ^ ^ ^ mapping.sourceOffsets[0]
|
|
357
|
+
* | ^ ^ mapping.sourceOffsets[2]
|
|
358
|
+
* | ^ mapping.sourceOffsets[1]
|
|
359
|
+
* |
|
|
360
|
+
* 2 | @value c_1 as aliased_c_1 from './c.module.css';
|
|
361
|
+
* | ^ ^ ^ mapping.sourceOffsets[4]
|
|
362
|
+
* | ^ ^ mapping.sourceOffsets[3]
|
|
363
|
+
* | ^ mapping.sourceOffsets[5]
|
|
364
|
+
* |
|
|
365
|
+
*
|
|
366
|
+
* a.module.css.d.ts:
|
|
367
|
+
* 1 | declare const styles = {
|
|
368
|
+
* 2 | b_1: (await import('./b.module.css')).default.b_1,
|
|
369
|
+
* | ^ ^ ^ linkedCodeMapping.generatedOffsets[0]
|
|
370
|
+
* | ^ ^ mapping.generatedOffsets[1]
|
|
371
|
+
* | ^ mapping.generatedOffsets[0], linkedCodeMapping.sourceOffsets[0]
|
|
372
|
+
* |
|
|
373
|
+
* 3 | b_2: (await import('./b.module.css')).default.b_2,
|
|
374
|
+
* | ^ ^ linkedCodeMapping.generatedOffsets[1]
|
|
375
|
+
* | ^ mapping.generatedOffsets[2], linkedCodeMapping.sourceOffsets[1]
|
|
376
|
+
* |
|
|
377
|
+
* 4 | aliased_c_1: (await import('./c.module.css')).default.c_1,
|
|
378
|
+
* | ^ ^ ^ mapping.generatedOffsets[5], linkedCodeMapping.generatedOffsets[2]
|
|
379
|
+
* | ^ ^ mapping.generatedOffsets[4]
|
|
380
|
+
* | ^ mapping.generatedOffsets[3], linkedCodeMapping.sourceOffsets[2]
|
|
381
|
+
* |
|
|
382
|
+
* 5 | };
|
|
383
|
+
*
|
|
384
|
+
* NOTE: Not only the specifier but also the surrounding quotes are included in the mapping.
|
|
385
|
+
*/
|
|
386
|
+
|
|
239
387
|
// eslint-disable-next-line no-loop-func
|
|
240
388
|
tokenImporter.values.forEach((value, i) => {
|
|
241
389
|
const localName = value.localName ?? value.name;
|
|
@@ -254,9 +402,11 @@ function generateDefaultExportDts(
|
|
|
254
402
|
mapping.generatedOffsets.push(text.length);
|
|
255
403
|
}
|
|
256
404
|
text += `'${tokenImporter.from}')).default.`;
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
405
|
+
if ('localName' in value) {
|
|
406
|
+
mapping.sourceOffsets.push(value.loc.start.offset);
|
|
407
|
+
mapping.lengths.push(value.name.length);
|
|
408
|
+
mapping.generatedOffsets.push(text.length);
|
|
409
|
+
}
|
|
260
410
|
linkedCodeMapping.generatedOffsets.push(text.length);
|
|
261
411
|
linkedCodeMapping.generatedLengths.push(value.name.length);
|
|
262
412
|
text += `${value.name},\n`;
|
package/src/index.ts
CHANGED
|
@@ -15,6 +15,7 @@ export {
|
|
|
15
15
|
type Resolver,
|
|
16
16
|
type MatchesPattern,
|
|
17
17
|
type ExportBuilder,
|
|
18
|
+
type ExportRecord,
|
|
18
19
|
type DiagnosticSourceFile,
|
|
19
20
|
type Diagnostic,
|
|
20
21
|
type DiagnosticWithLocation,
|
|
@@ -33,8 +34,8 @@ export {
|
|
|
33
34
|
createMatchesPattern,
|
|
34
35
|
getFileNamesByPattern,
|
|
35
36
|
} from './file.js';
|
|
36
|
-
export { checkCSSModule } from './checker.js';
|
|
37
|
+
export { checkCSSModule, type CheckerArgs } from './checker.js';
|
|
37
38
|
export { createExportBuilder } from './export-builder.js';
|
|
38
|
-
export { join, resolve, relative, dirname, basename, parse
|
|
39
|
+
export { join, resolve, relative, dirname, basename, parse } from './path.js';
|
|
39
40
|
export { findUsedTokenNames } from './util.js';
|
|
40
41
|
export { convertDiagnostic, convertDiagnosticWithLocation, convertSystemError } from './diagnostic.js';
|
package/src/path.ts
CHANGED
|
@@ -32,6 +32,3 @@ export function parse(path: string): ParsedPath {
|
|
|
32
32
|
const { root, dir, base, name, ext } = nodePath.parse(path);
|
|
33
33
|
return { root: slash(root), dir: slash(dir), base, name, ext };
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
37
|
-
export const isAbsolute = nodePath.isAbsolute;
|
package/src/resolver.ts
CHANGED
|
@@ -1,21 +1,19 @@
|
|
|
1
|
-
import { fileURLToPath, pathToFileURL } from 'node:url';
|
|
2
1
|
import type { CompilerOptions } from 'typescript';
|
|
3
2
|
import ts from 'typescript';
|
|
4
|
-
import { isAbsolute, resolve } from './path.js';
|
|
5
3
|
import type { Resolver, ResolverOptions } from './type.js';
|
|
4
|
+
import { isURLSpecifier } from './util.js';
|
|
6
5
|
|
|
7
6
|
export function createResolver(
|
|
8
7
|
compilerOptions: CompilerOptions,
|
|
9
8
|
moduleResolutionCache: ts.ModuleResolutionCache | undefined,
|
|
10
9
|
): Resolver {
|
|
11
|
-
return (
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
return (specifier: string, options: ResolverOptions) => {
|
|
11
|
+
if (isURLSpecifier(specifier)) return undefined;
|
|
14
12
|
const host: ts.ModuleResolutionHost = {
|
|
15
13
|
...ts.sys,
|
|
16
14
|
fileExists: (fileName) => {
|
|
17
|
-
if (fileName.endsWith('.
|
|
18
|
-
return ts.sys.fileExists(fileName.replace(/\.
|
|
15
|
+
if (fileName.endsWith('.d.css.ts')) {
|
|
16
|
+
return ts.sys.fileExists(fileName.replace(/\.d\.css\.ts$/u, '.css'));
|
|
19
17
|
}
|
|
20
18
|
return ts.sys.fileExists(fileName);
|
|
21
19
|
},
|
|
@@ -28,28 +26,8 @@ export function createResolver(
|
|
|
28
26
|
moduleResolutionCache,
|
|
29
27
|
);
|
|
30
28
|
if (resolvedModule) {
|
|
31
|
-
|
|
32
|
-
specifier = resolvedModule.resolvedFileName.replace(/\.module\.d\.css\.ts$/u, '.module.css');
|
|
33
|
-
}
|
|
34
|
-
if (isAbsolute(specifier)) {
|
|
35
|
-
return resolve(specifier);
|
|
36
|
-
} else if (isRelativeSpecifier(specifier)) {
|
|
37
|
-
// Convert the specifier to an absolute path
|
|
38
|
-
// NOTE: Node.js resolves relative specifier with standard relative URL resolution semantics. So we will follow that here as well.
|
|
39
|
-
// ref: https://nodejs.org/docs/latest-v23.x/api/esm.html#terminology
|
|
40
|
-
return resolve(fileURLToPath(new URL(specifier, pathToFileURL(options.request)).href));
|
|
41
|
-
} else {
|
|
42
|
-
// Do not support URL or bare specifiers
|
|
43
|
-
// TODO: Logging that the specifier could not resolve.
|
|
44
|
-
return undefined;
|
|
29
|
+
return resolvedModule.resolvedFileName.replace(/\.d\.css\.ts$/u, '.css');
|
|
45
30
|
}
|
|
31
|
+
return undefined;
|
|
46
32
|
};
|
|
47
33
|
}
|
|
48
|
-
|
|
49
|
-
/**
|
|
50
|
-
* Check if the specifier is a relative specifier.
|
|
51
|
-
* @see https://nodejs.org/docs/latest-v23.x/api/esm.html#terminology
|
|
52
|
-
*/
|
|
53
|
-
function isRelativeSpecifier(specifier: string): boolean {
|
|
54
|
-
return specifier.startsWith('./') || specifier.startsWith('../');
|
|
55
|
-
}
|
package/src/type.ts
CHANGED