The api-links generator reads your JavaScript sources and writes
apilinks.json, which maps each exported API, such as fs.readFile, to the
line on GitHub that defines it. It's built for the Node.js lib/ folder, and
works for any CommonJS codebase laid out the same way.
Target: api-links · Package: @node-core/doc-kit · Reads: Parsing JavaScript · Writes: apilinks.json
The other doc-kit generators don't read apilinks.json, so load it from your
own tooling. To link a page of the
website to its source file, use
the source_link directive instead (see
Page metadata).
The links are GitHub URLs, so the generator needs your repository. There is no flag for it, so set it in your configuration file:
export default { global: { repository: 'my-org/my-lib', }, };
npm install --save-dev @doc-kit/cli @node-core/doc-kit npx doc-kit generate -t api-links -i "lib/*.js" -o out
This writes out/apilinks.json. Links point at HEAD; pass --git-ref to
link to a tag or commit, such as --git-ref v24.0.0. To build the Node.js
docs, extend the
Node.js preset
instead, which sets nodejs/node.
Without a repository, every link keeps the literal {repository}
placeholder, and nothing warns you about it.
Options go in the api-links section of the configuration file:
string'https://github.com/{repository}/blob/{ref}/lib/{fileName}'.stringowner/name.
Default: from global.repository.string'HEAD', from global.ref (--git-ref).stringapilinks.json to. Without one,
nothing is written. Default: from global.output (--output).booleanfalse, from global.minify (--minify).In sourceURL, {fileName} is the source file's name, such as fs.js,
without its directories. Other placeholders take configuration values, global
options included, such as {repository}, {ref} and {version}, and
{name|fallback} uses fallback when the option has no value. {version} has
no leading v (24.0.0), so write v{version} to point at a release tag.
Each link is the filled-in template followed by #L and a line number.
The default assumes the files live in lib/ at the root of a GitHub
repository. For sources in src/ on GitLab:
export default { 'api-links': { sourceURL: 'https://gitlab.com/{repository}/-/blob/{ref}/src/{fileName}', }, };
The Parsing JavaScript stage
reads the files input matches and parses them with Acorn:
- Only files ending in
.jsare read. Other matches,.cjsand.mjsincluded, are skipped. - Files are parsed as CommonJS scripts. A file that uses
importorexportstops the run with a syntax error. - Links use the file's name without its directories, so match the files of a
single folder, as
lib/*.jsdoes. Withlib/**/*.js,lib/internal/util.jswould link tolib/util.js, and files with the same name would overwrite each other's keys.
When the same run builds the website or other Markdown targets, give the
JavaScript to ast-js through its own input, and keep global.input for
your docs (see
Parsing JavaScript).
apilinks.json is one flat object for all the input files. Each key names an
API, and each value links to the line that defines it. For this file:
'use strict'; function readFile() {} class Stats { constructor() {} isFile() {} } function Dirent() {} Dirent.prototype.isDirectory = function () {}; Dirent.from = function () {}; module.exports = { readFile, Stats, Dirent, };
the generator writes:
{ "fs.readFile": "https://github.com/my-org/my-lib/blob/HEAD/lib/fs.js#L3", "Stats": "https://github.com/my-org/my-lib/blob/HEAD/lib/fs.js#L5", "new Stats": "https://github.com/my-org/my-lib/blob/HEAD/lib/fs.js#L6", "stats.isFile": "https://github.com/my-org/my-lib/blob/HEAD/lib/fs.js#L7", "fs.Dirent": "https://github.com/my-org/my-lib/blob/HEAD/lib/fs.js#L10", "dirent.isDirectory": "https://github.com/my-org/my-lib/blob/HEAD/lib/fs.js#L12", "Dirent.from": "https://github.com/my-org/my-lib/blob/HEAD/lib/fs.js#L13" }
The generator first finds what each file exports, then where each export is
defined. With the file named fs.js:
| In the source | Key | Links to |
|---|---|---|
function readFile() {}, exported as module.exports = { readFile } or exports.readFile = readFile | fs.readFile | The function |
exports.writeFile = function () {} | fs.writeFile | The assignment |
class Stats {}, exported as module.exports = { Stats } | Stats | The class |
The class's constructor() | new Stats | The constructor |
A method of the class, such as isFile() | stats.isFile | The method |
function Dirent() {}, exported as module.exports = { Dirent } | fs.Dirent | The function |
Dirent.prototype.isDirectory = function () {} | dirent.isDirectory | The assignment |
Dirent.from = function () {} | Dirent.from | The assignment |
const assert = module.exports = ok | assert | The declaration |
assert.strictEqual = function () {} | assert.strictEqual | The assignment |
- A class, and the members of a class or constructor function, are picked up
for a capitalized name listed in
module.exports = { ... }, for the class inmodule.exports = new Agent(), and for the variable inconst assert = module.exports = ok. The last two work whatever the name's case. - Prototype methods lowercase the whole name (
Direntbecomesdirent), and the methods of aclass, static ones included, lowercase only its first letter (WASIbecomeswASI).Bufferprototype methods usebufinstead, as inbuf.toString, matching the Node.js docs. - A function exported as
deprecate(fn, message)inmodule.exports = { ... }counts asfn. - In a file whose name starts with
_, functions exported by name throughmodule.exports(asmodule.exports = { fn }ormodule.exports.fn = fn) are left out as internal. Functions exported throughexports.fn = ...are still linked. - Other forms aren't linked, among them arrow functions
(
exports.read = () => {}),module.exports.read = function () {}, and classes exported asmodule.exports.Agent = Agentormodule.exports = Agent.