Skip to content

Commit e98355d

Browse files
1 parent f89d491 commit e98355d

9 files changed

Lines changed: 927 additions & 136 deletions

File tree

package-lock.json

Lines changed: 738 additions & 84 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,24 +33,24 @@
3333
"./package.json": "./package.json"
3434
},
3535
"scripts": {
36-
"build": "run-s build:*",
37-
"build:cjs": "tsc --project tsconfig.build.json",
38-
"build:esm": "rollup --config --failAfterWarnings --environment ESM:true && scripts/fix-esm.sh",
39-
"build:umd": "rollup --config --failAfterWarnings --environment UMD:true",
36+
"build": "run-s clean build:*",
37+
"build:cjs": "scripts/build.sh --cjs",
38+
"build:esm": "scripts/build.sh --esm",
39+
"build:umd": "scripts/build.sh --umd",
4040
"clean": "rm -rf .nyc_output coverage dist esm lib",
4141
"lint": "eslint .",
4242
"lint:fix": "npm run lint -- --fix",
4343
"lint:package": "publint",
44-
"lint:tsc": "tsc --noEmit",
44+
"lint:tsc": "tsc --project tsconfig.test.json",
4545
"prepare": "husky",
4646
"prepublishOnly": "run-s lint lint:tsc clean build lint:package",
4747
"size-limit": "size-limit",
4848
"test": "run-s test:server test:client",
4949
"test:client": "npm run test:client:watch -- --single-run",
50-
"test:client:build": "NODE_ENV=test npm run build",
50+
"test:client:build": "run-p build:cjs build:umd",
5151
"test:client:watch": "npm run test:client:build && karma start",
5252
"test:coverage": "npm run test:server && nyc report --reporter=html",
53-
"test:esm": "npm run build && node --test test/esm",
53+
"test:esm": "npm run build:esm && node --test test/esm",
5454
"test:server": "npm run build:cjs && nyc mocha"
5555
},
5656
"repository": {
@@ -85,6 +85,7 @@
8585
"@size-limit/preset-big-lib": "12.0.0",
8686
"@types/chai": "4.3.16",
8787
"@types/estree": "1.0.8",
88+
"@types/jscodeshift": "17.3.0",
8889
"@types/mocha": "10.0.10",
8990
"@types/node": "25.1.0",
9091
"chai": "4.5.0",
@@ -95,6 +96,7 @@
9596
"globals": "17.2.0",
9697
"html-minifier": "4.0.0",
9798
"husky": "9.1.7",
99+
"jscodeshift": "17.3.0",
98100
"jsdomify": "3.1.1",
99101
"karma": "6.4.4",
100102
"karma-chai": "0.1.0",

rollup.config.mjs

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -8,28 +8,28 @@ import typescript from '@rollup/plugin-typescript';
88

99
const require = createRequire(import.meta.url);
1010

11-
const getPlugins = ({ browser = false, minify = false, outDir = '' }) =>
12-
[
13-
browser &&
14-
alias({
15-
entries: [
16-
{
17-
find: './server/html-to-dom',
18-
replacement: './client/html-to-dom',
19-
},
20-
],
21-
}),
22-
typescript({
23-
tsconfig: 'tsconfig.build.json',
24-
compilerOptions: {
25-
module: 'esnext',
26-
outDir,
27-
},
11+
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
12+
const getPlugins = ({ browser = false, minify = false, outDir = '' }) => [
13+
browser &&
14+
alias({
15+
entries: [
16+
{
17+
find: './server/html-to-dom',
18+
replacement: './client/html-to-dom',
19+
},
20+
],
2821
}),
29-
commonjs(),
30-
resolve({ browser }),
31-
minify && terser(),
32-
].filter(Boolean);
22+
typescript({
23+
tsconfig: 'tsconfig.build.json',
24+
compilerOptions: {
25+
module: 'esnext',
26+
outDir,
27+
},
28+
}),
29+
commonjs(),
30+
resolve({ browser }),
31+
minify && terser(),
32+
];
3333

3434
const getUMDConfig = (minify = false) => {
3535
const output = `dist/html-dom-parser${minify ? '.min' : ''}.js`;
@@ -52,7 +52,7 @@ const getUMDConfig = (minify = false) => {
5252
const esmConfigs = [
5353
// ESM server
5454
{
55-
input: 'src/index.ts',
55+
input: 'src/index.mts',
5656
output: {
5757
dir: 'esm',
5858
entryFileNames: '[name].mjs',
@@ -70,7 +70,7 @@ const esmConfigs = [
7070

7171
// ESM client
7272
{
73-
input: 'src/client/html-to-dom.ts',
73+
input: 'src/client/html-to-dom.mts',
7474
output: {
7575
dir: 'esm/client',
7676
entryFileNames: '[name].mjs',

scripts/add-mjs-extension.ts

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import * as path from 'node:path';
2+
3+
import type { API, FileInfo } from 'jscodeshift';
4+
5+
/**
6+
* Codemod to add .mjs extension to all imports in TypeScript files
7+
*
8+
* This codemod transforms:
9+
* import { something } from './module';
10+
* To:
11+
* import { something } from './module.mjs';
12+
*
13+
* It handles:
14+
* - Named imports
15+
* - Default imports
16+
* - Namespace imports
17+
* - Dynamic imports
18+
* - Re-exports
19+
*/
20+
21+
export default function transformer(fileInfo: FileInfo, api: API): string {
22+
const j = api.jscodeshift;
23+
const root = j(fileInfo.source);
24+
25+
// Helper to check if a module path is relative
26+
function isRelativeModulePath(modulePath: string): boolean {
27+
return modulePath.startsWith('./') || modulePath.startsWith('../');
28+
}
29+
30+
// Helper to check if module already has an extension
31+
function hasExtension(modulePath: string): boolean {
32+
return path.extname(modulePath) !== '';
33+
}
34+
35+
// Helper to add .mjs extension
36+
function addMjsExtension(modulePath: string): string {
37+
return modulePath + '.mjs';
38+
}
39+
40+
// Transform import declarations
41+
root.find(j.ImportDeclaration).forEach((path) => {
42+
const source = path.node.source.value as string;
43+
44+
if (isRelativeModulePath(source) && !hasExtension(source)) {
45+
path.node.source.value = addMjsExtension(source);
46+
}
47+
});
48+
49+
// Transform export from declarations
50+
root
51+
.find(j.ExportNamedDeclaration, { source: { type: 'StringLiteral' } })
52+
.forEach((path) => {
53+
const source = path.node.source?.value as string;
54+
55+
if (
56+
path.node.source &&
57+
isRelativeModulePath(source) &&
58+
!hasExtension(source)
59+
) {
60+
path.node.source.value = addMjsExtension(source);
61+
}
62+
});
63+
64+
// Transform export all declarations
65+
root
66+
.find(j.ExportAllDeclaration, { source: { type: 'StringLiteral' } })
67+
.forEach((path) => {
68+
const source = path.node.source.value as string;
69+
70+
if (isRelativeModulePath(source) && !hasExtension(source)) {
71+
path.node.source.value = addMjsExtension(source);
72+
}
73+
});
74+
75+
// Transform dynamic import() calls
76+
root
77+
.find(j.CallExpression, {
78+
callee: { type: 'Import' },
79+
})
80+
.forEach((path) => {
81+
const argument = path.node.arguments[0];
82+
83+
if (j.StringLiteral.check(argument)) {
84+
const source = argument.value;
85+
86+
if (isRelativeModulePath(source) && !hasExtension(source)) {
87+
argument.value = addMjsExtension(source);
88+
}
89+
}
90+
});
91+
92+
// Transform require() calls (for completeness, though less common in ESM)
93+
root
94+
.find(j.CallExpression, {
95+
callee: { name: 'require' },
96+
})
97+
.forEach((path) => {
98+
const argument = path.node.arguments[0];
99+
100+
if (j.StringLiteral.check(argument)) {
101+
const source = argument.value;
102+
103+
if (isRelativeModulePath(source) && !hasExtension(source)) {
104+
argument.value = addMjsExtension(source);
105+
}
106+
}
107+
});
108+
109+
return root.toSource({
110+
quote: 'single',
111+
trailingComma: true,
112+
lineTerminator: '\n',
113+
});
114+
}
115+
116+
export const parser = 'ts';

scripts/build.sh

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#!/usr/bin/env bash
2+
3+
if [[ $1 == '--cjs' ]]; then
4+
tsc --project tsconfig.build.json
5+
find lib -type f \( -name '*.mjs*' -or -name '*.mts*' \) -delete
6+
7+
elif [[ $1 == '--esm' ]]; then
8+
find src -type f -name '*.ts' -exec bash -c 'mv "$1" "${1%.ts}.mts"' _ {} \;
9+
jscodeshift -t scripts/add-mjs-extension.ts src --extensions=mts
10+
rollup --config --failAfterWarnings --environment ESM:true
11+
rm -rf esm/client/{client,server,index.*,types.*}
12+
git restore src
13+
git clean -f src
14+
15+
elif [[ $1 == '--umd' ]]; then
16+
rollup --config --failAfterWarnings --environment UMD:true
17+
rm -rf dist/{client,server,*.mts*,*.ts*}
18+
fi

scripts/fix-esm.sh

Lines changed: 0 additions & 13 deletions
This file was deleted.

test/types/index.test.mts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import parse from '../../esm/index.mjs';
2+
3+
// $ExpectType (Element | Text | Comment | ProcessingInstruction)[]
4+
parse('<div>text</div>');
5+
6+
// $ExpectType (Element | Text | Comment | ProcessingInstruction)[]
7+
parse('<div>text</div>', { xmlMode: true });
8+
9+
// $ExpectType (Element | Text | Comment | ProcessingInstruction)[]
10+
parse('<div>text</div>', { decodeEntities: false });
11+
12+
// $ExpectType (Element | Text | Comment | ProcessingInstruction)[]
13+
parse('<div>text</div>', { lowerCaseTags: true });
14+
15+
// $ExpectType (Element | Text | Comment | ProcessingInstruction)[]
16+
parse('');

test/types/index.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,10 @@ parse('<div>text</div>');
77
parse('<div>text</div>', { xmlMode: true });
88

99
// $ExpectType (Element | Text | Comment | ProcessingInstruction)[]
10-
parse('<div>text</div>', { withStartIndices: true });
10+
parse('<div>text</div>', { decodeEntities: false });
1111

1212
// $ExpectType (Element | Text | Comment | ProcessingInstruction)[]
13-
parse('<div>text</div>', { withEndIndices: true });
13+
parse('<div>text</div>', { lowerCaseTags: true });
1414

1515
// $ExpectType (Element | Text | Comment | ProcessingInstruction)[]
1616
parse('');

tsconfig.test.json

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
11
{
22
"extends": "./tsconfig.build.json",
33
"compilerOptions": {
4+
"target": "esnext",
5+
"module": "nodenext",
6+
"moduleResolution": "nodenext",
7+
"noEmit": true,
48
"allowJs": true
59
},
6-
"include": [
7-
"src",
8-
"test",
9-
"eslint.config.mjs",
10-
"karma.conf.js",
11-
"rollup.config.mjs"
12-
]
10+
"include": ["scripts", "src", "test", "*.mjs", "*.js"]
1311
}

0 commit comments

Comments
 (0)