@css-modules-kit/core 0.1.0 → 0.3.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/dist/checker.d.ts +2 -6
- package/dist/checker.d.ts.map +1 -1
- package/dist/checker.js +4 -6
- package/dist/checker.js.map +1 -1
- package/dist/config.d.ts +13 -17
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +41 -30
- package/dist/config.js.map +1 -1
- package/dist/diagnostic.d.ts +6 -33
- package/dist/diagnostic.d.ts.map +1 -1
- package/dist/diagnostic.js +71 -0
- package/dist/diagnostic.js.map +1 -1
- package/dist/dts-creator.d.ts +8 -28
- package/dist/dts-creator.d.ts.map +1 -1
- package/dist/dts-creator.js +106 -7
- package/dist/dts-creator.js.map +1 -1
- package/dist/export-builder.d.ts +1 -14
- package/dist/export-builder.d.ts.map +1 -1
- package/dist/export-builder.js.map +1 -1
- package/dist/file.d.ts +1 -1
- package/dist/file.d.ts.map +1 -1
- package/dist/file.js.map +1 -1
- package/dist/index.d.ts +7 -7
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/parser/at-import-parser.d.ts +1 -1
- package/dist/parser/at-import-parser.d.ts.map +1 -1
- package/dist/parser/at-value-parser.d.ts +2 -3
- package/dist/parser/at-value-parser.d.ts.map +1 -1
- package/dist/parser/at-value-parser.js +2 -13
- package/dist/parser/at-value-parser.js.map +1 -1
- package/dist/parser/css-module-parser.d.ts +2 -83
- package/dist/parser/css-module-parser.d.ts.map +1 -1
- package/dist/parser/css-module-parser.js +7 -8
- package/dist/parser/css-module-parser.js.map +1 -1
- package/dist/parser/rule-parser.d.ts +8 -4
- package/dist/parser/rule-parser.d.ts.map +1 -1
- package/dist/parser/rule-parser.js +9 -10
- 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 +1 -3
- package/dist/path.js.map +1 -1
- package/dist/resolver.d.ts +3 -12
- package/dist/resolver.d.ts.map +1 -1
- package/dist/resolver.js +2 -2
- package/dist/resolver.js.map +1 -1
- package/dist/type.d.ts +174 -0
- package/dist/type.d.ts.map +1 -0
- package/dist/type.js +3 -0
- package/dist/type.js.map +1 -0
- package/package.json +2 -2
- package/src/checker.ts +13 -15
- package/src/config.ts +50 -45
- package/src/diagnostic.ts +69 -29
- package/src/dts-creator.ts +120 -13
- package/src/export-builder.ts +1 -16
- package/src/file.ts +1 -2
- package/src/index.ts +14 -14
- package/src/parser/at-import-parser.ts +1 -1
- package/src/parser/at-value-parser.ts +5 -17
- package/src/parser/css-module-parser.ts +16 -98
- package/src/parser/rule-parser.ts +17 -14
- package/src/path.ts +0 -3
- package/src/resolver.ts +12 -15
- package/src/type.ts +191 -0
- package/dist/parser/location.d.ts +0 -34
- package/dist/parser/location.d.ts.map +0 -1
- package/dist/parser/location.js +0 -9
- package/dist/parser/location.js.map +0 -1
- package/src/parser/location.ts +0 -40
package/dist/resolver.js
CHANGED
|
@@ -7,7 +7,7 @@ exports.createResolver = createResolver;
|
|
|
7
7
|
const node_url_1 = require("node:url");
|
|
8
8
|
const typescript_1 = __importDefault(require("typescript"));
|
|
9
9
|
const path_js_1 = require("./path.js");
|
|
10
|
-
function createResolver(compilerOptions) {
|
|
10
|
+
function createResolver(compilerOptions, moduleResolutionCache) {
|
|
11
11
|
return (_specifier, options) => {
|
|
12
12
|
let specifier = _specifier;
|
|
13
13
|
const host = {
|
|
@@ -19,7 +19,7 @@ function createResolver(compilerOptions) {
|
|
|
19
19
|
return typescript_1.default.sys.fileExists(fileName);
|
|
20
20
|
},
|
|
21
21
|
};
|
|
22
|
-
const { resolvedModule } = typescript_1.default.resolveModuleName(specifier, options.request, compilerOptions, host);
|
|
22
|
+
const { resolvedModule } = typescript_1.default.resolveModuleName(specifier, options.request, compilerOptions, host, moduleResolutionCache);
|
|
23
23
|
if (resolvedModule) {
|
|
24
24
|
// TODO: Logging that the paths is used.
|
|
25
25
|
specifier = resolvedModule.resolvedFileName.replace(/\.module\.d\.css\.ts$/u, '.module.css');
|
package/dist/resolver.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":";;;;;AAMA,wCAwCC;AA9CD,uCAAwD;AAExD,4DAA4B;AAC5B,uCAAgD;AAGhD,SAAgB,cAAc,CAC5B,eAAgC,EAChC,qBAA2D;IAE3D,OAAO,CAAC,UAAkB,EAAE,OAAwB,EAAE,EAAE;QACtD,IAAI,SAAS,GAAG,UAAU,CAAC;QAE3B,MAAM,IAAI,GAA4B;YACpC,GAAG,oBAAE,CAAC,GAAG;YACT,UAAU,EAAE,CAAC,QAAQ,EAAE,EAAE;gBACvB,IAAI,QAAQ,CAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,CAAC;oBAC1C,OAAO,oBAAE,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,OAAO,CAAC,wBAAwB,EAAE,aAAa,CAAC,CAAC,CAAC;gBACtF,CAAC;gBACD,OAAO,oBAAE,CAAC,GAAG,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;YACrC,CAAC;SACF,CAAC;QACF,MAAM,EAAE,cAAc,EAAE,GAAG,oBAAE,CAAC,iBAAiB,CAC7C,SAAS,EACT,OAAO,CAAC,OAAO,EACf,eAAe,EACf,IAAI,EACJ,qBAAqB,CACtB,CAAC;QACF,IAAI,cAAc,EAAE,CAAC;YACnB,wCAAwC;YACxC,SAAS,GAAG,cAAc,CAAC,gBAAgB,CAAC,OAAO,CAAC,wBAAwB,EAAE,aAAa,CAAC,CAAC;QAC/F,CAAC;QACD,IAAI,IAAA,oBAAU,EAAC,SAAS,CAAC,EAAE,CAAC;YAC1B,OAAO,IAAA,iBAAO,EAAC,SAAS,CAAC,CAAC;QAC5B,CAAC;aAAM,IAAI,mBAAmB,CAAC,SAAS,CAAC,EAAE,CAAC;YAC1C,4CAA4C;YAC5C,kIAAkI;YAClI,qEAAqE;YACrE,OAAO,IAAA,iBAAO,EAAC,IAAA,wBAAa,EAAC,IAAI,GAAG,CAAC,SAAS,EAAE,IAAA,wBAAa,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;QACzF,CAAC;aAAM,CAAC;YACN,wCAAwC;YACxC,sDAAsD;YACtD,OAAO,SAAS,CAAC;QACnB,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,SAAS,mBAAmB,CAAC,SAAiB;IAC5C,OAAO,SAAS,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AACnE,CAAC"}
|
package/dist/type.d.ts
ADDED
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
/** The position of the node in the source file. */
|
|
2
|
+
export interface Position {
|
|
3
|
+
/**
|
|
4
|
+
* The line number in the source file. It is 1-based.
|
|
5
|
+
* This is compatible with postcss and tsserver.
|
|
6
|
+
*/
|
|
7
|
+
line: number;
|
|
8
|
+
/**
|
|
9
|
+
* The column number in the source file. It is 1-based.
|
|
10
|
+
* This is compatible with postcss and tsserver.
|
|
11
|
+
*/
|
|
12
|
+
column: number;
|
|
13
|
+
/** The offset in the source file. It is 0-based. */
|
|
14
|
+
offset: number;
|
|
15
|
+
}
|
|
16
|
+
/** The location of the node in the source file. */
|
|
17
|
+
export interface Location {
|
|
18
|
+
/**
|
|
19
|
+
* The starting position of the node. It is inclusive.
|
|
20
|
+
* This is compatible with postcss and tsserver.
|
|
21
|
+
*/
|
|
22
|
+
start: Position;
|
|
23
|
+
/**
|
|
24
|
+
* The ending position of the node. It is exclusive.
|
|
25
|
+
* This is compatible with tsserver, but not postcss.
|
|
26
|
+
*/
|
|
27
|
+
end: Position;
|
|
28
|
+
}
|
|
29
|
+
/** The item being exported from a CSS module file (a.k.a. token). */
|
|
30
|
+
export interface Token {
|
|
31
|
+
/** The token name. */
|
|
32
|
+
name: string;
|
|
33
|
+
/** The location of the token in the source file. */
|
|
34
|
+
loc: Location;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A token importer using `@import '...'`.
|
|
38
|
+
* `@import` imports all tokens from the file. Therefore, it does not have
|
|
39
|
+
* the name of the imported token unlike {@link AtValueTokenImporter}.
|
|
40
|
+
*/
|
|
41
|
+
export interface AtImportTokenImporter {
|
|
42
|
+
type: 'import';
|
|
43
|
+
/**
|
|
44
|
+
* The specifier of the file from which the token is imported.
|
|
45
|
+
* This is a string before being resolved and unquoted.
|
|
46
|
+
* @example `@import './a.module.css'` would have `from` as `'./a.module.css'`.
|
|
47
|
+
*/
|
|
48
|
+
from: string;
|
|
49
|
+
/** The location of the `from` in *.module.css file. */
|
|
50
|
+
fromLoc: Location;
|
|
51
|
+
}
|
|
52
|
+
/** A token importer using `@value ... from '...'`. */
|
|
53
|
+
export interface AtValueTokenImporter {
|
|
54
|
+
type: 'value';
|
|
55
|
+
/** The values imported from the file. */
|
|
56
|
+
values: AtValueTokenImporterValue[];
|
|
57
|
+
/**
|
|
58
|
+
* The specifier of the file from which the token is imported.
|
|
59
|
+
* This is a string before being resolved and unquoted.
|
|
60
|
+
* @example `@value a from './a.module.css'` would have `from` as `'./a.module.css'`.
|
|
61
|
+
*/
|
|
62
|
+
from: string;
|
|
63
|
+
/** The location of the `from` in *.module.css file. */
|
|
64
|
+
fromLoc: Location;
|
|
65
|
+
}
|
|
66
|
+
/** A value imported from a CSS module file using `@value ... from '...'`. */
|
|
67
|
+
export interface AtValueTokenImporterValue {
|
|
68
|
+
/**
|
|
69
|
+
* The name of the token in the file from which it is imported.
|
|
70
|
+
* @example `@value a from './a.module.css'` would have `name` as `'a'`.
|
|
71
|
+
* @example `@value a as b from './a.module.css'` would have `name` as `'a'`.
|
|
72
|
+
*/
|
|
73
|
+
name: string;
|
|
74
|
+
/** The location of the `name` in *.module.css file. */
|
|
75
|
+
loc: Location;
|
|
76
|
+
/**
|
|
77
|
+
* The name of the token in the current file.
|
|
78
|
+
* @example `@value a from './a.module.css'` would not have `localName`.
|
|
79
|
+
* @example `@value a as b from './a.module.css'` would have `localName` as `'b'`.
|
|
80
|
+
*/
|
|
81
|
+
localName?: string;
|
|
82
|
+
/**
|
|
83
|
+
* The location of the `localName` in *.module.css file.
|
|
84
|
+
* This is `undefined` when `localName` is `undefined`.
|
|
85
|
+
*/
|
|
86
|
+
localLoc?: Location;
|
|
87
|
+
}
|
|
88
|
+
export type TokenImporter = AtImportTokenImporter | AtValueTokenImporter;
|
|
89
|
+
export interface CSSModule {
|
|
90
|
+
/** Absolute path of the file */
|
|
91
|
+
fileName: string;
|
|
92
|
+
/** The content of the file */
|
|
93
|
+
text: string;
|
|
94
|
+
/**
|
|
95
|
+
* List of token names defined in the file.
|
|
96
|
+
* @example
|
|
97
|
+
* Consider the following file:
|
|
98
|
+
* ```css
|
|
99
|
+
* .foo { color: red }
|
|
100
|
+
* .bar, .baz { color: red }
|
|
101
|
+
* ```
|
|
102
|
+
* The `localTokens` for this file would be `['foo', 'bar', 'baz']`.
|
|
103
|
+
*/
|
|
104
|
+
localTokens: Token[];
|
|
105
|
+
/**
|
|
106
|
+
* List of token importers in the file.
|
|
107
|
+
* Token importer is a statement that imports tokens from another file.
|
|
108
|
+
*/
|
|
109
|
+
tokenImporters: TokenImporter[];
|
|
110
|
+
}
|
|
111
|
+
export interface ResolverOptions {
|
|
112
|
+
/** The file that imports the specifier. It is a absolute path. */
|
|
113
|
+
request: string;
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* A resolver function that resolves import specifiers.
|
|
117
|
+
* @param specifier The import specifier.
|
|
118
|
+
* @param options The options.
|
|
119
|
+
* @returns The resolved import specifier. It is a absolute path. If the import specifier cannot be resolved, return `undefined`.
|
|
120
|
+
*/
|
|
121
|
+
export type Resolver = (specifier: string, options: ResolverOptions) => string | undefined;
|
|
122
|
+
/**
|
|
123
|
+
* A function that checks if a file name matches a pattern.
|
|
124
|
+
* @param fileName The file name. It is an absolute path.
|
|
125
|
+
* @returns `true` if the file name matches the pattern, otherwise `false`.
|
|
126
|
+
*/
|
|
127
|
+
export type MatchesPattern = (fileName: string) => boolean;
|
|
128
|
+
/** The export token record of a CSS module. */
|
|
129
|
+
export interface ExportRecord {
|
|
130
|
+
/** The all exported tokens of the CSS module. */
|
|
131
|
+
allTokens: string[];
|
|
132
|
+
}
|
|
133
|
+
export interface ExportBuilder {
|
|
134
|
+
build(cssModule: CSSModule): ExportRecord;
|
|
135
|
+
clearCache(): void;
|
|
136
|
+
}
|
|
137
|
+
export type DiagnosticCategory = 'error' | 'warning';
|
|
138
|
+
export interface DiagnosticSourceFile {
|
|
139
|
+
fileName: string;
|
|
140
|
+
text: string;
|
|
141
|
+
}
|
|
142
|
+
export interface DiagnosticPosition {
|
|
143
|
+
/** The line number in the source file. It is 1-based. */
|
|
144
|
+
line: number;
|
|
145
|
+
/** The column number in the source file. It is 1-based. */
|
|
146
|
+
column: number;
|
|
147
|
+
}
|
|
148
|
+
interface DiagnosticWithoutLocation {
|
|
149
|
+
/** Text of diagnostic message. */
|
|
150
|
+
text: string;
|
|
151
|
+
/** The category of the diagnostic message. */
|
|
152
|
+
category: DiagnosticCategory;
|
|
153
|
+
}
|
|
154
|
+
export interface DiagnosticWithLocation extends DiagnosticWithoutLocation {
|
|
155
|
+
/** The file in which the diagnostic occurred */
|
|
156
|
+
file: DiagnosticSourceFile;
|
|
157
|
+
/** Starting file position at which text applies. It is inclusive. */
|
|
158
|
+
start: DiagnosticPosition;
|
|
159
|
+
/** Length of the diagnostic. */
|
|
160
|
+
length: number;
|
|
161
|
+
}
|
|
162
|
+
export type Diagnostic = DiagnosticWithLocation | DiagnosticWithoutLocation;
|
|
163
|
+
/**
|
|
164
|
+
* A diagnostic with location information detached from the source file.
|
|
165
|
+
* It is an intermediate representation used inside the CSS Module parser.
|
|
166
|
+
*/
|
|
167
|
+
export interface DiagnosticWithDetachedLocation extends DiagnosticWithoutLocation {
|
|
168
|
+
/** Starting file position at which text applies. It is inclusive. */
|
|
169
|
+
start: DiagnosticPosition;
|
|
170
|
+
/** Length of the diagnostic. */
|
|
171
|
+
length: number;
|
|
172
|
+
}
|
|
173
|
+
export {};
|
|
174
|
+
//# sourceMappingURL=type.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":"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"}
|
package/dist/type.js
ADDED
package/dist/type.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"type.js","sourceRoot":"","sources":["../src/type.ts"],"names":[],"mappings":""}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@css-modules-kit/core",
|
|
3
3
|
"description": "The core of css-modules-kit",
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.3.0",
|
|
5
5
|
"type": "commonjs",
|
|
6
6
|
"sideEffects": false,
|
|
7
7
|
"repository": {
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"build": "tsc -b tsconfig.build.json"
|
|
25
25
|
},
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": ">=
|
|
27
|
+
"node": ">=20.19.0"
|
|
28
28
|
},
|
|
29
29
|
"publishConfig": {
|
|
30
30
|
"access": "public",
|
package/src/checker.ts
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
|
-
import type { SemanticDiagnostic } from './diagnostic.js';
|
|
2
|
-
import type { ExportBuilder } from './export-builder.js';
|
|
3
|
-
import type { MatchesPattern } from './file.js';
|
|
4
1
|
import type {
|
|
5
2
|
AtValueTokenImporter,
|
|
6
3
|
AtValueTokenImporterValue,
|
|
7
4
|
CSSModule,
|
|
5
|
+
Diagnostic,
|
|
6
|
+
ExportBuilder,
|
|
7
|
+
MatchesPattern,
|
|
8
|
+
Resolver,
|
|
8
9
|
TokenImporter,
|
|
9
|
-
} from './
|
|
10
|
-
import type { Resolver } from './resolver.js';
|
|
10
|
+
} from './type.js';
|
|
11
11
|
|
|
12
12
|
export function checkCSSModule(
|
|
13
13
|
cssModule: CSSModule,
|
|
@@ -15,8 +15,8 @@ export function checkCSSModule(
|
|
|
15
15
|
matchesPattern: MatchesPattern,
|
|
16
16
|
resolver: Resolver,
|
|
17
17
|
getCSSModule: (path: string) => CSSModule | undefined,
|
|
18
|
-
):
|
|
19
|
-
const diagnostics:
|
|
18
|
+
): Diagnostic[] {
|
|
19
|
+
const diagnostics: Diagnostic[] = [];
|
|
20
20
|
|
|
21
21
|
for (const tokenImporter of cssModule.tokenImporters) {
|
|
22
22
|
const from = resolver(tokenImporter.from, { request: cssModule.fileName });
|
|
@@ -39,14 +39,13 @@ export function checkCSSModule(
|
|
|
39
39
|
return diagnostics;
|
|
40
40
|
}
|
|
41
41
|
|
|
42
|
-
function createCannotImportModuleDiagnostic(cssModule: CSSModule, tokenImporter: TokenImporter):
|
|
42
|
+
function createCannotImportModuleDiagnostic(cssModule: CSSModule, tokenImporter: TokenImporter): Diagnostic {
|
|
43
43
|
return {
|
|
44
|
-
type: 'semantic',
|
|
45
44
|
text: `Cannot import module '${tokenImporter.from}'`,
|
|
46
45
|
category: 'error',
|
|
47
|
-
fileName: cssModule.fileName,
|
|
46
|
+
file: { fileName: cssModule.fileName, text: cssModule.text },
|
|
48
47
|
start: { line: tokenImporter.fromLoc.start.line, column: tokenImporter.fromLoc.start.column },
|
|
49
|
-
|
|
48
|
+
length: tokenImporter.fromLoc.end.offset - tokenImporter.fromLoc.start.offset,
|
|
50
49
|
};
|
|
51
50
|
}
|
|
52
51
|
|
|
@@ -54,13 +53,12 @@ function createModuleHasNoExportedTokenDiagnostic(
|
|
|
54
53
|
cssModule: CSSModule,
|
|
55
54
|
tokenImporter: AtValueTokenImporter,
|
|
56
55
|
value: AtValueTokenImporterValue,
|
|
57
|
-
):
|
|
56
|
+
): Diagnostic {
|
|
58
57
|
return {
|
|
59
|
-
type: 'semantic',
|
|
60
58
|
text: `Module '${tokenImporter.from}' has no exported token '${value.name}'.`,
|
|
61
59
|
category: 'error',
|
|
62
|
-
fileName: cssModule.fileName,
|
|
60
|
+
file: { fileName: cssModule.fileName, text: cssModule.text },
|
|
63
61
|
start: { line: value.loc.start.line, column: value.loc.start.column },
|
|
64
|
-
|
|
62
|
+
length: value.loc.end.offset - value.loc.start.offset,
|
|
65
63
|
};
|
|
66
64
|
}
|
package/src/config.ts
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
1
|
import ts from 'typescript';
|
|
2
|
-
import type { SemanticDiagnostic } from './diagnostic.js';
|
|
3
2
|
import { TsConfigFileNotFoundError } from './error.js';
|
|
4
3
|
import { basename, dirname, join, resolve } from './path.js';
|
|
4
|
+
import type { Diagnostic } from './type.js';
|
|
5
5
|
|
|
6
6
|
// https://github.com/microsoft/TypeScript/blob/caf1aee269d1660b4d2a8b555c2d602c97cb28d7/src/compiler/commandLineParser.ts#L3006
|
|
7
7
|
const DEFAULT_INCLUDE_SPEC = '**/*';
|
|
8
8
|
|
|
9
|
-
type RemoveUndefined<T> = {
|
|
10
|
-
[K in keyof T]: Exclude<T[K], undefined>;
|
|
11
|
-
};
|
|
12
|
-
|
|
13
9
|
/**
|
|
14
10
|
* The config used by css-modules-kit.
|
|
15
11
|
* This is normalized. Paths are resolved from relative to absolute, and default values are set for missing options.
|
|
@@ -19,6 +15,8 @@ export interface CMKConfig {
|
|
|
19
15
|
excludes: string[];
|
|
20
16
|
dtsOutDir: string;
|
|
21
17
|
arbitraryExtensions: boolean;
|
|
18
|
+
namedExports: boolean;
|
|
19
|
+
prioritizeNamedImports: boolean;
|
|
22
20
|
/**
|
|
23
21
|
* A root directory to resolve relative path entries in the config file to.
|
|
24
22
|
* This is an absolute path.
|
|
@@ -60,7 +58,7 @@ export interface CMKConfig {
|
|
|
60
58
|
configFileName: string;
|
|
61
59
|
compilerOptions: ts.CompilerOptions;
|
|
62
60
|
/** The diagnostics that occurred while reading the config file. */
|
|
63
|
-
diagnostics:
|
|
61
|
+
diagnostics: Diagnostic[];
|
|
64
62
|
}
|
|
65
63
|
|
|
66
64
|
/**
|
|
@@ -68,10 +66,12 @@ export interface CMKConfig {
|
|
|
68
66
|
* This is unnormalized. Paths are relative, and some options may be omitted.
|
|
69
67
|
*/
|
|
70
68
|
interface UnnormalizedRawConfig {
|
|
71
|
-
includes
|
|
72
|
-
excludes
|
|
73
|
-
dtsOutDir
|
|
74
|
-
arbitraryExtensions
|
|
69
|
+
includes?: string[];
|
|
70
|
+
excludes?: string[];
|
|
71
|
+
dtsOutDir?: string;
|
|
72
|
+
arbitraryExtensions?: boolean;
|
|
73
|
+
namedExports?: boolean;
|
|
74
|
+
prioritizeNamedImports?: boolean;
|
|
75
75
|
}
|
|
76
76
|
|
|
77
77
|
/**
|
|
@@ -79,7 +79,7 @@ interface UnnormalizedRawConfig {
|
|
|
79
79
|
*/
|
|
80
80
|
interface ParsedRawData {
|
|
81
81
|
config: UnnormalizedRawConfig;
|
|
82
|
-
diagnostics:
|
|
82
|
+
diagnostics: Diagnostic[];
|
|
83
83
|
}
|
|
84
84
|
|
|
85
85
|
export function findTsConfigFile(project: string): string | undefined {
|
|
@@ -91,14 +91,9 @@ export function findTsConfigFile(project: string): string | undefined {
|
|
|
91
91
|
return resolve(configFile);
|
|
92
92
|
}
|
|
93
93
|
|
|
94
|
-
function parseRawData(raw: unknown,
|
|
94
|
+
function parseRawData(raw: unknown, tsConfigSourceFile: ts.TsConfigSourceFile): ParsedRawData {
|
|
95
95
|
const result: ParsedRawData = {
|
|
96
|
-
config: {
|
|
97
|
-
includes: undefined,
|
|
98
|
-
excludes: undefined,
|
|
99
|
-
dtsOutDir: undefined,
|
|
100
|
-
arbitraryExtensions: undefined,
|
|
101
|
-
},
|
|
96
|
+
config: {},
|
|
102
97
|
diagnostics: [],
|
|
103
98
|
};
|
|
104
99
|
if (typeof raw !== 'object' || raw === null) return result;
|
|
@@ -126,10 +121,9 @@ function parseRawData(raw: unknown, configFileName: string): ParsedRawData {
|
|
|
126
121
|
result.config.dtsOutDir = raw.cmkOptions.dtsOutDir;
|
|
127
122
|
} else {
|
|
128
123
|
result.diagnostics.push({
|
|
129
|
-
type: 'semantic',
|
|
130
124
|
category: 'error',
|
|
131
|
-
text:
|
|
132
|
-
|
|
125
|
+
text: `\`dtsOutDir\` in ${tsConfigSourceFile.fileName} must be a string.`,
|
|
126
|
+
// MEMO: Location information can be obtained from `tsConfigSourceFile.statements`, but this is complicated and will be omitted.
|
|
133
127
|
});
|
|
134
128
|
}
|
|
135
129
|
}
|
|
@@ -138,10 +132,31 @@ function parseRawData(raw: unknown, configFileName: string): ParsedRawData {
|
|
|
138
132
|
result.config.arbitraryExtensions = raw.cmkOptions.arbitraryExtensions;
|
|
139
133
|
} else {
|
|
140
134
|
result.diagnostics.push({
|
|
141
|
-
type: 'semantic',
|
|
142
135
|
category: 'error',
|
|
143
|
-
text:
|
|
144
|
-
|
|
136
|
+
text: `\`arbitraryExtensions\` in ${tsConfigSourceFile.fileName} must be a boolean.`,
|
|
137
|
+
// MEMO: Location information can be obtained from `tsConfigSourceFile.statements`, but this is complicated and will be omitted.
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
if ('namedExports' in raw.cmkOptions) {
|
|
142
|
+
if (typeof raw.cmkOptions.namedExports === 'boolean') {
|
|
143
|
+
result.config.namedExports = raw.cmkOptions.namedExports;
|
|
144
|
+
} else {
|
|
145
|
+
result.diagnostics.push({
|
|
146
|
+
category: 'error',
|
|
147
|
+
text: `\`namedExports\` in ${tsConfigSourceFile.fileName} must be a boolean.`,
|
|
148
|
+
// MEMO: Location information can be obtained from `tsConfigSourceFile.statements`, but this is complicated and will be omitted.
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if ('prioritizeNamedImports' in raw.cmkOptions) {
|
|
153
|
+
if (typeof raw.cmkOptions.prioritizeNamedImports === 'boolean') {
|
|
154
|
+
result.config.prioritizeNamedImports = raw.cmkOptions.prioritizeNamedImports;
|
|
155
|
+
} else {
|
|
156
|
+
result.diagnostics.push({
|
|
157
|
+
category: 'error',
|
|
158
|
+
text: `\`prioritizeNamedImports\` in ${tsConfigSourceFile.fileName} must be a boolean.`,
|
|
159
|
+
// MEMO: Location information can be obtained from `tsConfigSourceFile.statements`, but this is complicated and will be omitted.
|
|
145
160
|
});
|
|
146
161
|
}
|
|
147
162
|
}
|
|
@@ -157,6 +172,7 @@ function mergeParsedRawData(base: ParsedRawData, overrides: ParsedRawData): Pars
|
|
|
157
172
|
if (overrides.config.dtsOutDir !== undefined) result.config.dtsOutDir = overrides.config.dtsOutDir;
|
|
158
173
|
if (overrides.config.arbitraryExtensions !== undefined)
|
|
159
174
|
result.config.arbitraryExtensions = overrides.config.arbitraryExtensions;
|
|
175
|
+
if (overrides.config.namedExports !== undefined) result.config.namedExports = overrides.config.namedExports;
|
|
160
176
|
result.diagnostics.push(...overrides.diagnostics);
|
|
161
177
|
return result;
|
|
162
178
|
}
|
|
@@ -168,7 +184,7 @@ export function readTsConfigFile(project: string): {
|
|
|
168
184
|
configFileName: string;
|
|
169
185
|
config: UnnormalizedRawConfig;
|
|
170
186
|
compilerOptions: ts.CompilerOptions;
|
|
171
|
-
diagnostics:
|
|
187
|
+
diagnostics: Diagnostic[];
|
|
172
188
|
} {
|
|
173
189
|
const configFileName = findTsConfigFile(project);
|
|
174
190
|
if (!configFileName) throw new TsConfigFileNotFoundError();
|
|
@@ -195,7 +211,7 @@ export function readTsConfigFile(project: string): {
|
|
|
195
211
|
],
|
|
196
212
|
);
|
|
197
213
|
// Read options from `parsedCommandLine.raw`
|
|
198
|
-
let parsedRawData = parseRawData(parsedCommandLine.raw,
|
|
214
|
+
let parsedRawData = parseRawData(parsedCommandLine.raw, tsConfigSourceFile);
|
|
199
215
|
|
|
200
216
|
// The options read from `parsedCommandLine.raw` do not inherit values from the file specified in `extends`.
|
|
201
217
|
// So here we read the options from those files and merge them into `parsedRawData`.
|
|
@@ -219,24 +235,6 @@ export function readTsConfigFile(project: string): {
|
|
|
219
235
|
};
|
|
220
236
|
}
|
|
221
237
|
|
|
222
|
-
/**
|
|
223
|
-
* Normalize `UnnormalizedRawConfig`. Resolve relative paths to absolute paths, and set default values for missing options.
|
|
224
|
-
* @param basePath A root directory to resolve relative path entries in the config file to.
|
|
225
|
-
*/
|
|
226
|
-
export function normalizeConfig(
|
|
227
|
-
config: UnnormalizedRawConfig,
|
|
228
|
-
basePath: string,
|
|
229
|
-
): RemoveUndefined<UnnormalizedRawConfig> {
|
|
230
|
-
return {
|
|
231
|
-
// If `include` is not specified, fallback to the default include spec.
|
|
232
|
-
// ref: https://github.com/microsoft/TypeScript/blob/caf1aee269d1660b4d2a8b555c2d602c97cb28d7/src/compiler/commandLineParser.ts#L3102
|
|
233
|
-
includes: (config.includes ?? [DEFAULT_INCLUDE_SPEC]).map((i) => join(basePath, i)),
|
|
234
|
-
excludes: (config.excludes ?? []).map((e) => join(basePath, e)),
|
|
235
|
-
dtsOutDir: join(basePath, config.dtsOutDir ?? 'generated'),
|
|
236
|
-
arbitraryExtensions: config.arbitraryExtensions ?? false,
|
|
237
|
-
};
|
|
238
|
-
}
|
|
239
|
-
|
|
240
238
|
/**
|
|
241
239
|
* Reads the `tsconfig.json` file and returns the normalized config.
|
|
242
240
|
* Even if the `tsconfig.json` file contains syntax or semantic errors,
|
|
@@ -249,7 +247,14 @@ export function readConfigFile(project: string): CMKConfig {
|
|
|
249
247
|
const { configFileName, config, compilerOptions, diagnostics } = readTsConfigFile(project);
|
|
250
248
|
const basePath = dirname(configFileName);
|
|
251
249
|
return {
|
|
252
|
-
|
|
250
|
+
// If `include` is not specified, fallback to the default include spec.
|
|
251
|
+
// ref: https://github.com/microsoft/TypeScript/blob/caf1aee269d1660b4d2a8b555c2d602c97cb28d7/src/compiler/commandLineParser.ts#L3102
|
|
252
|
+
includes: (config.includes ?? [DEFAULT_INCLUDE_SPEC]).map((i) => join(basePath, i)),
|
|
253
|
+
excludes: (config.excludes ?? []).map((e) => join(basePath, e)),
|
|
254
|
+
dtsOutDir: join(basePath, config.dtsOutDir ?? 'generated'),
|
|
255
|
+
arbitraryExtensions: config.arbitraryExtensions ?? false,
|
|
256
|
+
namedExports: config.namedExports ?? false,
|
|
257
|
+
prioritizeNamedImports: config.prioritizeNamedImports ?? false,
|
|
253
258
|
basePath,
|
|
254
259
|
configFileName,
|
|
255
260
|
compilerOptions,
|
package/src/diagnostic.ts
CHANGED
|
@@ -1,37 +1,77 @@
|
|
|
1
|
-
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import type { SystemError } from './error.js';
|
|
3
|
+
import type { Diagnostic, DiagnosticSourceFile, DiagnosticWithLocation } from './type.js';
|
|
2
4
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
column: number;
|
|
8
|
-
}
|
|
5
|
+
/** The error code used by tsserver to display the css-modules-kit error in the editor. */
|
|
6
|
+
const TS_ERROR_CODE = 0;
|
|
7
|
+
|
|
8
|
+
const TS_ERROR_SOURCE = 'css-modules-kit';
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
function convertErrorCategory(category: 'error' | 'warning' | 'suggestion'): ts.DiagnosticCategory {
|
|
11
|
+
switch (category) {
|
|
12
|
+
case 'error':
|
|
13
|
+
return ts.DiagnosticCategory.Error;
|
|
14
|
+
case 'warning':
|
|
15
|
+
return ts.DiagnosticCategory.Warning;
|
|
16
|
+
case 'suggestion':
|
|
17
|
+
return ts.DiagnosticCategory.Suggestion;
|
|
18
|
+
default:
|
|
19
|
+
throw new Error(`Unknown category: ${String(category)}`);
|
|
20
|
+
}
|
|
21
|
+
}
|
|
11
22
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
23
|
+
export function convertDiagnostic(
|
|
24
|
+
diagnostic: Diagnostic,
|
|
25
|
+
getSourceFile: (file: DiagnosticSourceFile) => ts.SourceFile,
|
|
26
|
+
): ts.Diagnostic {
|
|
27
|
+
if ('file' in diagnostic) {
|
|
28
|
+
return convertDiagnosticWithLocation(diagnostic, getSourceFile);
|
|
29
|
+
} else {
|
|
30
|
+
return {
|
|
31
|
+
file: undefined,
|
|
32
|
+
start: undefined,
|
|
33
|
+
length: undefined,
|
|
34
|
+
category: convertErrorCategory(diagnostic.category),
|
|
35
|
+
messageText: diagnostic.text,
|
|
36
|
+
code: TS_ERROR_CODE,
|
|
37
|
+
source: TS_ERROR_SOURCE,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
17
40
|
}
|
|
18
41
|
|
|
19
|
-
export
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
start
|
|
25
|
-
|
|
26
|
-
|
|
42
|
+
export function convertDiagnosticWithLocation(
|
|
43
|
+
diagnostic: DiagnosticWithLocation,
|
|
44
|
+
getSourceFile: (file: DiagnosticSourceFile) => ts.SourceFile,
|
|
45
|
+
): ts.DiagnosticWithLocation {
|
|
46
|
+
const sourceFile = getSourceFile(diagnostic.file);
|
|
47
|
+
const start = ts.getPositionOfLineAndCharacter(sourceFile, diagnostic.start.line - 1, diagnostic.start.column - 1);
|
|
48
|
+
return {
|
|
49
|
+
file: sourceFile,
|
|
50
|
+
start,
|
|
51
|
+
length: diagnostic.length,
|
|
52
|
+
category: convertErrorCategory(diagnostic.category),
|
|
53
|
+
messageText: diagnostic.text,
|
|
54
|
+
code: TS_ERROR_CODE,
|
|
55
|
+
source: TS_ERROR_SOURCE,
|
|
56
|
+
};
|
|
27
57
|
}
|
|
28
58
|
|
|
29
|
-
export
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
59
|
+
export function convertSystemError(systemError: SystemError): ts.Diagnostic {
|
|
60
|
+
let messageText = systemError.message;
|
|
61
|
+
if (systemError.cause) {
|
|
62
|
+
if (systemError.cause instanceof Error) {
|
|
63
|
+
messageText += `: ${systemError.cause.message}`;
|
|
64
|
+
} else {
|
|
65
|
+
messageText += `: ${JSON.stringify(systemError.cause)}`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
file: undefined,
|
|
70
|
+
start: undefined,
|
|
71
|
+
length: undefined,
|
|
72
|
+
category: ts.DiagnosticCategory.Error,
|
|
73
|
+
messageText,
|
|
74
|
+
code: TS_ERROR_CODE,
|
|
75
|
+
source: TS_ERROR_SOURCE,
|
|
76
|
+
};
|
|
37
77
|
}
|