@css-modules-kit/core 0.0.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/LICENSE +21 -0
- package/dist/checker.d.ts +7 -0
- package/dist/checker.d.ts.map +1 -0
- package/dist/checker.js +46 -0
- package/dist/checker.js.map +1 -0
- package/dist/config.d.ts +101 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +200 -0
- package/dist/config.js.map +1 -0
- package/dist/diagnostic.d.ts +34 -0
- package/dist/diagnostic.d.ts.map +1 -0
- package/dist/diagnostic.js +3 -0
- package/dist/diagnostic.js.map +1 -0
- package/dist/dts-creator.d.ts +56 -0
- package/dist/dts-creator.d.ts.map +1 -0
- package/dist/dts-creator.js +95 -0
- package/dist/dts-creator.js.map +1 -0
- package/dist/error.d.ts +8 -0
- package/dist/error.d.ts.map +1 -0
- package/dist/error.js +18 -0
- package/dist/error.js.map +1 -0
- package/dist/export-builder.d.ts +23 -0
- package/dist/export-builder.d.ts.map +1 -0
- package/dist/export-builder.js +34 -0
- package/dist/export-builder.js.map +1 -0
- package/dist/external-file.d.ts +2 -0
- package/dist/external-file.d.ts.map +1 -0
- package/dist/external-file.js +3 -0
- package/dist/external-file.js.map +1 -0
- package/dist/file.d.ts +28 -0
- package/dist/file.d.ts.map +1 -0
- package/dist/file.js +73 -0
- package/dist/file.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +39 -0
- package/dist/index.js.map +1 -0
- package/dist/language-plugin.d.ts +23 -0
- package/dist/language-plugin.d.ts.map +1 -0
- package/dist/language-plugin.js +73 -0
- package/dist/language-plugin.js.map +1 -0
- package/dist/parser/at-import-parser.d.ts +14 -0
- package/dist/parser/at-import-parser.d.ts.map +1 -0
- package/dist/parser/at-import-parser.js +47 -0
- package/dist/parser/at-import-parser.js.map +1 -0
- package/dist/parser/at-value-parser.d.ts +44 -0
- package/dist/parser/at-value-parser.d.ts.map +1 -0
- package/dist/parser/at-value-parser.js +147 -0
- package/dist/parser/at-value-parser.js.map +1 -0
- package/dist/parser/css-module-parser.d.ts +93 -0
- package/dist/parser/css-module-parser.d.ts.map +1 -0
- package/dist/parser/css-module-parser.js +96 -0
- package/dist/parser/css-module-parser.js.map +1 -0
- package/dist/parser/diagnostic.d.ts +34 -0
- package/dist/parser/diagnostic.d.ts.map +1 -0
- package/dist/parser/diagnostic.js +3 -0
- package/dist/parser/diagnostic.js.map +1 -0
- package/dist/parser/location.d.ts +34 -0
- package/dist/parser/location.d.ts.map +1 -0
- package/dist/parser/location.js +9 -0
- package/dist/parser/location.js.map +1 -0
- package/dist/parser/rule-parser.d.ts +19 -0
- package/dist/parser/rule-parser.d.ts.map +1 -0
- package/dist/parser/rule-parser.js +122 -0
- package/dist/parser/rule-parser.js.map +1 -0
- package/dist/path.d.ts +11 -0
- package/dist/path.d.ts.map +1 -0
- package/dist/path.js +43 -0
- package/dist/path.js.map +1 -0
- package/dist/resolver.d.ts +13 -0
- package/dist/resolver.d.ts.map +1 -0
- package/dist/resolver.js +50 -0
- package/dist/resolver.js.map +1 -0
- package/dist/semantic-builder.d.ts +23 -0
- package/dist/semantic-builder.d.ts.map +1 -0
- package/dist/semantic-builder.js +33 -0
- package/dist/semantic-builder.js.map +1 -0
- package/dist/util.d.ts +2 -0
- package/dist/util.d.ts.map +1 -0
- package/dist/util.js +7 -0
- package/dist/util.js.map +1 -0
- package/package.json +54 -0
- package/src/checker.ts +66 -0
- package/src/config.ts +285 -0
- package/src/diagnostic.ts +37 -0
- package/src/dts-creator.ts +128 -0
- package/src/error.ts +13 -0
- package/src/export-builder.ts +51 -0
- package/src/file.ts +83 -0
- package/src/index.ts +38 -0
- package/src/parser/at-import-parser.ts +47 -0
- package/src/parser/at-value-parser.ts +177 -0
- package/src/parser/css-module-parser.ts +193 -0
- package/src/parser/location.ts +43 -0
- package/src/parser/rule-parser.ts +140 -0
- package/src/path.ts +40 -0
- package/src/resolver.ts +57 -0
- package/src/typing/typescript.d.ts +19 -0
- package/src/util.ts +3 -0
package/dist/path.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.isAbsolute = exports.matchesGlob = void 0;
|
|
7
|
+
exports.slash = slash;
|
|
8
|
+
exports.join = join;
|
|
9
|
+
exports.resolve = resolve;
|
|
10
|
+
exports.relative = relative;
|
|
11
|
+
exports.dirname = dirname;
|
|
12
|
+
exports.basename = basename;
|
|
13
|
+
exports.parse = parse;
|
|
14
|
+
// eslint-disable-next-line no-restricted-imports
|
|
15
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
16
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
17
|
+
function slash(path) {
|
|
18
|
+
return typescript_1.default.server.toNormalizedPath(path);
|
|
19
|
+
}
|
|
20
|
+
function join(...paths) {
|
|
21
|
+
return slash(node_path_1.default.join(...paths));
|
|
22
|
+
}
|
|
23
|
+
function resolve(...paths) {
|
|
24
|
+
return slash(node_path_1.default.resolve(...paths));
|
|
25
|
+
}
|
|
26
|
+
function relative(from, to) {
|
|
27
|
+
return slash(node_path_1.default.relative(from, to));
|
|
28
|
+
}
|
|
29
|
+
function dirname(path) {
|
|
30
|
+
return slash(node_path_1.default.dirname(path));
|
|
31
|
+
}
|
|
32
|
+
function basename(path) {
|
|
33
|
+
return slash(node_path_1.default.basename(path));
|
|
34
|
+
}
|
|
35
|
+
function parse(path) {
|
|
36
|
+
const { root, dir, base, name, ext } = node_path_1.default.parse(path);
|
|
37
|
+
return { root: slash(root), dir: slash(dir), base, name, ext };
|
|
38
|
+
}
|
|
39
|
+
// eslint-disable-next-line n/no-unsupported-features/node-builtins, @typescript-eslint/unbound-method
|
|
40
|
+
exports.matchesGlob = node_path_1.default.matchesGlob;
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
42
|
+
exports.isAbsolute = node_path_1.default.isAbsolute;
|
|
43
|
+
//# sourceMappingURL=path.js.map
|
package/dist/path.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path.js","sourceRoot":"","sources":["../src/path.ts"],"names":[],"mappings":";;;;;;AAMA,sBAEC;AAED,oBAEC;AAED,0BAEC;AAED,4BAEC;AAED,0BAEC;AAED,4BAEC;AAED,sBAGC;AA/BD,iDAAiD;AACjD,0DAAiC;AACjC,4DAA4B;AAE5B,SAAgB,KAAK,CAAC,IAAY;IAChC,OAAO,oBAAE,CAAC,MAAM,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAC1C,CAAC;AAED,SAAgB,IAAI,CAAC,GAAG,KAAe;IACrC,OAAO,KAAK,CAAC,mBAAQ,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,SAAgB,OAAO,CAAC,GAAG,KAAe;IACxC,OAAO,KAAK,CAAC,mBAAQ,CAAC,OAAO,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC;AAC3C,CAAC;AAED,SAAgB,QAAQ,CAAC,IAAY,EAAE,EAAU;IAC/C,OAAO,KAAK,CAAC,mBAAQ,CAAC,QAAQ,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC;AAC5C,CAAC;AAED,SAAgB,OAAO,CAAC,IAAY;IAClC,OAAO,KAAK,CAAC,mBAAQ,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,SAAgB,QAAQ,CAAC,IAAY;IACnC,OAAO,KAAK,CAAC,mBAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC;AACxC,CAAC;AAED,SAAgB,KAAK,CAAC,IAAY;IAChC,MAAM,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,GAAG,mBAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,KAAK,CAAC,GAAG,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,CAAC;AACjE,CAAC;AAED,sGAAsG;AACzF,QAAA,WAAW,GAAG,mBAAQ,CAAC,WAAW,CAAC;AAEhD,6DAA6D;AAChD,QAAA,UAAU,GAAG,mBAAQ,CAAC,UAAU,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export interface ResolverOptions {
|
|
2
|
+
/** The file that imports the specifier. It is a absolute path. */
|
|
3
|
+
request: string;
|
|
4
|
+
}
|
|
5
|
+
/**
|
|
6
|
+
* A resolver function that resolves import specifiers.
|
|
7
|
+
* @param specifier The import specifier.
|
|
8
|
+
* @param options The options.
|
|
9
|
+
* @returns The resolved import specifier. It is a absolute path. If the import specifier cannot be resolved, return `undefined`.
|
|
10
|
+
*/
|
|
11
|
+
export type Resolver = (specifier: string, options: ResolverOptions) => string | undefined;
|
|
12
|
+
export declare function createResolver(paths: Record<string, string[]>): Resolver;
|
|
13
|
+
//# sourceMappingURL=resolver.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.d.ts","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":"AAIA,MAAM,WAAW,eAAe;IAC9B,kEAAkE;IAClE,OAAO,EAAE,MAAM,CAAC;CACjB;AAED;;;;;GAKG;AACH,MAAM,MAAM,QAAQ,GAAG,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,KAAK,MAAM,GAAG,SAAS,CAAC;AAE3F,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAAG,QAAQ,CA+BxE"}
|
package/dist/resolver.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.createResolver = createResolver;
|
|
7
|
+
const node_url_1 = require("node:url");
|
|
8
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
9
|
+
const path_js_1 = require("./path.js");
|
|
10
|
+
function createResolver(paths) {
|
|
11
|
+
return (_specifier, options) => {
|
|
12
|
+
let specifier = _specifier;
|
|
13
|
+
const host = {
|
|
14
|
+
...typescript_1.default.sys,
|
|
15
|
+
fileExists: (fileName) => {
|
|
16
|
+
if (fileName.endsWith('.module.d.css.ts')) {
|
|
17
|
+
return typescript_1.default.sys.fileExists(fileName.replace(/\.module\.d\.css\.ts$/u, '.module.css'));
|
|
18
|
+
}
|
|
19
|
+
return typescript_1.default.sys.fileExists(fileName);
|
|
20
|
+
},
|
|
21
|
+
};
|
|
22
|
+
const { resolvedModule } = typescript_1.default.resolveModuleName(specifier, options.request, { paths }, host);
|
|
23
|
+
if (resolvedModule) {
|
|
24
|
+
// TODO: Logging that the paths is used.
|
|
25
|
+
specifier = resolvedModule.resolvedFileName.replace(/\.module\.d\.css\.ts$/u, '.module.css');
|
|
26
|
+
}
|
|
27
|
+
if ((0, path_js_1.isAbsolute)(specifier)) {
|
|
28
|
+
return (0, path_js_1.resolve)(specifier);
|
|
29
|
+
}
|
|
30
|
+
else if (isRelativeSpecifier(specifier)) {
|
|
31
|
+
// Convert the specifier to an absolute path
|
|
32
|
+
// NOTE: Node.js resolves relative specifier with standard relative URL resolution semantics. So we will follow that here as well.
|
|
33
|
+
// ref: https://nodejs.org/docs/latest-v23.x/api/esm.html#terminology
|
|
34
|
+
return (0, path_js_1.resolve)((0, node_url_1.fileURLToPath)(new URL(specifier, (0, node_url_1.pathToFileURL)(options.request)).href));
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
// Do not support URL or bare specifiers
|
|
38
|
+
// TODO: Logging that the specifier could not resolve.
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Check if the specifier is a relative specifier.
|
|
45
|
+
* @see https://nodejs.org/docs/latest-v23.x/api/esm.html#terminology
|
|
46
|
+
*/
|
|
47
|
+
function isRelativeSpecifier(specifier) {
|
|
48
|
+
return specifier.startsWith('./') || specifier.startsWith('../');
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resolver.js","sourceRoot":"","sources":["../src/resolver.ts"],"names":[],"mappings":";;;;;AAiBA,wCA+BC;AAhDD,uCAAwD;AACxD,4DAA4B;AAC5B,uCAAgD;AAehD,SAAgB,cAAc,CAAC,KAA+B;IAC5D,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,CAAC,SAAS,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;QAC7F,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"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { MatchesPattern } from './file.js';
|
|
2
|
+
import type { CSSModule } from './parser/css-module-parser.js';
|
|
3
|
+
export interface SemanticBuilderHost {
|
|
4
|
+
matchesPattern: MatchesPattern;
|
|
5
|
+
getCSSModule: (path: string) => CSSModule | undefined;
|
|
6
|
+
getCSSModuleVersion: (path: string) => string | undefined;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* The semantic record for a CSS module.
|
|
10
|
+
*/
|
|
11
|
+
export interface SemanticRecord {
|
|
12
|
+
/** The version of the source code. It should be updated when the source code changes. */
|
|
13
|
+
version: string;
|
|
14
|
+
/** The all exported tokens of the CSS module. */
|
|
15
|
+
allTokens: string[];
|
|
16
|
+
}
|
|
17
|
+
export declare class SemanticBuilder {
|
|
18
|
+
readonly records: Map<string, SemanticRecord>;
|
|
19
|
+
readonly host: SemanticBuilderHost;
|
|
20
|
+
constructor(host: SemanticBuilderHost);
|
|
21
|
+
build(cssModule: CSSModule): SemanticRecord;
|
|
22
|
+
}
|
|
23
|
+
//# sourceMappingURL=semantic-builder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic-builder.d.ts","sourceRoot":"","sources":["../src/semantic-builder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAE/D,MAAM,WAAW,mBAAmB;IAClC,cAAc,EAAE,cAAc,CAAC;IAC/B,YAAY,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,SAAS,GAAG,SAAS,CAAC;IACtD,mBAAmB,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,MAAM,GAAG,SAAS,CAAC;CAC3D;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yFAAyF;IACzF,OAAO,EAAE,MAAM,CAAC;IAChB,iDAAiD;IACjD,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,qBAAa,eAAe;IAC1B,QAAQ,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAa;IAC1D,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAC;gBACvB,IAAI,EAAE,mBAAmB;IAIrC,KAAK,CAAC,SAAS,EAAE,SAAS,GAAG,cAAc;CAmB5C"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SemanticBuilder = void 0;
|
|
4
|
+
class SemanticBuilder {
|
|
5
|
+
records = new Map();
|
|
6
|
+
host;
|
|
7
|
+
constructor(host) {
|
|
8
|
+
this.records = new Map();
|
|
9
|
+
this.host = host;
|
|
10
|
+
}
|
|
11
|
+
build(cssModule) {
|
|
12
|
+
const cached = this.records.get(cssModule.fileName);
|
|
13
|
+
const version = this.host.getCSSModuleVersion(cssModule.fileName) ?? '1';
|
|
14
|
+
if (cached && version === cached.version)
|
|
15
|
+
return cached;
|
|
16
|
+
const result = { version, allTokens: [...cssModule.localTokens.map((t) => t.name)] };
|
|
17
|
+
for (const tokenImporter of cssModule.tokenImporters) {
|
|
18
|
+
if (!this.host.matchesPattern(tokenImporter.from))
|
|
19
|
+
continue;
|
|
20
|
+
const imported = this.host.getCSSModule(tokenImporter.from);
|
|
21
|
+
if (!imported)
|
|
22
|
+
continue;
|
|
23
|
+
const importedResult = this.build(imported);
|
|
24
|
+
if (tokenImporter.type === 'import') {
|
|
25
|
+
result.allTokens.push(...importedResult.allTokens);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
this.records.set(cssModule.fileName, result);
|
|
29
|
+
return result;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
exports.SemanticBuilder = SemanticBuilder;
|
|
33
|
+
//# sourceMappingURL=semantic-builder.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"semantic-builder.js","sourceRoot":"","sources":["../src/semantic-builder.ts"],"names":[],"mappings":";;;AAmBA,MAAa,eAAe;IACjB,OAAO,GAAgC,IAAI,GAAG,EAAE,CAAC;IACjD,IAAI,CAAsB;IACnC,YAAY,IAAyB;QACnC,IAAI,CAAC,OAAO,GAAG,IAAI,GAAG,EAAE,CAAC;QACzB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;IACnB,CAAC;IACD,KAAK,CAAC,SAAoB;QACxB,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;QACpD,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,CAAC,mBAAmB,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,GAAG,CAAC;QACzE,IAAI,MAAM,IAAI,OAAO,KAAK,MAAM,CAAC,OAAO;YAAE,OAAO,MAAM,CAAC;QACxD,MAAM,MAAM,GAAmB,EAAE,OAAO,EAAE,SAAS,EAAE,CAAC,GAAG,SAAS,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC;QAErG,KAAK,MAAM,aAAa,IAAI,SAAS,CAAC,cAAc,EAAE,CAAC;YACrD,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,CAAC,aAAa,CAAC,IAAI,CAAC;gBAAE,SAAS;YAC5D,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC;YAC5D,IAAI,CAAC,QAAQ;gBAAE,SAAS;YAExB,MAAM,cAAc,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;YAC5C,IAAI,aAAa,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACpC,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,SAAS,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QACD,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;QAC7C,OAAO,MAAM,CAAC;IAChB,CAAC;CACF;AA1BD,0CA0BC"}
|
package/dist/util.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.d.ts","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":"AAAA,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAEzD"}
|
package/dist/util.js
ADDED
package/dist/util.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"util.js","sourceRoot":"","sources":["../src/util.ts"],"names":[],"mappings":";;AAAA,kDAEC;AAFD,SAAgB,mBAAmB,CAAC,IAAY;IAC9C,OAAO,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;AACzD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@css-modules-kit/core",
|
|
3
|
+
"description": "The core of css-modules-kit",
|
|
4
|
+
"version": "0.0.1",
|
|
5
|
+
"type": "commonjs",
|
|
6
|
+
"sideEffects": false,
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/mizdra/css-modules-kit.git",
|
|
10
|
+
"directory": "packages/core"
|
|
11
|
+
},
|
|
12
|
+
"author": "mizdra <pp.mizdra@gmail.com>",
|
|
13
|
+
"license": "MIT",
|
|
14
|
+
"private": false,
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"default": {
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
23
|
+
"scripts": {
|
|
24
|
+
"build": "tsc -b tsconfig.build.json"
|
|
25
|
+
},
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=22.0.0"
|
|
28
|
+
},
|
|
29
|
+
"publishConfig": {
|
|
30
|
+
"access": "public",
|
|
31
|
+
"registry": "https://registry.npmjs.org/"
|
|
32
|
+
},
|
|
33
|
+
"keywords": [
|
|
34
|
+
"css-modules",
|
|
35
|
+
"typescript"
|
|
36
|
+
],
|
|
37
|
+
"files": [
|
|
38
|
+
"bin",
|
|
39
|
+
"src",
|
|
40
|
+
"!src/**/*.test.ts",
|
|
41
|
+
"!src/**/__snapshots__",
|
|
42
|
+
"!src/test",
|
|
43
|
+
"dist"
|
|
44
|
+
],
|
|
45
|
+
"dependencies": {
|
|
46
|
+
"postcss": "^8.4.49",
|
|
47
|
+
"postcss-safe-parser": "^7.0.1",
|
|
48
|
+
"postcss-selector-parser": "^7.1.0",
|
|
49
|
+
"postcss-value-parser": "^4.2.0"
|
|
50
|
+
},
|
|
51
|
+
"peerDependencies": {
|
|
52
|
+
"typescript": "^5.7.3"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/src/checker.ts
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import type { SemanticDiagnostic } from './diagnostic.js';
|
|
2
|
+
import type { ExportBuilder } from './export-builder.js';
|
|
3
|
+
import type { MatchesPattern } from './file.js';
|
|
4
|
+
import type {
|
|
5
|
+
AtValueTokenImporter,
|
|
6
|
+
AtValueTokenImporterValue,
|
|
7
|
+
CSSModule,
|
|
8
|
+
TokenImporter,
|
|
9
|
+
} from './parser/css-module-parser.js';
|
|
10
|
+
import type { Resolver } from './resolver.js';
|
|
11
|
+
|
|
12
|
+
export function checkCSSModule(
|
|
13
|
+
cssModule: CSSModule,
|
|
14
|
+
exportBuilder: ExportBuilder,
|
|
15
|
+
matchesPattern: MatchesPattern,
|
|
16
|
+
resolver: Resolver,
|
|
17
|
+
getCSSModule: (path: string) => CSSModule | undefined,
|
|
18
|
+
): SemanticDiagnostic[] {
|
|
19
|
+
const diagnostics: SemanticDiagnostic[] = [];
|
|
20
|
+
|
|
21
|
+
for (const tokenImporter of cssModule.tokenImporters) {
|
|
22
|
+
const from = resolver(tokenImporter.from, { request: cssModule.fileName });
|
|
23
|
+
if (!from || !matchesPattern(from)) continue;
|
|
24
|
+
const imported = getCSSModule(from);
|
|
25
|
+
if (!imported) {
|
|
26
|
+
diagnostics.push(createCannotImportModuleDiagnostic(cssModule, tokenImporter));
|
|
27
|
+
continue;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
if (tokenImporter.type === 'value') {
|
|
31
|
+
const exportRecord = exportBuilder.build(imported);
|
|
32
|
+
for (const value of tokenImporter.values) {
|
|
33
|
+
if (!exportRecord.allTokens.includes(value.name)) {
|
|
34
|
+
diagnostics.push(createModuleHasNoExportedTokenDiagnostic(cssModule, tokenImporter, value));
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return diagnostics;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
function createCannotImportModuleDiagnostic(cssModule: CSSModule, tokenImporter: TokenImporter): SemanticDiagnostic {
|
|
43
|
+
return {
|
|
44
|
+
type: 'semantic',
|
|
45
|
+
text: `Cannot import module '${tokenImporter.from}'`,
|
|
46
|
+
category: 'error',
|
|
47
|
+
fileName: cssModule.fileName,
|
|
48
|
+
start: { line: tokenImporter.fromLoc.start.line, column: tokenImporter.fromLoc.start.column },
|
|
49
|
+
end: { line: tokenImporter.fromLoc.end.line, column: tokenImporter.fromLoc.end.column },
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function createModuleHasNoExportedTokenDiagnostic(
|
|
54
|
+
cssModule: CSSModule,
|
|
55
|
+
tokenImporter: AtValueTokenImporter,
|
|
56
|
+
value: AtValueTokenImporterValue,
|
|
57
|
+
): SemanticDiagnostic {
|
|
58
|
+
return {
|
|
59
|
+
type: 'semantic',
|
|
60
|
+
text: `Module '${tokenImporter.from}' has no exported token '${value.name}'.`,
|
|
61
|
+
category: 'error',
|
|
62
|
+
fileName: cssModule.fileName,
|
|
63
|
+
start: { line: value.loc.start.line, column: value.loc.start.column },
|
|
64
|
+
end: { line: value.loc.end.line, column: value.loc.end.column },
|
|
65
|
+
};
|
|
66
|
+
}
|
package/src/config.ts
ADDED
|
@@ -0,0 +1,285 @@
|
|
|
1
|
+
import ts from 'typescript';
|
|
2
|
+
import type { SemanticDiagnostic } from './diagnostic.js';
|
|
3
|
+
import { TsConfigFileNotFoundError } from './error.js';
|
|
4
|
+
import { basename, dirname, join, resolve } from './path.js';
|
|
5
|
+
|
|
6
|
+
// https://github.com/microsoft/TypeScript/blob/caf1aee269d1660b4d2a8b555c2d602c97cb28d7/src/compiler/commandLineParser.ts#L3006
|
|
7
|
+
const DEFAULT_INCLUDE_SPEC = '**/*';
|
|
8
|
+
|
|
9
|
+
type RemoveUndefined<T> = {
|
|
10
|
+
[K in keyof T]: Exclude<T[K], undefined>;
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* The config used by css-modules-kit.
|
|
15
|
+
* This is normalized. Paths are resolved from relative to absolute, and default values are set for missing options.
|
|
16
|
+
*/
|
|
17
|
+
export interface CMKConfig {
|
|
18
|
+
includes: string[];
|
|
19
|
+
excludes: string[];
|
|
20
|
+
paths: Record<string, string[]>;
|
|
21
|
+
dtsOutDir: string;
|
|
22
|
+
arbitraryExtensions: boolean;
|
|
23
|
+
dashedIdents: boolean;
|
|
24
|
+
/**
|
|
25
|
+
* A root directory to resolve relative path entries in the config file to.
|
|
26
|
+
* This is an absolute path.
|
|
27
|
+
*
|
|
28
|
+
* This is also used to determine the output directory of the d.ts file.
|
|
29
|
+
* For example, let’s say you have some input files:
|
|
30
|
+
* ```
|
|
31
|
+
* /app
|
|
32
|
+
* ├── tsconfig.json
|
|
33
|
+
* ├── src
|
|
34
|
+
* │ ├── a.module.css
|
|
35
|
+
* │ ├── b.module.css
|
|
36
|
+
* │ ├── sub
|
|
37
|
+
* │ │ ├── c.module.css
|
|
38
|
+
* ```
|
|
39
|
+
*
|
|
40
|
+
* If you set `basePath` to `/app/src`, the output files will be:
|
|
41
|
+
* ```
|
|
42
|
+
* /app
|
|
43
|
+
* ├── dist
|
|
44
|
+
* │ ├── a.module.css.d.ts
|
|
45
|
+
* │ ├── b.module.css.d.ts
|
|
46
|
+
* │ ├── sub
|
|
47
|
+
* │ │ ├── c.module.css.d.ts
|
|
48
|
+
* ```
|
|
49
|
+
*
|
|
50
|
+
* If you set `basePath` to `/app`, the output files will be:
|
|
51
|
+
* ```
|
|
52
|
+
* /app
|
|
53
|
+
* ├── dist
|
|
54
|
+
* │ ├── src
|
|
55
|
+
* │ │ ├── a.module.css.d.ts
|
|
56
|
+
* │ │ ├── b.module.css.d.ts
|
|
57
|
+
* │ │ ├── sub
|
|
58
|
+
* │ │ │ ├── c.module.css.d.ts
|
|
59
|
+
* ```
|
|
60
|
+
*/
|
|
61
|
+
basePath: string;
|
|
62
|
+
configFileName: string;
|
|
63
|
+
/** The diagnostics that occurred while reading the config file. */
|
|
64
|
+
diagnostics: SemanticDiagnostic[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* The config loaded from `tsconfig.json`.
|
|
69
|
+
* This is unnormalized. Paths are relative, and some options may be omitted.
|
|
70
|
+
*/
|
|
71
|
+
interface UnnormalizedCMKConfig {
|
|
72
|
+
includes: string[] | undefined;
|
|
73
|
+
excludes: string[] | undefined;
|
|
74
|
+
paths: Record<string, string[]> | undefined;
|
|
75
|
+
dtsOutDir: string | undefined;
|
|
76
|
+
arbitraryExtensions: boolean | undefined;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
/**
|
|
80
|
+
* The validated data of `ts.ParsedCommandLine['raw']`.
|
|
81
|
+
*/
|
|
82
|
+
interface ParsedRawData {
|
|
83
|
+
config: UnnormalizedCMKConfig;
|
|
84
|
+
diagnostics: SemanticDiagnostic[];
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// eslint-disable-next-line complexity
|
|
88
|
+
function parseRawData(raw: unknown, configFileName: string): ParsedRawData {
|
|
89
|
+
const result: ParsedRawData = {
|
|
90
|
+
config: {
|
|
91
|
+
includes: undefined,
|
|
92
|
+
excludes: undefined,
|
|
93
|
+
paths: undefined,
|
|
94
|
+
dtsOutDir: undefined,
|
|
95
|
+
arbitraryExtensions: undefined,
|
|
96
|
+
},
|
|
97
|
+
diagnostics: [],
|
|
98
|
+
};
|
|
99
|
+
if (typeof raw !== 'object' || raw === null) return result;
|
|
100
|
+
|
|
101
|
+
// `tsConfigSourceFile.configFileSpecs` contains `includes` and `excludes`. However, it is an internal API.
|
|
102
|
+
// So we collect `includes` and `excludes` from `parsedCommandLine.raw` without the internal API.
|
|
103
|
+
|
|
104
|
+
if ('include' in raw) {
|
|
105
|
+
if (Array.isArray(raw.include)) {
|
|
106
|
+
const includes = raw.include.filter((i) => typeof i === 'string');
|
|
107
|
+
result.config.includes = includes;
|
|
108
|
+
}
|
|
109
|
+
// MEMO: The errors for this option are reported by `tsc` or `tsserver`, so we don't need to report.
|
|
110
|
+
}
|
|
111
|
+
if ('exclude' in raw) {
|
|
112
|
+
if (Array.isArray(raw.exclude)) {
|
|
113
|
+
const excludes = raw.exclude.filter((e) => typeof e === 'string');
|
|
114
|
+
result.config.excludes = excludes;
|
|
115
|
+
}
|
|
116
|
+
// MEMO: The errors for this option are reported by `tsc` or `tsserver`, so we don't need to report.
|
|
117
|
+
}
|
|
118
|
+
if ('compilerOptions' in raw && typeof raw.compilerOptions === 'object' && raw.compilerOptions !== null) {
|
|
119
|
+
if ('paths' in raw.compilerOptions) {
|
|
120
|
+
if (typeof raw.compilerOptions.paths === 'object' && raw.compilerOptions.paths !== null) {
|
|
121
|
+
const paths: Record<string, string[]> = {};
|
|
122
|
+
for (const [key, value] of Object.entries(raw.compilerOptions.paths)) {
|
|
123
|
+
if (Array.isArray(value)) {
|
|
124
|
+
const resolvedValue = value.filter((v) => typeof v === 'string');
|
|
125
|
+
paths[key] = resolvedValue;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
result.config.paths = paths;
|
|
129
|
+
}
|
|
130
|
+
// MEMO: The errors for this option are reported by `tsc` or `tsserver`, so we don't need to report.
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
if ('cmkOptions' in raw && typeof raw.cmkOptions === 'object' && raw.cmkOptions !== null) {
|
|
134
|
+
if ('dtsOutDir' in raw.cmkOptions) {
|
|
135
|
+
if (typeof raw.cmkOptions.dtsOutDir === 'string') {
|
|
136
|
+
result.config.dtsOutDir = raw.cmkOptions.dtsOutDir;
|
|
137
|
+
} else {
|
|
138
|
+
result.diagnostics.push({
|
|
139
|
+
type: 'semantic',
|
|
140
|
+
category: 'error',
|
|
141
|
+
text: '`dtsOutDir` must be a string.',
|
|
142
|
+
fileName: configFileName,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
if ('arbitraryExtensions' in raw.cmkOptions) {
|
|
147
|
+
if (typeof raw.cmkOptions.arbitraryExtensions === 'boolean') {
|
|
148
|
+
result.config.arbitraryExtensions = raw.cmkOptions.arbitraryExtensions;
|
|
149
|
+
} else {
|
|
150
|
+
result.diagnostics.push({
|
|
151
|
+
type: 'semantic',
|
|
152
|
+
category: 'error',
|
|
153
|
+
text: '`arbitraryExtensions` must be a boolean.',
|
|
154
|
+
fileName: configFileName,
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
export { parseRawData as parseRawDataForTest };
|
|
162
|
+
|
|
163
|
+
/**
|
|
164
|
+
* Reads the `tsconfig.json` file and returns the normalized config.
|
|
165
|
+
* Even if the `tsconfig.json` file contains syntax or semantic errors,
|
|
166
|
+
* this function attempts to parse as much as possible and still returns a valid config.
|
|
167
|
+
*
|
|
168
|
+
* @param project The absolute path to the project directory or the path to `tsconfig.json`.
|
|
169
|
+
* @throws {TsConfigFileNotFoundError}
|
|
170
|
+
*/
|
|
171
|
+
export function readConfigFile(project: string): CMKConfig {
|
|
172
|
+
const { configFileName, config, diagnostics } = readTsConfigFile(project);
|
|
173
|
+
const basePath = dirname(configFileName);
|
|
174
|
+
return {
|
|
175
|
+
...normalizeConfig(config, basePath),
|
|
176
|
+
basePath,
|
|
177
|
+
configFileName,
|
|
178
|
+
diagnostics,
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
export function findTsConfigFile(project: string): string | undefined {
|
|
183
|
+
const configFile =
|
|
184
|
+
ts.sys.directoryExists(project) ?
|
|
185
|
+
ts.findConfigFile(project, ts.sys.fileExists.bind(ts.sys), 'tsconfig.json')
|
|
186
|
+
: ts.findConfigFile(dirname(project), ts.sys.fileExists.bind(ts.sys), basename(project));
|
|
187
|
+
if (!configFile) return undefined;
|
|
188
|
+
return resolve(configFile);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function mergeParsedRawData(base: ParsedRawData, overrides: ParsedRawData): ParsedRawData {
|
|
192
|
+
const result: ParsedRawData = { config: { ...base.config }, diagnostics: [...base.diagnostics] };
|
|
193
|
+
if (overrides.config.includes !== undefined) result.config.includes = overrides.config.includes;
|
|
194
|
+
if (overrides.config.excludes !== undefined) result.config.excludes = overrides.config.excludes;
|
|
195
|
+
if (overrides.config.paths !== undefined) result.config.paths = overrides.config.paths;
|
|
196
|
+
if (overrides.config.dtsOutDir !== undefined) result.config.dtsOutDir = overrides.config.dtsOutDir;
|
|
197
|
+
if (overrides.config.arbitraryExtensions !== undefined)
|
|
198
|
+
result.config.arbitraryExtensions = overrides.config.arbitraryExtensions;
|
|
199
|
+
result.diagnostics.push(...overrides.diagnostics);
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* @throws {TsConfigFileNotFoundError}
|
|
205
|
+
*/
|
|
206
|
+
// TODO: Allow `extends` options to inherit `cmkOptions`
|
|
207
|
+
export function readTsConfigFile(project: string): {
|
|
208
|
+
configFileName: string;
|
|
209
|
+
} & ParsedRawData {
|
|
210
|
+
const configFileName = findTsConfigFile(project);
|
|
211
|
+
if (!configFileName) throw new TsConfigFileNotFoundError();
|
|
212
|
+
|
|
213
|
+
const tsConfigSourceFile = ts.readJsonConfigFile(configFileName, ts.sys.readFile.bind(ts.sys));
|
|
214
|
+
// MEMO: `tsConfigSourceFile.parseDiagnostics` (Internal API) contains a syntax error for `tsconfig.json`.
|
|
215
|
+
// However, it is ignored so that ts-plugin will work even if `tsconfig.json` is somewhat broken.
|
|
216
|
+
// Also, this error is reported to the user by `tsc` or `tsserver`.
|
|
217
|
+
// We discard it since there is no need to report it from css-modules-kit.
|
|
218
|
+
|
|
219
|
+
const parsedCommandLine = ts.parseJsonSourceFileConfigFileContent(
|
|
220
|
+
tsConfigSourceFile,
|
|
221
|
+
ts.sys,
|
|
222
|
+
dirname(configFileName),
|
|
223
|
+
undefined,
|
|
224
|
+
configFileName,
|
|
225
|
+
undefined,
|
|
226
|
+
[
|
|
227
|
+
{
|
|
228
|
+
extension: 'css',
|
|
229
|
+
isMixedContent: false,
|
|
230
|
+
scriptKind: ts.ScriptKind.Deferred,
|
|
231
|
+
},
|
|
232
|
+
],
|
|
233
|
+
);
|
|
234
|
+
// Read options from `parsedCommandLine.raw`
|
|
235
|
+
let parsedRawData = parseRawData(parsedCommandLine.raw, configFileName);
|
|
236
|
+
|
|
237
|
+
// The options read from `parsedCommandLine.raw` do not inherit values from the file specified in `extends`.
|
|
238
|
+
// So here we read the options from those files and merge them into `parsedRawData`.
|
|
239
|
+
if (tsConfigSourceFile.extendedSourceFiles) {
|
|
240
|
+
for (const extendedSourceFile of tsConfigSourceFile.extendedSourceFiles) {
|
|
241
|
+
let base: ParsedRawData;
|
|
242
|
+
try {
|
|
243
|
+
base = readTsConfigFile(extendedSourceFile);
|
|
244
|
+
} catch (error) {
|
|
245
|
+
if (error instanceof TsConfigFileNotFoundError) continue;
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
parsedRawData = mergeParsedRawData(base, parsedRawData);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
return {
|
|
253
|
+
configFileName,
|
|
254
|
+
...parsedRawData,
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function resolvePaths(paths: Record<string, string[]> | undefined, cwd: string): Record<string, string[]> {
|
|
259
|
+
if (paths === undefined) return {};
|
|
260
|
+
const resolvedPaths: Record<string, string[]> = {};
|
|
261
|
+
for (const [key, value] of Object.entries(paths)) {
|
|
262
|
+
resolvedPaths[key] = value.map((path) => join(cwd, path));
|
|
263
|
+
}
|
|
264
|
+
return resolvedPaths;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Normalize the config. Resolve relative paths to absolute paths, and set default values for missing options.
|
|
269
|
+
* @param basePath A root directory to resolve relative path entries in the config file to.
|
|
270
|
+
*/
|
|
271
|
+
export function normalizeConfig(
|
|
272
|
+
config: UnnormalizedCMKConfig,
|
|
273
|
+
basePath: string,
|
|
274
|
+
): RemoveUndefined<UnnormalizedCMKConfig> & { dashedIdents: boolean } {
|
|
275
|
+
return {
|
|
276
|
+
// If `include` is not specified, fallback to the default include spec.
|
|
277
|
+
// ref: https://github.com/microsoft/TypeScript/blob/caf1aee269d1660b4d2a8b555c2d602c97cb28d7/src/compiler/commandLineParser.ts#L3102
|
|
278
|
+
includes: (config.includes ?? [DEFAULT_INCLUDE_SPEC]).map((i) => join(basePath, i)),
|
|
279
|
+
excludes: (config.excludes ?? []).map((e) => join(basePath, e)),
|
|
280
|
+
paths: resolvePaths(config.paths, basePath),
|
|
281
|
+
dtsOutDir: join(basePath, config.dtsOutDir ?? 'generated'),
|
|
282
|
+
arbitraryExtensions: config.arbitraryExtensions ?? false,
|
|
283
|
+
dashedIdents: false, // TODO: Support dashedIdents
|
|
284
|
+
};
|
|
285
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
export type DiagnosticCategory = 'error' | 'warning';
|
|
2
|
+
|
|
3
|
+
export interface DiagnosticPosition {
|
|
4
|
+
/** The line number in the source file. It is 1-based. */
|
|
5
|
+
line: number;
|
|
6
|
+
/** The column number in the source file. It is 1-based. */
|
|
7
|
+
column: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export type Diagnostic = SemanticDiagnostic | SyntacticDiagnostic;
|
|
11
|
+
|
|
12
|
+
interface DiagnosticBase {
|
|
13
|
+
/** Text of diagnostic message. */
|
|
14
|
+
text: string;
|
|
15
|
+
/** The category of the diagnostic message. */
|
|
16
|
+
category: DiagnosticCategory;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export interface SemanticDiagnostic extends DiagnosticBase {
|
|
20
|
+
type: 'semantic';
|
|
21
|
+
/** The filename of the file in which the diagnostic occurred */
|
|
22
|
+
fileName?: string;
|
|
23
|
+
/** Starting file position at which text applies. It is inclusive. */
|
|
24
|
+
start?: DiagnosticPosition;
|
|
25
|
+
/** The last file position at which the text applies. It is exclusive. */
|
|
26
|
+
end?: DiagnosticPosition;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export interface SyntacticDiagnostic extends DiagnosticBase {
|
|
30
|
+
type: 'syntactic';
|
|
31
|
+
/** The filename of the file in which the diagnostic occurred */
|
|
32
|
+
fileName: string;
|
|
33
|
+
/** Starting file position at which text applies. It is inclusive. */
|
|
34
|
+
start: DiagnosticPosition;
|
|
35
|
+
/** The last file position at which the text applies. It is exclusive. */
|
|
36
|
+
end?: DiagnosticPosition;
|
|
37
|
+
}
|