Skip to content

Commit 6c1804f

Browse files
fix(compiler): get to handle .cts files (#6199)
* fix(compiler): get to handle .cts files * reorg * lower path param * moved tests around * prettier * re-use utils functions * prettier
1 parent bad6e1e commit 6c1804f

10 files changed

+788
-1219
lines changed

package-lock.json

+668-1,091
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/compiler/bundle/bundle-output.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const getRollupOptions = (
6262
browser: true,
6363
rootDir: config.rootDir,
6464
...(config.nodeResolve as any),
65-
extensions: ['.tsx', '.ts', '.js', '.mjs', '.json', '.d.ts', '.d.mts'],
65+
extensions: ['.tsx', '.ts', '.mts', '.cts', '.js', '.mjs', '.cjs', '.json', '.d.ts', '.d.mts', '.d.cts'],
6666
});
6767

6868
// @ts-expect-error - this is required now.

src/compiler/bundle/file-load-plugin.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { normalizeFsPath } from '@utils';
1+
import { isDtsFile, normalizeFsPath } from '@utils';
22
import type { Plugin } from 'rollup';
33

44
import { InMemoryFileSystem } from '../sys/in-memory-fs';
@@ -9,7 +9,7 @@ export const fileLoadPlugin = (fs: InMemoryFileSystem): Plugin => {
99

1010
load(id) {
1111
const fsFilePath = normalizeFsPath(id);
12-
if (id.endsWith('.d.ts') || id.endsWith('.d.mts')) {
12+
if (isDtsFile(fsFilePath)) {
1313
return '';
1414
}
1515
return fs.readFile(fsFilePath);

src/compiler/bundle/typescript-plugin.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { isString, normalizeFsPath } from '@utils';
1+
import { isDtsFile, isString, normalizeFsPath } from '@utils';
22
import { basename, isAbsolute } from 'path';
33
import type { LoadResult, Plugin, TransformResult } from 'rollup';
44
import ts from 'typescript';
@@ -88,7 +88,7 @@ export const resolveIdWithTypeScript = (config: d.ValidatedConfig, compilerCtx:
8888
// this is probably a .d.ts file for whatever reason in how TS resolves this
8989
// use this resolved file as the "importer"
9090
const tsResolvedPath = tsResolved.resolvedModule.resolvedFileName;
91-
if (isString(tsResolvedPath) && !(tsResolvedPath.endsWith('.d.ts') || tsResolvedPath.endsWith('.d.mts'))) {
91+
if (isString(tsResolvedPath) && !isDtsFile(tsResolvedPath)) {
9292
return tsResolvedPath;
9393
}
9494
}

src/compiler/sys/fetch/fetch-utils.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { isFunction, normalizePath } from '@utils';
1+
import { isFunction, isTsFile, isTsxFile, normalizePath } from '@utils';
22

33
import type * as d from '../../../declarations';
4-
import { isCommonDirModuleFile, isTsFile, isTsxFile } from '../resolve/resolve-utils';
4+
import { isCommonDirModuleFile } from '../resolve/resolve-utils';
55

66
/**
77
* A fetch wrapper which dispatches to `sys.fetch` if present, and otherwise

src/compiler/sys/resolve/resolve-utils.ts

+1-37
Original file line numberDiff line numberDiff line change
@@ -2,43 +2,7 @@ import { normalizePath } from '@utils';
22

33
import type * as d from '../../../declarations';
44

5-
const COMMON_DIR_MODULE_EXTS = ['.tsx', '.ts', '.mjs', '.js', '.jsx', '.json', '.md'];
6-
7-
/**
8-
* Determine if a stringified file path is a TypeScript declaration file based on the extension at the end of the path.
9-
* @param p the path to evaluate
10-
* @returns `true` if the path ends in `.d.ts` (case-sensitive), `false` otherwise.
11-
*/
12-
export const isDtsFile = (p: string) => p.endsWith('.d.ts') || p.endsWith('.d.mts');
13-
14-
/**
15-
* Determine if a stringified file path is a TypeScript file based on the extension at the end of the path. This
16-
* function does _not_ consider type declaration files (`.d.ts` files) to be TypeScript files.
17-
* @param p the path to evaluate
18-
* @returns `true` if the path ends in `.ts` (case-sensitive) but does _not_ end in `.d.ts`, `false` otherwise.
19-
*/
20-
export const isTsFile = (p: string) => !isDtsFile(p) && p.endsWith('.ts');
21-
22-
/**
23-
* Determine if a stringified file path is a TSX file based on the extension at the end of the path
24-
* @param p the path to evaluate
25-
* @returns `true` if the path ends in `.tsx` (case-sensitive), `false` otherwise.
26-
*/
27-
export const isTsxFile = (p: string) => p.endsWith('.tsx');
28-
29-
/**
30-
* Determine if a stringified file path is a JSX file based on the extension at the end of the path
31-
* @param p the path to evaluate
32-
* @returns `true` if the path ends in `.jsx` (case-sensitive), `false` otherwise.
33-
*/
34-
export const isJsxFile = (p: string) => p.endsWith('.jsx');
35-
36-
/**
37-
* Determine if a stringified file path is a JavaScript file based on the extension at the end of the path
38-
* @param p the path to evaluate
39-
* @returns `true` if the path ends in `.js` (case-sensitive), `false` otherwise.
40-
*/
41-
export const isJsFile = (p: string) => p.endsWith('.js');
5+
const COMMON_DIR_MODULE_EXTS = ['.tsx', '.ts', '.mts', '.cts', '.mjs', '.js', '.cjs', '.jsx', '.json', '.md'];
426

437
export const isCommonDirModuleFile = (p: string) => COMMON_DIR_MODULE_EXTS.some((ext) => p.endsWith(ext));
448

src/compiler/sys/resolve/tests/resolve-utils.spec.ts

-70
This file was deleted.

src/compiler/sys/typescript/typescript-resolve-module.ts

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
1-
import { isString, join, normalizePath, resolve } from '@utils';
1+
import { isDtsFile, isJsFile, isJsxFile, isString, isTsFile, isTsxFile, join, normalizePath, resolve } from '@utils';
22
import { basename, dirname } from 'path';
33
import ts from 'typescript';
44

55
import type * as d from '../../../declarations';
6-
import { isDtsFile, isJsFile, isJsxFile, isTsFile, isTsxFile } from '../resolve/resolve-utils';
76
import { patchTsSystemFileSystem } from './typescript-sys';
87

98
export const tsResolveModuleName = (

src/utils/test/util.spec.ts

+64
Original file line numberDiff line numberDiff line change
@@ -234,4 +234,68 @@ interface Foo extends Components.Foo, HTMLStencilElement {`);
234234
},
235235
);
236236
});
237+
238+
describe('isTsFile', () => {
239+
it.each(['.ts', 'foo.ts', 'foo.bar.ts', 'foo/bar.ts'])(
240+
'returns true for a file ending with .ts (%s)',
241+
(fileName) => {
242+
expect(util.isTsFile(fileName)).toEqual(true);
243+
},
244+
);
245+
246+
it.each(['.tsx', 'foo.tsx', 'foo.bar.tsx', 'foo/bar.tsx'])(
247+
'returns false for a file ending with .tsx (%s)',
248+
(fileName) => {
249+
expect(util.isTsFile(fileName)).toEqual(false);
250+
},
251+
);
252+
253+
it.each(['foo.js', 'foo.doc', 'foo.css', 'foo.html'])(
254+
'returns false for other a file with another extension (%s)',
255+
(fileName) => {
256+
expect(util.isTsFile(fileName)).toEqual(false);
257+
},
258+
);
259+
260+
it('returns false for .d.ts and .d.tsx files', () => {
261+
expect(util.isTsFile('foo/bar.d.ts')).toEqual(false);
262+
expect(util.isTsFile('foo/bar.d.tsx')).toEqual(false);
263+
});
264+
265+
it('returns true for a file named "spec.ts"', () => {
266+
expect(util.isTsFile('spec.ts')).toEqual(true);
267+
});
268+
269+
it('returns true for a file named "d.ts"', () => {
270+
expect(util.isTsFile('d.ts')).toEqual(true);
271+
});
272+
273+
it.each(['foo.tS', 'foo.Ts', 'foo.TS'])('returns true for non-lowercase extensions (%s)', (fileName) => {
274+
expect(util.isTsFile(fileName)).toEqual(true);
275+
});
276+
});
277+
278+
describe('isJsFile', () => {
279+
it.each(['.js', 'foo.js', 'foo.bar.js', 'foo/bar.js'])(
280+
'returns true for a file ending with .js (%s)',
281+
(fileName) => {
282+
expect(util.isJsFile(fileName)).toEqual(true);
283+
},
284+
);
285+
286+
it.each(['.jsx', 'foo.txt', 'foo/bar.css', 'foo.bar.html'])(
287+
'returns false for other a file with another extension (%s)',
288+
(fileName) => {
289+
expect(util.isJsFile(fileName)).toEqual(false);
290+
},
291+
);
292+
293+
it('returns true for a file named "spec.js"', () => {
294+
expect(util.isJsFile('spec.js')).toEqual(true);
295+
});
296+
297+
it.each(['foo.jS', 'foo.Js', 'foo.JS'])('returns true for non-lowercase extensions (%s)', (fileName) => {
298+
expect(util.isJsFile(fileName)).toEqual(true);
299+
});
300+
});
237301
});

src/utils/util.ts

+47-12
Original file line numberDiff line numberDiff line change
@@ -42,18 +42,53 @@ export const createJsVarName = (fileName: string): string => {
4242
};
4343

4444
/**
45-
* Determines if a given file path points to a type declaration file (ending in .d.ts) or not. This function is
46-
* case-insensitive in its heuristics.
47-
* @param filePath the path to check
48-
* @returns `true` if the given `filePath` points to a type declaration file, `false` otherwise
49-
*/
50-
export const isDtsFile = (filePath: string): boolean => {
51-
const parts = filePath.toLowerCase().split('.');
52-
if (parts.length > 2) {
53-
return parts[parts.length - 2] === 'd' && parts[parts.length - 1] === 'ts';
54-
}
55-
return false;
56-
};
45+
* Create a function that lowercases the first string parameter before passing it to the provided function
46+
* @param fn the function to pass the lowercased path to
47+
* @returns the result of the provided function
48+
*/
49+
const lowerPathParam = (fn: (p: string) => boolean) => (p: string) => fn(p.toLowerCase());
50+
51+
/**
52+
* Determine if a stringified file path is a TypeScript declaration file based on the extension at the end of the path.
53+
* @param p the path to evaluate
54+
* @returns `true` if the path ends in `.d.ts` (case-sensitive), `false` otherwise.
55+
*/
56+
export const isDtsFile = lowerPathParam((p) => p.endsWith('.d.ts') || p.endsWith('.d.mts') || p.endsWith('.d.cts'));
57+
58+
/**
59+
* Determine if a stringified file path is a TypeScript file based on the extension at the end of the path. This
60+
* function does _not_ consider type declaration files (`.d.ts` files) to be TypeScript files.
61+
* @param p the path to evaluate
62+
* @returns `true` if the path ends in `.ts` (case-sensitive) but does _not_ end in `.d.ts`, `false` otherwise.
63+
*/
64+
export const isTsFile = lowerPathParam(
65+
(p: string) => !isDtsFile(p) && (p.endsWith('.ts') || p.endsWith('.mts') || p.endsWith('.cts')),
66+
);
67+
68+
/**
69+
* Determine if a stringified file path is a TSX file based on the extension at the end of the path
70+
* @param p the path to evaluate
71+
* @returns `true` if the path ends in `.tsx` (case-sensitive), `false` otherwise.
72+
*/
73+
export const isTsxFile = lowerPathParam(
74+
(p: string) => p.endsWith('.tsx') || p.endsWith('.mtsx') || p.endsWith('.ctsx'),
75+
);
76+
77+
/**
78+
* Determine if a stringified file path is a JSX file based on the extension at the end of the path
79+
* @param p the path to evaluate
80+
* @returns `true` if the path ends in `.jsx` (case-sensitive), `false` otherwise.
81+
*/
82+
export const isJsxFile = lowerPathParam(
83+
(p: string) => p.endsWith('.jsx') || p.endsWith('.mjsx') || p.endsWith('.cjsx'),
84+
);
85+
86+
/**
87+
* Determine if a stringified file path is a JavaScript file based on the extension at the end of the path
88+
* @param p the path to evaluate
89+
* @returns `true` if the path ends in `.js` (case-sensitive), `false` otherwise.
90+
*/
91+
export const isJsFile = lowerPathParam((p: string) => p.endsWith('.js') || p.endsWith('.mjs') || p.endsWith('.cjs'));
5792

5893
/**
5994
* Generate the preamble to be placed atop the main file of the build

0 commit comments

Comments
 (0)