Version: 1.0.1
Authored By: Aviv Keller (me@aviv.sh)
This document specifies the Markdown format consumed by
@node-core/doc-kit. It defines the structural, syntactic, and
semantic rules that documents MUST follow to be correctly parsed. The format
is a strict superset of GitHub Flavored Markdown (which itself is a
strict superset of CommonMark), adding conventions for API
metadata, type annotations, stability indicators, and structured parameter
lists.
Because this format is a superset, all constructs valid in GFM remain valid here. This specification only defines the additional constraints and semantics layered on top. Where a GFM construct is given special meaning by this specification (e.g., blockquotes as stability indicators, unordered lists as typed parameter lists), that special meaning is documented in the relevant section.
- 1. Terminology and Conventions
- 2. Conformance
- 3. Document Structure
- 4. Headings
- 5. Signature Syntax
- 6. YAML Comment Blocks
- 7. Stability Indicators
- 8. Type Annotations
- 9. Typed Parameter Lists
- 10. Code Blocks
- 11. Links and Cross-References
The key words "MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT", "SHOULD", "SHOULD NOT", "RECOMMENDED", "NOT RECOMMENDED", "MAY", and "OPTIONAL" in this document are to be interpreted as described in BCP 14 (RFC 2119, RFC 8174) when, and only when, they appear in ALL CAPITALS, as shown here.
The following terms are used throughout this specification with the meanings given below.
Document. A single Markdown source file conforming to this specification. Each document describes one API module, one conceptual topic, or one index listing.
Entry. A discrete API element within a document. An entry begins at a heading and extends to the next heading of equal or lesser depth, or to the end of the file. An entry comprises a heading, optional YAML metadata, optional stability indicator, optional typed parameter list, and a prose body.
Section. A contiguous range of entries sharing a common parent heading.
Typed list. An unordered list whose items follow the typed parameter syntax defined in §9. Typed lists provide structured type, default-value, and description metadata for function parameters, return values, or object properties.
Stability indicator. A blockquote element whose text content begins with
Stability: followed by a numeric level, indicating the API lifecycle stage
of the enclosing entry. See §7.
YAML metadata block. An HTML comment whose content
begins with the keyword YAML and contains YAML 1.2 data
providing version-history and classification metadata for the enclosing
entry. See §6.
Simple directive. An HTML comment whose content follows
the compact key=value pattern, providing document-level or
section-level metadata. See §6.2.
Type annotation. A TypeScript type expression enclosed in
balanced {curly braces} within a typed list item, or in
prose. It is rendered as a single code fragment whose type names are resolved
to hyperlinks. See §8.
A conforming document MUST be valid GitHub Flavored Markdown (GFM), which is itself a superset of CommonMark. This specification is a strict superset of GFM: all GFM constructs are valid, and this specification layers additional structure and semantics on top.
Where this specification assigns special meaning to a GFM construct (for example, blockquotes used as stability indicators, or unordered lists used as typed parameter lists), that special meaning is defined in the relevant section. All other GFM constructs retain their standard behavior.
Documents MUST be encoded in UTF-8. A byte order mark (BOM) MUST NOT be present.
Documents SHOULD use LF (U+000A) line endings. Both LF and CRLF
(U+000D U+000A) MUST be accepted by a conforming implementation. Documents
MUST end with a trailing newline.
Indentation MUST use spaces. Tab characters (U+0009) MUST NOT appear in
document source except within fenced code block content, where they
reproduce literal output.
A conforming document MUST contain elements in the following order. Items marked OPTIONAL MAY be omitted entirely.
- Title heading (REQUIRED) - Exactly one ATX heading at depth 1.
- Simple directives (OPTIONAL) - Zero or more HTML comment directives providing document-level metadata. These MUST immediately follow the title heading.
- Module-level stability indicator (OPTIONAL) - A stability blockquote applying to the document as a whole.
- Introductory prose (OPTIONAL) - Free-form Markdown content.
- API entry sections (OPTIONAL, REPEATABLE) - One or more headings at depth 2 or greater, each introducing an entry. Each entry follows the sub-ordering in §3.2.
- Link reference definitions (OPTIONAL) - Collected at the end of the file, after all entry sections.
# Command-line API
<!--introduced_in=v5.9.1-->
<!--type=misc-->
Node.js comes with a variety of CLI options. These options expose built-in
debugging, multiple ways to execute scripts, and other helpful runtime options.Within each API entry, elements MUST appear in this order:
- Heading (REQUIRED) - An ATX heading.
- YAML metadata block (OPTIONAL) - Immediately following the heading, with no intervening content.
- Stability indicator (OPTIONAL) - A stability blockquote.
- Typed parameter list (OPTIONAL) - An unordered list describing parameters, return value, type, or extends clause.
- Prose body (OPTIONAL) - Free-form Markdown content.
- Code examples (OPTIONAL) - Fenced code blocks.
- Sub-entries (OPTIONAL, REPEATABLE) - Deeper headings beginning nested entries, following this same ordering recursively.
All headings MUST use ATX style (# prefix).
Setext-style headings (underline with = or -) MUST
NOT be used.
The document title. Exactly one depth-1 heading MUST appear per document.
Top-level API entries: classes, module-level functions, module-level properties, module-level events, and major conceptual sections.
Nested API entries: instance methods, instance properties, class events, constructors, static methods, sub-properties, and further nesting. Static methods SHOULD appear at one depth below their class heading.
Documents SHOULD NOT use heading depths greater than 5.
Each heading is classified into an entry type by testing its text against the patterns below, evaluated in the order given. The first match wins. All pattern matching is performed on the plain text of the heading after stripping the ATX prefix.
The heading text is a backtick-wrapped expression containing a dotted or bracketed receiver, a member accessor, and parentheses. The parentheses distinguish methods from properties.
### `fs.readFile(path[, options], callback)`
### `buf.write(string[, offset[, length]][, encoding])`
### `request[Symbol.asyncIterator]()`The heading text begins with the literal prefix Event: followed by optional
whitespace and a backtick-wrapped, single-quoted event name.
### Event: `'close'`
### Event: `'data'`The heading text begins with the literal prefix Class: followed by optional
whitespace and a backtick-wrapped class identifier. The class name SHOULD begin
with an uppercase ASCII letter.
## Class: `http.Server`
## Class: `EventEmitterAsyncResource`The heading text is a backtick-wrapped expression beginning with the keyword
new, followed by whitespace, then an uppercase-initial class identifier and
parenthesized parameters.
### `new Agent([options])`
### `new Buffer(size)`The heading text begins with the literal prefix Static method: followed by
optional whitespace and a backtick-wrapped qualified method call (with
parentheses).
#### Static method: `Buffer.alloc(size[, fill[, encoding]])`
#### Static method: `Buffer.from(string[, encoding])`The heading text is a backtick-wrapped dotted or bracketed property access that does not contain parentheses. The absence of parentheses distinguishes properties from methods.
### `buf.length`
### `os.EOL`
### `http.METHODS`If no pattern matches, the entry is classified as a miscellaneous section.
The document-level type directive determines how
classified entries are interpreted with respect to module
membership and export scope. The type establishes a default context for
all headings in the file. This context can be overridden at the
section level or at the individual entry level.
When type is module (or when no type directive is present, as module
is the default), classified entries are treated as exports of
the module identified by the document's filename or module simple directive.
A single module document MAY describe exports from more than one related
module (e.g., fs and fs/promises). The module boundary does not affect
entry classification or rendering; the classification algorithm in §4.3
operates identically regardless of which module an entry belongs to. Where the
distinction does matter (e.g., for import paths or module-specific rendering),
a module context override SHOULD be used.
# File system
<!--type=module-->
<!--name=fs-->When type is misc, headings are not assumed to be module exports.
Classified entries are treated as conceptual sections or
standalone topics.
# C++ addons
<!--type=misc-->When type is global, classified entries are treated as
global APIs, available without an import or require. Implementations
MAY render global entries differently from module exports (e.g., omitting a
module prefix).
# Global objects
<!--type=global-->The module simple directive overrides the owning module for all
sub-entries beneath the heading it is attached to. This allows a single
document to describe exports from multiple modules without splitting into
separate files.
## Promises API
<!--module=node:fs/promises-->
### `fsPromises.readFile(path[, options])`All headings beneath the annotated heading inherit the overridden module
context until the next heading of equal or lesser depth, or until another
module directive.
Individual entries MAY override their classification context
using the type field in a YAML metadata block:
### `globalThis.structuredClone(value[, options])`
<!-- YAML
added: v17.0.0
type: global
-->This is useful in module-type documents that contain isolated global entries,
or in misc-type documents that contain isolated module exports.
Programmatic identifiers (method names, property names, class names, event
names, flag names) MUST be wrapped in backtick code spans. Prose
section headings (e.g., ## Synopsis) MUST NOT use backticks.
Event names SHOULD be wrapped in single quotes inside the backticks:
### Event: `'drain'`When a single API entry has multiple invocation forms (e.g.,
short and long flag names), they SHOULD be listed in a single heading
separated by , :
### `-c`, `--check`Method and constructor headings encode their call signature directly in the heading text.
Required parameters appear as bare identifiers inside the parentheses:
### `fs.readFile(path, callback)`Optional parameters are wrapped in square brackets:
### `fs.readFile(path[, options], callback)`Parameters that are only meaningful when a preceding optional parameter is provided use nested brackets:
### `buf.write(string[, offset[, length]][, encoding])`Rest parameters use ellipsis notation within square brackets:
### `path.join([...paths])`Default values MUST NOT appear in the heading signature. Defaults are
documented in the typed parameter list using the **Default:** pattern.
Type annotations MUST NOT appear in the heading signature. Types are documented in the typed parameter list.
YAML metadata is embedded in HTML comments.
The opening delimiter is <!-- YAML (with at least one space before YAML)
and the closing delimiter is -->. The content between these delimiters MUST
be valid YAML 1.2.
<!-- YAML
added: v12.0.0
-->The comment MUST appear on its own lines. A heading MAY contain multiple YAML metadata blocks and related HTML comments within its subtree; such blocks MUST be merged into a single metadata object for that heading.
Document-level and section-level metadata
uses a compact key=value syntax inside HTML comments.
Each directive has the form <!--key=value-->.
Document-level directives (i.e. introduced_in) SHOULD appear immediately
after the depth-1 heading. Section-level directives (see §6.2.5)
SHOULD appear immediately after the heading they annotate.
# File System
<!--introduced_in=v0.10.0-->
<!--type=module-->
<!--name=fs-->
<!--source_link=lib/fs.js-->Each directive occupies exactly one HTML comment. The following keys are defined:
A version string indicating when the module was introduced.
The document classification. Recognized values are module,
misc, and global. Implementations MAY define additional values. If no
type directive is present, the default is module.
See §4.4 for how document type influences heading interpretation.
A relative file path to the implementation source. Rendered as a link.
A plain-text description optimized for consumption by Large Language Models, used in preference to extracted prose where available.
Overrides the owning module for all sub-entries beneath the annotated heading.
The value is a module specifier (e.g., node:fs/promises). This directive
is placed immediately after a heading, not after the depth-1 heading.
See §4.4.4 for full semantics.
## Promises API
<!--module=node:fs/promises-->The following fields are defined within YAML metadata blocks. Any field not listed here is reserved for future specification and MUST be ignored by conforming implementations that do not recognize it.
The version(s) in which this entry was first available.
- Type: version string, or array of version strings for backports.
- Example:
added: v8.0.0
When an API was backported, the array MUST list versions in descending order.
The version(s) in which this API was deprecated.
- Type: version string, or array of version strings.
- Example:
deprecated: v6.0.0
The version(s) in which this API was removed.
- Type: version string, or array of version strings.
- Example:
removed: v14.0.0
A chronological array of change records. Each record MUST contain the following properties:
version(REQUIRED) - A version string or array of version strings.pr-url(REQUIRED) - A full URL to the pull request.description(REQUIRED) - A human-readable description. Inline Markdown is permitted. Multi-line descriptions use YAML block-scalar indentation.
changes:
- version: v18.0.0
pr-url: https://github.com/nodejs/node/pull/41678
description: Passing an invalid callback now throws
`ERR_INVALID_ARG_TYPE`.
- version:
- v21.7.0
- v20.12.0
pr-url: https://github.com/nodejs/node/pull/51289
description: Added multi-line value support.When present in a YAML block, this overrides the heading classification type for the enclosing entry. It can also override the document-level export/global context as described in §4.4.5.
- Type: string (one of the type names defined in §4.3, or a
context value such as
global). - Example:
type: method
Relative path to the implementation source file. Identical semantics to the simple directive of the same name.
Identical semantics to the simple directive of the same name.
Version strings MUST follow semantic versioning with a lowercase
v prefix, in the form v<MAJOR>.<MINOR>.<PATCH>. Implementations MAY
define additional sentinel values for unreleased features (e.g., placeholder
strings that are replaced during a release process).
HTML comments that do not match the YAML block pattern and do not match the simple directive pattern are parsed as tags. If the content is a simple string, it is stored as a tag on the entry:
<!-- legacy -->Implementations MAY define reserved tag values for special purposes such as content slot markers.
Standard YAML frontmatter delimited by --- at the start of a
file is converted to a YAML comment block during
preprocessing. The following two forms are equivalent:
---
introduced_in: v0.10.0
---Documents SHOULD use the HTML comment syntax directly. Frontmatter is accepted for compatibility.
A YAML metadata block SHOULD immediately follow the heading it annotates. This placement is RECOMMENDED for clarity and consistency, but the parser accepts YAML blocks anywhere within the annotated entry's subtree.
A stability indicator is a blockquote whose first paragraph
begins with Stability: followed by a numeric level, a dash separator
(-), and a textual label. The level is an integer or a decimal
sub-level. The description extends to the end of the blockquote.
> [Stability: 2](documentation.html#stability-index) - StableFour stability levels are defined.
The feature may emit warnings. Backward compatibility is not guaranteed.
Not subject to semantic versioning rules. Non-backward-compatible changes or removal may occur in any future release.
Compatibility with the ecosystem is a high priority.
Still covered by semantic versioning guarantees, but no longer actively maintained. Other alternatives are available.
Level 1 supports decimal sub-levels indicating maturity within the experimental phase. This specification only defines semantics for decimal sub-levels of level 1.
Unfinished and subject to substantial change.
Nearing minimum viability.
Expected to become stable.
The description MAY continue on subsequent blockquote lines:
> Stability: 1 - Experimental. This API is under active development and
> may change without notice between minor releases.The description MAY contain inline Markdown such as links and code spans:
> Stability: 3 - Legacy: Use [`alternative()`][] instead.A stability indicator MUST appear after the YAML metadata block (if present) and before the typed parameter list and prose body. A document SHOULD have at most one stability indicator per entry:
### `myModule.myMethod()`
<!-- YAML
added: v1.2.3
-->
> Stability: 3 - Legacy: Use [`alternative()`][] instead.A stability indicator on the depth-1 heading applies to the document as a whole.
A type annotation is any balanced {curly brace}
span in text. The content between the braces is a TypeScript
type expression — anything valid on the right-hand side of a TypeScript
type X = ... alias.
Annotations appear both in typed parameter lists (as part of item structure) and in prose text (as inline references); both forms are parsed and rendered identically.
Implementations MUST parse each annotation whose value is not a whole-value map match under the TypeScript type grammar. Implementations SHOULD collect every annotation in a document and parse them in a single batch.
An annotation that fails to parse MUST produce a warning identifying the source location, and MUST be rendered as plain, unlinked code.
Each annotation resolves to a set of hyperlinks:
- Whole-value lookup. If the entire annotation value matches a type-map
entry verbatim, the whole annotation becomes a single link. This permits
display-name keys that are not valid TypeScript identifiers (e.g.
zlib options). - Identifier resolution. Otherwise, every type name in the parsed
expression resolves individually: keyword types (
string,number,boolean, ...), type-reference names, qualified names (vm.Module),typeoftargets, andimport('mod').Xqualifiers. Structural names — function parameter names, object property keys — are never resolved.
Each name resolves through the following tiers; the first match wins:
- The configurable type map provided to the toolchain, which associates names with documentation URLs. An example type map is available for viewing here.
- JavaScript primitives and built-in (TC39) globals, matched
case-insensitively:
string,number,boolean,bigint,symbol,null,undefined,integer,Array,Object,Function,Promise, and others. - Web platform APIs documented on MDN, matched case-insensitively.
- Dotted-name heuristic: names containing
.are split on the first.to derive a module name and member identifier, producing a cross-document link of the form<module>.md#<identifier>.
A name that no tier resolves stays plain — this is not an error.
The whole annotation renders as ONE inline code fragment. Each resolved name becomes a hyperlink spanning exactly its character range within the fragment; unresolved names remain plain text inside it. Implementations MAY syntax-highlight the fragment as TypeScript.
A typed list is an unordered Markdown list used to define parameters, properties, or other lists of types.
A typed list is an unordered Markdown list recognized by the content of its first item. A list is a typed list if its first item matches any of these conditions:
- It begins with text matching one of the special prefixes
(
Returns:,Extends:,Type:). - It begins with a type annotation.
- It begins with an inline code span (the parameter name) followed by a space and then a type annotation.
Each item in a typed list has the form:
* `name` {Type} Description text. **Default:** `value`.The components, in order, are:
- Bullet marker -
*,+, or-. - Parameter name - A backtick code span. REQUIRED for parameter items;
absent for
Returns:,Type:, andExtends:items. - Type annotation - A single
{...}TypeScript type expression (a union belongs inside it, e.g.{string|Buffer}). OPTIONAL. - Description - Free-form prose. OPTIONAL.
- Default value - The exact pattern
**Default:** \value``. OPTIONAL.
Denotes the return value of a function:
* Returns: {Promise} The file contents.Denotes the superclass of a class:
* Extends: {EventEmitter}Extends: items SHOULD appear as the first item in a class
entry's typed list.
Denotes the type of a property or constant:
* Type: {string}Object parameters document their properties using indented sub-lists:
* `options` {Object}
* `encoding` {string} Character encoding. **Default:** `'utf8'`.
* `flag` {string} File system flag. **Default:** `'r'`.
* `signal` {AbortSignal} Abort signal.Nesting MAY continue to arbitrary depth.
Optionality is indicated by the **Default:** pattern. Parameters with a
documented default are considered optional. The default value MUST be wrapped
in a backtick code span:
* `encoding` {string} **Default:** `'utf8'`.A typed list MUST appear after the stability indicator (if present) and before the prose body. When present, the list is extracted from the content flow and represented as structured data in output.
Code blocks MUST use fenced syntax (triple backticks). Indented code blocks MUST NOT be used.
Every fenced code block SHOULD include a language identifier in its info string. The language identifier is the first whitespace-delimited token after the opening fence.
Common language identifiers include: js, cjs, mjs, json, console,
bash, text, typescript, c, cpp, http, markdown, diff.
A fenced code block MAY include a displayName
key-value attribute after the language identifier in the
info string. The displayName provides a human-readable
label for the code block, used in rendered output. The attribute syntax is
displayName="value" where the value is a double-quoted string.
Implementations MAY support additional info string
attributes using the same key="value" syntax.
```js displayName="Reading a file"
const data = fs.readFileSync('/path/to/file');
```All links SHOULD use collapsed reference-style links:
See [`fs.readFile()`][] for details.with corresponding link reference definitions at the end of the document.
Links to other documents in the same documentation set MUST
use relative paths with .md extensions in the source. Conforming
implementations MUST rewrite the .md extension to the appropriate output
extension (e.g., .html) during generation:
[Stream documentation]: stream.md#class-streamreadableExternal links MUST use full URLs including the protocol:
[MDN Web Docs]: https://developer.mozilla.org/References to system calls in the format name(section)
(e.g., open(2) links to https://man7.org/linux/man-pages/man2/open.2.html)
are automatically converted to links to the appropriate manual page
documentation by conforming implementations.
Type annotations in prose text (§8.1) are parsed (§8.2), resolved (§8.3), and rendered (§8.4) exactly like annotations in typed parameter lists.
Link reference definitions SHOULD be collected at the end of the document, after all content sections:
[`fs.readFile()`]: #fsreadfilepath-options-callback
[`stream.Readable`]: stream.md#class-streamreadable