jsdoc-scribe
v2.4.7
Published
Automated, AST-based JSDoc comment generator and static documentation site builder for JavaScript & TypeScript. Fast, deterministic, and 100% local (No AI involved).
Maintainers
Readme
jsdoc-scribe
Automated, AST-based JSDoc comment generator and static documentation site builder for JavaScript & TypeScript. Fast, deterministic, and 100% local (No AI involved). No AI. No LLM. No surprises. Same input always produces the same output.
Documentation
The official documentation site is available at imchintoo.github.io/jsdoc-scribe.
| Resource | Link | |---|---| | Website | What is jsdoc-scribe? | | Quick Start | Install and generate your first docs | | CLI Usage | Commands, checks, lint, and fix | | GitHub Pages | Deploy generated docs | | API Reference | Generated API docs | | Blog | Guides and release notes |
Two CLIs, one dependency (typescript >=5.0.0, used purely as a syntax parser), 234
passing tests (deterministic, zero network calls — same self-test suite runs on every
npm test and before every npm publish). typescript ships as a regular dependency,
not a peerDependency, because it parses every file this tool touches (.js included, not
just .ts) and can't be left for a consumer to optionally provide.
| Tool | What it does |
|---|---|
| gen-comments | Inserts /** */ JSDoc blocks into your source by reading the AST — no guessing |
| gen-docs | Builds a static, multi-page HTML documentation site from your documented source |
Preview
Sticky topnav with centered search, white sidebar with an N-level folder tree, two-column symbol cards (prose left / dark code panel right), and a scroll-spy TOC on module pages.
Code Health dashboard (--quality)
With --quality, the index page becomes a Code Health dashboard — health score,
maintainability, complexity, duplicate-code, and orphan-file stats, each linking to a full
detail page — and every module page gets a compact per-file health strip. Full breakdown:
Features.
Real-world sample code
sample/ is a real, runnable-shaped fixture set — not toy one-liners — covering the stacks
teams actually ship with:
| Path | Stack | What's in it |
|---|---|---|
| sample/express/ | Express.js (TS) | app.ts, routes, a controller, a service, and auth middleware for a small task API |
| sample/nestjs/ | NestJS (TS, decorators) | A UsersModule with @Controller/@Injectable classes, a DTO using class-validator decorators, an entity, and a guard |
| sample/vanilla-js/ | Plain JavaScript (CommonJS, no types) | A logger, an event emitter, a retry/circuit-breaker helper, and input validators |
| sample/*.ts (top-level) | Generic TS | A fully-documented DI container, error hierarchy, event bus, HTTP middleware, models, and API layer — used as the "already good" reference case for --check-drift/--lint |
Run any of the CLIs directly against them to see real output on real code, not a demo script:
gen-comments sample/nestjs --dry-run # see what would be generated for decorator-heavy NestJS classes
gen-comments sample/express --check # coverage on an undocumented Express app
gen-docs sample --out docs --title "jsdoc-scribe sample"Benchmarks
Measured directly against the CLIs, single Node process, no caching between runs.
| Source size | gen-comments --dry-run | gen-docs (single file) |
|---|---|---|
| 231 LOC | 1.15s · 96 MB | 0.49s · 94 MB |
| 23K LOC | 1.47s · 167 MB | 0.71s · 155 MB |
| 233K LOC | 4.17s · 345 MB | 2.29s · 445 MB |
Both CLIs scale close to linearly with source size. A real 1,000-file/70K-LOC project
finishes gen-comments --write in 1.03s at 115 MB. gen-docs's multi-file scaling
had a superlinear ceiling past ~300-500 files, fixed in v2.4.2 (400→1,000 files is now
~5.2x time for 2.5x files, down from an unbounded curve) — enforced continuously by
npm run bench:perf-gate in CI. Full numbers and root cause: CHANGELOG;
residual memory-footprint notes at very large file counts: Known limitations.
Install
npx jsdoc-scribe . --write # run once, no install
npm install --save-dev jsdoc-scribe # add to project
npm install -g jsdoc-scribe # or install globallyThree ways to use jsdoc-scribe
Comments, docs, and lint are all reachable from the CLI, from inside your own Node code, or wired into CI — pick whichever fits the moment. Everything below is expanded in its own section further down; this is the map.
| | Comments (gen-comments) | Docs (gen-docs) | Lint (--lint) |
|---|---|---|---|
| CLI | gen-comments src --write | gen-docs src --out docs | gen-comments src --lint / --lint --fix |
| Inside your codebase | require('jsdoc-scribe').processFile(file, { write: true }) | require('jsdoc-scribe/docs').generateSite(['src'], opts) | require('jsdoc-scribe/lint').lintModule(moduleData) |
| GitHub Actions | run: npx gen-comments src --check (PR gate) | run: npx gen-docs src --out _site (Pages deploy) | run: npx gen-comments src --lint (PR gate) |
1. CLI
gen-comments src --write # insert missing JSDoc blocks in place
gen-comments src --check # CI gate: fail if anything is undocumented
gen-comments src --check-drift # CI gate: fail if JSDoc has drifted from the AST
gen-comments src --lint --fix # validate JSDoc content, autofix what's safe to fix
gen-docs src --out docs --quality # build the docs site (add --quality for the Code Health dashboard)Full flag references and walkthroughs live on the docs site: Quick Start · CLI Usage · Features.
2. Inside your codebase
Every CLI capability is also a plain function import — no child-process spawning, no
parsing your own stdout. Three subpath exports, one per capability, all with hand-written
TypeScript declarations (no @types/jsdoc-scribe needed):
const { processFile, analyseFile, collectFiles } = require('jsdoc-scribe'); // comments
const { generateSite, extractModule } = require('jsdoc-scribe/docs'); // docs
const { lintModule } = require('jsdoc-scribe/lint'); // lintFull walkthrough with real return shapes: Programmatic API.
3. GitHub Actions
Every CLI flag is a plain process exit code (0/1), so any of them drop straight into a
run: step. Copy-pasteable workflows (a PR quality gate covering comments + drift + lint,
plus a docs-to-Pages deploy) are documented in
GitHub Actions Integration
and GitHub Pages Deployment —
this repo's own test.yml, docs.yml,
and publish.yml (npm OIDC trusted publishing, no stored
token) are the same workflows running live.
Highlights
- JSDoc linting without ESLint.
gen-comments --lintruns the same category of checks eslint-plugin-jsdoc'srecommendedconfig does — missing tags, bad ordering, blank descriptions — with zero new dependencies.--lint --fixrewrites what's mechanically safe to fix (tag order, stray asterisks, placeholderTODO:descriptions) and never touches what it can't safely resolve (a missing block entirely, or a typo'd tag name). - Already on ESLint? The same rules ship as a native flat-config plugin —
packages/eslint-plugin-jsdoc-scribe— so findings and fixes show up in your existingeslint/eslint --fixrun instead of a separate CLI invocation. - Optional code-quality dashboard.
gen-docs --qualitycan run code-multivitals (complexity, maintainability, duplicate-code, orphan-file detection) against the same files it documents. It's an optionalpeerDependency— never installed by default, andgen-docsbehaves identically whether it's present or not. - Config file support.
.jsdoc-scribe.jsonforgen-docsoutput dir, title, source URL, and ignore globs — CLI flags override it. Full reference: Features.
Contributing
Bug reports and PRs welcome — see CONTRIBUTING.md for dev setup and guidelines (determinism is non-negotiable, no new runtime dependency without discussion first). This project follows the Code of Conduct. Found a security issue? See SECURITY.md rather than opening a public issue with exploit details.
Known limitations
- Inline anonymous callbacks (
arr.map(x => x * 2)) aren't documented — named declarations only. - Type inference is 100% syntactic — no evaluation, no imports, no type-checking.
- Multi-declarator statements (
const a = 1, b = 2;) get one combined block. .d.tsfiles are skipped.gen-docsdoesn't serve — usenpx serve docsor deploy statically.gen-docs's per-page superlinear scaling past ~300-500 files (unmemoized sidebar path-prefix recomputation) is fixed as of v2.4.2 — see Benchmarks and the CHANGELOG. The parse phase (TS Compiler API per file) was profiled and confirmed not co-dominant at the file counts tested, so it stays single-threaded (worker_threadsexplicitly out of scope for this fix — seedocs/backlog/adr-linear-scaling-fix.md).gen-docsholds every generated page's full HTML (including its own embedded sidebar markup) in memory until the whole site has been built, then writes it all to disk — at very large file counts (order of thousands) this is a memory-footprint concern independent of the scaling fix above. Not yet sized against real hardware; tracked indocs/backlog/task-ls-04-sidebar-node-caching.md's implementation notes.
See CHANGELOG.md for release history.
License
MIT © Chintan
