diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..220e029 --- /dev/null +++ b/.editorconfig @@ -0,0 +1,14 @@ +# https://editorconfig.org + +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 4 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true + +[package.json] +indent_size = 2 diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 6cd9a23..0e0dd58 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -12,18 +12,18 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v2.0.0 + uses: actions/checkout@v4 - name: Setup Node - uses: actions/setup-node@v3 + uses: actions/setup-node@v4 with: - node-version: 16 + node-version: 20 - name: Run run: chmod +x run.sh && ./run.sh - name: Upload Results - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: typedoc-output path: docs diff --git a/.gitignore b/.gitignore index d3d3c53..f2b8dce 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ node_modules -docs -build dist +docs +*.tsbuildinfo +docs-json diff --git a/README.md b/README.md index 2a3e09f..a376430 100644 --- a/README.md +++ b/README.md @@ -1,15 +1,36 @@ -# TypeDoc reproductions +# TypeDoc Packages Example -If you find a bug in TypeDoc and file an issue, it's helpful -- even necessary -- to create a minimal reproduction of the bug. +This monorepo provides an example of how TypeDoc's packages mode can be used to generate documentation +for multiple projects and combine it into a single site which contains all documented projects. -This link explains why we ask for a minimal reproduction. Thank you in advance! -https://gist.github.com/Rich-Harris/88c5fc2ac6dc941b22e7996af05d70ff +You can see the result of building this at -One way to do that is opening a pull-request on this repository with your reproduction. Github Actions will execute `./run.sh`. +## Building -You can put anything you want here: add/remove dependencies in `package.json`, change the commands in `run.sh`, change the code in `./src/index.ts`, -or add a hundred more `.ts` files. +```bash +git clone git@github.com:Gerrit0/typedoc-packages-example.git +npm install -Once your pull request is submitted here, link to it in your TypeDoc bug report. +# We need to build before building the docs so that `foo` can reference types from `bar` +# TypeDoc can't use TypeScript's build mode to do this for us because build mode may skip +# a project that needs documenting, or include packages that shouldn't be included in the docs +npm run build -Forked from the [ts-node-repros](https://github.com/TypeStrong/ts-node-repros) for TypeDoc. +# Now, we can run TypeDoc with packages mode to generate a single docs folder +npm run docs +``` + +## Building - Advanced + +If your build system requires running with multiple versions of TypeDoc, you can instead manually +generate JSON files for each package, and then run TypeDoc on the generated JSON files. + +```bash +# Cross-package links will be invalid during initial conversion, they will be validated when merging +for package in packages/*; do + npx typedoc --json docs-json/$(basename $package).json --options $package/typedoc.json --validation.invalidLink false +done + +# Merge previously generated documentation together into a site +npx typedoc --entryPointStrategy merge "docs-json/*.json" +``` diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..8e11ba6 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,220 @@ +{ + "name": "typedoc-packages-example", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "typedoc-packages-example", + "version": "1.0.0", + "workspaces": [ + "packages/*" + ], + "dependencies": { + "typedoc": "^0.26.3", + "typescript": "^5.5.2" + } + }, + "node_modules/@shikijs/core": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/@shikijs/core/-/core-1.10.0.tgz", + "integrity": "sha512-BZcr6FCmPfP6TXaekvujZcnkFmJHZ/Yglu97r/9VjzVndQA56/F4WjUKtJRQUnK59Wi7p/UTAOekMfCJv7jnYg==" + }, + "node_modules/@typedoc/lib": { + "resolved": "packages/lib", + "link": true + }, + "node_modules/@typedoc/shared-assets": { + "resolved": "packages/shared-assets", + "link": true + }, + "node_modules/@typedoc/wrapping-lib": { + "resolved": "packages/wrapping-lib", + "link": true + }, + "node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==", + "license": "Python-2.0" + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/linkify-it": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/linkify-it/-/linkify-it-5.0.0.tgz", + "integrity": "sha512-5aHCbzQRADcdP+ATqnDuhhJ/MRIqDkZX5pyjFHRRysS8vZ5AbqGEoFIb6pYHPZ+L/OC2Lc+xT8uHVVR5CAK/wQ==", + "license": "MIT", + "dependencies": { + "uc.micro": "^2.0.0" + } + }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==" + }, + "node_modules/markdown-it": { + "version": "14.1.0", + "resolved": "https://registry.npmjs.org/markdown-it/-/markdown-it-14.1.0.tgz", + "integrity": "sha512-a54IwgWPaeBCAAsv13YgmALOF1elABB08FxO9i+r4VFk5Vl4pKokRPeX8u5TCgSsPi6ec1otfLjdOpVcgbpshg==", + "license": "MIT", + "dependencies": { + "argparse": "^2.0.1", + "entities": "^4.4.0", + "linkify-it": "^5.0.0", + "mdurl": "^2.0.0", + "punycode.js": "^2.3.1", + "uc.micro": "^2.1.0" + }, + "bin": { + "markdown-it": "bin/markdown-it.mjs" + } + }, + "node_modules/mdurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mdurl/-/mdurl-2.0.0.tgz", + "integrity": "sha512-Lf+9+2r+Tdp5wXDXC4PcIBjTDtq4UKjCPMQhKIuzpJNW0b96kVqSwW0bT7FhRSfmAiFYgP+SCRvdrDozfh0U5w==", + "license": "MIT" + }, + "node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/punycode.js": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz", + "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==", + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/shiki": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-1.10.0.tgz", + "integrity": "sha512-YD2sXQ+TMD/F9BimV9Jn0wj35pqOvywvOG/3PB6hGHyGKlM7TJ9tyJ02jOb2kF8F0HfJwKNYrh3sW7jEcuRlXA==", + "dependencies": { + "@shikijs/core": "1.10.0" + } + }, + "node_modules/typedoc": { + "version": "0.26.3", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.26.3.tgz", + "integrity": "sha512-6d2Sw9disvvpdk4K7VNjKr5/3hzijtfQVHRthhDqJgnhMHy1wQz4yPMJVKXElvnZhFr0nkzo+GzjXDTRV5yLpg==", + "dependencies": { + "lunr": "^2.3.9", + "markdown-it": "^14.1.0", + "minimatch": "^9.0.5", + "shiki": "^1.9.1", + "yaml": "^2.4.5" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 18" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x" + } + }, + "node_modules/typescript": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.2.tgz", + "integrity": "sha512-NcRtPEOsPFFWjobJEtfihkLCZCXZt/os3zf8nTxjVH3RvTSxjrCamJpbExGvYOF+tFHc3pA65qpdwPbzjohhew==", + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uc.micro": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/uc.micro/-/uc.micro-2.1.0.tgz", + "integrity": "sha512-ARDJmphmdvUk6Glw7y9DQ2bFkKBHwQHLi2lsaH6PPmz/Ka9sFOBsBluozhDltWmnv9u/cF6Rt87znRTPV+yp/A==", + "license": "MIT" + }, + "node_modules/yaml": { + "version": "2.4.5", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.4.5.tgz", + "integrity": "sha512-aBx2bnqDzVOyNKfsysjA2ms5ZlnjSAW2eG3/L5G/CSujfjLJTJsEw1bGw8kCf04KodQWk1pxlGnZ56CRxiawmg==", + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, + "packages/bar": { + "name": "@typedoc/bar", + "version": "0.0.1", + "extraneous": true + }, + "packages/baz": { + "name": "@typedoc/baz", + "version": "0.0.1", + "extraneous": true + }, + "packages/foo": { + "name": "@typedoc/foo", + "version": "0.0.2", + "extraneous": true, + "dependencies": { + "@typedoc/bar": "0.0.1" + } + }, + "packages/lib": { + "name": "@typedoc/lib", + "version": "0.0.1" + }, + "packages/shared-assets": { + "name": "@typedoc/shared-assets", + "version": "0.0.1" + }, + "packages/wrapping-lib": { + "name": "@typedoc/wrapping-lib", + "version": "0.0.2", + "dependencies": { + "@typedoc/lib": "0.0.1" + } + } + } +} diff --git a/package.json b/package.json index a94cd64..2d4a0b2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,17 @@ { - "name": "typedoc-repros", + "name": "typedoc-packages-example", + "version": "1.0.0", + "private": true, + "workspaces": [ + "packages/*" + ], + "scripts": { + "build": "tsc --build", + "docs": "typedoc", + "docs-all": "npm run docs --workspaces --if-present" + }, "dependencies": { - "typedoc": "latest", - "typescript": "latest" + "typedoc": "^0.26.3", + "typescript": "^5.5.2" } } diff --git a/packages/lib/README.md b/packages/lib/README.md new file mode 100644 index 0000000..1bdae8a --- /dev/null +++ b/packages/lib/README.md @@ -0,0 +1,3 @@ +# lib + +Simple package which is depended upon by the `wrapping-lib` package. diff --git a/packages/lib/package.json b/packages/lib/package.json new file mode 100644 index 0000000..83cde17 --- /dev/null +++ b/packages/lib/package.json @@ -0,0 +1,8 @@ +{ + "name": "@typedoc/lib", + "version": "0.0.1", + "exports": "./dist/index.js", + "scripts": { + "docs": "typedoc --out docs" + } +} diff --git a/packages/lib/src/func.ts b/packages/lib/src/func.ts new file mode 100644 index 0000000..0a5b32f --- /dev/null +++ b/packages/lib/src/func.ts @@ -0,0 +1,6 @@ +import type { LibInt } from "./intf"; + +export function libFunc(): LibInt { + console.log("Bar"); + return { bar: true }; +} diff --git a/packages/lib/src/index.ts b/packages/lib/src/index.ts new file mode 100644 index 0000000..6d84d43 --- /dev/null +++ b/packages/lib/src/index.ts @@ -0,0 +1,2 @@ +export * from "./func"; +export type * from "./intf"; diff --git a/packages/lib/src/intf.ts b/packages/lib/src/intf.ts new file mode 100644 index 0000000..d5daa2a --- /dev/null +++ b/packages/lib/src/intf.ts @@ -0,0 +1,4 @@ +export interface LibInt { + /** Assigned by {@link libFunc}. */ + bar: true; +} diff --git a/packages/lib/tsconfig.json b/packages/lib/tsconfig.json new file mode 100644 index 0000000..5285d28 --- /dev/null +++ b/packages/lib/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist" + }, + "include": ["src"] +} diff --git a/packages/lib/typedoc.json b/packages/lib/typedoc.json new file mode 100644 index 0000000..747ac77 --- /dev/null +++ b/packages/lib/typedoc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../typedoc.base.jsonc"], + "entryPoints": ["src/index.ts"] +} diff --git a/packages/shared-assets/README.md b/packages/shared-assets/README.md new file mode 100644 index 0000000..3341214 --- /dev/null +++ b/packages/shared-assets/README.md @@ -0,0 +1,7 @@ +# README only package + +This package only contains a readme file, without any entry points. This is intended to support +packages which don't export any JS, only shared assets. See [#2264](https://github.com/TypeStrong/typedoc/issues/2264). + +This package also does not contain a `docs` script in its `package.json`, so `npm run docs-all` will not run TypeDoc +within it, and therefore not generate a docs folder here. diff --git a/packages/shared-assets/package.json b/packages/shared-assets/package.json new file mode 100644 index 0000000..bee1d9e --- /dev/null +++ b/packages/shared-assets/package.json @@ -0,0 +1,4 @@ +{ + "name": "@typedoc/shared-assets", + "version": "0.0.1" +} diff --git a/packages/shared-assets/typedoc.json b/packages/shared-assets/typedoc.json new file mode 100644 index 0000000..4a0b645 --- /dev/null +++ b/packages/shared-assets/typedoc.json @@ -0,0 +1,5 @@ +{ + "extends": ["../../typedoc.base.jsonc"], + // If not set, will result in a warning being printed since it's likely a misconfiguration + "entryPoints": [] +} diff --git a/packages/wrapping-lib/README.md b/packages/wrapping-lib/README.md new file mode 100644 index 0000000..80de080 --- /dev/null +++ b/packages/wrapping-lib/README.md @@ -0,0 +1,5 @@ +# Foo + +This package depends on `bar` and contains exports which references types within it. + +This package's configuration is in the `tsconfig.json` file for this project. diff --git a/packages/wrapping-lib/package.json b/packages/wrapping-lib/package.json new file mode 100644 index 0000000..164fb7a --- /dev/null +++ b/packages/wrapping-lib/package.json @@ -0,0 +1,11 @@ +{ + "name": "@typedoc/wrapping-lib", + "version": "0.0.2", + "exports": "./dist/index.js", + "dependencies": { + "@typedoc/lib": "0.0.1" + }, + "scripts": { + "docs": "typedoc --out docs" + } +} diff --git a/packages/wrapping-lib/src/index.ts b/packages/wrapping-lib/src/index.ts new file mode 100644 index 0000000..7610a14 --- /dev/null +++ b/packages/wrapping-lib/src/index.ts @@ -0,0 +1,4 @@ +import type { LibInt } from "@typedoc/lib"; + +export interface WrappingInt extends LibInt { +} diff --git a/packages/wrapping-lib/tsconfig.json b/packages/wrapping-lib/tsconfig.json new file mode 100644 index 0000000..5285d28 --- /dev/null +++ b/packages/wrapping-lib/tsconfig.json @@ -0,0 +1,8 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "rootDir": "src", + "outDir": "dist" + }, + "include": ["src"] +} diff --git a/packages/wrapping-lib/typedoc.json b/packages/wrapping-lib/typedoc.json new file mode 100644 index 0000000..747ac77 --- /dev/null +++ b/packages/wrapping-lib/typedoc.json @@ -0,0 +1,4 @@ +{ + "extends": ["../../typedoc.base.jsonc"], + "entryPoints": ["src/index.ts"] +} diff --git a/run.sh b/run.sh index a656ae0..c046d74 100644 --- a/run.sh +++ b/run.sh @@ -4,7 +4,8 @@ set -e # Install package.json dependencies -yarn +npm ci # Run TypeDoc -yarn typedoc +npm run build +npm run docs diff --git a/tsconfig.base.json b/tsconfig.base.json new file mode 100644 index 0000000..e6e4de1 --- /dev/null +++ b/tsconfig.base.json @@ -0,0 +1,11 @@ +{ + "compilerOptions": { + "module": "Node16", + "strict": true, + "composite": true, + + // These options are necessary so that TypeDoc can resolve references across packages + "declaration": true, + "declarationMap": true + } +} diff --git a/tsconfig.json b/tsconfig.json index 8b08d45..627cfd6 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,6 +1,11 @@ { - "compilerOptions": { - "strict": true - }, - "include": ["src"] + "files": [], + "references": [ + { + "path": "./packages/lib" + }, + { + "path": "./packages/wrapping-lib" + } + ] } diff --git a/typedoc.base.jsonc b/typedoc.base.jsonc new file mode 100644 index 0000000..aabaf9f --- /dev/null +++ b/typedoc.base.jsonc @@ -0,0 +1,9 @@ +{ + // Note: In TypeDoc 0.26 you can instead specify `packageOptions` if running + // only with packages mode. The separate base config file is retained in this + // example so that individual packages can be built for demonstration of the + // advanced method in the readme. + + "$schema": "https://typedoc.org/schema.json", + "includeVersion": true +} diff --git a/typedoc.json b/typedoc.json index c990e40..51c535b 100644 --- a/typedoc.json +++ b/typedoc.json @@ -1,8 +1,19 @@ { - "$schema": "https://typedoc.org/schema.json", - "entryPoints": ["src/index.ts"], + "entryPoints": ["packages/*"], + "name": "Packages Example", + "entryPointStrategy": "packages", + "includeVersion": false - "treatWarningsAsErrors": true, - "out": "docs", - "json": "docs/docs.json" + // In TypeDoc 0.26 it is possible to specify options which should be inherited + // by packages here, instead of in a separate file which is extended by each + // package. We don't use this here as relying on it would prevent us from running + // TypeDoc individually in each package, which is required for the advanced method + // of generating monorepo documentation. + // "packageOptions": { + // "includeVersion": true, + // "entryPoints": ["src/index.ts"] + // } + + // Potentially useful for debugging + // "logLevel": "Verbose" }