diff --git a/.vscode/settings.json b/.vscode/settings.json
index f2c994728..b305aa521 100644
--- a/.vscode/settings.json
+++ b/.vscode/settings.json
@@ -5,6 +5,7 @@
},
"typescript.tsdk": "./node_modules/typescript/lib",
+ "dprint.path": "./node_modules/dprint/dprint",
// Automatically run the formatter when certain files are saved.
"[javascript]": {
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 5e4432d04..5d93ff70e 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -4,6 +4,44 @@ title: Changelog
## Unreleased
+## v0.28.10 (2025-08-10)
+
+### Bug Fixes
+
+- Fixed inconsistent anchors on module pages for re-exports, #2990.
+- Markdown references which appear to be footnotes will no longer be checked for links, #2991.
+
+## v0.28.9 (2025-08-01)
+
+### Features
+
+- Add support for TypeScript 5.9, #2989.
+
+### Bug Fixes
+
+- Fixed bug introduced in 0.28.8 where TypeDoc could not render docs when members inherited from a complex type alias, #2982.
+- Fixed automatic discovery of entry points when not running in packages mode, #2988.
+- Fixed discovery of package.json file when running with entry points containing a glob, #2985.
+
+## v0.28.8 (2025-07-28)
+
+### Features
+
+- If using JS config files, the `plugin` function can now be given plugin functions to load.
+- Permit `-` within tag names to support `typescript-json-schema`'s `@TJS-type` tag, #2972.
+- Exposed `Context.createSymbolId` for use by plugins.
+
+### Bug Fixes
+
+- Relative links in `
` will now be discovered by TypeDoc, #2975.
+- Relative links in `` and `` elements will now be discovered by TypeDoc, #2975.
+- Improved inherited from/overwrites link discovery to point to parent properties in more cases, #2978
+
+### Thanks!
+
+- @jonathanhefner
+- @laymonage
+
## v0.28.7 (2025-06-30)
### Features
diff --git a/dprint.json b/dprint.json
index 2237a8ba6..4faadb249 100644
--- a/dprint.json
+++ b/dprint.json
@@ -19,9 +19,9 @@
"src/test/converter2/issues/gh2631/crlf.md"
],
"plugins": [
- "https://plugins.dprint.dev/typescript-0.95.8.wasm",
+ "https://plugins.dprint.dev/typescript-0.95.9.wasm",
"https://plugins.dprint.dev/json-0.20.0.wasm",
"https://plugins.dprint.dev/markdown-0.19.0.wasm",
- "https://plugins.dprint.dev/g-plane/malva-v0.12.1.wasm"
+ "https://plugins.dprint.dev/g-plane/malva-v0.14.1.wasm"
]
}
diff --git a/eslint.config.mjs b/eslint.config.mjs
index 9544f7862..a72f396c1 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -244,6 +244,12 @@ export default tslint.config(
eslint.configs.recommended,
...tslint.configs.strictTypeChecked,
config,
+ {
+ files: ["src/test/**/*"],
+ rules: {
+ "@typescript-eslint/no-deprecated": "off",
+ },
+ },
{
ignores: [
"eslint.config.mjs",
diff --git a/index.html b/index.html
new file mode 100644
index 000000000..cf7ca8870
--- /dev/null
+++ b/index.html
@@ -0,0 +1,6 @@
+
+
+
+
+
+
diff --git a/package.json b/package.json
index d2bcf6d45..2725280d5 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "typedoc",
"description": "Create api documentation for TypeScript projects.",
- "version": "0.28.7",
+ "version": "0.28.10",
"homepage": "https://typedoc.org",
"type": "module",
"exports": {
@@ -31,32 +31,32 @@
"pnpm": ">= 10"
},
"dependencies": {
- "@gerrit0/mini-shiki": "^3.7.0",
+ "@gerrit0/mini-shiki": "^3.9.0",
"lunr": "^2.3.9",
"markdown-it": "^14.1.0",
"minimatch": "^9.0.5",
"yaml": "^2.8.0"
},
"peerDependencies": {
- "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x"
+ "typescript": "5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x"
},
"devDependencies": {
- "@eslint/js": "^9.30.0",
+ "@eslint/js": "^9.32.0",
"@types/lunr": "^2.3.7",
"@types/markdown-it": "^14.1.2",
"@types/mocha": "^10.0.10",
"@types/node": "18",
"@typestrong/fs-fixture-builder": "github:TypeStrong/fs-fixture-builder#34113409e3a171e68ce5e2b55461ef5c35591cfe",
"c8": "^10.1.3",
- "dprint": "^0.50.0",
- "esbuild": "^0.25.5",
- "eslint": "^9.30.0",
+ "dprint": "^0.50.1",
+ "esbuild": "^0.25.8",
+ "eslint": "^9.32.0",
"mocha": "^11.7.1",
"puppeteer": "^24.11.1",
"semver": "^7.7.2",
"tsx": "^4.20.3",
- "typescript": "5.8.3",
- "typescript-eslint": "^8.35.0"
+ "typescript": "5.9.2",
+ "typescript-eslint": "^8.38.0"
},
"files": [
"/bin",
diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml
index a59df8b90..7809dfed2 100644
--- a/pnpm-lock.yaml
+++ b/pnpm-lock.yaml
@@ -9,8 +9,8 @@ importers:
.:
dependencies:
'@gerrit0/mini-shiki':
- specifier: ^3.7.0
- version: 3.7.0
+ specifier: ^3.9.0
+ version: 3.9.0
lunr:
specifier: ^2.3.9
version: 2.3.9
@@ -25,8 +25,8 @@ importers:
version: 2.8.0
devDependencies:
'@eslint/js':
- specifier: ^9.30.0
- version: 9.30.0
+ specifier: ^9.32.0
+ version: 9.32.0
'@types/lunr':
specifier: ^2.3.7
version: 2.3.7
@@ -46,20 +46,20 @@ importers:
specifier: ^10.1.3
version: 10.1.3
dprint:
- specifier: ^0.50.0
- version: 0.50.0
+ specifier: ^0.50.1
+ version: 0.50.1
esbuild:
- specifier: ^0.25.5
- version: 0.25.5
+ specifier: ^0.25.8
+ version: 0.25.8
eslint:
- specifier: ^9.30.0
- version: 9.30.0
+ specifier: ^9.32.0
+ version: 9.32.0
mocha:
specifier: ^11.7.1
version: 11.7.1
puppeteer:
specifier: ^24.11.1
- version: 24.11.1(typescript@5.8.3)
+ version: 24.11.1(typescript@5.9.2)
semver:
specifier: ^7.7.2
version: 7.7.2
@@ -67,11 +67,11 @@ importers:
specifier: ^4.20.3
version: 4.20.3
typescript:
- specifier: 5.8.3
- version: 5.8.3
+ specifier: 5.9.2
+ version: 5.9.2
typescript-eslint:
- specifier: ^8.35.0
- version: 8.35.0(eslint@9.30.0)(typescript@5.8.3)
+ specifier: ^8.38.0
+ version: 8.38.0(eslint@9.32.0)(typescript@5.9.2)
packages:
@@ -87,197 +87,203 @@ packages:
resolution: {integrity: sha512-6zABk/ECA/QYSCQ1NGiVwwbQerUCZ+TQbp64Q3AgmfNvurHH0j8TtXa1qbShXA6qqkpAj4V5W8pP6mLe1mcMqA==}
engines: {node: '>=18'}
- '@dprint/darwin-arm64@0.50.0':
- resolution: {integrity: sha512-KqWpsvm4JveYdKDLSLlQINGNW4pEAGHcTFPEHR5qXMYV4pPomLgHHPyBrxe3XdGtlUp4I8HfvBMBw3b/LKd06A==}
+ '@dprint/darwin-arm64@0.50.1':
+ resolution: {integrity: sha512-NNKf3dxXn567pd/hpCVLHLbC0dI7s3YvQnUEwjRTOAQVMp6O7/ME+Tg1RPGsDP1IB+Y2fIYSM4qmG02zQrqjAQ==}
cpu: [arm64]
os: [darwin]
- '@dprint/darwin-x64@0.50.0':
- resolution: {integrity: sha512-kFeeLYhCIVAe1SMtFYk1q0qWxrkmW8FhOBTUh2oblr4AnAjpjb03m8BVUrHHKFeBTsppwck+1b8hzU6LRZO7fA==}
+ '@dprint/darwin-x64@0.50.1':
+ resolution: {integrity: sha512-PcY75U3UC/0CLOxWzE0zZJZ2PxzUM5AX2baYL1ovgDGCfqO1H0hINiyxfx/8ncGgPojWBkLs+zrcFiGnXx7BQg==}
cpu: [x64]
os: [darwin]
- '@dprint/linux-arm64-glibc@0.50.0':
- resolution: {integrity: sha512-EL0+uMSdj/n+cZOP9ZO8ndvjmtOSWXNsMHKdAAaTG0+EjH9M9YKXD6kopP6PKOR5pJuiyHCRpVKJ4xoD4adfpQ==}
+ '@dprint/linux-arm64-glibc@0.50.1':
+ resolution: {integrity: sha512-q0TOGy9FsoSKsEQ4sIMKyFweF5M8rW1S5OfwJDNRR2TU2riWByU9TKYIZUzg53iuwYKRypr/kJ5kdbl516afRQ==}
cpu: [arm64]
os: [linux]
- '@dprint/linux-arm64-musl@0.50.0':
- resolution: {integrity: sha512-bzyYxKtFw/hYAA+7lWQGQGo2YFPnH7Ql9uWxxWqiGaWVPU66K9WQt0RUEqu1hQBrCk9mMz3jx5l4oKWQ/Dc0fw==}
+ '@dprint/linux-arm64-musl@0.50.1':
+ resolution: {integrity: sha512-XRtxN2cA9rc06WFzzVPDIZYGGLmUXqpVf3F0XhhHV77ikQLJZ5reF4xBOQ+0HjJ/zy8W/HzuGDAHedWyCrRf9g==}
cpu: [arm64]
os: [linux]
- '@dprint/linux-riscv64-glibc@0.50.0':
- resolution: {integrity: sha512-ElFqmKs96NyVXWqd2SJGJGtyVmUWNiLUyaImEzL7XZRmpoJG+Ky7SryhccMQU0ENtQmY0CVgZipLZ1SqhIoluA==}
+ '@dprint/linux-riscv64-glibc@0.50.1':
+ resolution: {integrity: sha512-vAk/eYhSjA3LJ/yuYgxkHamiK8+m6YdqVBO/Ka+i16VxyjQyOdcMKBkrLCIqSxgyXd6b8raf9wM59HJbaIpoOg==}
cpu: [riscv64]
os: [linux]
- '@dprint/linux-x64-glibc@0.50.0':
- resolution: {integrity: sha512-Kim8TtCdpCQUNqF2D96vunuonYy6tPfp/AQblSVA4ADChVyFLGfPaQIECpGAAKxXnIG2SX5JRQP7nB/4JgPNbA==}
+ '@dprint/linux-x64-glibc@0.50.1':
+ resolution: {integrity: sha512-EpW5KLekaq4hXmKBWWtfBgZ244S4C+vFmMOd1YaGi8+f0hmPTJzVWLdIgpO2ZwfPQ5iycaVI/JS514PQmXPOvg==}
cpu: [x64]
os: [linux]
- '@dprint/linux-x64-musl@0.50.0':
- resolution: {integrity: sha512-ChZf0BnS3S6BIfqAPgQKqEh/7vgD1xc0MpcFcTrvkVQHuSdCQu1XiqUN12agzxB+Y5Ml9exgzP8lYgNza7iXvw==}
+ '@dprint/linux-x64-musl@0.50.1':
+ resolution: {integrity: sha512-assISBbaKKL8LkjrIy/5tpE157MVW6HbyIKAjTtg3tPNM3lDn1oH3twuGtK9WBsN/VoEP3QMZVauolcUJT/VOg==}
cpu: [x64]
os: [linux]
- '@dprint/win32-arm64@0.50.0':
- resolution: {integrity: sha512-xSY607bRyIPG7UO3uRa5c5wTGHKJqLUkQst85Hcz89EL/It6wswwUSNcywDydssN99HmSHop4fIf6FJTEpEp2g==}
+ '@dprint/win32-arm64@0.50.1':
+ resolution: {integrity: sha512-ZeaRMQYoFjrsO3lvI1SqzDWDGH1GGXWmNSeXvcFuAf2OgYQJWMBlLotCKiHNJ3uyYneoyhTg2tv9QkApNkZV4Q==}
cpu: [arm64]
os: [win32]
- '@dprint/win32-x64@0.50.0':
- resolution: {integrity: sha512-uGDjrK88LOet9a8pPRM9nKins93mK2NLozqL/hCNV88Nu5Nk0bBeVwRMAnPapjV3Jo+hsJOeq3Z1ibrq2c3v8w==}
+ '@dprint/win32-x64@0.50.1':
+ resolution: {integrity: sha512-pMm8l/hRZ9zYylKw/yCaYkSV3btYB9UyMDbWqyxNthkQ1gckWrk17VTI6WjwwQuHD4Iaz5JgAYLS36hlUzWkxA==}
cpu: [x64]
os: [win32]
- '@esbuild/aix-ppc64@0.25.5':
- resolution: {integrity: sha512-9o3TMmpmftaCMepOdA5k/yDw8SfInyzWWTjYTFCX3kPSDJMROQTb8jg+h9Cnwnmm1vOzvxN7gIfB5V2ewpjtGA==}
+ '@esbuild/aix-ppc64@0.25.8':
+ resolution: {integrity: sha512-urAvrUedIqEiFR3FYSLTWQgLu5tb+m0qZw0NBEasUeo6wuqatkMDaRT+1uABiGXEu5vqgPd7FGE1BhsAIy9QVA==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [aix]
- '@esbuild/android-arm64@0.25.5':
- resolution: {integrity: sha512-VGzGhj4lJO+TVGV1v8ntCZWJktV7SGCs3Pn1GRWI1SBFtRALoomm8k5E9Pmwg3HOAal2VDc2F9+PM/rEY6oIDg==}
+ '@esbuild/android-arm64@0.25.8':
+ resolution: {integrity: sha512-OD3p7LYzWpLhZEyATcTSJ67qB5D+20vbtr6vHlHWSQYhKtzUYrETuWThmzFpZtFsBIxRvhO07+UgVA9m0i/O1w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [android]
- '@esbuild/android-arm@0.25.5':
- resolution: {integrity: sha512-AdJKSPeEHgi7/ZhuIPtcQKr5RQdo6OO2IL87JkianiMYMPbCtot9fxPbrMiBADOWWm3T2si9stAiVsGbTQFkbA==}
+ '@esbuild/android-arm@0.25.8':
+ resolution: {integrity: sha512-RONsAvGCz5oWyePVnLdZY/HHwA++nxYWIX1atInlaW6SEkwq6XkP3+cb825EUcRs5Vss/lGh/2YxAb5xqc07Uw==}
engines: {node: '>=18'}
cpu: [arm]
os: [android]
- '@esbuild/android-x64@0.25.5':
- resolution: {integrity: sha512-D2GyJT1kjvO//drbRT3Hib9XPwQeWd9vZoBJn+bu/lVsOZ13cqNdDeqIF/xQ5/VmWvMduP6AmXvylO/PIc2isw==}
+ '@esbuild/android-x64@0.25.8':
+ resolution: {integrity: sha512-yJAVPklM5+4+9dTeKwHOaA+LQkmrKFX96BM0A/2zQrbS6ENCmxc4OVoBs5dPkCCak2roAD+jKCdnmOqKszPkjA==}
engines: {node: '>=18'}
cpu: [x64]
os: [android]
- '@esbuild/darwin-arm64@0.25.5':
- resolution: {integrity: sha512-GtaBgammVvdF7aPIgH2jxMDdivezgFu6iKpmT+48+F8Hhg5J/sfnDieg0aeG/jfSvkYQU2/pceFPDKlqZzwnfQ==}
+ '@esbuild/darwin-arm64@0.25.8':
+ resolution: {integrity: sha512-Jw0mxgIaYX6R8ODrdkLLPwBqHTtYHJSmzzd+QeytSugzQ0Vg4c5rDky5VgkoowbZQahCbsv1rT1KW72MPIkevw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [darwin]
- '@esbuild/darwin-x64@0.25.5':
- resolution: {integrity: sha512-1iT4FVL0dJ76/q1wd7XDsXrSW+oLoquptvh4CLR4kITDtqi2e/xwXwdCVH8hVHU43wgJdsq7Gxuzcs6Iq/7bxQ==}
+ '@esbuild/darwin-x64@0.25.8':
+ resolution: {integrity: sha512-Vh2gLxxHnuoQ+GjPNvDSDRpoBCUzY4Pu0kBqMBDlK4fuWbKgGtmDIeEC081xi26PPjn+1tct+Bh8FjyLlw1Zlg==}
engines: {node: '>=18'}
cpu: [x64]
os: [darwin]
- '@esbuild/freebsd-arm64@0.25.5':
- resolution: {integrity: sha512-nk4tGP3JThz4La38Uy/gzyXtpkPW8zSAmoUhK9xKKXdBCzKODMc2adkB2+8om9BDYugz+uGV7sLmpTYzvmz6Sw==}
+ '@esbuild/freebsd-arm64@0.25.8':
+ resolution: {integrity: sha512-YPJ7hDQ9DnNe5vxOm6jaie9QsTwcKedPvizTVlqWG9GBSq+BuyWEDazlGaDTC5NGU4QJd666V0yqCBL2oWKPfA==}
engines: {node: '>=18'}
cpu: [arm64]
os: [freebsd]
- '@esbuild/freebsd-x64@0.25.5':
- resolution: {integrity: sha512-PrikaNjiXdR2laW6OIjlbeuCPrPaAl0IwPIaRv+SMV8CiM8i2LqVUHFC1+8eORgWyY7yhQY+2U2fA55mBzReaw==}
+ '@esbuild/freebsd-x64@0.25.8':
+ resolution: {integrity: sha512-MmaEXxQRdXNFsRN/KcIimLnSJrk2r5H8v+WVafRWz5xdSVmWLoITZQXcgehI2ZE6gioE6HirAEToM/RvFBeuhw==}
engines: {node: '>=18'}
cpu: [x64]
os: [freebsd]
- '@esbuild/linux-arm64@0.25.5':
- resolution: {integrity: sha512-Z9kfb1v6ZlGbWj8EJk9T6czVEjjq2ntSYLY2cw6pAZl4oKtfgQuS4HOq41M/BcoLPzrUbNd+R4BXFyH//nHxVg==}
+ '@esbuild/linux-arm64@0.25.8':
+ resolution: {integrity: sha512-WIgg00ARWv/uYLU7lsuDK00d/hHSfES5BzdWAdAig1ioV5kaFNrtK8EqGcUBJhYqotlUByUKz5Qo6u8tt7iD/w==}
engines: {node: '>=18'}
cpu: [arm64]
os: [linux]
- '@esbuild/linux-arm@0.25.5':
- resolution: {integrity: sha512-cPzojwW2okgh7ZlRpcBEtsX7WBuqbLrNXqLU89GxWbNt6uIg78ET82qifUy3W6OVww6ZWobWub5oqZOVtwolfw==}
+ '@esbuild/linux-arm@0.25.8':
+ resolution: {integrity: sha512-FuzEP9BixzZohl1kLf76KEVOsxtIBFwCaLupVuk4eFVnOZfU+Wsn+x5Ryam7nILV2pkq2TqQM9EZPsOBuMC+kg==}
engines: {node: '>=18'}
cpu: [arm]
os: [linux]
- '@esbuild/linux-ia32@0.25.5':
- resolution: {integrity: sha512-sQ7l00M8bSv36GLV95BVAdhJ2QsIbCuCjh/uYrWiMQSUuV+LpXwIqhgJDcvMTj+VsQmqAHL2yYaasENvJ7CDKA==}
+ '@esbuild/linux-ia32@0.25.8':
+ resolution: {integrity: sha512-A1D9YzRX1i+1AJZuFFUMP1E9fMaYY+GnSQil9Tlw05utlE86EKTUA7RjwHDkEitmLYiFsRd9HwKBPEftNdBfjg==}
engines: {node: '>=18'}
cpu: [ia32]
os: [linux]
- '@esbuild/linux-loong64@0.25.5':
- resolution: {integrity: sha512-0ur7ae16hDUC4OL5iEnDb0tZHDxYmuQyhKhsPBV8f99f6Z9KQM02g33f93rNH5A30agMS46u2HP6qTdEt6Q1kg==}
+ '@esbuild/linux-loong64@0.25.8':
+ resolution: {integrity: sha512-O7k1J/dwHkY1RMVvglFHl1HzutGEFFZ3kNiDMSOyUrB7WcoHGf96Sh+64nTRT26l3GMbCW01Ekh/ThKM5iI7hQ==}
engines: {node: '>=18'}
cpu: [loong64]
os: [linux]
- '@esbuild/linux-mips64el@0.25.5':
- resolution: {integrity: sha512-kB/66P1OsHO5zLz0i6X0RxlQ+3cu0mkxS3TKFvkb5lin6uwZ/ttOkP3Z8lfR9mJOBk14ZwZ9182SIIWFGNmqmg==}
+ '@esbuild/linux-mips64el@0.25.8':
+ resolution: {integrity: sha512-uv+dqfRazte3BzfMp8PAQXmdGHQt2oC/y2ovwpTteqrMx2lwaksiFZ/bdkXJC19ttTvNXBuWH53zy/aTj1FgGw==}
engines: {node: '>=18'}
cpu: [mips64el]
os: [linux]
- '@esbuild/linux-ppc64@0.25.5':
- resolution: {integrity: sha512-UZCmJ7r9X2fe2D6jBmkLBMQetXPXIsZjQJCjgwpVDz+YMcS6oFR27alkgGv3Oqkv07bxdvw7fyB71/olceJhkQ==}
+ '@esbuild/linux-ppc64@0.25.8':
+ resolution: {integrity: sha512-GyG0KcMi1GBavP5JgAkkstMGyMholMDybAf8wF5A70CALlDM2p/f7YFE7H92eDeH/VBtFJA5MT4nRPDGg4JuzQ==}
engines: {node: '>=18'}
cpu: [ppc64]
os: [linux]
- '@esbuild/linux-riscv64@0.25.5':
- resolution: {integrity: sha512-kTxwu4mLyeOlsVIFPfQo+fQJAV9mh24xL+y+Bm6ej067sYANjyEw1dNHmvoqxJUCMnkBdKpvOn0Ahql6+4VyeA==}
+ '@esbuild/linux-riscv64@0.25.8':
+ resolution: {integrity: sha512-rAqDYFv3yzMrq7GIcen3XP7TUEG/4LK86LUPMIz6RT8A6pRIDn0sDcvjudVZBiiTcZCY9y2SgYX2lgK3AF+1eg==}
engines: {node: '>=18'}
cpu: [riscv64]
os: [linux]
- '@esbuild/linux-s390x@0.25.5':
- resolution: {integrity: sha512-K2dSKTKfmdh78uJ3NcWFiqyRrimfdinS5ErLSn3vluHNeHVnBAFWC8a4X5N+7FgVE1EjXS1QDZbpqZBjfrqMTQ==}
+ '@esbuild/linux-s390x@0.25.8':
+ resolution: {integrity: sha512-Xutvh6VjlbcHpsIIbwY8GVRbwoviWT19tFhgdA7DlenLGC/mbc3lBoVb7jxj9Z+eyGqvcnSyIltYUrkKzWqSvg==}
engines: {node: '>=18'}
cpu: [s390x]
os: [linux]
- '@esbuild/linux-x64@0.25.5':
- resolution: {integrity: sha512-uhj8N2obKTE6pSZ+aMUbqq+1nXxNjZIIjCjGLfsWvVpy7gKCOL6rsY1MhRh9zLtUtAI7vpgLMK6DxjO8Qm9lJw==}
+ '@esbuild/linux-x64@0.25.8':
+ resolution: {integrity: sha512-ASFQhgY4ElXh3nDcOMTkQero4b1lgubskNlhIfJrsH5OKZXDpUAKBlNS0Kx81jwOBp+HCeZqmoJuihTv57/jvQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [linux]
- '@esbuild/netbsd-arm64@0.25.5':
- resolution: {integrity: sha512-pwHtMP9viAy1oHPvgxtOv+OkduK5ugofNTVDilIzBLpoWAM16r7b/mxBvfpuQDpRQFMfuVr5aLcn4yveGvBZvw==}
+ '@esbuild/netbsd-arm64@0.25.8':
+ resolution: {integrity: sha512-d1KfruIeohqAi6SA+gENMuObDbEjn22olAR7egqnkCD9DGBG0wsEARotkLgXDu6c4ncgWTZJtN5vcgxzWRMzcw==}
engines: {node: '>=18'}
cpu: [arm64]
os: [netbsd]
- '@esbuild/netbsd-x64@0.25.5':
- resolution: {integrity: sha512-WOb5fKrvVTRMfWFNCroYWWklbnXH0Q5rZppjq0vQIdlsQKuw6mdSihwSo4RV/YdQ5UCKKvBy7/0ZZYLBZKIbwQ==}
+ '@esbuild/netbsd-x64@0.25.8':
+ resolution: {integrity: sha512-nVDCkrvx2ua+XQNyfrujIG38+YGyuy2Ru9kKVNyh5jAys6n+l44tTtToqHjino2My8VAY6Lw9H7RI73XFi66Cg==}
engines: {node: '>=18'}
cpu: [x64]
os: [netbsd]
- '@esbuild/openbsd-arm64@0.25.5':
- resolution: {integrity: sha512-7A208+uQKgTxHd0G0uqZO8UjK2R0DDb4fDmERtARjSHWxqMTye4Erz4zZafx7Di9Cv+lNHYuncAkiGFySoD+Mw==}
+ '@esbuild/openbsd-arm64@0.25.8':
+ resolution: {integrity: sha512-j8HgrDuSJFAujkivSMSfPQSAa5Fxbvk4rgNAS5i3K+r8s1X0p1uOO2Hl2xNsGFppOeHOLAVgYwDVlmxhq5h+SQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [openbsd]
- '@esbuild/openbsd-x64@0.25.5':
- resolution: {integrity: sha512-G4hE405ErTWraiZ8UiSoesH8DaCsMm0Cay4fsFWOOUcz8b8rC6uCvnagr+gnioEjWn0wC+o1/TAHt+It+MpIMg==}
+ '@esbuild/openbsd-x64@0.25.8':
+ resolution: {integrity: sha512-1h8MUAwa0VhNCDp6Af0HToI2TJFAn1uqT9Al6DJVzdIBAd21m/G0Yfc77KDM3uF3T/YaOgQq3qTJHPbTOInaIQ==}
engines: {node: '>=18'}
cpu: [x64]
os: [openbsd]
- '@esbuild/sunos-x64@0.25.5':
- resolution: {integrity: sha512-l+azKShMy7FxzY0Rj4RCt5VD/q8mG/e+mDivgspo+yL8zW7qEwctQ6YqKX34DTEleFAvCIUviCFX1SDZRSyMQA==}
+ '@esbuild/openharmony-arm64@0.25.8':
+ resolution: {integrity: sha512-r2nVa5SIK9tSWd0kJd9HCffnDHKchTGikb//9c7HX+r+wHYCpQrSgxhlY6KWV1nFo1l4KFbsMlHk+L6fekLsUg==}
+ engines: {node: '>=18'}
+ cpu: [arm64]
+ os: [openharmony]
+
+ '@esbuild/sunos-x64@0.25.8':
+ resolution: {integrity: sha512-zUlaP2S12YhQ2UzUfcCuMDHQFJyKABkAjvO5YSndMiIkMimPmxA+BYSBikWgsRpvyxuRnow4nS5NPnf9fpv41w==}
engines: {node: '>=18'}
cpu: [x64]
os: [sunos]
- '@esbuild/win32-arm64@0.25.5':
- resolution: {integrity: sha512-O2S7SNZzdcFG7eFKgvwUEZ2VG9D/sn/eIiz8XRZ1Q/DO5a3s76Xv0mdBzVM5j5R639lXQmPmSo0iRpHqUUrsxw==}
+ '@esbuild/win32-arm64@0.25.8':
+ resolution: {integrity: sha512-YEGFFWESlPva8hGL+zvj2z/SaK+pH0SwOM0Nc/d+rVnW7GSTFlLBGzZkuSU9kFIGIo8q9X3ucpZhu8PDN5A2sQ==}
engines: {node: '>=18'}
cpu: [arm64]
os: [win32]
- '@esbuild/win32-ia32@0.25.5':
- resolution: {integrity: sha512-onOJ02pqs9h1iMJ1PQphR+VZv8qBMQ77Klcsqv9CNW2w6yLqoURLcgERAIurY6QE63bbLuqgP9ATqajFLK5AMQ==}
+ '@esbuild/win32-ia32@0.25.8':
+ resolution: {integrity: sha512-hiGgGC6KZ5LZz58OL/+qVVoZiuZlUYlYHNAmczOm7bs2oE1XriPFi5ZHHrS8ACpV5EjySrnoCKmcbQMN+ojnHg==}
engines: {node: '>=18'}
cpu: [ia32]
os: [win32]
- '@esbuild/win32-x64@0.25.5':
- resolution: {integrity: sha512-TXv6YnJ8ZMVdX+SXWVBo/0p8LTcrUYngpWjvm91TMjjBQii7Oz11Lw5lbDV5Y0TzuhSJHwiH4hEtC1I42mMS0g==}
+ '@esbuild/win32-x64@0.25.8':
+ resolution: {integrity: sha512-cn3Yr7+OaaZq1c+2pe+8yxC8E144SReCQjN6/2ynubzYjvyqZjTXfQJpAcQpsdJq3My7XADANiYGHoFC69pLQw==}
engines: {node: '>=18'}
cpu: [x64]
os: [win32]
@@ -300,10 +306,6 @@ packages:
resolution: {integrity: sha512-ViuymvFmcJi04qdZeDc2whTHryouGcDlaxPqarTD0ZE10ISpxGUVZGZDx4w01upyIynL3iu6IXH2bS1NhclQMw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/core@0.14.0':
- resolution: {integrity: sha512-qIbV0/JZr7iSDjqAc60IqbLdsj9GDt16xQtWD+B78d/HAlvysGdZZ6rpJHGAc2T0FQx1X6thsSPdnoiGKdNtdg==}
- engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
-
'@eslint/core@0.15.1':
resolution: {integrity: sha512-bkOp+iumZCCbt1K1CmWf0R9pM5yKpDv+ZXtvSyQpudrI9kuFLp+bM2WOPXImuD/ceQuaa8f5pj93Y7zyECIGNA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -312,20 +314,20 @@ packages:
resolution: {integrity: sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/js@9.30.0':
- resolution: {integrity: sha512-Wzw3wQwPvc9sHM+NjakWTcPx11mbZyiYHuwWa/QfZ7cIRX7WK54PSk7bdyXDaoaopUcMatv1zaQvOAAO8hCdww==}
+ '@eslint/js@9.32.0':
+ resolution: {integrity: sha512-BBpRFZK3eX6uMLKz8WxFOBIFFcGFJ/g8XuwjTHCqHROSIsopI+ddn/d5Cfh36+7+e5edVS8dbSHnBNhrLEX0zg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@eslint/object-schema@2.1.6':
resolution: {integrity: sha512-RBMg5FRL0I0gs51M/guSAj5/e14VQ4tpZnQNWwuDT66P14I43ItmPfIZRhO9fUVIPOAQXU47atlywZ/czoqFPA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@eslint/plugin-kit@0.3.3':
- resolution: {integrity: sha512-1+WqvgNMhmlAambTvT3KPtCl/Ibr68VldY2XY40SL1CE0ZXiakFR/cbTspaF5HsnpDMvcYYoJHfl4980NBjGag==}
+ '@eslint/plugin-kit@0.3.4':
+ resolution: {integrity: sha512-Ul5l+lHEcw3L5+k8POx6r74mxEYKG5kOb6Xpy2gCRW6zweT6TEhAf8vhxGgjhqrd/VO/Dirhsb+1hNpD1ue9hw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@gerrit0/mini-shiki@3.7.0':
- resolution: {integrity: sha512-7iY9wg4FWXmeoFJpUL2u+tsmh0d0jcEJHAIzVxl3TG4KL493JNnisdLAILZ77zcD+z3J0keEXZ+lFzUgzQzPDg==}
+ '@gerrit0/mini-shiki@3.9.0':
+ resolution: {integrity: sha512-p58r5PE/hIKtE7aYzeDYZr4DPrOidwoUFPX3p6rPEZWtb7zWX3b7Bu9LZ17XODFiRO4x/VzTE15KYNEaZ3khuw==}
'@humanfs/core@0.19.1':
resolution: {integrity: sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==}
@@ -386,17 +388,17 @@ packages:
engines: {node: '>=18'}
hasBin: true
- '@shikijs/engine-oniguruma@3.7.0':
- resolution: {integrity: sha512-5BxcD6LjVWsGu4xyaBC5bu8LdNgPCVBnAkWTtOCs/CZxcB22L8rcoWfv7Hh/3WooVjBZmFtyxhgvkQFedPGnFw==}
+ '@shikijs/engine-oniguruma@3.9.1':
+ resolution: {integrity: sha512-WPlL/xqviwS3te4unSGGGfflKsuHLMI6tPdNYvgz/IygcBT6UiwDFSzjBKyebwi5GGSlXsjjdoJLIBnAplmEZw==}
- '@shikijs/langs@3.7.0':
- resolution: {integrity: sha512-1zYtdfXLr9xDKLTGy5kb7O0zDQsxXiIsw1iIBcNOO8Yi5/Y1qDbJ+0VsFoqTlzdmneO8Ij35g7QKF8kcLyznCQ==}
+ '@shikijs/langs@3.9.1':
+ resolution: {integrity: sha512-Vyy2Yv9PP3Veh3VSsIvNncOR+O93wFsNYgN2B6cCCJlS7H9SKFYc55edsqernsg8WT/zam1cfB6llJsQWLnVhA==}
- '@shikijs/themes@3.7.0':
- resolution: {integrity: sha512-VJx8497iZPy5zLiiCTSIaOChIcKQwR0FebwE9S3rcN0+J/GTWwQ1v/bqhTbpbY3zybPKeO8wdammqkpXc4NVjQ==}
+ '@shikijs/themes@3.9.1':
+ resolution: {integrity: sha512-zAykkGECNICCMXpKeVvq04yqwaSuAIvrf8MjsU5bzskfg4XreU+O0B5wdNCYRixoB9snd3YlZ373WV5E/g5T9A==}
- '@shikijs/types@3.7.0':
- resolution: {integrity: sha512-MGaLeaRlSWpnP0XSAum3kP3a8vtcTsITqoEPYdt3lQG3YCdQH4DnEhodkYcNMcU0uW0RffhoD1O3e0vG5eSBBg==}
+ '@shikijs/types@3.9.1':
+ resolution: {integrity: sha512-rqM3T7a0iM1oPKz9iaH/cVgNX9Vz1HERcUcXJ94/fulgVdwqfnhXzGxO4bLrAnh/o5CPLy3IcYedogfV+Ns0Qg==}
'@shikijs/vscode-textmate@10.0.2':
resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==}
@@ -440,63 +442,63 @@ packages:
'@types/yauzl@2.10.3':
resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==}
- '@typescript-eslint/eslint-plugin@8.35.0':
- resolution: {integrity: sha512-ijItUYaiWuce0N1SoSMrEd0b6b6lYkYt99pqCPfybd+HKVXtEvYhICfLdwp42MhiI5mp0oq7PKEL+g1cNiz/Eg==}
+ '@typescript-eslint/eslint-plugin@8.38.0':
+ resolution: {integrity: sha512-CPoznzpuAnIOl4nhj4tRr4gIPj5AfKgkiJmGQDaq+fQnRJTYlcBjbX3wbciGmpoPf8DREufuPRe1tNMZnGdanA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
- '@typescript-eslint/parser': ^8.35.0
+ '@typescript-eslint/parser': ^8.38.0
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/parser@8.35.0':
- resolution: {integrity: sha512-6sMvZePQrnZH2/cJkwRpkT7DxoAWh+g6+GFRK6bV3YQo7ogi3SX5rgF6099r5Q53Ma5qeT7LGmOmuIutF4t3lA==}
+ '@typescript-eslint/parser@8.38.0':
+ resolution: {integrity: sha512-Zhy8HCvBUEfBECzIl1PKqF4p11+d0aUJS1GeUiuqK9WmOug8YCmC4h4bjyBvMyAMI9sbRczmrYL5lKg/YMbrcQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/project-service@8.35.0':
- resolution: {integrity: sha512-41xatqRwWZuhUMF/aZm2fcUsOFKNcG28xqRSS6ZVr9BVJtGExosLAm5A1OxTjRMagx8nJqva+P5zNIGt8RIgbQ==}
+ '@typescript-eslint/project-service@8.38.0':
+ resolution: {integrity: sha512-dbK7Jvqcb8c9QfH01YB6pORpqX1mn5gDZc9n63Ak/+jD67oWXn3Gs0M6vddAN+eDXBCS5EmNWzbSxsn9SzFWWg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/scope-manager@8.35.0':
- resolution: {integrity: sha512-+AgL5+mcoLxl1vGjwNfiWq5fLDZM1TmTPYs2UkyHfFhgERxBbqHlNjRzhThJqz+ktBqTChRYY6zwbMwy0591AA==}
+ '@typescript-eslint/scope-manager@8.38.0':
+ resolution: {integrity: sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/tsconfig-utils@8.35.0':
- resolution: {integrity: sha512-04k/7247kZzFraweuEirmvUj+W3bJLI9fX6fbo1Qm2YykuBvEhRTPl8tcxlYO8kZZW+HIXfkZNoasVb8EV4jpA==}
+ '@typescript-eslint/tsconfig-utils@8.38.0':
+ resolution: {integrity: sha512-Lum9RtSE3EroKk/bYns+sPOodqb2Fv50XOl/gMviMKNvanETUuUcC9ObRbzrJ4VSd2JalPqgSAavwrPiPvnAiQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/type-utils@8.35.0':
- resolution: {integrity: sha512-ceNNttjfmSEoM9PW87bWLDEIaLAyR+E6BoYJQ5PfaDau37UGca9Nyq3lBk8Bw2ad0AKvYabz6wxc7DMTO2jnNA==}
+ '@typescript-eslint/type-utils@8.38.0':
+ resolution: {integrity: sha512-c7jAvGEZVf0ao2z+nnz8BUaHZD09Agbh+DY7qvBQqLiz8uJzRgVPj5YvOh8I8uEiH8oIUGIfHzMwUcGVco/SJg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/types@8.35.0':
- resolution: {integrity: sha512-0mYH3emanku0vHw2aRLNGqe7EXh9WHEhi7kZzscrMDf6IIRUQ5Jk4wp1QrledE/36KtdZrVfKnE32eZCf/vaVQ==}
+ '@typescript-eslint/types@8.38.0':
+ resolution: {integrity: sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- '@typescript-eslint/typescript-estree@8.35.0':
- resolution: {integrity: sha512-F+BhnaBemgu1Qf8oHrxyw14wq6vbL8xwWKKMwTMwYIRmFFY/1n/9T/jpbobZL8vp7QyEUcC6xGrnAO4ua8Kp7w==}
+ '@typescript-eslint/typescript-estree@8.38.0':
+ resolution: {integrity: sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/utils@8.35.0':
- resolution: {integrity: sha512-nqoMu7WWM7ki5tPgLVsmPM8CkqtoPUG6xXGeefM5t4x3XumOEKMoUZPdi+7F+/EotukN4R9OWdmDxN80fqoZeg==}
+ '@typescript-eslint/utils@8.38.0':
+ resolution: {integrity: sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- '@typescript-eslint/visitor-keys@8.35.0':
- resolution: {integrity: sha512-zTh2+1Y8ZpmeQaQVIc/ZZxsx8UzgKJyNg1PTvjzC7WMhPSVS8bfDX34k1SrwOf016qd5RU3az2UxUNue3IfQ5g==}
+ '@typescript-eslint/visitor-keys@8.38.0':
+ resolution: {integrity: sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typestrong/fs-fixture-builder@https://codeload.github.com/TypeStrong/fs-fixture-builder/tar.gz/34113409e3a171e68ce5e2b55461ef5c35591cfe':
@@ -692,8 +694,8 @@ packages:
resolution: {integrity: sha512-PJWHUb1RFevKCwaFA9RlG5tCd+FO5iRh9A8HEtkmBH2Li03iJriB6m6JIN4rGz3K3JLawI7/veA1xzRKP6ISBw==}
engines: {node: '>=0.3.1'}
- dprint@0.50.0:
- resolution: {integrity: sha512-aNJhOQsUS5D9k/YkMUaLLniIpxEBUR0ZwT0RXGQV5YpaGwE2nx6FcKuVkC6wRaZXTr8X0NpV/2HFbcvNuI2jtA==}
+ dprint@0.50.1:
+ resolution: {integrity: sha512-s+kUyQp2rGpwsM3vVmXySOY3v1NjYyRpKfQZdP4rfNTz6zQuICSO6nqIXNm3YdK1MwNFR/EXSFMuE1YPuulhow==}
hasBin: true
eastasianwidth@0.2.0:
@@ -719,8 +721,8 @@ packages:
error-ex@1.3.2:
resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==}
- esbuild@0.25.5:
- resolution: {integrity: sha512-P8OtKZRv/5J5hhz0cUAdu/cLuPIKXpQl1R9pZtvmHWQvrAUVd0UNIPT4IB4W3rNOqVO0rlqHmCIbSwxh/c9yUQ==}
+ esbuild@0.25.8:
+ resolution: {integrity: sha512-vVC0USHGtMi8+R4Kz8rt6JhEWLxsv9Rnu/lGYbPR8u47B+DCBksq9JarW0zOO7bs37hyOK1l2/oqtbciutL5+Q==}
engines: {node: '>=18'}
hasBin: true
@@ -749,8 +751,8 @@ packages:
resolution: {integrity: sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
- eslint@9.30.0:
- resolution: {integrity: sha512-iN/SiPxmQu6EVkf+m1qpBxzUhE12YqFLOSySuOyVLJLEF9nzTf+h/1AJYc1JWzCnktggeNrjvQGLngDzXirU6g==}
+ eslint@9.32.0:
+ resolution: {integrity: sha512-LSehfdpgMeWcTZkWZVIJl+tkZ2nuSkyyB9C27MZqFWXuph7DvaowgcTvKqxvpLW1JZIk8PN7hFY3Rj9LQ7m7lg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
hasBin: true
peerDependencies:
@@ -1295,15 +1297,15 @@ packages:
typed-query-selector@2.12.0:
resolution: {integrity: sha512-SbklCd1F0EiZOyPiW192rrHZzZ5sBijB6xM+cpmrwDqObvdtunOHHIk9fCGsoK5JVIYXoyEp4iEdE3upFH3PAg==}
- typescript-eslint@8.35.0:
- resolution: {integrity: sha512-uEnz70b7kBz6eg/j0Czy6K5NivaYopgxRjsnAJ2Fx5oTLo3wefTHIbL7AkQr1+7tJCRVpTs/wiM8JR/11Loq9A==}
+ typescript-eslint@8.38.0:
+ resolution: {integrity: sha512-FsZlrYK6bPDGoLeZRuvx2v6qrM03I0U0SnfCLPs/XCCPCFD80xU9Pg09H/K+XFa68uJuZo7l/Xhs+eDRg2l3hg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
- typescript@5.8.3:
- resolution: {integrity: sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ==}
+ typescript@5.9.2:
+ resolution: {integrity: sha512-CWBzXQrc/qOkhidw1OzBTQuYRbfyxDXJMVJ1XNwUHGROVmuaeiEm3OslpZ1RV96d7SKKjZKrSJu3+t/xlw3R9A==}
engines: {node: '>=14.17'}
hasBin: true
@@ -1398,111 +1400,114 @@ snapshots:
'@bcoe/v8-coverage@1.0.2': {}
- '@dprint/darwin-arm64@0.50.0':
+ '@dprint/darwin-arm64@0.50.1':
optional: true
- '@dprint/darwin-x64@0.50.0':
+ '@dprint/darwin-x64@0.50.1':
optional: true
- '@dprint/linux-arm64-glibc@0.50.0':
+ '@dprint/linux-arm64-glibc@0.50.1':
optional: true
- '@dprint/linux-arm64-musl@0.50.0':
+ '@dprint/linux-arm64-musl@0.50.1':
optional: true
- '@dprint/linux-riscv64-glibc@0.50.0':
+ '@dprint/linux-riscv64-glibc@0.50.1':
optional: true
- '@dprint/linux-x64-glibc@0.50.0':
+ '@dprint/linux-x64-glibc@0.50.1':
optional: true
- '@dprint/linux-x64-musl@0.50.0':
+ '@dprint/linux-x64-musl@0.50.1':
optional: true
- '@dprint/win32-arm64@0.50.0':
+ '@dprint/win32-arm64@0.50.1':
optional: true
- '@dprint/win32-x64@0.50.0':
+ '@dprint/win32-x64@0.50.1':
optional: true
- '@esbuild/aix-ppc64@0.25.5':
+ '@esbuild/aix-ppc64@0.25.8':
optional: true
- '@esbuild/android-arm64@0.25.5':
+ '@esbuild/android-arm64@0.25.8':
optional: true
- '@esbuild/android-arm@0.25.5':
+ '@esbuild/android-arm@0.25.8':
optional: true
- '@esbuild/android-x64@0.25.5':
+ '@esbuild/android-x64@0.25.8':
optional: true
- '@esbuild/darwin-arm64@0.25.5':
+ '@esbuild/darwin-arm64@0.25.8':
optional: true
- '@esbuild/darwin-x64@0.25.5':
+ '@esbuild/darwin-x64@0.25.8':
optional: true
- '@esbuild/freebsd-arm64@0.25.5':
+ '@esbuild/freebsd-arm64@0.25.8':
optional: true
- '@esbuild/freebsd-x64@0.25.5':
+ '@esbuild/freebsd-x64@0.25.8':
optional: true
- '@esbuild/linux-arm64@0.25.5':
+ '@esbuild/linux-arm64@0.25.8':
optional: true
- '@esbuild/linux-arm@0.25.5':
+ '@esbuild/linux-arm@0.25.8':
optional: true
- '@esbuild/linux-ia32@0.25.5':
+ '@esbuild/linux-ia32@0.25.8':
optional: true
- '@esbuild/linux-loong64@0.25.5':
+ '@esbuild/linux-loong64@0.25.8':
optional: true
- '@esbuild/linux-mips64el@0.25.5':
+ '@esbuild/linux-mips64el@0.25.8':
optional: true
- '@esbuild/linux-ppc64@0.25.5':
+ '@esbuild/linux-ppc64@0.25.8':
optional: true
- '@esbuild/linux-riscv64@0.25.5':
+ '@esbuild/linux-riscv64@0.25.8':
optional: true
- '@esbuild/linux-s390x@0.25.5':
+ '@esbuild/linux-s390x@0.25.8':
optional: true
- '@esbuild/linux-x64@0.25.5':
+ '@esbuild/linux-x64@0.25.8':
optional: true
- '@esbuild/netbsd-arm64@0.25.5':
+ '@esbuild/netbsd-arm64@0.25.8':
optional: true
- '@esbuild/netbsd-x64@0.25.5':
+ '@esbuild/netbsd-x64@0.25.8':
optional: true
- '@esbuild/openbsd-arm64@0.25.5':
+ '@esbuild/openbsd-arm64@0.25.8':
optional: true
- '@esbuild/openbsd-x64@0.25.5':
+ '@esbuild/openbsd-x64@0.25.8':
optional: true
- '@esbuild/sunos-x64@0.25.5':
+ '@esbuild/openharmony-arm64@0.25.8':
optional: true
- '@esbuild/win32-arm64@0.25.5':
+ '@esbuild/sunos-x64@0.25.8':
optional: true
- '@esbuild/win32-ia32@0.25.5':
+ '@esbuild/win32-arm64@0.25.8':
optional: true
- '@esbuild/win32-x64@0.25.5':
+ '@esbuild/win32-ia32@0.25.8':
optional: true
- '@eslint-community/eslint-utils@4.7.0(eslint@9.30.0)':
+ '@esbuild/win32-x64@0.25.8':
+ optional: true
+
+ '@eslint-community/eslint-utils@4.7.0(eslint@9.32.0)':
dependencies:
- eslint: 9.30.0
+ eslint: 9.32.0
eslint-visitor-keys: 3.4.3
'@eslint-community/regexpp@4.12.1': {}
@@ -1517,10 +1522,6 @@ snapshots:
'@eslint/config-helpers@0.3.0': {}
- '@eslint/core@0.14.0':
- dependencies:
- '@types/json-schema': 7.0.15
-
'@eslint/core@0.15.1':
dependencies:
'@types/json-schema': 7.0.15
@@ -1539,21 +1540,21 @@ snapshots:
transitivePeerDependencies:
- supports-color
- '@eslint/js@9.30.0': {}
+ '@eslint/js@9.32.0': {}
'@eslint/object-schema@2.1.6': {}
- '@eslint/plugin-kit@0.3.3':
+ '@eslint/plugin-kit@0.3.4':
dependencies:
'@eslint/core': 0.15.1
levn: 0.4.1
- '@gerrit0/mini-shiki@3.7.0':
+ '@gerrit0/mini-shiki@3.9.0':
dependencies:
- '@shikijs/engine-oniguruma': 3.7.0
- '@shikijs/langs': 3.7.0
- '@shikijs/themes': 3.7.0
- '@shikijs/types': 3.7.0
+ '@shikijs/engine-oniguruma': 3.9.1
+ '@shikijs/langs': 3.9.1
+ '@shikijs/themes': 3.9.1
+ '@shikijs/types': 3.9.1
'@shikijs/vscode-textmate': 10.0.2
'@humanfs/core@0.19.1': {}
@@ -1617,20 +1618,20 @@ snapshots:
- bare-buffer
- supports-color
- '@shikijs/engine-oniguruma@3.7.0':
+ '@shikijs/engine-oniguruma@3.9.1':
dependencies:
- '@shikijs/types': 3.7.0
+ '@shikijs/types': 3.9.1
'@shikijs/vscode-textmate': 10.0.2
- '@shikijs/langs@3.7.0':
+ '@shikijs/langs@3.9.1':
dependencies:
- '@shikijs/types': 3.7.0
+ '@shikijs/types': 3.9.1
- '@shikijs/themes@3.7.0':
+ '@shikijs/themes@3.9.1':
dependencies:
- '@shikijs/types': 3.7.0
+ '@shikijs/types': 3.9.1
- '@shikijs/types@3.7.0':
+ '@shikijs/types@3.9.1':
dependencies:
'@shikijs/vscode-textmate': 10.0.2
'@types/hast': 3.0.4
@@ -1673,96 +1674,97 @@ snapshots:
'@types/node': 18.19.113
optional: true
- '@typescript-eslint/eslint-plugin@8.35.0(@typescript-eslint/parser@8.35.0(eslint@9.30.0)(typescript@5.8.3))(eslint@9.30.0)(typescript@5.8.3)':
+ '@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0)(typescript@5.9.2)':
dependencies:
'@eslint-community/regexpp': 4.12.1
- '@typescript-eslint/parser': 8.35.0(eslint@9.30.0)(typescript@5.8.3)
- '@typescript-eslint/scope-manager': 8.35.0
- '@typescript-eslint/type-utils': 8.35.0(eslint@9.30.0)(typescript@5.8.3)
- '@typescript-eslint/utils': 8.35.0(eslint@9.30.0)(typescript@5.8.3)
- '@typescript-eslint/visitor-keys': 8.35.0
- eslint: 9.30.0
+ '@typescript-eslint/parser': 8.38.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/scope-manager': 8.38.0
+ '@typescript-eslint/type-utils': 8.38.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.38.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/visitor-keys': 8.38.0
+ eslint: 9.32.0
graphemer: 1.4.0
ignore: 7.0.5
natural-compare: 1.4.0
- ts-api-utils: 2.1.0(typescript@5.8.3)
- typescript: 5.8.3
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/parser@8.35.0(eslint@9.30.0)(typescript@5.8.3)':
+ '@typescript-eslint/parser@8.38.0(eslint@9.32.0)(typescript@5.9.2)':
dependencies:
- '@typescript-eslint/scope-manager': 8.35.0
- '@typescript-eslint/types': 8.35.0
- '@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3)
- '@typescript-eslint/visitor-keys': 8.35.0
+ '@typescript-eslint/scope-manager': 8.38.0
+ '@typescript-eslint/types': 8.38.0
+ '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2)
+ '@typescript-eslint/visitor-keys': 8.38.0
debug: 4.4.1(supports-color@8.1.1)
- eslint: 9.30.0
- typescript: 5.8.3
+ eslint: 9.32.0
+ typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/project-service@8.35.0(typescript@5.8.3)':
+ '@typescript-eslint/project-service@8.38.0(typescript@5.9.2)':
dependencies:
- '@typescript-eslint/tsconfig-utils': 8.35.0(typescript@5.8.3)
- '@typescript-eslint/types': 8.35.0
+ '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.9.2)
+ '@typescript-eslint/types': 8.38.0
debug: 4.4.1(supports-color@8.1.1)
- typescript: 5.8.3
+ typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/scope-manager@8.35.0':
+ '@typescript-eslint/scope-manager@8.38.0':
dependencies:
- '@typescript-eslint/types': 8.35.0
- '@typescript-eslint/visitor-keys': 8.35.0
+ '@typescript-eslint/types': 8.38.0
+ '@typescript-eslint/visitor-keys': 8.38.0
- '@typescript-eslint/tsconfig-utils@8.35.0(typescript@5.8.3)':
+ '@typescript-eslint/tsconfig-utils@8.38.0(typescript@5.9.2)':
dependencies:
- typescript: 5.8.3
+ typescript: 5.9.2
- '@typescript-eslint/type-utils@8.35.0(eslint@9.30.0)(typescript@5.8.3)':
+ '@typescript-eslint/type-utils@8.38.0(eslint@9.32.0)(typescript@5.9.2)':
dependencies:
- '@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3)
- '@typescript-eslint/utils': 8.35.0(eslint@9.30.0)(typescript@5.8.3)
+ '@typescript-eslint/types': 8.38.0
+ '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.38.0(eslint@9.32.0)(typescript@5.9.2)
debug: 4.4.1(supports-color@8.1.1)
- eslint: 9.30.0
- ts-api-utils: 2.1.0(typescript@5.8.3)
- typescript: 5.8.3
+ eslint: 9.32.0
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/types@8.35.0': {}
+ '@typescript-eslint/types@8.38.0': {}
- '@typescript-eslint/typescript-estree@8.35.0(typescript@5.8.3)':
+ '@typescript-eslint/typescript-estree@8.38.0(typescript@5.9.2)':
dependencies:
- '@typescript-eslint/project-service': 8.35.0(typescript@5.8.3)
- '@typescript-eslint/tsconfig-utils': 8.35.0(typescript@5.8.3)
- '@typescript-eslint/types': 8.35.0
- '@typescript-eslint/visitor-keys': 8.35.0
+ '@typescript-eslint/project-service': 8.38.0(typescript@5.9.2)
+ '@typescript-eslint/tsconfig-utils': 8.38.0(typescript@5.9.2)
+ '@typescript-eslint/types': 8.38.0
+ '@typescript-eslint/visitor-keys': 8.38.0
debug: 4.4.1(supports-color@8.1.1)
fast-glob: 3.3.3
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.7.2
- ts-api-utils: 2.1.0(typescript@5.8.3)
- typescript: 5.8.3
+ ts-api-utils: 2.1.0(typescript@5.9.2)
+ typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/utils@8.35.0(eslint@9.30.0)(typescript@5.8.3)':
+ '@typescript-eslint/utils@8.38.0(eslint@9.32.0)(typescript@5.9.2)':
dependencies:
- '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.0)
- '@typescript-eslint/scope-manager': 8.35.0
- '@typescript-eslint/types': 8.35.0
- '@typescript-eslint/typescript-estree': 8.35.0(typescript@5.8.3)
- eslint: 9.30.0
- typescript: 5.8.3
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0)
+ '@typescript-eslint/scope-manager': 8.38.0
+ '@typescript-eslint/types': 8.38.0
+ '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2)
+ eslint: 9.32.0
+ typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- '@typescript-eslint/visitor-keys@8.35.0':
+ '@typescript-eslint/visitor-keys@8.38.0':
dependencies:
- '@typescript-eslint/types': 8.35.0
+ '@typescript-eslint/types': 8.38.0
eslint-visitor-keys: 4.2.1
'@typestrong/fs-fixture-builder@https://codeload.github.com/TypeStrong/fs-fixture-builder/tar.gz/34113409e3a171e68ce5e2b55461ef5c35591cfe': {}
@@ -1895,14 +1897,14 @@ snapshots:
convert-source-map@2.0.0: {}
- cosmiconfig@9.0.0(typescript@5.8.3):
+ cosmiconfig@9.0.0(typescript@5.9.2):
dependencies:
env-paths: 2.2.1
import-fresh: 3.3.1
js-yaml: 4.1.0
parse-json: 5.2.0
optionalDependencies:
- typescript: 5.8.3
+ typescript: 5.9.2
cross-spawn@7.0.6:
dependencies:
@@ -1932,17 +1934,17 @@ snapshots:
diff@7.0.0: {}
- dprint@0.50.0:
+ dprint@0.50.1:
optionalDependencies:
- '@dprint/darwin-arm64': 0.50.0
- '@dprint/darwin-x64': 0.50.0
- '@dprint/linux-arm64-glibc': 0.50.0
- '@dprint/linux-arm64-musl': 0.50.0
- '@dprint/linux-riscv64-glibc': 0.50.0
- '@dprint/linux-x64-glibc': 0.50.0
- '@dprint/linux-x64-musl': 0.50.0
- '@dprint/win32-arm64': 0.50.0
- '@dprint/win32-x64': 0.50.0
+ '@dprint/darwin-arm64': 0.50.1
+ '@dprint/darwin-x64': 0.50.1
+ '@dprint/linux-arm64-glibc': 0.50.1
+ '@dprint/linux-arm64-musl': 0.50.1
+ '@dprint/linux-riscv64-glibc': 0.50.1
+ '@dprint/linux-x64-glibc': 0.50.1
+ '@dprint/linux-x64-musl': 0.50.1
+ '@dprint/win32-arm64': 0.50.1
+ '@dprint/win32-x64': 0.50.1
eastasianwidth@0.2.0: {}
@@ -1962,33 +1964,34 @@ snapshots:
dependencies:
is-arrayish: 0.2.1
- esbuild@0.25.5:
+ esbuild@0.25.8:
optionalDependencies:
- '@esbuild/aix-ppc64': 0.25.5
- '@esbuild/android-arm': 0.25.5
- '@esbuild/android-arm64': 0.25.5
- '@esbuild/android-x64': 0.25.5
- '@esbuild/darwin-arm64': 0.25.5
- '@esbuild/darwin-x64': 0.25.5
- '@esbuild/freebsd-arm64': 0.25.5
- '@esbuild/freebsd-x64': 0.25.5
- '@esbuild/linux-arm': 0.25.5
- '@esbuild/linux-arm64': 0.25.5
- '@esbuild/linux-ia32': 0.25.5
- '@esbuild/linux-loong64': 0.25.5
- '@esbuild/linux-mips64el': 0.25.5
- '@esbuild/linux-ppc64': 0.25.5
- '@esbuild/linux-riscv64': 0.25.5
- '@esbuild/linux-s390x': 0.25.5
- '@esbuild/linux-x64': 0.25.5
- '@esbuild/netbsd-arm64': 0.25.5
- '@esbuild/netbsd-x64': 0.25.5
- '@esbuild/openbsd-arm64': 0.25.5
- '@esbuild/openbsd-x64': 0.25.5
- '@esbuild/sunos-x64': 0.25.5
- '@esbuild/win32-arm64': 0.25.5
- '@esbuild/win32-ia32': 0.25.5
- '@esbuild/win32-x64': 0.25.5
+ '@esbuild/aix-ppc64': 0.25.8
+ '@esbuild/android-arm': 0.25.8
+ '@esbuild/android-arm64': 0.25.8
+ '@esbuild/android-x64': 0.25.8
+ '@esbuild/darwin-arm64': 0.25.8
+ '@esbuild/darwin-x64': 0.25.8
+ '@esbuild/freebsd-arm64': 0.25.8
+ '@esbuild/freebsd-x64': 0.25.8
+ '@esbuild/linux-arm': 0.25.8
+ '@esbuild/linux-arm64': 0.25.8
+ '@esbuild/linux-ia32': 0.25.8
+ '@esbuild/linux-loong64': 0.25.8
+ '@esbuild/linux-mips64el': 0.25.8
+ '@esbuild/linux-ppc64': 0.25.8
+ '@esbuild/linux-riscv64': 0.25.8
+ '@esbuild/linux-s390x': 0.25.8
+ '@esbuild/linux-x64': 0.25.8
+ '@esbuild/netbsd-arm64': 0.25.8
+ '@esbuild/netbsd-x64': 0.25.8
+ '@esbuild/openbsd-arm64': 0.25.8
+ '@esbuild/openbsd-x64': 0.25.8
+ '@esbuild/openharmony-arm64': 0.25.8
+ '@esbuild/sunos-x64': 0.25.8
+ '@esbuild/win32-arm64': 0.25.8
+ '@esbuild/win32-ia32': 0.25.8
+ '@esbuild/win32-x64': 0.25.8
escalade@3.2.0: {}
@@ -2011,16 +2014,16 @@ snapshots:
eslint-visitor-keys@4.2.1: {}
- eslint@9.30.0:
+ eslint@9.32.0:
dependencies:
- '@eslint-community/eslint-utils': 4.7.0(eslint@9.30.0)
+ '@eslint-community/eslint-utils': 4.7.0(eslint@9.32.0)
'@eslint-community/regexpp': 4.12.1
'@eslint/config-array': 0.21.0
'@eslint/config-helpers': 0.3.0
- '@eslint/core': 0.14.0
+ '@eslint/core': 0.15.1
'@eslint/eslintrc': 3.3.1
- '@eslint/js': 9.30.0
- '@eslint/plugin-kit': 0.3.3
+ '@eslint/js': 9.32.0
+ '@eslint/plugin-kit': 0.3.4
'@humanfs/node': 0.16.6
'@humanwhocodes/module-importer': 1.0.1
'@humanwhocodes/retry': 0.4.3
@@ -2467,11 +2470,11 @@ snapshots:
- supports-color
- utf-8-validate
- puppeteer@24.11.1(typescript@5.8.3):
+ puppeteer@24.11.1(typescript@5.9.2):
dependencies:
'@puppeteer/browsers': 2.10.5
chromium-bidi: 5.1.0(devtools-protocol@0.0.1464554)
- cosmiconfig: 9.0.0(typescript@5.8.3)
+ cosmiconfig: 9.0.0(typescript@5.9.2)
devtools-protocol: 0.0.1464554
puppeteer-core: 24.11.1
typed-query-selector: 2.12.0
@@ -2605,15 +2608,15 @@ snapshots:
dependencies:
is-number: 7.0.0
- ts-api-utils@2.1.0(typescript@5.8.3):
+ ts-api-utils@2.1.0(typescript@5.9.2):
dependencies:
- typescript: 5.8.3
+ typescript: 5.9.2
tslib@2.8.1: {}
tsx@4.20.3:
dependencies:
- esbuild: 0.25.5
+ esbuild: 0.25.8
get-tsconfig: 4.10.1
optionalDependencies:
fsevents: 2.3.3
@@ -2624,17 +2627,18 @@ snapshots:
typed-query-selector@2.12.0: {}
- typescript-eslint@8.35.0(eslint@9.30.0)(typescript@5.8.3):
+ typescript-eslint@8.38.0(eslint@9.32.0)(typescript@5.9.2):
dependencies:
- '@typescript-eslint/eslint-plugin': 8.35.0(@typescript-eslint/parser@8.35.0(eslint@9.30.0)(typescript@5.8.3))(eslint@9.30.0)(typescript@5.8.3)
- '@typescript-eslint/parser': 8.35.0(eslint@9.30.0)(typescript@5.8.3)
- '@typescript-eslint/utils': 8.35.0(eslint@9.30.0)(typescript@5.8.3)
- eslint: 9.30.0
- typescript: 5.8.3
+ '@typescript-eslint/eslint-plugin': 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.32.0)(typescript@5.9.2))(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/parser': 8.38.0(eslint@9.32.0)(typescript@5.9.2)
+ '@typescript-eslint/typescript-estree': 8.38.0(typescript@5.9.2)
+ '@typescript-eslint/utils': 8.38.0(eslint@9.32.0)(typescript@5.9.2)
+ eslint: 9.32.0
+ typescript: 5.9.2
transitivePeerDependencies:
- supports-color
- typescript@5.8.3: {}
+ typescript@5.9.2: {}
uc.micro@2.1.0: {}
diff --git a/scripts/build_site.sh b/scripts/build_site.sh
index 6c8276895..11622b4d9 100755
--- a/scripts/build_site.sh
+++ b/scripts/build_site.sh
@@ -14,6 +14,10 @@ fi
if [[ -n "$CI" || ! -d example/docs ]]; then
cd example
pnpm i
+ # Ignoring warnings here because we inherit from Array, which results in
+ # a few warnings because the docs in the .d.ts have bad @param comments
+ # We might want to change TypeDoc's validation logic to make this not a
+ # warning at some point if the relevant comments show up on both signatures.
pnpm run typedoc --logLevel Error
cd ..
fi
@@ -22,7 +26,7 @@ fi
git show $(git describe --tags --abbrev=0):CHANGELOG.md | sed 's/#* Unreleased//' > site/generated/CHANGELOG.md
# Build the actual site, references the API docs
-node bin/typedoc --options site/typedoc.config.jsonc
+node bin/typedoc --options site/typedoc.config.jsonc --treatWarningsAsErrors
# Create/copy static files
node scripts/generate_options_schema.js docs-site/schema.json
diff --git a/scripts/clone_api_users.js b/scripts/clone_api_users.js
index 3a77f5e6e..d38c890db 100755
--- a/scripts/clone_api_users.js
+++ b/scripts/clone_api_users.js
@@ -93,6 +93,7 @@ if (import.meta.url.endsWith(process.argv[1])) {
}
console.log(`Cloning/updating took ${(Date.now() - start) / 1000} seconds`);
+ console.log(`Output is in ${args.values.output}`);
// Check for repos listed in the wrong list
const currentMinor = semver.parse(JSON.parse(readFileSync("package.json", "utf-8")).version)?.minor;
diff --git a/scripts/generate_options_schema.js b/scripts/generate_options_schema.js
index 333444196..8c8375f3f 100644
--- a/scripts/generate_options_schema.js
+++ b/scripts/generate_options_schema.js
@@ -36,6 +36,7 @@ addTypeDocOptions({
case ParameterType.GlobArray:
case ParameterType.PathArray:
case ParameterType.ModuleArray:
+ case ParameterType.PluginArray:
data.type = "array";
data.items = { type: "string" };
data.default = /** @type {import("../dist/index.js").ArrayDeclarationOption} */ (
diff --git a/scripts/generate_site_plugins.js b/scripts/generate_site_plugins.js
index e7889a8f3..7e0fde228 100644
--- a/scripts/generate_site_plugins.js
+++ b/scripts/generate_site_plugins.js
@@ -8,7 +8,6 @@ const NEXT_BREAKING_TYPEDOC_VERSION = semver.parse(TYPEDOC_VERSION)?.inc("minor"
if (!NEXT_BREAKING_TYPEDOC_VERSION) {
throw new Error("Failed to determine next TypeDoc version");
}
-console.log(NEXT_BREAKING_TYPEDOC_VERSION);
const CACHE_ROOT = "tmp/site-cache";
mkdirSync(CACHE_ROOT, { recursive: true });
diff --git a/scripts/rebuild_specs.js b/scripts/rebuild_specs.js
old mode 100644
new mode 100755
index cbdcba2dc..dd333c4a7
--- a/scripts/rebuild_specs.js
+++ b/scripts/rebuild_specs.js
@@ -1,3 +1,4 @@
+#!/usr/bin/env node
// @ts-check
"use strict";
diff --git a/scripts/testcase.js b/scripts/testcase.js
old mode 100644
new mode 100755
index 365bbe84d..2a5c0d744
--- a/scripts/testcase.js
+++ b/scripts/testcase.js
@@ -1,3 +1,4 @@
+#!/usr/bin/env node
// @ts-check
import md from "markdown-it";
import cp from "child_process";
diff --git a/site/options/configuration.md b/site/options/configuration.md
index 74c5da8fa..a96aa0859 100644
--- a/site/options/configuration.md
+++ b/site/options/configuration.md
@@ -106,3 +106,6 @@ typedoc --plugin ./custom-plugin.js
Specifies the plugins that should be loaded. By default, no plugins are loaded.
See [Plugins](../plugins.md) for a list of available plugins.
+
+If using a JavaScript configuration file, the `plugin` option may be given
+a function which will be called to load a plugin.
diff --git a/site/tags/sortStrategy.md b/site/tags/sortStrategy.md
index d68e1afcc..c795c08e0 100644
--- a/site/tags/sortStrategy.md
+++ b/site/tags/sortStrategy.md
@@ -4,7 +4,7 @@ title: "@sortStrategy"
# @sortStrategy
-**Tag Kind:** [Block](../tags.md#Block-tags)
+**Tag Kind:** [Block](../tags.md#block-tags)
This tag can be used to override the [sort](../options/organization.md#sort) locally
for a module, namespace, class, or interface. The override will be applied to direct
diff --git a/site/typedoc.config.jsonc b/site/typedoc.config.jsonc
index 48f0b91ae..ab9eca333 100644
--- a/site/typedoc.config.jsonc
+++ b/site/typedoc.config.jsonc
@@ -1,6 +1,7 @@
{
"$schema": "https://typedoc.org/schema.json",
"logLevel": "Verbose",
+ "treatWarningsAsErrors": true,
"entryPointStrategy": "merge",
"entryPoints": [],
diff --git a/src/index.ts b/src/index.ts
index 88fb52d87..166802605 100644
--- a/src/index.ts
+++ b/src/index.ts
@@ -139,6 +139,7 @@ export {
MinimalSourceFile,
type NormalizedPath,
type NormalizedPathOrModule,
+ type NormalizedPathOrModuleOrFunction,
type SymbolReference,
type TranslatedString,
translateTagName,
diff --git a/src/lib/application.ts b/src/lib/application.ts
index 779b3310a..68f3afb35 100644
--- a/src/lib/application.ts
+++ b/src/lib/application.ts
@@ -43,7 +43,6 @@ import { Outputs } from "./output/output.js";
import { validateMergeModuleWith } from "./validation/unusedMergeModuleWith.js";
import { diagnostic, diagnostics } from "./utils/loggers.js";
import { ValidatingFileRegistry } from "./utils/ValidatingFileRegistry.js";
-import { addInferredDeclarationMapPaths } from "./converter/factories/symbol-id.js";
import { Internationalization } from "./internationalization/internationalization.js";
const packageInfo = JSON.parse(
@@ -822,11 +821,6 @@ export class Application extends AbstractComponent<
continue;
}
- addInferredDeclarationMapPaths(
- opts.getCompilerOptions(),
- opts.getFileNames(),
- );
-
projectsToConvert.push({ dir, options: opts });
}
diff --git a/src/lib/converter/comments/blockLexer.ts b/src/lib/converter/comments/blockLexer.ts
index 7bd0bb5af..dae38840f 100644
--- a/src/lib/converter/comments/blockLexer.ts
+++ b/src/lib/converter/comments/blockLexer.ts
@@ -1,12 +1,15 @@
import ts from "typescript";
import { type Token, TokenSyntaxKind } from "./lexer.js";
import { resolveAliasedSymbol } from "../utils/symbols.js";
-import { createSymbolId } from "../factories/symbol-id.js";
+import type { Context } from "../context.js";
export function* lexBlockComment(
file: string,
pos = 0,
end = file.length,
+ createSymbolId: Context["createSymbolId"] = () => {
+ throw new Error("unreachable");
+ },
jsDoc: ts.JSDoc | undefined = undefined,
checker: ts.TypeChecker | undefined = undefined,
): Generator {
@@ -19,6 +22,7 @@ export function* lexBlockComment(
end,
getLinkTags(jsDoc),
checker,
+ createSymbolId,
)
) {
if (token.kind === TokenSyntaxKind.Text) {
@@ -82,6 +86,7 @@ function* lexBlockComment2(
ts.JSDocLink | ts.JSDocLinkCode | ts.JSDocLinkPlain
>,
checker: ts.TypeChecker | undefined,
+ createSymbolId: Context["createSymbolId"],
): Generator {
pos += 2; // Leading '/*'
end -= 2; // Trailing '*/'
@@ -263,7 +268,7 @@ function* lexBlockComment2(
if (lookahead !== pos + 1) {
while (
lookahead < end &&
- /[a-z0-9]/i.test(file[lookahead])
+ /[a-z0-9-]/i.test(file[lookahead])
) {
lookahead++;
}
diff --git a/src/lib/converter/comments/index.ts b/src/lib/converter/comments/index.ts
index 5828e711a..7b2b69db7 100644
--- a/src/lib/converter/comments/index.ts
+++ b/src/lib/converter/comments/index.ts
@@ -13,6 +13,7 @@ import { lexLineComments } from "./lineLexer.js";
import { parseComment } from "./parser.js";
import type { FileRegistry } from "../../models/FileRegistry.js";
import { assertNever, i18n, type Logger } from "#utils";
+import type { Context } from "../context.js";
export interface CommentParserConfig {
blockTags: Set;
@@ -24,6 +25,22 @@ export interface CommentParserConfig {
commentStyle: CommentStyle;
}
+export interface CommentContext {
+ config: CommentParserConfig;
+ logger: Logger;
+ checker: ts.TypeChecker;
+ files: FileRegistry;
+ createSymbolId: Context["createSymbolId"];
+}
+
+export interface CommentContextOptionalChecker {
+ config: CommentParserConfig;
+ logger: Logger;
+ checker?: ts.TypeChecker | undefined;
+ files: FileRegistry;
+ createSymbolId: Context["createSymbolId"];
+}
+
const jsDocCommentKinds = [
ts.SyntaxKind.JSDocPropertyTag,
ts.SyntaxKind.JSDocCallbackTag,
@@ -45,10 +62,7 @@ export function clearCommentCache() {
function getCommentWithCache(
discovered: DiscoveredComment | undefined,
- config: CommentParserConfig,
- logger: Logger,
- checker: ts.TypeChecker | undefined,
- files: FileRegistry,
+ context: CommentContextOptionalChecker,
) {
if (!discovered) return;
@@ -68,22 +82,19 @@ function getCommentWithCache(
file.text,
ranges[0].pos,
ranges[0].end,
+ context.createSymbolId,
jsDoc,
- checker,
+ context.checker,
),
- config,
file,
- logger,
- files,
+ context,
);
break;
case ts.SyntaxKind.SingleLineCommentTrivia:
comment = parseComment(
lexLineComments(file.text, ranges),
- config,
file,
- logger,
- files,
+ context,
);
break;
default:
@@ -100,18 +111,15 @@ function getCommentWithCache(
function getCommentImpl(
commentSource: DiscoveredComment | undefined,
- config: CommentParserConfig,
- logger: Logger,
moduleComment: boolean,
- checker: ts.TypeChecker | undefined,
- files: FileRegistry,
+ context: CommentContext,
) {
const comment = getCommentWithCache(
commentSource,
- config,
- logger,
- config.useTsLinkResolution ? checker : undefined,
- files,
+ {
+ ...context,
+ checker: context.config.useTsLinkResolution ? context.checker : undefined,
+ },
);
if (comment?.getTag("@import") || comment?.getTag("@license")) {
@@ -145,10 +153,7 @@ function getCommentImpl(
export function getComment(
symbol: ts.Symbol,
kind: ReflectionKind,
- config: CommentParserConfig,
- logger: Logger,
- checker: ts.TypeChecker,
- files: FileRegistry,
+ context: CommentContext,
): Comment | undefined {
const declarations = symbol.declarations || [];
@@ -158,16 +163,13 @@ export function getComment(
) {
return getJsDocComment(
declarations[0] as ts.JSDocPropertyLikeTag,
- config,
- logger,
- checker,
- files,
+ context,
);
}
const sf = declarations.find(ts.isSourceFile);
if (sf) {
- return getFileComment(sf, config, logger, checker, files);
+ return getFileComment(sf, context);
}
const isModule = declarations.some((decl) => {
@@ -181,25 +183,19 @@ export function getComment(
discoverComment(
symbol,
kind,
- logger,
- config.commentStyle,
- checker,
- !config.suppressCommentWarningsInDeclarationFiles,
+ context.logger,
+ context.config.commentStyle,
+ context.checker,
+ !context.config.suppressCommentWarningsInDeclarationFiles,
),
- config,
- logger,
isModule,
- checker,
- files,
+ context,
);
if (!comment && kind === ReflectionKind.Property) {
return getConstructorParamPropertyComment(
symbol,
- config,
- logger,
- checker,
- files,
+ context,
);
}
@@ -209,40 +205,28 @@ export function getComment(
export function getNodeComment(
node: ts.Node,
moduleComment: boolean,
- config: CommentParserConfig,
- logger: Logger,
- checker: ts.TypeChecker | undefined,
- files: FileRegistry,
+ context: CommentContext,
) {
return getCommentImpl(
- discoverNodeComment(node, config.commentStyle),
- config,
- logger,
+ discoverNodeComment(node, context.config.commentStyle),
moduleComment,
- checker,
- files,
+ context,
);
}
export function getFileComment(
file: ts.SourceFile,
- config: CommentParserConfig,
- logger: Logger,
- checker: ts.TypeChecker | undefined,
- files: FileRegistry,
+ context: CommentContext,
): Comment | undefined {
for (
const commentSource of discoverFileComments(
file,
- config.commentStyle,
+ context.config.commentStyle,
)
) {
const comment = getCommentWithCache(
commentSource,
- config,
- logger,
- config.useTsLinkResolution ? checker : undefined,
- files,
+ context,
);
if (comment?.getTag("@license") || comment?.getTag("@import")) {
@@ -261,16 +245,13 @@ export function getFileComment(
function getConstructorParamPropertyComment(
symbol: ts.Symbol,
- config: CommentParserConfig,
- logger: Logger,
- checker: ts.TypeChecker,
- files: FileRegistry,
+ context: CommentContext,
): Comment | undefined {
const decl = symbol.declarations?.find(ts.isParameter);
if (!decl) return;
const ctor = decl.parent;
- const comment = getSignatureComment(ctor, config, logger, checker, files);
+ const comment = getSignatureComment(ctor, context);
const paramTag = comment?.getIdentifiedTag(symbol.name, "@param");
if (paramTag) {
@@ -282,18 +263,12 @@ function getConstructorParamPropertyComment(
export function getSignatureComment(
declaration: ts.SignatureDeclaration | ts.JSDocSignature,
- config: CommentParserConfig,
- logger: Logger,
- checker: ts.TypeChecker,
- files: FileRegistry,
+ context: CommentContext,
): Comment | undefined {
return getCommentImpl(
- discoverSignatureComment(declaration, checker, config.commentStyle),
- config,
- logger,
+ discoverSignatureComment(declaration, context.checker, context.config.commentStyle),
false,
- checker,
- files,
+ context,
);
}
@@ -304,10 +279,7 @@ export function getJsDocComment(
| ts.JSDocTypedefTag
| ts.JSDocTemplateTag
| ts.JSDocEnumTag,
- config: CommentParserConfig,
- logger: Logger,
- checker: ts.TypeChecker | undefined,
- files: FileRegistry,
+ context: CommentContext,
): Comment | undefined {
const file = declaration.getSourceFile();
@@ -331,10 +303,7 @@ export function getJsDocComment(
jsDoc: parent,
inheritedFromParentDeclaration: false,
},
- config,
- logger,
- config.useTsLinkResolution ? checker : undefined,
- files,
+ context,
)!;
// And pull out the tag we actually care about.
@@ -352,7 +321,7 @@ export function getJsDocComment(
// We could just put the same comment on everything, but due to how comment parsing works,
// we'd have to search for any @template with a name starting with the first type parameter's name
// which feels horribly hacky.
- logger.warn(
+ context.logger.warn(
i18n.multiple_type_parameters_on_template_tag_unsupported(),
declaration,
);
@@ -378,7 +347,7 @@ export function getJsDocComment(
// was a comment attached. If there wasn't, then don't error about failing to find
// a tag because this is unsupported.
if (!ts.isJSDocTemplateTag(declaration)) {
- logger.error(
+ context.logger.error(
i18n.failed_to_find_jsdoc_tag_for_name_0(name),
declaration,
);
diff --git a/src/lib/converter/comments/lineLexer.ts b/src/lib/converter/comments/lineLexer.ts
index b7312f433..876494d77 100644
--- a/src/lib/converter/comments/lineLexer.ts
+++ b/src/lib/converter/comments/lineLexer.ts
@@ -179,7 +179,7 @@ function* lexLineComments2(
if (lookahead !== pos + 1) {
while (
lookahead < end &&
- /[a-z0-9]/i.test(file[lookahead])
+ /[a-z0-9-]/i.test(file[lookahead])
) {
lookahead++;
}
diff --git a/src/lib/converter/comments/parser.ts b/src/lib/converter/comments/parser.ts
index b95210555..cc016ab2b 100644
--- a/src/lib/converter/comments/parser.ts
+++ b/src/lib/converter/comments/parser.ts
@@ -1,6 +1,6 @@
import assert, { ok } from "assert";
import { parseDocument as parseYamlDoc } from "yaml";
-import type { CommentParserConfig } from "./index.js";
+import type { CommentContextOptionalChecker, CommentParserConfig } from "./index.js";
import { Comment, type CommentDisplayPart, CommentTag, type InlineTagDisplayPart } from "../../models/index.js";
import type { MinimalSourceFile } from "#utils";
import { nicePath } from "../../utils/paths.js";
@@ -62,10 +62,8 @@ function makeLookaheadGenerator(
export function parseComment(
tokens: Generator,
- config: CommentParserConfig,
file: MinimalSourceFile,
- logger: Logger,
- files: FileRegistry,
+ context: CommentContextOptionalChecker,
): Comment {
const lexer = makeLookaheadGenerator(tokens);
const tok = lexer.done() || lexer.peek();
@@ -75,15 +73,15 @@ export function parseComment(
comment.summary = blockContent(
comment,
lexer,
- config,
+ context.config,
i18n,
warningImpl,
- files,
+ context.files,
);
while (!lexer.done()) {
comment.blockTags.push(
- blockTag(comment, lexer, config, i18n, warningImpl, files),
+ blockTag(comment, lexer, context.config, i18n, warningImpl, context.files),
);
}
@@ -93,19 +91,19 @@ export function parseComment(
comment,
i18n,
() => `${nicePath(file.fileName)}:${file.getLineAndCharacterOfPosition(tok2.pos).line + 1}`,
- (message) => logger.warn(message),
+ (message) => context.logger.warn(message),
);
return comment;
function warningImpl(message: TranslatedString, token: Token) {
if (
- config.suppressCommentWarningsInDeclarationFiles &&
+ context.config.suppressCommentWarningsInDeclarationFiles &&
hasDeclarationFileExtension(file.fileName)
) {
return;
}
- logger.warn(message, token.pos, file);
+ context.logger.warn(message, token.pos, file);
}
}
diff --git a/src/lib/converter/comments/rawLexer.ts b/src/lib/converter/comments/rawLexer.ts
index e8bc8d6bc..ff063dc11 100644
--- a/src/lib/converter/comments/rawLexer.ts
+++ b/src/lib/converter/comments/rawLexer.ts
@@ -176,7 +176,7 @@ function* lexCommentString2(
if (lookahead !== pos + 1) {
while (
lookahead < end &&
- /[a-z0-9]/i.test(file[lookahead])
+ /[a-z0-9-]/i.test(file[lookahead])
) {
lookahead++;
}
diff --git a/src/lib/converter/comments/textParser.ts b/src/lib/converter/comments/textParser.ts
index 6277e9aa2..4078b7aef 100644
--- a/src/lib/converter/comments/textParser.ts
+++ b/src/lib/converter/comments/textParser.ts
@@ -136,9 +136,11 @@ export function textContent(
continue;
}
- const tagLink = checkTagLink(data);
- if (tagLink) {
- addRef(tagLink);
+ const tagLinks = checkTagLink(data);
+ if (tagLinks.length) {
+ for (const tagLink of tagLinks) {
+ addRef(tagLink);
+ }
continue;
}
@@ -256,7 +258,13 @@ function checkReference(data: TextParserData): RelativeLink | undefined {
while (/[ \t]/.test(token.text[lookahead])) {
++lookahead;
}
- if (token.text[lookahead] === "[") {
+ // #2991, we check that this reference also doesn't look like a footnote reference
+ // as it is unlikely that someone uses that syntax without intending for footnote behavior.
+ // This introduces a problem if someone has an [^ref] and doesn't intend for that to
+ // be interpreted as a footnote, but as a reference, but we can't have it both ways,
+ // and having people rename their reference to not be confused with a footnote isn't a
+ // horrible workaround.
+ if (token.text[lookahead] === "[" && token.text[lookahead + 1] !== "^") {
while (
lookahead < token.text.length &&
/[^\n\]]/.test(token.text[lookahead])
@@ -297,52 +305,152 @@ function checkReference(data: TextParserData): RelativeLink | undefined {
}
/**
- * Looks for `` and `
`
+ * Looks for ``, `
`, and ``
*/
-function checkTagLink(data: TextParserData): RelativeLink | undefined {
+function checkTagLink(data: TextParserData): RelativeLink[] {
const { pos, token } = data;
if (token.text.startsWith("
RelativeLink[]
+ >,
+): RelativeLink[] {
+ const links: RelativeLink[] = [];
const parser = new HtmlAttributeParser(data.token.text, data.pos);
while (parser.state !== ParserState.END) {
if (
parser.state === ParserState.BeforeAttributeValue &&
- parser.currentAttributeName === attr
+ Object.prototype.hasOwnProperty.call(attributes, parser.currentAttributeName)
) {
parser.step();
- if (isRelativePath(parser.currentAttributeValue)) {
- data.pos = parser.pos;
- const { target, anchor } = data.files.register(
- data.sourcePath,
- parser.currentAttributeValue as NormalizedPath,
- ) || { target: undefined, anchor: undefined };
- return {
- pos: parser.currentAttributeValueStart,
- end: parser.currentAttributeValueEnd,
- target,
- targetAnchor: anchor,
- };
- }
- return;
+ links.push(...attributes[parser.currentAttributeName](
+ data,
+ parser.currentAttributeValue,
+ parser.currentAttributeValueStart,
+ parser.currentAttributeValueEnd,
+ ));
}
parser.step();
}
+
+ return links;
+}
+
+function checkAttributeDirectPath(
+ data: TextParserData,
+ text: string,
+ pos: number,
+ end: number,
+): RelativeLink[] {
+ if (isRelativePath(text.trim())) {
+ const { target, anchor } = data.files.register(
+ data.sourcePath,
+ text.trim() as NormalizedPath,
+ ) || { target: undefined, anchor: undefined };
+ return [{
+ pos,
+ end,
+ target,
+ targetAnchor: anchor,
+ }];
+ }
+
+ return [];
+}
+
+// See https://html.spec.whatwg.org/multipage/images.html#srcset-attribute
+function checkAttributeSrcSet(data: TextParserData, text: string, pos: number, _end: number): RelativeLink[] {
+ const result: RelativeLink[] = [];
+
+ let textPos = 0;
+ parseImageCandidate();
+ while (textPos < text.length && text[textPos] == ",") {
+ ++textPos;
+ parseImageCandidate();
+ }
+
+ return result;
+
+ function parseImageCandidate() {
+ // 1. Zero or more ASCII whitespace
+ while (textPos < text.length && /[\t\r\f\n ]/.test(text[textPos])) ++textPos;
+ // 2. A valid non-empty URL that does not start or end with a comma
+ // TypeDoc: We don't exactly match this, PR welcome! For now, just permit anything
+ // that's not whitespace or a comma
+ const url = text.slice(textPos).match(/^[^\t\r\f\n ,]+/);
+
+ if (url && isRelativePath(url[0])) {
+ const { target, anchor } = data.files.register(
+ data.sourcePath,
+ url[0] as NormalizedPath,
+ ) || { target: undefined, anchor: undefined };
+ result.push({
+ pos: pos + textPos,
+ end: pos + textPos + url[0].length,
+ target,
+ targetAnchor: anchor,
+ });
+ }
+ textPos += url ? url[0].length : 0;
+
+ // 3. Zero or more ASCII whitespace
+ while (textPos < text.length && /[\t\r\f\n ]/.test(text[textPos])) ++textPos;
+
+ // 4. Zero or one of the following:
+ {
+ // A width descriptor, consisting of: ASCII whitespace, a valid non-negative integer giving
+ // a number greater than zero representing the width descriptor value, and a U+0077 LATIN
+ // SMALL LETTER W character.
+ const w = text.slice(textPos).match(/^\+?\d+\s*w/);
+ textPos += w ? w[0].length : 0;
+
+ // A pixel density descriptor, consisting of: ASCII whitespace, a valid floating-point number
+ // giving a number greater than zero representing the pixel density descriptor value, and a
+ // U+0078 LATIN SMALL LETTER X character.
+ if (!w) {
+ const x = text.slice(textPos).match(/^\+?\d+(\.\d+)?([eE][+-]\d+)?\s*x/);
+ textPos += x ? x[0].length : 0;
+ }
+ }
+
+ // 5. Zero or more ASCII whitespace
+ while (textPos < text.length && /[\t\r\f\n ]/.test(text[textPos])) ++textPos;
+ }
}
function isRelativePath(link: string) {
diff --git a/src/lib/converter/context.ts b/src/lib/converter/context.ts
index f2df66df1..7f5697164 100644
--- a/src/lib/converter/context.ts
+++ b/src/lib/converter/context.ts
@@ -17,10 +17,17 @@ import type { Converter } from "./converter.js";
import { isNamedNode } from "./utils/nodes.js";
import { ConverterEvents } from "./converter-events.js";
import { resolveAliasedSymbol } from "./utils/symbols.js";
-import { getComment, getFileComment, getJsDocComment, getNodeComment, getSignatureComment } from "./comments/index.js";
+import {
+ type CommentContext,
+ getComment,
+ getFileComment,
+ getJsDocComment,
+ getNodeComment,
+ getSignatureComment,
+} from "./comments/index.js";
import { getHumanName, getQualifiedName } from "../utils/tsutils.js";
import { findPackageForPath, normalizePath } from "#node-utils";
-import { createSymbolId } from "./factories/symbol-id.js";
+import { createSymbolIdImpl } from "./factories/symbol-id.js";
import { type NormalizedPath, removeIf } from "#utils";
/**
@@ -267,7 +274,7 @@ export class Context {
): ReferenceType {
const ref = ReferenceType.createUnresolvedReference(
name ?? symbol.name,
- createSymbolId(symbol),
+ this.createSymbolId(symbol),
context.project,
getQualifiedName(symbol, name ?? symbol.name),
);
@@ -282,6 +289,18 @@ export class Context {
return ref;
}
+ /**
+ * Create a stable {@link ReflectionSymbolId} for the provided symbol,
+ * optionally targeting a specific declaration.
+ *
+ * @privateRemarks
+ * This is available on Context so that it can be monkey-patched by typedoc-plugin-missing-exports
+ * It might also turn out to be generally useful for other plugin users.
+ */
+ createSymbolId(symbol: ts.Symbol, declaration?: ts.Declaration) {
+ return createSymbolIdImpl(symbol, declaration);
+ }
+
addChild(reflection: DeclarationReflection | DocumentReflection) {
if (this.scope instanceof ContainerReflection) {
this.scope.addChild(reflection);
@@ -302,7 +321,7 @@ export class Context {
registerReflection(reflection: Reflection, symbol: ts.Symbol | undefined, filePath?: NormalizedPath) {
if (symbol) {
this.reflectionIdToSymbolMap.set(reflection.id, symbol);
- const id = createSymbolId(symbol);
+ const id = this.createSymbolId(symbol);
// #2466
// If we just registered a member of a class or interface, then we need to check if
@@ -339,7 +358,7 @@ export class Context {
}
getReflectionFromSymbol(symbol: ts.Symbol) {
- return this.project.getReflectionFromSymbolId(createSymbolId(symbol));
+ return this.project.getReflectionFromSymbolId(this.createSymbolId(symbol));
}
getSymbolFromReflection(reflection: Reflection) {
@@ -351,14 +370,21 @@ export class Context {
this._program = program;
}
+ private createCommentContext(): CommentContext {
+ return {
+ config: this.converter.config,
+ logger: this.logger,
+ checker: this.checker,
+ files: this.project.files,
+ createSymbolId: (s, d) => this.createSymbolId(s, d),
+ };
+ }
+
getComment(symbol: ts.Symbol, kind: ReflectionKind) {
return getComment(
symbol,
kind,
- this.converter.config,
- this.logger,
- this.checker,
- this.project.files,
+ this.createCommentContext(),
);
}
@@ -366,20 +392,14 @@ export class Context {
return getNodeComment(
node,
moduleComment,
- this.converter.config,
- this.logger,
- this.checker,
- this.project.files,
+ this.createCommentContext(),
);
}
getFileComment(node: ts.SourceFile) {
return getFileComment(
node,
- this.converter.config,
- this.logger,
- this.checker,
- this.project.files,
+ this.createCommentContext(),
);
}
@@ -393,10 +413,7 @@ export class Context {
) {
return getJsDocComment(
declaration,
- this.converter.config,
- this.logger,
- this.checker,
- this.project.files,
+ this.createCommentContext(),
);
}
@@ -405,10 +422,7 @@ export class Context {
) {
return getSignatureComment(
declaration,
- this.converter.config,
- this.logger,
- this.checker,
- this.project.files,
+ this.createCommentContext(),
);
}
diff --git a/src/lib/converter/converter.ts b/src/lib/converter/converter.ts
index 5e6b43615..296d2c0cb 100644
--- a/src/lib/converter/converter.ts
+++ b/src/lib/converter/converter.ts
@@ -36,7 +36,7 @@ import {
unique,
} from "#utils";
import type { DocumentationEntryPoint } from "../utils/entry-point.js";
-import type { CommentParserConfig } from "./comments/index.js";
+import { clearCommentCache, type CommentParserConfig } from "./comments/index.js";
import type { CommentStyle, ValidationOptions } from "../utils/options/declaration.js";
import { parseCommentString } from "./comments/parser.js";
import { lexCommentString } from "./comments/rawLexer.js";
@@ -343,6 +343,10 @@ export class Converter extends AbstractComponent {
delete this.excludeCache;
delete this.externalPatternCache;
+ // Also clear the comment cache so if we convert this ts.Program again
+ // later we will re-parse comments.
+ clearCommentCache();
+
return project;
}
diff --git a/src/lib/converter/factories/signature.ts b/src/lib/converter/factories/signature.ts
index 8bc9727bc..f3dc84e0a 100644
--- a/src/lib/converter/factories/signature.ts
+++ b/src/lib/converter/factories/signature.ts
@@ -17,7 +17,6 @@ import type { Context } from "../context.js";
import { ConverterEvents } from "../converter-events.js";
import { convertDefaultValue } from "../convert-expression.js";
import { removeUndefined } from "../utils/reflections.js";
-import { createSymbolId } from "./symbol-id.js";
export function createSignature(
context: Context,
@@ -51,7 +50,7 @@ export function createSignature(
if (symbol && declaration) {
context.project.registerSymbolId(
sigRef,
- createSymbolId(symbol, declaration),
+ context.createSymbolId(symbol, declaration),
);
}
diff --git a/src/lib/converter/factories/symbol-id.ts b/src/lib/converter/factories/symbol-id.ts
index d74964250..75c45cdfe 100644
--- a/src/lib/converter/factories/symbol-id.ts
+++ b/src/lib/converter/factories/symbol-id.ts
@@ -1,16 +1,14 @@
import { ReflectionSymbolId } from "#models";
-import { findPackageForPath, getCommonDirectory, getQualifiedName, normalizePath, readFile } from "#node-utils";
-import { type NormalizedPath, Validation } from "#utils";
-import { existsSync } from "fs";
-import { join, relative, resolve } from "node:path";
+import { findPackageForPath, getQualifiedName, normalizePath, resolveDeclarationMaps } from "#node-utils";
+import { type NormalizedPath } from "#utils";
+import { relative } from "node:path";
import ts from "typescript";
-const declarationMapCache = new Map();
-
let transientCount = 0;
const transientIds = new WeakMap();
-export function createSymbolId(symbol: ts.Symbol, declaration?: ts.Declaration) {
+// Don't use this directly, use Context.createSymbolId instead.
+export function createSymbolIdImpl(symbol: ts.Symbol, declaration?: ts.Declaration) {
declaration ??= symbol.declarations?.[0];
const tsSource = declaration?.getSourceFile().fileName ?? "";
const sourceFileName = resolveDeclarationMaps(tsSource);
@@ -50,66 +48,3 @@ export function createSymbolId(symbol: ts.Symbol, declaration?: ts.Declaration)
return id;
}
-
-function resolveDeclarationMaps(file: string): string {
- if (!/\.d\.[cm]?ts$/.test(file)) return file;
- if (declarationMapCache.has(file)) return declarationMapCache.get(file)!;
-
- const mapFile = file + ".map";
- if (!existsSync(mapFile)) return file;
-
- let sourceMap: unknown;
- try {
- sourceMap = JSON.parse(readFile(mapFile)) as unknown;
- } catch {
- return file;
- }
-
- if (
- Validation.validate(
- {
- file: String,
- sourceRoot: Validation.optional(String),
- sources: [Array, String],
- },
- sourceMap,
- )
- ) {
- // There's a pretty large assumption in here that we only have
- // 1 source file per js file. This is a pretty standard typescript approach,
- // but people might do interesting things with transpilation that could break this.
- let source = sourceMap.sources[0];
-
- // If we have a sourceRoot, trim any leading slash from the source, and join them
- // Similar to how it's done at https://github.com/mozilla/source-map/blob/58819f09018d56ef84dc41ba9c93f554e0645169/lib/util.js#L412
- if (sourceMap.sourceRoot !== undefined) {
- source = source.replace(/^\//, "");
- source = join(sourceMap.sourceRoot, source);
- }
-
- const result = resolve(mapFile, "..", source);
- declarationMapCache.set(file, result);
- return result;
- }
-
- return file;
-}
-
-// See also: inferEntryPoints in entry-point.ts
-export function addInferredDeclarationMapPaths(
- opts: ts.CompilerOptions,
- files: readonly string[],
-) {
- const rootDir = opts.rootDir || getCommonDirectory(files);
- const declDir = opts.declarationDir || opts.outDir || rootDir;
-
- for (const file of files) {
- const mapFile = normalizePath(
- resolve(declDir, relative(rootDir, file)).replace(
- /\.([cm]?[tj]s)x?$/,
- ".d.$1",
- ),
- );
- declarationMapCache.set(mapFile, file);
- }
-}
diff --git a/src/lib/converter/jsdoc.ts b/src/lib/converter/jsdoc.ts
index 53836f906..ca9be368e 100644
--- a/src/lib/converter/jsdoc.ts
+++ b/src/lib/converter/jsdoc.ts
@@ -14,7 +14,6 @@ import {
import type { Context } from "./context.js";
import { ConverterEvents } from "./converter-events.js";
import { convertParameterNodes, convertTemplateParameterNodes } from "./factories/signature.js";
-import { createSymbolId } from "./factories/symbol-id.js";
export function convertJsDocAlias(
context: Context,
@@ -134,7 +133,7 @@ function convertJsDocSignature(context: Context, node: ts.JSDocSignature) {
);
context.project.registerSymbolId(
signature,
- createSymbolId(symbol, node),
+ context.createSymbolId(symbol, node),
);
context.registerReflection(signature, void 0);
const signatureCtx = rc.withScope(signature);
diff --git a/src/lib/converter/plugins/ImplementsPlugin.ts b/src/lib/converter/plugins/ImplementsPlugin.ts
index c79215ed9..cab484371 100644
--- a/src/lib/converter/plugins/ImplementsPlugin.ts
+++ b/src/lib/converter/plugins/ImplementsPlugin.ts
@@ -110,8 +110,10 @@ export class ImplementsPlugin extends ConverterComponent {
project: ProjectReflection,
reflection: DeclarationReflection,
) {
+ if (!reflection.extendedTypes) return;
+
const extendedTypes = filterMap(
- reflection.extendedTypes ?? [],
+ reflection.extendedTypes,
(type) => {
return type instanceof ReferenceType &&
type.reflection instanceof DeclarationReflection
@@ -139,23 +141,59 @@ export class ImplementsPlugin extends ConverterComponent {
parentMember.signatures ?? [],
)
) {
- childSig[key] = ReferenceType.createResolvedReference(
+ // If we're already pointing at something because TS said we should reference
+ // it, then don't overwrite the reference.
+ if (!childSig[key]?.reflection) {
+ childSig[key] = ReferenceType.createResolvedReference(
+ `${parent.name}.${parentMember.name}`,
+ parentSig,
+ project,
+ );
+ }
+ }
+
+ if (!child[key]?.reflection) {
+ child[key] = ReferenceType.createResolvedReference(
`${parent.name}.${parentMember.name}`,
- parentSig,
+ parentMember,
project,
);
}
- child[key] = ReferenceType.createResolvedReference(
- `${parent.name}.${parentMember.name}`,
- parentMember,
- project,
- );
-
this.handleInheritedComments(child, parentMember);
}
}
}
+
+ // #2978, this is very unfortunate. If a child's parent links are broken at this point,
+ // we replace them with an intentionally broken link so that they won't ever be resolved.
+ // This is done because if we don't do it then we run into issues where we have a link which
+ // points to some ReflectionSymbolId which might not exist now, but once we've gone through
+ // serialization/deserialization, might point to an unexpected location. (See the mixin
+ // converter tests, I suspect this might actually be an indication of something else slightly
+ // broken there, but don't want to spend more time with this right now.)
+ // #2982, even more unfortunately, we only want to keep the link if it is pointing to a reflection
+ // which will receive a link during rendering.
+ const isValidRef = (ref: ReferenceType) =>
+ ref.reflection && !ref.reflection.parent?.kindOf(ReflectionKind.TypeLiteral);
+
+ for (const child of reflection.children || []) {
+ if (child.inheritedFrom && !isValidRef(child.inheritedFrom)) {
+ child.inheritedFrom = ReferenceType.createBrokenReference(child.inheritedFrom.name, project);
+ }
+ if (child.overwrites && !isValidRef(child.overwrites)) {
+ child.overwrites = ReferenceType.createBrokenReference(child.overwrites.name, project);
+ }
+
+ for (const childSig of child.getAllSignatures()) {
+ if (childSig.inheritedFrom && !isValidRef(childSig.inheritedFrom)) {
+ childSig.inheritedFrom = ReferenceType.createBrokenReference(childSig.inheritedFrom.name, project);
+ }
+ if (childSig.overwrites && !isValidRef(childSig.overwrites)) {
+ childSig.overwrites = ReferenceType.createBrokenReference(childSig.overwrites.name, project);
+ }
+ }
+ }
}
private onResolveEnd(context: Context) {
@@ -522,9 +560,21 @@ function createLink(
symbol: ts.Symbol,
isInherit: boolean,
) {
- const project = context.project;
const name = `${expr.expression.getText()}.${getHumanName(symbol.name)}`;
+ // We should always have rootSymbols, but check just in case. We use the first
+ // symbol here as TypeDoc's models don't have multiple symbols for the parent
+ // reference. This is technically wrong because symbols might be declared in
+ // multiple locations (interface declaration merging), but that's an uncommon
+ // enough use case that it doesn't seem worthwhile to complicate the rest of the
+ // world to deal with it.
+ // Note that we also need to check that the root symbol isn't this symbol.
+ // This seems to happen sometimes when dealing with interface inheritance.
+ const rootSymbols = context.checker.getRootSymbols(symbol);
+ const ref = rootSymbols.length && rootSymbols[0] != symbol
+ ? context.createSymbolReference(rootSymbols[0], context, name)
+ : ReferenceType.createBrokenReference(name, context.project);
+
link(reflection);
link(reflection.getSignature);
link(reflection.setSignature);
@@ -535,34 +585,21 @@ function createLink(
link(sig);
}
- // Intentionally create broken links here. These will be replaced with real links during
- // resolution if we can do so. We create broken links rather than real links because in the
- // case of an inherited symbol, we'll end up referencing a single symbol ID rather than one
- // for each class.
function link(
target: DeclarationReflection | SignatureReflection | undefined,
) {
if (!target) return;
if (clause.token === ts.SyntaxKind.ImplementsKeyword) {
- target.implementationOf ??= ReferenceType.createBrokenReference(
- name,
- project,
- );
+ target.implementationOf ??= ref;
return;
}
if (isInherit) {
target.setFlag(ReflectionFlag.Inherited);
- target.inheritedFrom ??= ReferenceType.createBrokenReference(
- name,
- project,
- );
+ target.inheritedFrom ??= ref;
} else {
- target.overwrites ??= ReferenceType.createBrokenReference(
- name,
- project,
- );
+ target.overwrites ??= ref;
}
}
}
diff --git a/src/lib/converter/plugins/PackagePlugin.ts b/src/lib/converter/plugins/PackagePlugin.ts
index 8dbe44b41..5225e910b 100644
--- a/src/lib/converter/plugins/PackagePlugin.ts
+++ b/src/lib/converter/plugins/PackagePlugin.ts
@@ -8,9 +8,9 @@ import { ConverterEvents } from "../converter-events.js";
import type { Converter } from "../converter.js";
import { type GlobString, i18n, MinimalSourceFile, type NormalizedPath, NormalizedPathUtils } from "#utils";
import {
+ deriveRootDir,
discoverPackageJson,
type EntryPointStrategy,
- getCommonDirectory,
nicePath,
normalizePath,
Option,
@@ -79,7 +79,7 @@ export class PackagePlugin extends ConverterComponent {
this.packageJson = undefined;
const dirName = this.application.options.packageDir ??
- Path.resolve(getCommonDirectory(this.entryPoints.map(g => `${g}/`)));
+ Path.resolve(deriveRootDir(this.entryPoints));
this.application.logger.verbose(
`Begin package.json search at ${nicePath(dirName)}`,
diff --git a/src/lib/converter/types.ts b/src/lib/converter/types.ts
index f8b8764ab..56a08bafb 100644
--- a/src/lib/converter/types.ts
+++ b/src/lib/converter/types.ts
@@ -35,7 +35,6 @@ import { convertParameterNodes, convertTypeParameterNodes, createSignature } fro
import { convertSymbol } from "./symbols.js";
import { isObjectType, isTypeReference } from "./utils/nodes.js";
import { removeUndefined } from "./utils/reflections.js";
-import { createSymbolId } from "./factories/symbol-id.js";
export interface TypeConverter<
TNode extends ts.TypeNode = ts.TypeNode,
@@ -277,7 +276,7 @@ const constructorConverter: TypeConverter = {
}
context.project.registerSymbolId(
signature,
- createSymbolId(symbol, node),
+ context.createSymbolId(symbol, node),
);
context.registerReflection(signature, void 0);
const signatureCtx = rc.withScope(signature);
@@ -380,7 +379,7 @@ const functionTypeConverter: TypeConverter = {
);
context.project.registerSymbolId(
signature,
- createSymbolId(symbol, node),
+ context.createSymbolId(symbol, node),
);
context.registerReflection(signature, undefined);
const signatureCtx = rc.withScope(signature);
diff --git a/src/lib/internationalization/locales/en.cts b/src/lib/internationalization/locales/en.cts
index 3c0a45ade..703f37664 100644
--- a/src/lib/internationalization/locales/en.cts
+++ b/src/lib/internationalization/locales/en.cts
@@ -414,6 +414,7 @@ export = {
favicon_must_have_one_of_the_following_extensions_0: "Favicon must have one of the following extensions: {0}",
option_0_must_be_an_object: "The '{0}' option must be a non-array object",
option_0_must_be_an_array_of_string: "The '{0}' option must be set to an array of strings",
+ option_0_must_be_an_array_of_string_or_functions: "The '{0}' option must be set to an array of strings/functions",
option_0_must_be_a_function: "The '{0}' option must be a function",
option_0_must_be_object_with_urls: `{0} must be an object with string labels as keys and URL values`,
visibility_filters_only_include_0: `visibilityFilters can only include the following non-@ keys: {0}`,
diff --git a/src/lib/internationalization/locales/zh.cts b/src/lib/internationalization/locales/zh.cts
index 9250ad7e9..5a0293423 100644
--- a/src/lib/internationalization/locales/zh.cts
+++ b/src/lib/internationalization/locales/zh.cts
@@ -79,6 +79,8 @@ export = localeUtils.buildIncompleteTranslation({
inline_tag_not_closed: "内联标签未关闭",
// validation
+ comment_for_0_links_to_1_not_included_in_docs_use_external_link_2:
+ `{0} 注释中指向 “{1}” 的已解析的链接不会被包含在文档中。请将 {2} 导出或添加至 externalSymbolLinkMappings 选项以修复该警告`,
failed_to_resolve_link_to_0_in_comment_for_1: "无法解析 {1} 注释中指向 “{0}” 的链接",
failed_to_resolve_link_to_0_in_comment_for_1_may_have_meant_2:
"无法解析 {1} 的注释中指向 “{0}” 的链接。您可能想要 “{2}”",
@@ -103,9 +105,11 @@ export = localeUtils.buildIncompleteTranslation({
"文档中并未使用 searchCategoryBoosts 中指定的所有类别。未使用的类别包括:\n{0}",
not_all_search_group_boosts_used_0: "文档中并未使用 searchGroupBoosts 中指定的所有组。未使用的组为:\n{0}",
comment_for_0_includes_categoryDescription_for_1_but_no_child_in_group:
- "{0} 的评论包含“{1}”的 @categoryDescription,但该类别中没有子项",
+ "{0} 的注释中包含了 “{1}” 的 @categoryDescription,但该类别中没有子项",
comment_for_0_includes_groupDescription_for_1_but_no_child_in_group:
- "{0} 的注释包含“{1}”的 @groupDescription,但该组中没有子项",
+ "{0} 的注释中包含了 “{1}” 的 @groupDescription,但该分组中没有子项",
+ comment_for_0_specifies_1_as_sort_strategy_but_only_2_is_valid:
+ `{0} 的注释中指定的 “{1}” 的 @sortStrategy 无效,以下是有效的选项:\n\t{2}`,
label_0_for_1_cannot_be_referenced:
"无法使用声明引用来引用 {1} 的标签“{0}”。标签只能包含 A-Z、0-9 和 _,并且不能以数字开头",
modifier_tag_0_is_mutually_exclusive_with_1_in_comment_for_2: "修饰符标签 {0} 与 {2} 注释中的 {1} 互斥",
@@ -187,6 +191,8 @@ export = localeUtils.buildIncompleteTranslation({
circular_reference_extends_0: "{0} 的“extends”字段出现循环引用",
failed_resolve_0_to_file_in_1: "无法将 {0} 解析为 {1} 中的文件",
+ glob_0_should_use_posix_slash:
+ `该 glob “{0}” 中转义了不是特殊字符的字符。输入 TypeDoc 的 glob 可能不会使用 Windows 路径分隔符(\\),请尝试将其替换为 POSIX 路径分隔符(/)`,
option_0_can_only_be_specified_by_config_file: "“{0}”选项只能通过配置文件指定",
option_0_expected_a_value_but_none_provided: "--{0} 需要一个值,但没有给出任何参数",
unknown_option_0_may_have_meant_1: "未知选项:{0},你可能指的是:\n\t{1}",
@@ -348,6 +354,8 @@ export = localeUtils.buildIncompleteTranslation({
"useHostedBaseUrlForAbsoluteLinks 选项要求设置 hostingBaseUrl",
favicon_must_have_one_of_the_following_extensions_0: "favicon 的后缀名必须是下列之一:{0}",
option_0_must_be_an_object: "“{0}”选项必须是非数组对象",
+ option_0_must_be_an_array_of_string: "“{0}”选项必须是字符串数组",
+ option_0_must_be_an_array_of_string_or_functions: "“{0}”选项必须是由字符串或函数构成的数组",
option_0_must_be_a_function: "‘{0}’ 选项必须是一个函数",
option_0_must_be_object_with_urls: "{0} 必须是具有字符串标签作为键和 URL 值的对象",
visibility_filters_only_include_0: "visibilityFilters 只能包含以下非@键:{0}",
@@ -514,6 +522,7 @@ export = localeUtils.buildIncompleteTranslation({
tag_return: "返回",
tag_satisfies: "满足",
tag_since: "添加于",
+ tag_sortStrategy: "排序策略",
tag_template: "类型参数",
tag_type: "类型",
tag_typedef: "类型定义",
@@ -545,6 +554,7 @@ export = localeUtils.buildIncompleteTranslation({
tag_virtual: "虚函数",
tag_abstract: "抽象类",
tag_class: "类",
+ tag_disableGroups: "禁用分组",
tag_enum: "枚举",
tag_event: "事件",
tag_expand: "展开",
diff --git a/src/lib/models/ProjectReflection.ts b/src/lib/models/ProjectReflection.ts
index 4a6ebaa0a..bc9fd66a5 100644
--- a/src/lib/models/ProjectReflection.ts
+++ b/src/lib/models/ProjectReflection.ts
@@ -10,7 +10,15 @@ import { ReflectionKind } from "./kind.js";
import { Comment, type CommentDisplayPart } from "./Comment.js";
import { ReflectionSymbolId } from "./ReflectionSymbolId.js";
import type { Deserializer, JSONOutput, Serializer } from "#serialization";
-import { assertNever, DefaultMap, i18n, type NormalizedPath, removeIfPresent, StableKeyMap } from "#utils";
+import {
+ assertNever,
+ DefaultMap,
+ i18n,
+ NonEnumerable,
+ type NormalizedPath,
+ removeIfPresent,
+ StableKeyMap,
+} from "#utils";
import type { DocumentReflection } from "./DocumentReflection.js";
import type { FileRegistry } from "./FileRegistry.js";
@@ -28,18 +36,24 @@ export class ProjectReflection extends ContainerReflection {
readonly variant = "project";
// Used to resolve references.
+ @NonEnumerable
private symbolToReflectionIdMap: Map<
ReflectionSymbolId,
number | number[]
> = new StableKeyMap();
+ @NonEnumerable
private reflectionIdToSymbolIdMap = new Map();
+ @NonEnumerable
private removedSymbolIds = new StableKeyMap();
// Maps a reflection ID to all references eventually referring to it.
+ @NonEnumerable
private referenceGraph?: Map;
+
// Maps a reflection ID to all reflections with it as their parent.
+ @NonEnumerable
private reflectionChildren = new DefaultMap(() => []);
/**
@@ -49,6 +63,7 @@ export class ProjectReflection extends ContainerReflection {
*
* This may be replaced with a `Map` someday.
*/
+ @NonEnumerable
reflections: { [id: number]: Reflection } = {};
/**
diff --git a/src/lib/output/themes/default/partials/moduleReflection.tsx b/src/lib/output/themes/default/partials/moduleReflection.tsx
index fb358841b..31418441d 100644
--- a/src/lib/output/themes/default/partials/moduleReflection.tsx
+++ b/src/lib/output/themes/default/partials/moduleReflection.tsx
@@ -75,7 +75,7 @@ export function moduleMemberSummary(
context: DefaultThemeRenderContext,
member: DeclarationReflection | DocumentReflection,
) {
- const id = context.slugger.slug(member.name);
+ const id = member.isReference() ? context.getAnchor(member)! : context.slugger.slug(member.name);
context.page.pageHeadings.push({
link: `#${id}`,
text: getDisplayName(member),
diff --git a/src/lib/serialization/schema.ts b/src/lib/serialization/schema.ts
index 1db8459f5..34debec86 100644
--- a/src/lib/serialization/schema.ts
+++ b/src/lib/serialization/schema.ts
@@ -58,6 +58,7 @@ type _ModelToObject =
T extends M.CommentDisplayPart ? CommentDisplayPart :
T extends M.SourceReference ? SourceReference :
T extends M.FileRegistry ? FileRegistry :
+ T extends M.ReflectionSymbolId ? ReflectionSymbolId :
never;
type Primitive = string | number | undefined | null | boolean;
diff --git a/src/lib/utils-common/path.ts b/src/lib/utils-common/path.ts
index 507846a51..feec89110 100644
--- a/src/lib/utils-common/path.ts
+++ b/src/lib/utils-common/path.ts
@@ -1,5 +1,9 @@
import { assert } from "./general.js";
+// Type only import is permitted
+// eslint-disable-next-line no-restricted-imports
+import type { Application } from "../application.js";
+
/**
* Represents a normalized path with path separators being `/`
* On Windows, drives are represented like `C:/Users` for consistency
@@ -15,6 +19,12 @@ export type NormalizedPath = "" | "/" | string & { readonly __normPath: unique s
*/
export type NormalizedPathOrModule = NormalizedPath | string & { readonly __normPathOrModule: unique symbol };
+/**
+ * Represents either a {@link NormalizedPath} or a Node module name
+ * (e.g. `typedoc-plugin-mdn-links` or `@gerrit0/typedoc-plugin`)
+ */
+export type NormalizedPathOrModuleOrFunction = NormalizedPathOrModule | ((app: Application) => Promise | void);
+
/**
* Represents a glob path configured by a user.
*/
diff --git a/src/lib/utils-common/validation.ts b/src/lib/utils-common/validation.ts
index 8febb48d6..eca8886d9 100644
--- a/src/lib/utils-common/validation.ts
+++ b/src/lib/utils-common/validation.ts
@@ -120,5 +120,5 @@ export function optional(x: T): Optional {
}
export function isTagString(x: unknown): x is `@${string}` {
- return typeof x === "string" && /^@[a-zA-Z][a-zA-Z0-9]*$/.test(x);
+ return typeof x === "string" && /^@[a-z][a-z0-9-]*$/i.test(x);
}
diff --git a/src/lib/utils/declaration-maps.ts b/src/lib/utils/declaration-maps.ts
new file mode 100644
index 000000000..a6183d6f7
--- /dev/null
+++ b/src/lib/utils/declaration-maps.ts
@@ -0,0 +1,71 @@
+import type ts from "typescript";
+import { existsSync } from "fs";
+import { readFile } from "./fs.js";
+import { Validation } from "#utils";
+import { join, relative, resolve } from "path";
+import { getCommonDirectory, normalizePath } from "./paths.js";
+
+const declarationMapCache = new Map();
+
+export function resolveDeclarationMaps(file: string): string {
+ if (!/\.d\.[cm]?ts$/.test(file)) return file;
+ if (declarationMapCache.has(file)) return declarationMapCache.get(file)!;
+
+ const mapFile = file + ".map";
+ if (!existsSync(mapFile)) return file;
+
+ let sourceMap: unknown;
+ try {
+ sourceMap = JSON.parse(readFile(mapFile)) as unknown;
+ } catch {
+ return file;
+ }
+
+ if (
+ Validation.validate(
+ {
+ file: String,
+ sourceRoot: Validation.optional(String),
+ sources: [Array, String],
+ },
+ sourceMap,
+ )
+ ) {
+ // There's a pretty large assumption in here that we only have
+ // 1 source file per js file. This is a pretty standard typescript approach,
+ // but people might do interesting things with transpilation that could break this.
+ let source = sourceMap.sources[0];
+
+ // If we have a sourceRoot, trim any leading slash from the source, and join them
+ // Similar to how it's done at https://github.com/mozilla/source-map/blob/58819f09018d56ef84dc41ba9c93f554e0645169/lib/util.js#L412
+ if (sourceMap.sourceRoot !== undefined) {
+ source = source.replace(/^\//, "");
+ source = join(sourceMap.sourceRoot, source);
+ }
+
+ const result = resolve(mapFile, "..", source);
+ declarationMapCache.set(file, result);
+ return result;
+ }
+
+ return file;
+}
+
+// See also: inferEntryPoints in entry-point.ts
+export function addInferredDeclarationMapPaths(
+ opts: ts.CompilerOptions,
+ files: readonly string[],
+) {
+ const rootDir = opts.rootDir || getCommonDirectory(files);
+ const declDir = opts.declarationDir || opts.outDir || rootDir;
+
+ for (const file of files) {
+ const mapFile = normalizePath(
+ resolve(declDir, relative(rootDir, file)).replace(
+ /\.([cm]?[tj]s)x?$/,
+ ".d.$1",
+ ),
+ );
+ declarationMapCache.set(mapFile, file);
+ }
+}
diff --git a/src/lib/utils/entry-point.ts b/src/lib/utils/entry-point.ts
index 4a28627e1..0e1aca810 100644
--- a/src/lib/utils/entry-point.ts
+++ b/src/lib/utils/entry-point.ts
@@ -6,6 +6,7 @@ import { deriveRootDir, getCommonDirectory, MinimatchSet, nicePath, normalizePat
import type { Options } from "./options/index.js";
import { discoverPackageJson, glob, inferPackageEntryPointPaths, isDir } from "./fs.js";
import { assertNever, type GlobString, i18n, type Logger, type NormalizedPath } from "#utils";
+import { addInferredDeclarationMapPaths, resolveDeclarationMaps } from "./declaration-maps.js";
/**
* Defines how entry points are interpreted.
@@ -65,7 +66,7 @@ export function inferEntryPoints(logger: Logger, options: Options, programs?: ts
options,
);
- // See also: addInferredDeclarationMapPaths in ReflectionSymbolId
+ // See also: addInferredDeclarationMapPaths in symbol-id factory
const jsToTsSource = new Map();
for (const program of programs) {
const opts = program.getCompilerOptions();
@@ -86,7 +87,7 @@ export function inferEntryPoints(logger: Logger, options: Options, programs?: ts
for (const [name, path] of pathEntries) {
// Strip leading ./ from the display name
const displayName = name.replace(/^\.\/?/, "");
- const targetPath = jsToTsSource.get(path) || path;
+ const targetPath = jsToTsSource.get(path) || resolveDeclarationMaps(path) || path;
const program = programs.find((p) => p.getSourceFile(targetPath));
if (program) {
@@ -107,6 +108,10 @@ export function inferEntryPoints(logger: Logger, options: Options, programs?: ts
return [];
}
+ logger.verbose(
+ `Inferred entry points to be:\n\t${entryPoints.map(e => nicePath(e.sourceFile.fileName)).join("\n\t")}`,
+ );
+
return entryPoints;
}
@@ -413,6 +418,11 @@ function getEntryPrograms(
projectReferences: options.getProjectReferences(),
});
+ addInferredDeclarationMapPaths(
+ options.getCompilerOptions(),
+ options.getFileNames(),
+ );
+
const programs = [rootProgram];
// This might be a solution style tsconfig, in which case we need to add a program for each
// reference so that the converter can look through each of these.
@@ -433,6 +443,11 @@ function getEntryPrograms(
projectReferences: ref.commandLine.projectReferences,
}),
);
+
+ addInferredDeclarationMapPaths(
+ ref.commandLine.options,
+ ref.commandLine.fileNames,
+ );
}
}
diff --git a/src/lib/utils/index.ts b/src/lib/utils/index.ts
index 605a8b406..a48c4f739 100644
--- a/src/lib/utils/index.ts
+++ b/src/lib/utils/index.ts
@@ -44,6 +44,7 @@ export type { SortStrategy } from "./sort.js";
export * from "./entry-point.js";
+export * from "./declaration-maps.js";
export * from "./highlighter.js";
export * from "./html.js";
export * from "./tsconfig.js";
diff --git a/src/lib/utils/options/declaration.ts b/src/lib/utils/options/declaration.ts
index a18c094c2..61ca04387 100644
--- a/src/lib/utils/options/declaration.ts
+++ b/src/lib/utils/options/declaration.ts
@@ -10,10 +10,12 @@ import {
type NeverIfInternal,
type NormalizedPath,
type NormalizedPathOrModule,
+ type NormalizedPathOrModuleOrFunction,
type TranslatedString,
} from "#utils";
import type { TranslationProxy } from "../../internationalization/internationalization.js";
import { createGlobString, normalizePath } from "../paths.js";
+import type { Application } from "../../application.js";
/** @enum */
export const EmitStrategy = {
@@ -122,7 +124,8 @@ export type TypeDocOptions = {
TypeDocOptionMap[K] extends ManuallyValidatedOption<
infer ManuallyValidated
> ? ManuallyValidated :
- TypeDocOptionMap[K] extends NormalizedPath[] | NormalizedPathOrModule[] | GlobString[] ? string[] :
+ TypeDocOptionMap[K] extends
+ NormalizedPath[] | NormalizedPathOrModule[] | NormalizedPathOrModuleOrFunction[] | GlobString[] ? string[] :
TypeDocOptionMap[K] extends NormalizedPath ? string :
TypeDocOptionMap[K] extends
| string
@@ -150,6 +153,8 @@ export type TypeDocOptionValues = {
| string
| string[]
| GlobString[]
+ | NormalizedPathOrModule[]
+ | NormalizedPathOrModuleOrFunction[]
| number
| boolean
| Record ? TypeDocOptionMap[K] :
@@ -183,7 +188,7 @@ export interface TypeDocOptionMap {
options: NormalizedPath;
tsconfig: NormalizedPath;
compilerOptions: unknown;
- plugin: NormalizedPathOrModule[];
+ plugin: NormalizedPathOrModuleOrFunction[];
lang: string;
locales: ManuallyValidatedOption>>;
packageOptions: ManuallyValidatedOption<
@@ -404,7 +409,9 @@ export type KeyToDeclaration = TypeDocOptionMa
TypeDocOptionMap[K] extends string | NormalizedPath ? StringDeclarationOption :
TypeDocOptionMap[K] extends number ? NumberDeclarationOption :
TypeDocOptionMap[K] extends GlobString[] ? GlobArrayDeclarationOption :
- TypeDocOptionMap[K] extends string[] | NormalizedPath[] | NormalizedPathOrModule[] ? ArrayDeclarationOption :
+ TypeDocOptionMap[K] extends
+ string[] | NormalizedPath[] | NormalizedPathOrModule[] | NormalizedPathOrModuleOrFunction[] ?
+ ArrayDeclarationOption :
unknown extends TypeDocOptionMap[K] ? MixedDeclarationOption | ObjectDeclarationOption :
TypeDocOptionMap[K] extends ManuallyValidatedOption ?
| (MixedDeclarationOption & {
@@ -452,8 +459,14 @@ export enum ParameterType {
PathArray,
/**
* Resolved according to the config directory if it starts with `.`
+ * @deprecated since 0.28.8, will be removed in 0.29
*/
ModuleArray,
+ /**
+ * Resolved according to the config directory if it starts with `.`
+ * @internal - only intended for use with the plugin option
+ */
+ PluginArray,
/**
* Relative to the config directory.
*/
@@ -567,7 +580,9 @@ export interface ArrayDeclarationOption extends DeclarationOptionBase {
type:
| ParameterType.Array
| ParameterType.PathArray
- | ParameterType.ModuleArray;
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
+ | ParameterType.ModuleArray
+ | ParameterType.PluginArray;
/**
* If not specified defaults to an empty array.
@@ -673,7 +688,9 @@ export interface ParameterTypeToOptionTypeMap {
[ParameterType.Object]: unknown;
[ParameterType.Array]: string[];
[ParameterType.PathArray]: NormalizedPath[];
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
[ParameterType.ModuleArray]: NormalizedPathOrModule[];
+ [ParameterType.PluginArray]: Array void | Promise)>;
[ParameterType.GlobArray]: GlobString[];
[ParameterType.Flags]: Record;
@@ -685,7 +702,7 @@ export type DeclarationOptionToOptionType = T exten
T extends FlagsDeclarationOption ? U :
ParameterTypeToOptionTypeMap[Exclude];
-function toStringArray(value: unknown, option: DeclarationOption) {
+function toStringArray(value: unknown, option: DeclarationOption): string[] {
if (Array.isArray(value) && value.every(v => typeof v === "string")) {
return value;
} else if (typeof value === "string") {
@@ -695,6 +712,19 @@ function toStringArray(value: unknown, option: DeclarationOption) {
throw new Error(i18n.option_0_must_be_an_array_of_string(option.name));
}
+function toStringOrFunctionArray(
+ value: unknown,
+ option: DeclarationOption,
+): Array void | Promise)> {
+ if (Array.isArray(value) && value.every(v => typeof v === "string" || typeof v === "function")) {
+ return value;
+ } else if (typeof value === "string") {
+ return [value];
+ }
+
+ throw new Error(i18n.option_0_must_be_an_array_of_string_or_functions(option.name));
+}
+
const converters: {
[K in ParameterType]: (
value: unknown,
@@ -757,12 +787,20 @@ const converters: {
option.validate?.(normalized);
return normalized;
},
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
[ParameterType.ModuleArray](value, option, configPath) {
const strArrValue = toStringArray(value, option);
const resolved = resolveModulePaths(strArrValue, configPath);
option.validate?.(resolved);
return resolved;
},
+ [ParameterType.PluginArray](value, option, configPath) {
+ const arrayValue = toStringOrFunctionArray(value, option);
+ const resolved = arrayValue.map(plugin =>
+ typeof plugin === "function" ? plugin : resolveModulePath(plugin, configPath)
+ );
+ return resolved;
+ },
[ParameterType.GlobArray](value, option, configPath) {
const toGlobString = (v: unknown) => {
const s = String(v);
@@ -936,12 +974,19 @@ const defaultGetters: {
option.defaultValue?.map((value) => normalizePath(resolve(process.cwd(), value))) ?? []
);
},
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
[ParameterType.ModuleArray](option) {
if (option.defaultValue) {
return resolveModulePaths(option.defaultValue, process.cwd());
}
return [];
},
+ [ParameterType.PluginArray](option) {
+ if (option.defaultValue) {
+ return resolveModulePaths(option.defaultValue, process.cwd());
+ }
+ return [];
+ },
[ParameterType.GlobArray](option) {
return (option.defaultValue ?? []).map(g => createGlobString(normalizePath(process.cwd()), g));
},
@@ -959,12 +1004,14 @@ export function getDefaultValue(option: DeclarationOption) {
}
function resolveModulePaths(modules: readonly string[], configPath: string): NormalizedPathOrModule[] {
- return modules.map((path) => {
- if (path.startsWith(".")) {
- return normalizePath(resolve(configPath, path));
- }
- return normalizePath(path);
- });
+ return modules.map(path => resolveModulePath(path, configPath));
+}
+
+function resolveModulePath(path: string, configPath: string): NormalizedPathOrModule {
+ if (path.startsWith(".")) {
+ return normalizePath(resolve(configPath, path));
+ }
+ return normalizePath(path);
}
function isTsNumericEnum(map: Record) {
diff --git a/src/lib/utils/options/readers/arguments.ts b/src/lib/utils/options/readers/arguments.ts
index e7a30c73f..9b277d526 100644
--- a/src/lib/utils/options/readers/arguments.ts
+++ b/src/lib/utils/options/readers/arguments.ts
@@ -6,7 +6,9 @@ import { i18n, type Logger, type TranslatedString } from "#utils";
const ARRAY_OPTION_TYPES = new Set([
ParameterType.Array,
ParameterType.PathArray,
+ // eslint-disable-next-line @typescript-eslint/no-deprecated
ParameterType.ModuleArray,
+ ParameterType.PluginArray,
ParameterType.GlobArray,
]);
diff --git a/src/lib/utils/options/sources/typedoc.ts b/src/lib/utils/options/sources/typedoc.ts
index c04289f8c..c1658768c 100644
--- a/src/lib/utils/options/sources/typedoc.ts
+++ b/src/lib/utils/options/sources/typedoc.ts
@@ -923,7 +923,7 @@ export function addTypeDocOptions(options: Pick) {
options.addDeclaration({
name: "plugin",
help: () => i18n.help_plugin(),
- type: ParameterType.ModuleArray,
+ type: ParameterType.PluginArray,
});
options.addDeclaration({
name: "logLevel",
diff --git a/src/lib/utils/plugins.ts b/src/lib/utils/plugins.ts
index 99f726639..591a9cceb 100644
--- a/src/lib/utils/plugins.ts
+++ b/src/lib/utils/plugins.ts
@@ -3,35 +3,42 @@ import { pathToFileURL } from "url";
import type { Application } from "../application.js";
import { nicePath } from "./paths.js";
-import { i18n, type TranslatedString } from "#utils";
+import { i18n, type NormalizedPathOrModuleOrFunction, type TranslatedString } from "#utils";
export async function loadPlugins(
app: Application,
- plugins: readonly string[],
+ plugins: readonly NormalizedPathOrModuleOrFunction[],
) {
for (const plugin of plugins) {
const pluginDisplay = getPluginDisplayName(plugin);
try {
- let instance: any;
- // Try importing first to avoid warnings about requiring ESM being experimental.
- // If that fails due to importing a directory, fall back to require.
- try {
- // On Windows, we need to ensure this path is a file path.
- // Or we'll get ERR_UNSUPPORTED_ESM_URL_SCHEME
- const esmPath = isAbsolute(plugin)
- ? pathToFileURL(plugin).toString()
- : plugin;
- instance = await import(esmPath);
- } catch (error: any) {
- if (error.code === "ERR_UNSUPPORTED_DIR_IMPORT") {
- // eslint-disable-next-line @typescript-eslint/no-require-imports
- instance = require(plugin);
- } else {
- throw error;
+ let initFunction: any;
+
+ if (typeof plugin === "function") {
+ initFunction = plugin;
+ } else {
+ let instance: any;
+
+ // Try importing first to avoid warnings about requiring ESM being experimental.
+ // If that fails due to importing a directory, fall back to require.
+ try {
+ // On Windows, we need to ensure this path is a file path.
+ // Or we'll get ERR_UNSUPPORTED_ESM_URL_SCHEME
+ const esmPath = isAbsolute(plugin)
+ ? pathToFileURL(plugin).toString()
+ : plugin;
+ instance = await import(esmPath);
+ } catch (error: any) {
+ if (error.code === "ERR_UNSUPPORTED_DIR_IMPORT") {
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
+ instance = require(plugin);
+ } else {
+ throw error;
+ }
}
+ initFunction = instance.load;
}
- const initFunction = instance.load;
if (typeof initFunction === "function") {
await initFunction(app);
@@ -54,7 +61,11 @@ export async function loadPlugins(
}
}
-function getPluginDisplayName(plugin: string) {
+function getPluginDisplayName(plugin: NormalizedPathOrModuleOrFunction) {
+ if (typeof plugin === "function") {
+ return plugin.name || "function";
+ }
+
const path = nicePath(plugin);
if (path.startsWith("./node_modules/")) {
return path.substring("./node_modules/".length);
diff --git a/src/test/comments.test.ts b/src/test/comments.test.ts
index 0d2d77405..352cdba30 100644
--- a/src/test/comments.test.ts
+++ b/src/test/comments.test.ts
@@ -13,6 +13,10 @@ import { extractTagName } from "../lib/converter/comments/tagName.js";
import { type FileId, FileRegistry } from "../lib/models/FileRegistry.js";
import { dedent, MinimalSourceFile, type NormalizedPath } from "#utils";
+const neverCalled = () => {
+ throw new Error("Should not be called");
+};
+
describe("Block Comment Lexer", () => {
function lex(text: string): Token[] {
return Array.from(lexBlockComment(text));
@@ -186,7 +190,7 @@ describe("Block Comment Lexer", () => {
});
it("Should recognize tags", () => {
- const tokens = lex("/* @tag @a @abc234 */");
+ const tokens = lex("/* @tag @a @abc234 @abc-234 */");
equal(tokens, [
{ kind: TokenSyntaxKind.Tag, text: "@tag", pos: 3 },
@@ -194,6 +198,8 @@ describe("Block Comment Lexer", () => {
{ kind: TokenSyntaxKind.Tag, text: "@a", pos: 8 },
{ kind: TokenSyntaxKind.Text, text: " ", pos: 10 },
{ kind: TokenSyntaxKind.Tag, text: "@abc234", pos: 11 },
+ { kind: TokenSyntaxKind.Text, text: " ", pos: 18 },
+ { kind: TokenSyntaxKind.Tag, text: "@abc-234", pos: 19 },
]);
});
@@ -641,7 +647,7 @@ describe("Line Comment Lexer", () => {
});
it("Should recognize tags", () => {
- const tokens = lex("// @tag @a @abc234");
+ const tokens = lex("// @tag @a @abc234 @abc-234");
equal(tokens, [
{ kind: TokenSyntaxKind.Tag, text: "@tag", pos: 3 },
@@ -649,6 +655,8 @@ describe("Line Comment Lexer", () => {
{ kind: TokenSyntaxKind.Tag, text: "@a", pos: 8 },
{ kind: TokenSyntaxKind.Text, text: " ", pos: 10 },
{ kind: TokenSyntaxKind.Tag, text: "@abc234", pos: 11 },
+ { kind: TokenSyntaxKind.Text, text: " ", pos: 18 },
+ { kind: TokenSyntaxKind.Tag, text: "@abc-234", pos: 19 },
]);
});
@@ -993,12 +1001,12 @@ describe("Raw Lexer", () => {
});
it("Should not recognize tags", () => {
- const tokens = lex("@123 @@ @ @tag @a @abc234");
+ const tokens = lex("@123 @@ @ @tag @a @abc234 @abc-234");
equal(tokens, [
{
kind: TokenSyntaxKind.Text,
- text: "@123 @@ @ @tag @a @abc234",
+ text: "@123 @@ @ @tag @a @abc234 @abc-234",
pos: 0,
},
]);
@@ -1155,10 +1163,8 @@ describe("Comment Parser", () => {
const content = lexBlockComment(file);
const comment = parseComment(
content,
- config,
new MinimalSourceFile(file, "/dev/zero" as NormalizedPath),
- logger,
- files,
+ { logger, files, config, createSymbolId: neverCalled },
);
equal(
@@ -1182,10 +1188,8 @@ describe("Comment Parser", () => {
const content = lexBlockComment(file);
const comment = parseComment(
content,
- config,
new MinimalSourceFile(file, "/dev/zero" as NormalizedPath),
- logger,
- files,
+ { logger, files, config, createSymbolId: neverCalled },
);
equal(
@@ -1210,10 +1214,8 @@ describe("Comment Parser", () => {
const content = lexBlockComment(file);
const comment = parseComment(
content,
- config,
new MinimalSourceFile(file, "/dev/zero" as NormalizedPath),
- logger,
- files,
+ { logger, files, config, createSymbolId: neverCalled },
);
equal(
@@ -1238,10 +1240,8 @@ describe("Comment Parser", () => {
const content = lexBlockComment(file);
const comment = parseComment(
content,
- config,
new MinimalSourceFile(file, "/dev/zero" as NormalizedPath),
- logger,
- files,
+ { logger, files, config, createSymbolId: neverCalled },
);
logger.expectMessage(
@@ -1258,10 +1258,8 @@ describe("Comment Parser", () => {
const content = lexBlockComment(text);
const comment = parseComment(
content,
- config,
new MinimalSourceFile(text, "/dev/zero" as NormalizedPath),
- logger,
- files,
+ { logger, files, config, createSymbolId: neverCalled },
);
logger.expectNoOtherMessages();
return comment;
@@ -1560,6 +1558,7 @@ describe("Comment Parser", () => {
* [2]:<./example with space>
* [3]: https://example.com
* [4]: #hash
+ * [^footnote]: ./example.md
*/`);
equal(
@@ -1581,7 +1580,7 @@ describe("Comment Parser", () => {
},
{
kind: "text",
- text: "\n[3]: https://example.com\n[4]: #hash",
+ text: "\n[3]: https://example.com\n[4]: #hash\n[^footnote]: ./example.md",
},
] satisfies CommentDisplayPart[],
);
@@ -1632,6 +1631,148 @@ describe("Comment Parser", () => {
);
});
+ it("Recognizes HTML picture source srcset links", () => {
+ const comment = getComment(`/**
+ *
+ *
+ *
+ *
+ */`);
+
+ equal(
+ comment.summary,
+ [
+ { kind: "text", text: '\n\n\n',
+ },
+ ] satisfies CommentDisplayPart[],
+ );
+ });
+
+ it("Recognizes links", () => {
+ const comment = getComment(`/**
+ *
+ */`);
+
+ equal(
+ comment.summary,
+ [
+ { kind: "text", text: '' },
+ ] satisfies CommentDisplayPart[],
+ );
+ });
+
+ it("Recognizes HTML audio and video src links", () => {
+ const comment = getComment(`/**
+ *
+ *
+ *
+ */`);
+
+ equal(
+ comment.summary,
+ [
+ { kind: "text", text: '\n\n',
+ },
+ ] satisfies CommentDisplayPart[],
+ );
+ });
+
+ it("Recognizes img tag with both src and srcset", () => {
+ const comment = getComment(`/**
+ *
+ */`);
+
+ equal(
+ comment.summary,
+ [
+ { kind: "text", text: '
',
+ },
+ ] satisfies CommentDisplayPart[],
+ );
+ });
+
it("Recognizes HTML anchor links", () => {
const comment = getComment(`/**
*
diff --git a/src/test/converter/class/class.ts b/src/test/converter/class/class.ts
index e46637b75..a1b693ce2 100644
--- a/src/test/converter/class/class.ts
+++ b/src/test/converter/class/class.ts
@@ -106,7 +106,7 @@ export interface TestSubClass {
mergedMethod();
}
-export module TestSubClass {
+export namespace TestSubClass {
/**
* staticMergedMethod short text.
*/
diff --git a/src/test/converter/class/specs-with-lump-categories.json b/src/test/converter/class/specs-with-lump-categories.json
index 96ab944f1..386ab2fe6 100644
--- a/src/test/converter/class/specs-with-lump-categories.json
+++ b/src/test/converter/class/specs-with-lump-categories.json
@@ -565,7 +565,7 @@
{
"fileName": "class.ts",
"line": 109,
- "character": 14,
+ "character": 17,
"url": "typedoc://class.ts#L109"
}
]
@@ -2239,7 +2239,7 @@
{
"fileName": "class.ts",
"line": 109,
- "character": 14,
+ "character": 17,
"url": "typedoc://class.ts#L109"
}
],
diff --git a/src/test/converter/class/specs.json b/src/test/converter/class/specs.json
index 96ab944f1..386ab2fe6 100644
--- a/src/test/converter/class/specs.json
+++ b/src/test/converter/class/specs.json
@@ -565,7 +565,7 @@
{
"fileName": "class.ts",
"line": 109,
- "character": 14,
+ "character": 17,
"url": "typedoc://class.ts#L109"
}
]
@@ -2239,7 +2239,7 @@
{
"fileName": "class.ts",
"line": 109,
- "character": 14,
+ "character": 17,
"url": "typedoc://class.ts#L109"
}
],
diff --git a/src/test/converter/enum/enum.ts b/src/test/converter/enum/enum.ts
index 5152f41ff..394ee4a47 100644
--- a/src/test/converter/enum/enum.ts
+++ b/src/test/converter/enum/enum.ts
@@ -41,7 +41,7 @@ export enum ModuleEnum {
/**
* This is a module extending an enumeration.
*/
-export module ModuleEnum {
+export namespace ModuleEnum {
/**
* This is a variable appended to an enumeration.
*/
diff --git a/src/test/converter/enum/specs.json b/src/test/converter/enum/specs.json
index d59f01d7e..144d9a4ff 100644
--- a/src/test/converter/enum/specs.json
+++ b/src/test/converter/enum/specs.json
@@ -117,7 +117,7 @@
{
"fileName": "enum.ts",
"line": 44,
- "character": 14,
+ "character": 17,
"url": "typedoc://enum.ts#L44"
}
]
@@ -313,7 +313,7 @@
{
"fileName": "enum.ts",
"line": 44,
- "character": 14,
+ "character": 17,
"url": "typedoc://enum.ts#L44"
}
]
diff --git a/src/test/converter/enum/specs.nodoc.json b/src/test/converter/enum/specs.nodoc.json
index d59f01d7e..144d9a4ff 100644
--- a/src/test/converter/enum/specs.nodoc.json
+++ b/src/test/converter/enum/specs.nodoc.json
@@ -117,7 +117,7 @@
{
"fileName": "enum.ts",
"line": 44,
- "character": 14,
+ "character": 17,
"url": "typedoc://enum.ts#L44"
}
]
@@ -313,7 +313,7 @@
{
"fileName": "enum.ts",
"line": 44,
- "character": 14,
+ "character": 17,
"url": "typedoc://enum.ts#L44"
}
]
diff --git a/src/test/converter/function/function.ts b/src/test/converter/function/function.ts
index f90d3c5af..077a9a6f7 100644
--- a/src/test/converter/function/function.ts
+++ b/src/test/converter/function/function.ts
@@ -161,7 +161,7 @@ export function isNonNull(arg: T | null | undefined): arg is T {
/**
* This is the module extending the function moduleFunction().
*/
-export module moduleFunction {
+export namespace moduleFunction {
/**
* This variable is appended to a function.
*/
diff --git a/src/test/converter/function/specs.json b/src/test/converter/function/specs.json
index eb4d6085a..8b391258c 100644
--- a/src/test/converter/function/specs.json
+++ b/src/test/converter/function/specs.json
@@ -169,7 +169,7 @@
{
"fileName": "function.ts",
"line": 164,
- "character": 14,
+ "character": 17,
"url": "typedoc://function.ts#L164"
}
]
@@ -1680,7 +1680,7 @@
{
"fileName": "function.ts",
"line": 164,
- "character": 14,
+ "character": 17,
"url": "typedoc://function.ts#L164"
}
],
diff --git a/src/test/converter/interface/interface-implementation.ts b/src/test/converter/interface/interface-implementation.ts
index df9f78650..aefd892fb 100644
--- a/src/test/converter/interface/interface-implementation.ts
+++ b/src/test/converter/interface/interface-implementation.ts
@@ -1,4 +1,4 @@
-export module Forms {
+export namespace Forms {
/**
* Function signature of an event listener callback
*/
diff --git a/src/test/converter/interface/specs.json b/src/test/converter/interface/specs.json
index b629a2d17..c554d89a9 100644
--- a/src/test/converter/interface/specs.json
+++ b/src/test/converter/interface/specs.json
@@ -2235,7 +2235,7 @@
{
"fileName": "interface-implementation.ts",
"line": 1,
- "character": 14,
+ "character": 17,
"url": "typedoc://interface-implementation.ts#L1"
}
]
@@ -2546,8 +2546,8 @@
},
"inheritedFrom": {
"type": "reference",
- "target": 106,
- "name": "Base.base"
+ "target": 112,
+ "name": "Child.base"
}
},
{
diff --git a/src/test/converter2/issues/gh2978.ts b/src/test/converter2/issues/gh2978.ts
new file mode 100644
index 000000000..9dd8876aa
--- /dev/null
+++ b/src/test/converter2/issues/gh2978.ts
@@ -0,0 +1,15 @@
+export interface Parent {
+ prop: string;
+}
+
+export interface Child extends Partial {}
+
+export type Tricky = Omit & { x: number };
+
+export interface HasX {
+ x: string;
+}
+
+export interface InheritsX extends Tricky {
+ // InheritsX.x should *not* be linked to HasX.x
+}
diff --git a/src/test/converter2/renderer/gh2982.ts b/src/test/converter2/renderer/gh2982.ts
new file mode 100644
index 000000000..678f957ec
--- /dev/null
+++ b/src/test/converter2/renderer/gh2982.ts
@@ -0,0 +1,6 @@
+export type TMXNode = {} & {
+ base: T;
+};
+
+export interface TMXDataNode extends TMXNode<{ extra: any }> {
+}
diff --git a/src/test/converter2/renderer/index.ts b/src/test/converter2/renderer/index.ts
index 8d354b5ea..2dbb7e53d 100644
--- a/src/test/converter2/renderer/index.ts
+++ b/src/test/converter2/renderer/index.ts
@@ -135,3 +135,5 @@ export interface DisabledGroups {
}
export * as ExpandType from "./expandType";
+export * as GH2982 from "./gh2982";
+export { box as boxAlias };
diff --git a/src/test/issues.c2.test.ts b/src/test/issues.c2.test.ts
index 94a1b6e76..4aaf6b6f0 100644
--- a/src/test/issues.c2.test.ts
+++ b/src/test/issues.c2.test.ts
@@ -2135,4 +2135,13 @@ describe("Issue Tests", () => {
["Var", "Comment"],
]);
});
+
+ it("#2978 handles parent properties through mapped types", () => {
+ const project = convert();
+ const prop = query(project, "Child.prop");
+ equal(prop.inheritedFrom?.reflection?.getFullName(), "Parent.prop");
+ const x = query(project, "InheritsX.x");
+ equal(x.inheritedFrom?.reflection?.getFullName(), undefined);
+ equal(x.inheritedFrom?.name, "Tricky.x");
+ });
});
diff --git a/src/test/programs.ts b/src/test/programs.ts
index c63b42f26..394f6a1d7 100644
--- a/src/test/programs.ts
+++ b/src/test/programs.ts
@@ -13,7 +13,6 @@ import {
import type { ModelToObject } from "../lib/serialization/schema.js";
import { createAppForTesting } from "../lib/application.js";
import { existsSync } from "fs";
-import { clearCommentCache } from "../lib/converter/comments/index.js";
import { diagnostics } from "../lib/utils/loggers.js";
import { normalizePath, readFile, ValidatingFileRegistry } from "#node-utils";
@@ -175,7 +174,6 @@ export function getConverter2Project(entries: string[], folder: string) {
app.options.setValue("entryPoints", entryPoints);
app.files = new ValidatingFileRegistry();
- clearCommentCache();
return app.converter.convert(
files.map((file, index) => {
return {
diff --git a/src/test/renderer/specs/interfaces/BaseInterface.json b/src/test/renderer/specs/interfaces/BaseInterface.json
index 46980afe2..9ccfa435d 100644
--- a/src/test/renderer/specs/interfaces/BaseInterface.json
+++ b/src/test/renderer/specs/interfaces/BaseInterface.json
@@ -41,7 +41,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-call-signature",
"props": {
@@ -65,7 +65,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-call-signature",
"props": {
diff --git a/src/test/renderer/specs/interfaces/DisabledGroups.json b/src/test/renderer/specs/interfaces/DisabledGroups.json
index 90d525305..14e3d537a 100644
--- a/src/test/renderer/specs/interfaces/DisabledGroups.json
+++ b/src/test/renderer/specs/interfaces/DisabledGroups.json
@@ -41,7 +41,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -62,7 +62,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-call-signature",
"props": {
diff --git a/src/test/renderer/specs/interfaces/ExpandType.ExpandedByDefault.json b/src/test/renderer/specs/interfaces/ExpandType.ExpandedByDefault.json
index 4df2574ad..a0a0fbe17 100644
--- a/src/test/renderer/specs/interfaces/ExpandType.ExpandedByDefault.json
+++ b/src/test/renderer/specs/interfaces/ExpandType.ExpandedByDefault.json
@@ -52,7 +52,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/interfaces/GH2982.TMXDataNode.json b/src/test/renderer/specs/interfaces/GH2982.TMXDataNode.json
new file mode 100644
index 000000000..4a14d5c79
--- /dev/null
+++ b/src/test/renderer/specs/interfaces/GH2982.TMXDataNode.json
@@ -0,0 +1,352 @@
+{
+ "div.container.container-main": [
+ {
+ "div.col-content": [
+ {
+ "div.tsd-page-title": [
+ {
+ "tag": "ul.tsd-breadcrumb",
+ "props": {
+ "aria-label": "Breadcrumb"
+ },
+ "children": [
+ {
+ "li": {
+ "tag": "a",
+ "props": {
+ "href": "../modules/GH2982.json"
+ },
+ "children": "GH2982"
+ }
+ },
+ {
+ "li": {
+ "tag": "a",
+ "props": {
+ "href": "",
+ "aria-current": "page"
+ },
+ "children": "TMXDataNode"
+ }
+ }
+ ]
+ },
+ {
+ "h1": "Interface TMXDataNode"
+ }
+ ]
+ },
+ {
+ "div.tsd-signature": [
+ {
+ "span.tsd-signature-keyword": "interface"
+ },
+ " ",
+ {
+ "span.tsd-kind-interface": "TMXDataNode"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "{"
+ },
+ {
+ "br": []
+ },
+ " ",
+ {
+ "tag": "a.tsd-kind-property",
+ "props": {
+ "href": "#base"
+ },
+ "children": "base"
+ },
+ {
+ "span.tsd-signature-symbol": ":"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "{"
+ },
+ " ",
+ {
+ "span.tsd-kind-property": "extra"
+ },
+ {
+ "span.tsd-signature-symbol": ":"
+ },
+ " ",
+ {
+ "span.tsd-signature-type": "any"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "}"
+ },
+ {
+ "span.tsd-signature-symbol": ";"
+ },
+ {
+ "br": []
+ },
+ {
+ "span.tsd-signature-symbol": "}"
+ }
+ ]
+ },
+ {
+ "tag": "section.tsd-panel.tsd-hierarchy",
+ "props": {
+ "data-refl": "123"
+ },
+ "children": [
+ {
+ "h4": [
+ "Hierarchy (",
+ {
+ "tag": "a",
+ "props": {
+ "href": "../hierarchy.html#GH2982.TMXDataNode"
+ },
+ "children": "View Summary"
+ },
+ ")"
+ ]
+ },
+ {
+ "ul.tsd-hierarchy": {
+ "li.tsd-hierarchy-item": [
+ {
+ "tag": "a.tsd-signature-type.tsd-kind-type-alias",
+ "props": {
+ "href": "../types/GH2982.TMXNode.json"
+ },
+ "children": "TMXNode"
+ },
+ {
+ "span.tsd-signature-symbol": "<"
+ },
+ {
+ "span.tsd-signature-symbol": "{"
+ },
+ " ",
+ {
+ "span.tsd-kind-property": "extra"
+ },
+ {
+ "span.tsd-signature-symbol": ":"
+ },
+ " ",
+ {
+ "span.tsd-signature-type": "any"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "}"
+ },
+ {
+ "span.tsd-signature-symbol": ">"
+ },
+ {
+ "ul.tsd-hierarchy": {
+ "li.tsd-hierarchy-item": {
+ "span.tsd-hierarchy-target": "TMXDataNode"
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ },
+ {
+ "aside.tsd-sources": {
+ "ul": {
+ "li": [
+ "Defined in ",
+ {
+ "tag": "a",
+ "props": {
+ "href": "gh2982.ts"
+ },
+ "children": "gh2982.ts:5"
+ }
+ ]
+ }
+ }
+ },
+ {
+ "section.tsd-panel-group.tsd-index-group": {
+ "section.tsd-panel.tsd-index-panel": {
+ "tag": "details.tsd-index-content.tsd-accordion",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "summary.tsd-accordion-summary.tsd-index-summary": {
+ "h5.tsd-index-heading.uppercase": "Index"
+ }
+ },
+ {
+ "div.tsd-accordion-details": {
+ "section.tsd-index-section": [
+ {
+ "h3.tsd-index-heading": "Properties"
+ },
+ {
+ "div.tsd-index-list": [
+ {
+ "tag": "a.tsd-index-link.tsd-is-inherited",
+ "props": {
+ "href": "#base"
+ },
+ "children": {
+ "span": "base"
+ }
+ },
+ "\n"
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ },
+ {
+ "tag": "details.tsd-panel-group.tsd-member-group.tsd-accordion",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "tag": "summary.tsd-accordion-summary",
+ "props": {
+ "data-key": "section-Properties"
+ },
+ "children": {
+ "h2": "Properties"
+ }
+ },
+ {
+ "section": {
+ "section.tsd-panel.tsd-member.tsd-is-inherited": [
+ {
+ "h3.tsd-anchor-link#base": [
+ {
+ "span": "base"
+ },
+ {
+ "tag": "a.tsd-anchor-icon",
+ "props": {
+ "href": "#base",
+ "aria-label": "Permalink"
+ }
+ }
+ ]
+ },
+ {
+ "div.tsd-signature": [
+ {
+ "span.tsd-kind-property": "base"
+ },
+ {
+ "span.tsd-signature-symbol": ":"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "{"
+ },
+ " ",
+ {
+ "span.tsd-kind-property": "extra"
+ },
+ {
+ "span.tsd-signature-symbol": ":"
+ },
+ " ",
+ {
+ "span.tsd-signature-type": "any"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "}"
+ }
+ ]
+ },
+ {
+ "aside.tsd-sources": [
+ {
+ "p": "Inherited from TMXNode.base"
+ },
+ {
+ "ul": {
+ "li": [
+ "Defined in ",
+ {
+ "tag": "a",
+ "props": {
+ "href": "gh2982.ts"
+ },
+ "children": "gh2982.ts:2"
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ }
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "div.col-sidebar": {
+ "div.page-menu": {
+ "tag": "details.tsd-accordion.tsd-page-navigation",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "summary.tsd-accordion-summary": {
+ "h3": "On This Page"
+ }
+ },
+ {
+ "div.tsd-accordion-details": {
+ "tag": "details.tsd-accordion.tsd-page-navigation-section",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "tag": "summary.tsd-accordion-summary",
+ "props": {
+ "data-key": "section-Properties"
+ },
+ "children": "Properties"
+ },
+ {
+ "div": {
+ "tag": "a.tsd-is-inherited",
+ "props": {
+ "href": "#base"
+ },
+ "children": {
+ "span": "base"
+ }
+ }
+ }
+ ]
+ }
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/src/test/renderer/specs/interfaces/NoneCategory.json b/src/test/renderer/specs/interfaces/NoneCategory.json
index f13e3d383..24d919665 100644
--- a/src/test/renderer/specs/interfaces/NoneCategory.json
+++ b/src/test/renderer/specs/interfaces/NoneCategory.json
@@ -41,7 +41,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -62,7 +62,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -83,7 +83,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/interfaces/NoneGroup.json b/src/test/renderer/specs/interfaces/NoneGroup.json
index 8970f3e31..fdca9ae0d 100644
--- a/src/test/renderer/specs/interfaces/NoneGroup.json
+++ b/src/test/renderer/specs/interfaces/NoneGroup.json
@@ -41,7 +41,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -62,7 +62,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/modules.json b/src/test/renderer/specs/modules.json
index 21b6084dd..cc6e97839 100644
--- a/src/test/renderer/specs/modules.json
+++ b/src/test/renderer/specs/modules.json
@@ -106,6 +106,29 @@
]
}
},
+ {
+ "dd.tsd-member-summary": []
+ },
+ {
+ "dt.tsd-member-summary#gh2982": {
+ "span.tsd-member-summary-name": [
+ {
+ "tag": "a",
+ "props": {
+ "href": "modules/GH2982.json"
+ },
+ "children": "GH2982"
+ },
+ {
+ "tag": "a.tsd-anchor-icon",
+ "props": {
+ "href": "#gh2982",
+ "aria-label": "Permalink"
+ }
+ }
+ ]
+ }
+ },
{
"dd.tsd-member-summary": []
}
@@ -493,6 +516,56 @@
]
}
]
+ },
+ {
+ "tag": "details.tsd-panel-group.tsd-member-group.tsd-accordion",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "tag": "summary.tsd-accordion-summary",
+ "props": {
+ "data-key": "section-References"
+ },
+ "children": {
+ "h2": "References"
+ }
+ },
+ {
+ "dl.tsd-member-summaries": [
+ {
+ "dt.tsd-member-summary#boxalias": {
+ "span.tsd-member-summary-name": [
+ {
+ "span": "boxAlias"
+ },
+ {
+ "span": " → "
+ },
+ {
+ "tag": "a",
+ "props": {
+ "href": "functions/box.json"
+ },
+ "children": "box"
+ },
+ {
+ "tag": "a.tsd-anchor-icon",
+ "props": {
+ "href": "#boxalias",
+ "aria-label": "Permalink"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "dd.tsd-member-summary": []
+ }
+ ]
+ }
+ ]
}
]
},
@@ -551,21 +624,32 @@
"children": "Namespaces"
},
{
- "div": {
- "tag": "a",
- "props": {
- "href": "#expandtype"
+ "div": [
+ {
+ "tag": "a",
+ "props": {
+ "href": "#expandtype"
+ },
+ "children": {
+ "span": [
+ "Expand",
+ {
+ "wbr": []
+ },
+ "Type"
+ ]
+ }
},
- "children": {
- "span": [
- "Expand",
- {
- "wbr": []
- },
- "Type"
- ]
+ {
+ "tag": "a",
+ "props": {
+ "href": "#gh2982"
+ },
+ "children": {
+ "span": "GH2982"
+ }
}
- }
+ ]
}
]
},
@@ -821,6 +905,38 @@
}
}
]
+ },
+ {
+ "tag": "details.tsd-accordion.tsd-page-navigation-section",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "tag": "summary.tsd-accordion-summary",
+ "props": {
+ "data-key": "section-References"
+ },
+ "children": "References"
+ },
+ {
+ "div": {
+ "tag": "a",
+ "props": {
+ "href": "#boxalias"
+ },
+ "children": {
+ "span": [
+ "box",
+ {
+ "wbr": []
+ },
+ "Alias"
+ ]
+ }
+ }
+ }
+ ]
}
]
}
diff --git a/src/test/renderer/specs/modules/GH2982.json b/src/test/renderer/specs/modules/GH2982.json
new file mode 100644
index 000000000..40c28d9dc
--- /dev/null
+++ b/src/test/renderer/specs/modules/GH2982.json
@@ -0,0 +1,208 @@
+{
+ "div.container.container-main": [
+ {
+ "div.col-content": [
+ {
+ "div.tsd-page-title": [
+ {
+ "tag": "ul.tsd-breadcrumb",
+ "props": {
+ "aria-label": "Breadcrumb"
+ },
+ "children": {
+ "li": {
+ "tag": "a",
+ "props": {
+ "href": "",
+ "aria-current": "page"
+ },
+ "children": "GH2982"
+ }
+ }
+ },
+ {
+ "h1": "Namespace GH2982"
+ }
+ ]
+ },
+ {
+ "tag": "details.tsd-panel-group.tsd-member-group.tsd-accordion",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "tag": "summary.tsd-accordion-summary",
+ "props": {
+ "data-key": "section-Interfaces"
+ },
+ "children": {
+ "h2": "Interfaces"
+ }
+ },
+ {
+ "dl.tsd-member-summaries": [
+ {
+ "dt.tsd-member-summary#tmxdatanode": {
+ "span.tsd-member-summary-name": [
+ {
+ "tag": "a",
+ "props": {
+ "href": "../interfaces/GH2982.TMXDataNode.json"
+ },
+ "children": "TMXDataNode"
+ },
+ {
+ "tag": "a.tsd-anchor-icon",
+ "props": {
+ "href": "#tmxdatanode",
+ "aria-label": "Permalink"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "dd.tsd-member-summary": []
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "tag": "details.tsd-panel-group.tsd-member-group.tsd-accordion",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "tag": "summary.tsd-accordion-summary",
+ "props": {
+ "data-key": "section-Type Aliases"
+ },
+ "children": {
+ "h2": "Type Aliases"
+ }
+ },
+ {
+ "dl.tsd-member-summaries": [
+ {
+ "dt.tsd-member-summary#tmxnode": {
+ "span.tsd-member-summary-name": [
+ {
+ "tag": "a",
+ "props": {
+ "href": "../types/GH2982.TMXNode.json"
+ },
+ "children": "TMXNode"
+ },
+ {
+ "tag": "a.tsd-anchor-icon",
+ "props": {
+ "href": "#tmxnode",
+ "aria-label": "Permalink"
+ }
+ }
+ ]
+ }
+ },
+ {
+ "dd.tsd-member-summary": []
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ },
+ {
+ "div.col-sidebar": {
+ "div.page-menu": {
+ "tag": "details.tsd-accordion.tsd-page-navigation",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "summary.tsd-accordion-summary": {
+ "h3": "On This Page"
+ }
+ },
+ {
+ "div.tsd-accordion-details": [
+ {
+ "tag": "details.tsd-accordion.tsd-page-navigation-section",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "tag": "summary.tsd-accordion-summary",
+ "props": {
+ "data-key": "section-Interfaces"
+ },
+ "children": "Interfaces"
+ },
+ {
+ "div": {
+ "tag": "a",
+ "props": {
+ "href": "#tmxdatanode"
+ },
+ "children": {
+ "span": [
+ "TMX",
+ {
+ "wbr": []
+ },
+ "Data",
+ {
+ "wbr": []
+ },
+ "Node"
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ "tag": "details.tsd-accordion.tsd-page-navigation-section",
+ "props": {
+ "open": true
+ },
+ "children": [
+ {
+ "tag": "summary.tsd-accordion-summary",
+ "props": {
+ "data-key": "section-Type Aliases"
+ },
+ "children": "Type Aliases"
+ },
+ {
+ "div": {
+ "tag": "a",
+ "props": {
+ "href": "#tmxnode"
+ },
+ "children": {
+ "span": [
+ "TMX",
+ {
+ "wbr": []
+ },
+ "Node"
+ ]
+ }
+ }
+ }
+ ]
+ }
+ ]
+ }
+ ]
+ }
+ }
+ }
+ ]
+}
diff --git a/src/test/renderer/specs/types/ExpandType.AExpanded.json b/src/test/renderer/specs/types/ExpandType.AExpanded.json
index 8b3b95b61..3fd838168 100644
--- a/src/test/renderer/specs/types/ExpandType.AExpanded.json
+++ b/src/test/renderer/specs/types/ExpandType.AExpanded.json
@@ -61,7 +61,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -86,7 +86,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -111,7 +111,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/types/ExpandType.BExpanded.json b/src/test/renderer/specs/types/ExpandType.BExpanded.json
index e8eff5cf4..2865052ec 100644
--- a/src/test/renderer/specs/types/ExpandType.BExpanded.json
+++ b/src/test/renderer/specs/types/ExpandType.BExpanded.json
@@ -56,7 +56,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -81,7 +81,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -106,7 +106,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/types/ExpandType.Expandable.json b/src/test/renderer/specs/types/ExpandType.Expandable.json
index be39fc09a..89de6658c 100644
--- a/src/test/renderer/specs/types/ExpandType.Expandable.json
+++ b/src/test/renderer/specs/types/ExpandType.Expandable.json
@@ -56,7 +56,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/types/ExpandType.Expandable2.json b/src/test/renderer/specs/types/ExpandType.Expandable2.json
index 1660b2262..efcacd043 100644
--- a/src/test/renderer/specs/types/ExpandType.Expandable2.json
+++ b/src/test/renderer/specs/types/ExpandType.Expandable2.json
@@ -56,7 +56,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/types/ExpandType.NestedBehavior1.AExpanded.json b/src/test/renderer/specs/types/ExpandType.NestedBehavior1.AExpanded.json
index 678a54354..6ecd11223 100644
--- a/src/test/renderer/specs/types/ExpandType.NestedBehavior1.AExpanded.json
+++ b/src/test/renderer/specs/types/ExpandType.NestedBehavior1.AExpanded.json
@@ -70,7 +70,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -95,7 +95,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -120,7 +120,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/types/ExpandType.NestedBehavior1.AllExpanded.json b/src/test/renderer/specs/types/ExpandType.NestedBehavior1.AllExpanded.json
index 69dd59a7a..70b147fe8 100644
--- a/src/test/renderer/specs/types/ExpandType.NestedBehavior1.AllExpanded.json
+++ b/src/test/renderer/specs/types/ExpandType.NestedBehavior1.AllExpanded.json
@@ -65,7 +65,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -90,7 +90,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -115,7 +115,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
diff --git a/src/test/renderer/specs/types/GH2982.TMXNode.json b/src/test/renderer/specs/types/GH2982.TMXNode.json
new file mode 100644
index 000000000..31febec59
--- /dev/null
+++ b/src/test/renderer/specs/types/GH2982.TMXNode.json
@@ -0,0 +1,120 @@
+{
+ "div.container.container-main": [
+ {
+ "div.col-content": [
+ {
+ "div.tsd-page-title": [
+ {
+ "tag": "ul.tsd-breadcrumb",
+ "props": {
+ "aria-label": "Breadcrumb"
+ },
+ "children": [
+ {
+ "li": {
+ "tag": "a",
+ "props": {
+ "href": "../modules/GH2982.json"
+ },
+ "children": "GH2982"
+ }
+ },
+ {
+ "li": {
+ "tag": "a",
+ "props": {
+ "href": "",
+ "aria-current": "page"
+ },
+ "children": "TMXNode"
+ }
+ }
+ ]
+ },
+ {
+ "h1": "Type Alias TMXNode"
+ }
+ ]
+ },
+ {
+ "div.tsd-signature": [
+ {
+ "span.tsd-kind-type-alias": "TMXNode"
+ },
+ {
+ "span.tsd-signature-symbol": ":"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "{}"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "&"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "{"
+ },
+ " ",
+ {
+ "span.tsd-kind-property": "base"
+ },
+ {
+ "span.tsd-signature-symbol": ":"
+ },
+ " ",
+ {
+ "tag": "a.tsd-signature-type.tsd-kind-type-parameter",
+ "props": {
+ "href": "#t"
+ },
+ "children": "T"
+ },
+ " ",
+ {
+ "span.tsd-signature-symbol": "}"
+ }
+ ]
+ },
+ {
+ "section.tsd-panel": [
+ {
+ "h4": "Type Parameters"
+ },
+ {
+ "ul.tsd-type-parameter-list": {
+ "li": {
+ "span#t": {
+ "span.tsd-kind-type-parameter": "T"
+ }
+ }
+ }
+ }
+ ]
+ },
+ {
+ "aside.tsd-sources": {
+ "ul": {
+ "li": [
+ "Defined in ",
+ {
+ "tag": "a",
+ "props": {
+ "href": "gh2982.ts"
+ },
+ "children": "gh2982.ts:1"
+ }
+ ]
+ }
+ }
+ }
+ ]
+ },
+ {
+ "div.col-sidebar": {
+ "div.page-menu": []
+ }
+ }
+ ]
+}
diff --git a/src/test/renderer/specs/types/Nested.json b/src/test/renderer/specs/types/Nested.json
index add5b69d4..cef1f3e4d 100644
--- a/src/test/renderer/specs/types/Nested.json
+++ b/src/test/renderer/specs/types/Nested.json
@@ -55,7 +55,7 @@
{
"br": []
},
- " ",
+ " ",
{
"tag": "a.tsd-kind-property",
"props": {
@@ -73,7 +73,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-kind-property": "anotherValue"
},
@@ -90,7 +90,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-kind-property": "emptyObject"
},
@@ -107,7 +107,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-kind-property": "moreOptions"
},
@@ -139,7 +139,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-kind-property": "value"
},
@@ -156,7 +156,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-signature-symbol": "}"
},
@@ -274,7 +274,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-kind-property": "anotherValue"
},
@@ -291,7 +291,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-kind-property": "emptyObject"
},
@@ -308,7 +308,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-kind-property": "moreOptions"
},
@@ -340,7 +340,7 @@
{
"br": []
},
- " ",
+ " ",
{
"span.tsd-kind-property": "value"
},
diff --git a/src/test/renderer/testRendererUtils.ts b/src/test/renderer/testRendererUtils.ts
index 1ecdd812f..544e441a7 100644
--- a/src/test/renderer/testRendererUtils.ts
+++ b/src/test/renderer/testRendererUtils.ts
@@ -48,7 +48,7 @@ function collapseStrings(data: any[]): unknown {
function renderElementToSnapshot(element: JsxChildren): unknown {
if (typeof element === "string" || typeof element === "number" || typeof element === "bigint") {
- return element.toString();
+ return element.toString().replaceAll("\u00a0", " ");
}
if (!element || typeof element === "boolean") {
diff --git a/src/test/utils/options/declaration.test.ts b/src/test/utils/options/declaration.test.ts
index cd943ab53..ef0252fab 100644
--- a/src/test/utils/options/declaration.test.ts
+++ b/src/test/utils/options/declaration.test.ts
@@ -239,6 +239,32 @@ describe("Options - conversions", () => {
new Error("The 'test' option must be set to an array of strings"),
);
+ equal(
+ convert("a,b", optionWithType(ParameterType.PluginArray), ""),
+ ["a,b"],
+ );
+ equal(
+ convert(
+ ["a,b"],
+ optionWithType(ParameterType.PluginArray),
+ "",
+ ),
+ ["a,b"],
+ );
+ const fn = () => {};
+ equal(
+ convert(
+ ["a", fn],
+ optionWithType(ParameterType.PluginArray),
+ "",
+ ),
+ ["a", fn],
+ );
+ throws(
+ () => convert(true, optionWithType(ParameterType.PluginArray), ""),
+ new Error("The 'test' option must be set to an array of strings/functions"),
+ );
+
throws(
() => convert(true, optionWithType(ParameterType.GlobArray), ""),
new Error("The 'test' option must be set to an array of strings"),
@@ -256,6 +282,17 @@ describe("Options - conversions", () => {
);
});
+ it("PluginArray is resolved if relative", () => {
+ equal(
+ convert(
+ ["./foo"],
+ optionWithType(ParameterType.PluginArray),
+ "",
+ ),
+ [normalizePath(join(process.cwd(), "foo"))],
+ );
+ });
+
it("Validates array options", () => {
const declaration: ArrayDeclarationOption = {
name: "test",
@@ -519,6 +556,21 @@ describe("Options - default values", () => {
);
});
+ it("PluginArray", () => {
+ equal(
+ getDefaultValue(getDeclaration(ParameterType.PluginArray, void 0)),
+ [],
+ );
+ equal(
+ getDefaultValue(getDeclaration(ParameterType.PluginArray, ["a"])),
+ ["a"],
+ );
+ equal(
+ getDefaultValue(getDeclaration(ParameterType.PluginArray, ["./a"])),
+ [normalizePath(resolve("./a"))],
+ );
+ });
+
it("GlobArray", () => {
equal(
getDefaultValue(getDeclaration(ParameterType.GlobArray, void 0)),
diff --git a/src/test/utils/options/default-options.test.ts b/src/test/utils/options/default-options.test.ts
index 5975bd99c..8b9ab552c 100644
--- a/src/test/utils/options/default-options.test.ts
+++ b/src/test/utils/options/default-options.test.ts
@@ -161,11 +161,15 @@ describe("Default Options", () => {
describe("blockTags", () => {
it("Should disallow non-tags", () => {
- throws(() => opts.setValue("blockTags", ["@bad-non-tag"]));
+ throws(() => opts.setValue("blockTags", ["@bad_tag"]));
+ throws(() => opts.setValue("blockTags", ["@2bad"]));
});
it("Should allow tags", () => {
doesNotThrow(() => opts.setValue("blockTags", ["@good"]));
+ doesNotThrow(() => opts.setValue("blockTags", ["@good2"]));
+ doesNotThrow(() => opts.setValue("blockTags", ["@Good"]));
+ doesNotThrow(() => opts.setValue("blockTags", ["@good-tag"]));
});
});
diff --git a/src/test/utils/plugins.test.ts b/src/test/utils/plugins.test.ts
index 31f5962ba..0199d5ab6 100644
--- a/src/test/utils/plugins.test.ts
+++ b/src/test/utils/plugins.test.ts
@@ -1,8 +1,9 @@
import { tempdirProject } from "@typestrong/fs-fixture-builder";
-import type { Application } from "../../index.js";
+import { type Application, normalizePath } from "../../index.js";
import { loadPlugins } from "../../lib/utils/plugins.js";
import { TestLogger } from "../TestLogger.js";
import { join, resolve } from "path";
+import { deepStrictEqual as equal } from "assert/strict";
describe("loadPlugins", () => {
let logger: TestLogger;
@@ -20,7 +21,7 @@ describe("loadPlugins", () => {
project.addFile("index.js", "exports.load = function load() {}");
project.write();
- const plugin = resolve(project.cwd, "index.js");
+ const plugin = normalizePath(resolve(project.cwd, "index.js"));
await loadPlugins(fakeApp, [plugin]);
logger.expectMessage(`info: Loaded plugin ${plugin}`);
});
@@ -31,10 +32,12 @@ describe("loadPlugins", () => {
type: "commonjs",
main: "index.js",
});
- const plugin = project.addFile(
- "index.js",
- "exports.load = function load() {}",
- ).path;
+ const plugin = normalizePath(
+ project.addFile(
+ "index.js",
+ "exports.load = function load() {}",
+ ).path,
+ );
project.write();
await loadPlugins(fakeApp, [plugin]);
@@ -50,11 +53,21 @@ describe("loadPlugins", () => {
project.addFile("index.js", "export function load() {}");
project.write();
- const plugin = join(resolve(project.cwd), "index.js");
+ const plugin = normalizePath(join(resolve(project.cwd), "index.js"));
await loadPlugins(fakeApp, [plugin]);
logger.expectMessage(`info: Loaded plugin ${plugin}`);
});
+ it("Should support loading a function plugin", async () => {
+ let called = false as boolean;
+ function testFn() {
+ called = true;
+ }
+ await loadPlugins(fakeApp, [testFn]);
+ logger.expectMessage(`info: Loaded plugin testFn`);
+ equal(called, true);
+ });
+
it("Should handle errors when requiring plugins", async () => {
using project = tempdirProject();
project.addJsonFile("package.json", {
@@ -64,7 +77,7 @@ describe("loadPlugins", () => {
project.addFile("index.js", "throw Error('bad')");
project.write();
- const plugin = join(resolve(project.cwd), "index.js");
+ const plugin = normalizePath(join(resolve(project.cwd), "index.js"));
await loadPlugins(fakeApp, [plugin]);
logger.expectMessage(`error: The plugin ${plugin} could not be loaded`);
});
@@ -81,7 +94,7 @@ describe("loadPlugins", () => {
);
project.write();
- const plugin = join(resolve(project.cwd), "index.js");
+ const plugin = normalizePath(join(resolve(project.cwd), "index.js"));
await loadPlugins(fakeApp, [plugin]);
logger.expectMessage(`error: The plugin ${plugin} could not be loaded`);
});
@@ -95,7 +108,7 @@ describe("loadPlugins", () => {
project.addFile("index.js", "");
project.write();
- const plugin = join(resolve(project.cwd), "index.js");
+ const plugin = normalizePath(join(resolve(project.cwd), "index.js"));
await loadPlugins(fakeApp, [plugin]);
logger.expectMessage(
`error: Invalid structure in plugin ${plugin}, no load function found`,