Skip to content

Commit 443279c

Browse files
build, doc: move to redesign
Co-authored-by: Brian Muenzenmeyer <brian.muenzenmeyer@gmail.com> Signed-off-by: avivkeller <me@aviv.sh>
1 parent fe91868 commit 443279c

10 files changed

Lines changed: 1435 additions & 933 deletions

File tree

‎.github/dependabot.yml‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,8 @@ updates:
5858
semver-minor-days: 5
5959
semver-patch-days: 5
6060
exclude:
61-
- '@node-core/doc-kit'
61+
- '@doc-kit/*'
62+
- '@node-core/*'
6263
commit-message:
6364
prefix: tools
6465
open-pull-requests-limit: 10

‎.github/workflows/build-tarball.yml‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ env:
6767
PYTHON_VERSION: '3.15'
6868
FLAKY_TESTS: keep_retrying
6969
CLANG_VERSION: '19'
70+
NODE_VERSION: lts/*
7071

7172
permissions:
7273
contents: read
@@ -84,6 +85,10 @@ jobs:
8485
with:
8586
python-version: ${{ env.PYTHON_VERSION }}
8687
allow-prereleases: true
88+
- name: Use Node.js ${{ env.NODE_VERSION }}
89+
uses: actions/setup-node@820762786026740c76f36085b0efc47a31fe5020 # v7.0.0
90+
with:
91+
node-version: ${{ env.NODE_VERSION }}
8792
- name: Make tarball
8893
run: |
8994
export DISTTYPE=nightly

‎Makefile‎

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,12 @@ ifeq ($(OSTYPE),os400)
402402
DOCBUILDSTAMP_PREREQS := $(DOCBUILDSTAMP_PREREQS) out/$(BUILDTYPE)/node.exp
403403
endif
404404

405-
DOC_KIT ?= tools/doc/node_modules/@node-core/doc-kit/bin/cli.mjs
405+
DOC_KIT ?= tools/doc/node_modules/@doc-kit/cli/bin/cli.mjs
406+
ifeq ($(V),1)
407+
DOC_KIT_LOG_LEVEL ?= debug
408+
else
409+
DOC_KIT_LOG_LEVEL ?= info
410+
endif
406411

407412
node_use_openssl_and_icu = $(call available-node,"-p" \
408413
"process.versions.openssl != undefined && process.versions.icu != undefined")
@@ -886,8 +891,10 @@ out/doc/api: doc/api
886891
mkdir -p $@
887892
cp -r doc/api out/doc
888893

889-
# Generate all doc files (individual and all.html/all.json) in a single doc-kit call
890-
# Using grouped targets (&:) so Make knows one command produces all outputs
894+
# Generate all doc files (individual and all.html/all.json) in a single doc-kit call.
895+
# A stamp tells Make that one command produces them all; a grouped target (&:)
896+
# needs GNU Make 4.3, and older ones (4.2.1 on RHEL 8) rerun the whole build for
897+
# every output that's still missing.
891898
ifeq ($(OSTYPE),aix)
892899
# TODO(@nodejs/web-infra): AIX is currently hanging during HTML minification
893900
$(apidocs_html) $(apidocs_json) out/doc/api/all.html out/doc/api/all.json:
@@ -902,23 +909,22 @@ else ifeq ($(ARCHTYPE),riscv64)
902909
$(apidocs_html) $(apidocs_json) out/doc/api/all.html out/doc/api/all.json:
903910
@echo "Skipping $@ (not currently supported by $(DESTCPU) machines)"
904911
else
905-
$(apidocs_html) $(apidocs_json) out/doc/api/all.html out/doc/api/all.json &: $(apidoc_sources) tools/doc/node_modules | out/doc/api
912+
out/doc/.docbuildstamp: $(apidoc_sources) tools/doc/node_modules | out/doc/api
906913
@if [ "$(shell $(node_use_openssl_and_icu))" != "true" ]; then \
907914
echo "Skipping $@ (no crypto and/or no ICU)"; \
908915
else \
909916
$(call available-node, \
910917
$(DOC_KIT) generate \
911-
-t legacy-html-all \
912-
-t legacy-json-all \
913-
-i doc/api/*.md \
914-
--ignore $(skip_apidoc_files) \
918+
--log-level $(DOC_KIT_LOG_LEVEL) \
919+
--config-file tools/doc/web.doc-kit.config.mjs \
915920
-o out/doc/api \
916-
-c ./CHANGELOG.md \
917921
-v $(VERSION) \
918-
--index doc/api/index.md \
919-
--type-map doc/type-map.json \
922+
$(if $(JOBS),-p $(JOBS)) \
920923
) \
921924
fi
925+
@touch $@
926+
927+
$(apidocs_html) $(apidocs_json) out/doc/api/all.html out/doc/api/all.json: out/doc/.docbuildstamp
922928
endif
923929

924930
out/doc/llms.txt: $(apidoc_sources) tools/doc/node_modules | out/doc
@@ -927,13 +933,11 @@ out/doc/llms.txt: $(apidoc_sources) tools/doc/node_modules | out/doc
927933
else \
928934
$(call available-node, \
929935
$(DOC_KIT) generate \
936+
--log-level $(DOC_KIT_LOG_LEVEL) \
937+
--config-file tools/doc/web.doc-kit.config.mjs \
930938
-t llms-txt \
931-
-i doc/api/*.md \
932-
--ignore $(skip_apidoc_files) \
933939
-o $(@D) \
934-
-c ./CHANGELOG.md \
935940
-v $(VERSION) \
936-
--type-map doc/type-map.json \
937941
) \
938942
fi
939943

@@ -943,12 +947,10 @@ out/doc/apilinks.json: $(wildcard lib/*.js) tools/doc/node_modules | out/doc
943947
else \
944948
$(call available-node, \
945949
$(DOC_KIT) generate \
946-
-t api-links \
947-
-i lib/*.js \
950+
--log-level $(DOC_KIT_LOG_LEVEL) \
951+
--config-file tools/doc/api-links.doc-kit.config.mjs \
948952
-o $(@D) \
949-
-c ./CHANGELOG.md \
950953
-v $(VERSION) \
951-
--type-map doc/type-map.json \
952954
) \
953955
fi
954956

@@ -962,6 +964,7 @@ node.1: doc/api/cli.md tools/doc/node_modules
962964
else \
963965
$(call available-node, \
964966
$(DOC_KIT) generate \
967+
--log-level $(DOC_KIT_LOG_LEVEL) \
965968
-v $(VERSION) \
966969
--config-file tools/doc/man-page.doc-kit.config.mjs \
967970
-o doc \
@@ -1505,6 +1508,7 @@ tools/.manpagelintstamp: doc/node.1 doc/api/cli.md tools/doc/node_modules
15051508
$(RM) -r tools/doc/.manpagecheck && \
15061509
$(call available-node, \
15071510
$(DOC_KIT) generate \
1511+
--log-level $(DOC_KIT_LOG_LEVEL) \
15081512
-v $(VERSION) \
15091513
--config-file tools/doc/man-page.doc-kit.config.mjs \
15101514
) \

‎doc/node.1‎

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
.\"
2-
.\" This file was generated automatically by the @node-core/doc-kit tool.
2+
.\" This file was generated automatically by Node.js's doc-kit tool.
33
.\" Please do not edit this file manually. Make any updates to cli.md
44
.\" and regenerate the file afterward.
55
.\"
6-
.\" To regenerate this file, run `make doc/node.1`.
6+
.\" To regenerate this file, run `make node.1`.
77
.\"
88
.\"======================================================================
99
.Dd $Mdocdate$
@@ -274,7 +274,7 @@ Error: connect ERR_ACCESS_DENIED Access to this API has been restricted. Use --a
274274
.It Fl -allow-openssl-store
275275
When using the Permission Model, the process will not be able to use
276276
OpenSSL STORE loaders by default, for example to load a private key from a
277-
\fB<URL>\fR passed to \fBcrypto.createPrivateKey()\fR. Attempts to do so will throw
277+
\fB{URL}\fR passed to \fBcrypto.createPrivateKey()\fR. Attempts to do so will throw
278278
an \fBERR_ACCESS_DENIED\fR unless the user explicitly passes the
279279
\fB--allow-openssl-store\fR flag. This permission can be dropped at runtime via
280280
\fBpermission.drop()\fR.
@@ -452,11 +452,11 @@ creation behavior.
452452
The following options are currently supported:
453453
.Bl -bullet
454454
.It
455-
\fBbuilder\fR \fB<string>\fR Required. Provides the name to the script that is executed
456-
before building the snapshot, as if \fB--build-snapshot\fR had been passed
455+
\fBbuilder\fR \fB{string}\fR Required. Provides the name to the script that is executed
456+
before building the snapshot, as if \fB--build-snapshot\fR had been passed
457457
with \fBbuilder\fR as the main script name.
458458
.It
459-
\fBwithoutCodeCache\fR \fB<boolean>\fR Optional. Including the code cache reduces the
459+
\fBwithoutCodeCache\fR \fB{boolean}\fR Optional. Including the code cache reduces the
460460
time spent on compiling functions included in the snapshot at the expense
461461
of a bigger snapshot size and potentially breaking portability of the
462462
snapshot.
@@ -1993,7 +1993,7 @@ Print node's version.
19931993
.It Fl -vfs-load Ns = Ns Ar source
19941994
.Bl -bullet
19951995
.It
1996-
\fBsource\fR \fB<string>\fR A directory or an archive file to mount and run.
1996+
\fBsource\fR \fB{string}\fR A directory or an archive file to mount and run.
19971997
.El
19981998
May be given at most once.
19991999
Mounts \fBsource\fR as a virtual file system (\fBnode:vfs\fR), and runs the entry

‎test/doctool/test-make-doc.mjs‎

Lines changed: 52 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -1,74 +1,72 @@
11
import * as common from '../common/index.mjs';
22

3-
import assert from 'assert';
4-
import fs from 'fs';
5-
import path from 'path';
3+
import assert from 'node:assert';
4+
import fs from 'node:fs';
5+
import path from 'node:path';
66

77
if (common.isWindows) {
88
common.skip('`make doc` does not run on Windows');
99
}
1010

11-
// This tests that `make doc` generates the documentation properly.
12-
// Note that for this test to pass, `make doc` must be run first.
11+
// This tests that `make doc` generates the documentation properly: an HTML
12+
// page and a JSON file for every Markdown file under `doc/api`, and nothing
13+
// for anything else. Note that for this test to pass, `make doc` must be run
14+
// first.
1315

1416
const apiURL = new URL('../../out/doc/api/', import.meta.url);
1517
const mdURL = new URL('../../doc/api/', import.meta.url);
16-
const allMD = fs.readdirSync(mdURL);
17-
const allDocs = fs.readdirSync(apiURL);
18-
assert.ok(allDocs.includes('index.html'));
1918

20-
const actualDocs = allDocs.filter(
21-
(name) => {
22-
const extension = path.extname(name);
23-
return extension === '.html' || extension === '.json';
24-
},
25-
);
26-
27-
for (const name of actualDocs) {
28-
if (name.startsWith('all.') || name === 'apilinks.json') continue;
29-
30-
assert.ok(
31-
allMD.includes(name.replace(/\.\w+$/, '.md')),
32-
`Unexpected output: out/doc/api/${name}, remove and rerun.`,
33-
);
19+
// Not all files under `doc/api` are expected in the generated output.
20+
// Parse out list of excluded files.
21+
let skippedDocs = [];
22+
const makefile = await fs.open(new URL('../../Makefile', import.meta.url));
23+
try {
24+
// Find the `skip_apidoc_files = ` line and parse out the list of files.
25+
for await (const line of makefile.readLines()) {
26+
if (line.startsWith('skip_apidoc_files')) {
27+
skippedDocs = line.split('=')[1]?.trim().split(/\s/).map((n) => path.basename(n));
28+
}
29+
}
30+
} finally {
31+
makefile.close();
3432
}
3533

36-
const toc = fs.readFileSync(new URL('./index.html', apiURL), 'utf8');
37-
const re = /href=("([^/]+\.html)"|([^/]+\.html))/;
38-
const globalRe = new RegExp(re, 'g');
39-
const links = toc.match(globalRe);
40-
assert.notStrictEqual(links, null);
34+
const sources = fs.readdirSync(mdURL)
35+
.filter((name) => path.extname(name) === '.md')
36+
.map((name) => path.basename(name, '.md'));
37+
const generated = fs.readdirSync(apiURL);
4138

42-
// Filter out duplicate links, leave just filenames, add expected JSON files.
43-
const linkedHtmls = [...new Set(links)].map((link) => link.match(re)[1])
44-
.concat(['index.html']);
45-
const expectedJsons = linkedHtmls
46-
.map((name) => name.replace('.html', '.json'));
47-
const expectedDocs = linkedHtmls.concat(expectedJsons);
48-
const renamedDocs = ['policy.json', 'policy.html'];
49-
const skipedDocs = ['dtls.json', 'dtls.html', 'quic.json', 'quic.html'];
39+
// These have no Markdown source of their own.
40+
const expectedExtras = ['index.html', 'all.html', 'all.json'];
41+
for (const name of expectedExtras) {
42+
assert.ok(generated.includes(name), `${name} was not generated`);
43+
}
5044

51-
// Test that all the relative links in the TOC match to the actual documents.
52-
for (const expectedDoc of expectedDocs) {
53-
if (skipedDocs.includes(expectedDoc)) continue;
54-
assert.ok(actualDocs.includes(expectedDoc), `${expectedDoc} does not exist`);
45+
for (const name of sources) {
46+
for (const extension of ['.html', '.json']) {
47+
const file = `${name}${extension}`;
48+
if (skippedDocs.includes(name)) {
49+
assert.ok(!generated.includes(file), `${file} was unexpectedly generated`);
50+
continue;
51+
}
52+
assert.ok(generated.includes(file), `${file} was not generated`);
53+
assert.notStrictEqual(
54+
fs.statSync(new URL(`./${file}`, apiURL)).size,
55+
0,
56+
`${file} is empty`,
57+
);
58+
}
5559
}
5660

57-
// Test that all the actual documents match to the relative links in the TOC
58-
// and that they are not empty files.
59-
for (const actualDoc of actualDocs) {
60-
// When renaming the documentation, the old url is lost
61-
// Unless the old file is still available pointing to the correct location
62-
// 301 redirects are not yet automated. So keeping the old URL is a
63-
// reasonable workaround.
64-
if (renamedDocs.includes(actualDoc) || skipedDocs.includes(actualDoc) ||
65-
actualDoc === 'apilinks.json') continue;
61+
// Every generated page must come from a current Markdown file, so a stale
62+
// `out/doc/api` (e.g. from a renamed document) is noticed.
63+
const expectedPages = ['404.html', 'apilinks.json', ...expectedExtras];
64+
for (const name of generated) {
65+
const extension = path.extname(name);
66+
if (extension !== '.html' && extension !== '.json') continue;
67+
if (expectedPages.includes(name)) continue;
6668
assert.ok(
67-
expectedDocs.includes(actualDoc), `${actualDoc} does not match TOC`);
68-
69-
assert.notStrictEqual(
70-
fs.statSync(new URL(`./${actualDoc}`, apiURL)).size,
71-
0,
72-
`${actualDoc} is empty`,
69+
sources.includes(path.basename(name, extension)),
70+
`Unexpected output: out/doc/api/${name}, remove and rerun.`,
7371
);
7472
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import { fileURLToPath } from 'node:url';
2+
3+
const root = new URL('../../', import.meta.url);
4+
5+
const fromRoot = (path) =>
6+
fileURLToPath(new URL(path, root)).replaceAll('\\', '/');
7+
8+
const urlFromRoot = (path) => new URL(path, root).href;
9+
10+
export default {
11+
extends: '@node-core/doc-kit/config',
12+
13+
target: ['api-links'],
14+
15+
global: {
16+
input: [fromRoot('lib/*.js')],
17+
output: fromRoot('out/doc'),
18+
19+
// Point every loadable URL at its local file so no network request is made.
20+
changelog: urlFromRoot('CHANGELOG.md'),
21+
},
22+
};

0 commit comments

Comments
 (0)