Skip to content

Commit

Permalink
Fix/issue support js index files fix 260 (#261)
Browse files Browse the repository at this point in the history
* Fix an ESM index.js/.mjs/.cjs import edge case

In [1] a removeFileExtensionToAllowForJs() utility function has been
added to help with normalizing import paths into extensionless ones in
order to handle ESM imports (which have to have extensions, either .js,
.mjs or .cjs).

One thing was missed though as index files are handled in a special way.

In the analyzer.ts:

    const processImports = (file: File, exportMap: ExportMap): void => {
      Object.keys(file.imports).forEach((key) => {
        let ex = exportMap[removeFileExtensionToAllowForJs(key)]?.exports;

exportMap had keys with extensions and "index" removed (so that
"xxx/index.ts" became "xxx" there) but paths in file.imports came from
getFromText() which only handled extensionless index imports so
xxx/index.js" stayed "xxx/index.js". The .js extension was then removed
by removeFileExtensionToAllowForJs() but the damage was done already and
"xxx" != "xxx/index".

This change brings the removeFileExtensionToAllowForJs()-like
ESM-compatible behavior to getFromText().

[1] 6e506ae ("Add .js extension support with es6 example (#255)")

* Fix test cleanup. Up changelog

* Bump package.json and changelog

Co-authored-by: Jakub Stasiak <[email protected]>
  • Loading branch information
mrseanryan and jstasiak authored Jan 4, 2023
1 parent 2d1b88c commit 0d956e8
Show file tree
Hide file tree
Showing 5 changed files with 28 additions and 4 deletions.
6 changes: 5 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
### Added
## [9.0.1] - 4 Jan 2023

### Changed

- Fix for index files that end with .js or .cjs or .mjs.

## [9.0.0] - 26 Dec 2022

Expand Down
18 changes: 18 additions & 0 deletions features/index.feature
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,24 @@ Scenario: Import './index'
When analyzing "tsconfig.json"
Then the result is {}

Scenario: Import './index.js'
Given file "index.ts" is export const a = 1;
And file "a.ts" is import { a } from './index.js';
When analyzing "tsconfig.json"
Then the result is {}

Scenario: Import './index.mjs'
Given file "index.mts" is export const a = 1;
And file "a.ts" is import { a } from './index.mjs';
When analyzing "tsconfig.json"
Then the result is {}

Scenario: Import './index.cjs'
Given file "index.cts" is export const a = 1;
And file "a.ts" is import { a } from './index.cjs';
When analyzing "tsconfig.json"
Then the result is {}

Scenario: Import './index' TSX
Given file "index.tsx" is export const a = 1;
And file "a.ts" is import { a } from './index';
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "ts-unused-exports",
"version": "9.0.0",
"version": "9.0.1",
"description": "ts-unused-exports finds unused exported symbols in your Typescript project",
"main": "lib/app.js",
"repository": {
Expand Down
2 changes: 1 addition & 1 deletion src/parser/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ export interface FromWhat {
const TRIM_QUOTES = /^['"](.*)['"]$/;

export const getFromText = (moduleSpecifier: string): string =>
moduleSpecifier.replace(TRIM_QUOTES, '$1').replace(/\/index$/, '');
moduleSpecifier.replace(TRIM_QUOTES, '$1').replace(/\/index(.[mc]?js)?$/, '');

export const getFrom = (moduleSpecifier: ts.Expression): string =>
getFromText(moduleSpecifier.getText());
4 changes: 3 additions & 1 deletion src/test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,9 @@ const setup: SetupFn = ({
const items = readdirSync(path, { encoding: 'utf8' }).filter(
(f) => f[0] !== '.',
);
const files = items.filter((f) => !!f.match(/\.(json|ts|tsx|js|jsx)$/));
const files = items.filter(
(f) => !!f.match(/\.(json|ts|tsx|js|jsx|mjs|cjs|mts|cts)$/),
);
files.forEach((f) => unlinkSync(join(path, f)));
const dirs = items.filter((i) => !files.includes(i));
dirs.forEach((d) => removeDir(join(path, d)));
Expand Down

0 comments on commit 0d956e8

Please sign in to comment.