Skip to content

Commit

Permalink
Improve support for .cts, .ts, and .tsx files.
Browse files Browse the repository at this point in the history
  • Loading branch information
jaydenseric committed Jul 1, 2024
1 parent 31d82a2 commit 5a8d115
Show file tree
Hide file tree
Showing 37 changed files with 101 additions and 8 deletions.
8 changes: 4 additions & 4 deletions MODULE_GLOB.mjs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
// @ts-check

/**
* File glob pattern to recursively match TypeScript (`.mts`, and `.cts`;
* excluding TypeScript definition files) and JavaScript (`.mjs`, `.cjs`, and
* `.js`) modules.
* File glob pattern to recursively match TypeScript (`.mts`, `.cts`, `.ts`, and
* `.tsx`; excluding TypeScript definition files) and JavaScript (`.mjs`,
* `.cjs`, and `.js`) modules.
*/
export default "**/{!(*.d).mts,!(*.d).cts,*.{mjs,cjs,js}}";
export default "**/{!(*.d).mts,!(*.d).cts,!(*.d).ts,*.{mjs,cjs,js,tsx}}";
22 changes: 22 additions & 0 deletions MODULE_GLOB.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -20,34 +20,56 @@ describe("Constant `MODULE_GLOB`.", { concurrency: true }, () => {
[
".a.ad.cts",
".a.ad.mts",
".a.ad.ts",
".a.cjs",
".a.cts",
".a.js",
".a.mjs",
".a.mts",
".a.ts",
".a.tsx",
".cjs",
".cts",
".js",
".mjs",
".mts",
".ts",
".tsx",
"a.cts",
"a.d.tsx",
"a.mjs",
"a.mts",
"a.ts",
"a.tsx",
"ad.cts",
"ad.mts",
"ad.ts",
"a/.a.ad.cts",
"a/.a.ad.mts",
"a/.a.ad.ts",
"a/.a.cjs",
"a/.a.cts",
"a/.a.js",
"a/.a.mjs",
"a/.a.mts",
"a/.a.ts",
"a/.a.tsx",
"a/.cjs",
"a/.cts",
"a/.js",
"a/.mjs",
"a/.mts",
"a/.ts",
"a/.tsx",
"a/a.cts",
"a/a.d.tsx",
"a/a.mjs",
"a/a.mts",
"a/a.ts",
"a/a.tsx",
"a/ad.cts",
"a/ad.mts",
"a/ad.ts",
],
);
});
Expand Down
9 changes: 9 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,15 @@
- Use the Node.js test runner API and remove the dev dependency [`test-director`](https://npm.im/test-director).
- Updated the dependency [`globby`](https://npm.im/globby) to v14.
- Updated the function `findUnusedExports` to no longer ignore dotfiles when executing the module glob.
- Changed the function `findUnusedExports` option `moduleGlob` and the CLI command `find-unused-exports` argument `--module-glob` default value from `**/{!(*.d).mts,!(*.d).cts,*.{mjs,cjs,js}}` to `**/{!(*.d).mts,!(*.d).cts,!(*.d).ts,*.{mjs,cjs,js,tsx}}`; `.ts` and `.tsx` files (but not TypeScript definition files) are now recursively matched by default.
- Support resolving additional kinds of TypeScript source modules (if the exist) depending on the import specifier path file extension:
- `.cjs` resolves `.cts`.
- `.js` resolves `.ts` and `.tsx`.

### Minor

- Enable TypeScript syntax when parsing `.ts` and `.tsx` files with Babel, even when the project has no Babel config for TypeScript.
- Enable JSX syntax when parsing `.tsx` files with Babel, even when the project has no Babel config for JSX.

### Patch

Expand Down
28 changes: 28 additions & 0 deletions findUnusedExports.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,34 @@ export default async function findUnusedExports(options = {}) {
break;
}

// TypeScript import specifiers may use the `.cjs` file extension to
// resolve a `.cts` file in that directory with the same name.
case ".cjs": {
specifierPossiblePaths.push(
`${specifierAbsolutePath.slice(
0,
-specifierExtension.length,
)}.cts`,
);
break;
}

// TypeScript import specifiers may use the `.js` file extension to
// resolve a `.ts` or `.tsx` file in that directory with the same
// name.
case ".js": {
const pathWithoutExtension = specifierAbsolutePath.slice(
0,
-specifierExtension.length,
);

specifierPossiblePaths.push(
`${pathWithoutExtension}.ts`,
`${pathWithoutExtension}.tsx`,
);
break;
}

// No file extension.
case "": {
if (resolveFileExtensions) {
Expand Down
3 changes: 2 additions & 1 deletion jsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@
"maxNodeModuleJsDepth": 10,
"module": "nodenext",
"noEmit": true,
"strict": true
"strict": true,
"jsx": "preserve"
},
"typeAcquisition": {
"enable": false
Expand Down
2 changes: 1 addition & 1 deletion readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ It implements the function [`findUnusedExports`](./findUnusedExports.mjs).

| Argument | Default | Description |
| :-- | :-- | :-- |
| `--module-glob` | `"**/{!(*.d).mts,!(*.d).cts,*.{mjs,cjs,js}}"` | Module file glob pattern. |
| `--module-glob` | `"**/{!(*.d).mts,!(*.d).cts,!(*.d).ts,*.{mjs,cjs,js,tsx}}"` | Module file glob pattern. |
| `--resolve-file-extensions` | | File extensions (without the leading `.`, multiple separated with `,` in preference order) to automatically resolve in extensionless import specifiers. [Import specifier file extensions are mandatory in Node.js](https://nodejs.org/api/esm.html#mandatory-file-extensions); if your project resolves extensionless imports at build time (e.g. [Next.js](https://nextjs.org), via [webpack](https://webpack.js.org)) `mjs,js` might be appropriate. |
| `--resolve-index-files` | | Should directory index files be automatically resolved in extensionless import specifiers. [Node.js doesn’t do this by default](https://nodejs.org/api/esm.html#mandatory-file-extensions); if your project resolves extensionless imports at build time (e.g. [Next.js](https://nextjs.org), via [webpack](https://webpack.js.org)) this argument might be appropriate. This argument only works if the argument `--resolve-file-extensions` is used. |

Expand Down
12 changes: 10 additions & 2 deletions scanModuleCode.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -53,11 +53,19 @@ export default async function scanModuleCode(code, path) {
if (
path &&
// Path is a TypeScript module.
(path.endsWith(".mts") || path.endsWith(".cts"))
)
(path.endsWith(".mts") ||
path.endsWith(".cts") ||
path.endsWith(".ts") ||
path.endsWith(".tsx"))
) {
// Allow parsing code containing TypeScript syntax.
plugins.push("typescript");

if (path.endsWith(".tsx"))
// Allow parsing code containing JSX syntax.
plugins.push("jsx");
}

const ast = await babel.parseAsync(code, {
// Provide the code file path for more useful Babel parse errors.
filename: path,
Expand Down
17 changes: 17 additions & 0 deletions scanModuleCode.test.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,23 @@ describe("Function `scanModuleCode`.", { concurrency: true }, () => {
exports: new Set(),
});
});

it("`.ts` file, TypeScript syntax.", async () => {
deepStrictEqual(await scanModuleCode("let a: boolean;", "a.ts"), {
imports: {},
exports: new Set(),
});
});

it("`.tsx` file, TypeScript and JSX syntax.", async () => {
deepStrictEqual(
await scanModuleCode("let a: boolean; const b = <div />;", "a.tsx"),
{
imports: {},
exports: new Set(),
},
);
});
});

it("No imports or exports.", async () => {
Expand Down
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
Empty file.
4 changes: 4 additions & 0 deletions test/fixtures/no-unused-exports/m.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
import n from "./n.js";
import o from "./o.js";
import p from "./p.js";
import q from "./q.cjs";
1 change: 1 addition & 0 deletions test/fixtures/no-unused-exports/n.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 1;
1 change: 1 addition & 0 deletions test/fixtures/no-unused-exports/o.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 1;
1 change: 1 addition & 0 deletions test/fixtures/no-unused-exports/p.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 1;
1 change: 1 addition & 0 deletions test/fixtures/no-unused-exports/q.cts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export default 1;

0 comments on commit 5a8d115

Please sign in to comment.