@doc-kit/core 1.1.0 → 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. package/CHANGELOG.md +16 -0
  2. package/README.md +2 -1
  3. package/package.json +9 -4
  4. package/src/generators/index.mjs +2 -0
  5. package/src/generators/json/README.md +151 -0
  6. package/src/generators/json/constants.mjs +57 -0
  7. package/src/generators/json/generate.mjs +65 -0
  8. package/src/generators/json/generated/schema.d.ts +351 -0
  9. package/src/generators/json/index.mjs +27 -0
  10. package/src/generators/json/schema.json +529 -0
  11. package/src/generators/json/types.d.ts +29 -0
  12. package/src/generators/json/utils/document.mjs +58 -0
  13. package/src/generators/json/utils/entry.mjs +87 -0
  14. package/src/generators/json/utils/lifecycle.mjs +61 -0
  15. package/src/generators/json/utils/markdown.mjs +57 -0
  16. package/src/generators/json/utils/node.mjs +153 -0
  17. package/src/generators/json/utils/schema.mjs +15 -0
  18. package/src/generators/json/utils/signature.mjs +185 -0
  19. package/src/generators/json/utils/types.mjs +28 -0
  20. package/src/generators/json-all/README.md +31 -0
  21. package/src/generators/json-all/constants.mjs +5 -0
  22. package/src/generators/json-all/generate.mjs +35 -0
  23. package/src/generators/json-all/index.mjs +25 -0
  24. package/src/generators/json-all/schema.json +22 -0
  25. package/src/generators/json-all/types.d.ts +20 -0
  26. package/src/generators/json-simple/generate.mjs +2 -7
  27. package/src/generators/metadata/maps/mdn.json +10 -2
  28. package/src/generators/metadata/types.d.ts +5 -0
  29. package/src/generators/metadata/utils/transformers.mjs +1 -1
  30. package/src/logger/logger.mjs +8 -0
  31. package/src/threading/chunk-worker.mjs +7 -0
  32. package/src/threading/index.mjs +1 -0
  33. package/src/utils/file.mjs +10 -0
  34. package/src/utils/hierarchy.mjs +50 -0
  35. package/src/utils/overloads.mjs +54 -0
  36. package/src/utils/queries/index.mjs +2 -0
  37. package/src/utils/queries/utils.mjs +15 -0
  38. package/src/utils/remark.mjs +1 -1
  39. package/src/utils/signature/constants.mjs +3 -0
  40. package/src/utils/signature/extractListItem.mjs +140 -0
  41. package/src/utils/stability.mjs +24 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # @doc-kit/core
2
2
 
3
+ ## 1.2.1
4
+
5
+ ### Patch Changes
6
+
7
+ - [#1105](https://github.com/nodejs/doc-kit/pull/1105) [`615aabe`](https://github.com/nodejs/doc-kit/commit/615aabeb1955a8028146e26fd4589c1172f58367) Thanks [@ryzrr](https://github.com/ryzrr)! - fix(metadata): link class types whose name starts with an acronym
8
+
9
+ ## 1.2.0
10
+
11
+ ### Minor Changes
12
+
13
+ - [#1079](https://github.com/nodejs/doc-kit/pull/1079) [`c4ec767`](https://github.com/nodejs/doc-kit/commit/c4ec76753c523cccb636a7f294669ec81d77dd47) Thanks [@avivkeller](https://github.com/avivkeller)! - feat: the `json` and `json-all` generators
14
+
15
+ ### Patch Changes
16
+
17
+ - [#1058](https://github.com/nodejs/doc-kit/pull/1058) [`2a356c3`](https://github.com/nodejs/doc-kit/commit/2a356c356858c631c45f1826edfa42a24b435d51) Thanks [@zeexzeex](https://github.com/zeexzeex)! - fix: respect `--log-level` in worker threads
18
+
3
19
  ## 1.1.0
4
20
 
5
21
  ### Minor Changes
package/README.md CHANGED
@@ -10,7 +10,8 @@ The command-line interface lives in the companion
10
10
  ## Generators
11
11
 
12
12
  Output formats are provided by generators. This package ships the shared
13
- pipeline stages and `json-simple`; the rest come from companion packages:
13
+ pipeline stages and the JSON generators (`json`, `json-all`, and the
14
+ debugging-only `json-simple`); the rest come from companion packages:
14
15
 
15
16
  | Package | Generators |
16
17
  | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------- |
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@doc-kit/core",
3
3
  "type": "module",
4
- "version": "1.1.0",
4
+ "version": "1.2.1",
5
5
  "description": "The doc-kit engine: the pipeline and shared APIs that power the doc-kit generators and CLI",
6
6
  "repository": {
7
7
  "type": "git",
@@ -14,6 +14,8 @@
14
14
  ".": "./src/generators.mjs",
15
15
  "./ast": "./src/generators/ast/index.mjs",
16
16
  "./ast-js": "./src/generators/ast-js/index.mjs",
17
+ "./json": "./src/generators/json/index.mjs",
18
+ "./json-all": "./src/generators/json-all/index.mjs",
17
19
  "./json-simple": "./src/generators/json-simple/index.mjs",
18
20
  "./metadata": "./src/generators/metadata/index.mjs",
19
21
  "./package.json": "./package.json",
@@ -45,7 +47,7 @@
45
47
  "dependencies": {
46
48
  "@actions/core": "^3.0.0",
47
49
  "@node-core/rehype-shiki": "^1.5.0",
48
- "@swc/html-wasm": "^1.15.46",
50
+ "@swc/html-wasm": "^1.16.1",
49
51
  "@swc/wasm": "^1.15.46",
50
52
  "acorn": "^8.17.0",
51
53
  "cosmiconfig": "^9.0.2",
@@ -53,6 +55,8 @@
53
55
  "github-slugger": "^2.0.0",
54
56
  "glob-parent": "^6.0.2",
55
57
  "hastscript": "^9.0.1",
58
+ "mdast-util-slice-markdown": "^2.0.1",
59
+ "mdast-util-to-string": "^4.0.0",
56
60
  "piscina": "^5.3.1",
57
61
  "rehype-stringify": "^10.0.1",
58
62
  "remark-gfm": "^4.0.1",
@@ -73,13 +77,14 @@
73
77
  "yaml": "^2.9.0"
74
78
  },
75
79
  "devDependencies": {
80
+ "ajv": "^8.20.0",
76
81
  "hast-util-to-html": "^9.0.5",
77
82
  "hast-util-to-string": "^3.0.1"
78
83
  },
79
84
  "peerDependencies": {
85
+ "@doc-kit/generator-react": ">=0.1.0",
80
86
  "@node-core/doc-kit": ">=2.0.0",
81
- "@node-core/doc-kit-legacy": ">=1.0.0",
82
- "@doc-kit/generator-react": ">=0.1.0"
87
+ "@node-core/doc-kit-legacy": ">=1.0.0"
83
88
  },
84
89
  "peerDependenciesMeta": {
85
90
  "@node-core/doc-kit": {
@@ -10,6 +10,8 @@
10
10
  * which is how third-party generator packages are loaded.
11
11
  */
12
12
  export const publicGenerators = {
13
+ json: '@doc-kit/core/json',
14
+ 'json-all': '@doc-kit/core/json-all',
13
15
  'json-simple': '@doc-kit/core/json-simple',
14
16
  'legacy-html': '@node-core/doc-kit-legacy/legacy-html',
15
17
  'legacy-html-all': '@node-core/doc-kit-legacy/legacy-html-all',
@@ -0,0 +1,151 @@
1
+ # `json` Generator
2
+
3
+ The `json` generator writes one JSON document per source file. Each document
4
+ is a tree of the file's headings, in document order, with the metadata,
5
+ signature or type, Markdown body, and code examples of every one of them.
6
+
7
+ The output is described by a JSON schema, published at the URL every document
8
+ carries in `$schema`, and shipped with the package as
9
+ `@doc-kit/core/generators/json/schema.json`.
10
+
11
+ ```sh
12
+ npx @doc-kit/cli generate -t json -i "doc/api/*.md" -o out
13
+ ```
14
+
15
+ Files keep the input's directory layout: `doc/api/some/fs.md` becomes `out/some/fs.json`.
16
+
17
+ ## Configuring
18
+
19
+ - `output` {string} The directory to write the documents to.
20
+ - `minify` {boolean} Whether to minify the output. Inherited from `global`.
21
+ **Default:** `true`.
22
+ - `repository` {string} The `owner/name` repository source links resolve
23
+ against. Inherited from `global`; without one, `sourceLink.url` is `null`.
24
+ - `schemaURL` {string} Where the schema is published. `{schemaVersion}` is
25
+ filled in. **Default:**
26
+ `'https://doc-kit.nodejs.org/schemas/api-doc/{schemaVersion}.json'`.
27
+
28
+ ## The document
29
+
30
+ ```json
31
+ {
32
+ "$schema": "https://doc-kit.nodejs.org/schemas/api-doc/1.0.0.json",
33
+ "id": "fs",
34
+ "path": "/fs",
35
+ "type": "module",
36
+ "module": "fs",
37
+ "title": "File system",
38
+ "introducedIn": "v0.10.0",
39
+ "sourceLink": {
40
+ "path": "lib/fs.js",
41
+ "url": "https://github.com/nodejs/node/blob/HEAD/lib/fs.js"
42
+ },
43
+ "stability": { "index": "2", "description": "Stable" },
44
+ "added": [],
45
+ "deprecated": [],
46
+ "removed": [],
47
+ "napiVersion": [],
48
+ "changes": [],
49
+ "description": "The `node:fs` module enables interacting with the file system in a\nway modeled on standard POSIX functions.\n\n…",
50
+ "summary": "The `node:fs` module enables interacting with the file system in a way modeled on standard POSIX functions.",
51
+ "examples": [],
52
+ "children": []
53
+ }
54
+ ```
55
+
56
+ - `id` is the file's path, slugged; `path` is that path without extension.
57
+ Cross-document links in Markdown target `<path>.html`.
58
+ - `type` is the file's `type=` directive: `module` (the default), `misc`, or
59
+ `global`. `module` is the module's name, from the `name=` directive.
60
+ - `introducedIn` and `sourceLink` are the `introduced_in=` and `source_link=`
61
+ directives.
62
+ - Everything from `title` on is what every heading carries, described below.
63
+ - `children` are the file's headings, nested by depth.
64
+
65
+ ## Every entry
66
+
67
+ The document and every node carry:
68
+
69
+ - `title` The heading text as authored, inline Markdown included.
70
+ - `stability` The stability index, or `null`: `{ index, description }`,
71
+ where `index` is the text as authored (`"1.1"`) and `description` the
72
+ Markdown after it.
73
+ - `added`, `deprecated`, `removed` Arrays of version strings, as authored.
74
+ - `napiVersion` An array of numbers.
75
+ - `changes` The change history: `{ versions, prUrl, commit, description }`.
76
+ - `description` The body as Markdown: everything under the heading except
77
+ its metadata, its stability index, and the typed list a signature or type
78
+ was taken from. Links are rewritten as they are for HTML output.
79
+ - `summary` A plain-text paragraph: the `llm_description` when there is one,
80
+ else the first paragraph.
81
+ - `examples` The fenced code blocks of the body, `{ language, displayName, code }`.
82
+ They stay in the description too.
83
+
84
+ Every key is always present. What is missing is `null` or an empty array.
85
+
86
+ ## Nodes
87
+
88
+ A node is a heading below the title. Its `kind` says what the heading
89
+ documents, and decides which further properties it has:
90
+
91
+ | `kind` | Heading | Further properties |
92
+ | -------------- | ---------------------------------------------- | ---------------------------- |
93
+ | `section` | Anything else: prose, `DEP0005: …`, `--flag` | none |
94
+ | `class` | `` Class: `net.Server` `` | `extends` (`Type` or `null`) |
95
+ | `constructor` | `` `new Agent([options])` `` | `signature` |
96
+ | `method` | `` `fs.readFile(path[, options], callback)` `` | `signature` |
97
+ | `staticMethod` | `` Static method: `Buffer.from(string)` `` | `signature` |
98
+ | `property` | `` `buf.length` `` | `type`, `default` |
99
+ | `event` | `` Event: `'close'` `` | `parameters` |
100
+
101
+ Every node also has:
102
+
103
+ - `id` The heading's slug, and its anchor in HTML output.
104
+ - `name` The bare identifier: `readFile`, `Server`, `close`. A section's
105
+ plain heading text. A `name=` directive overrides it.
106
+ - `scope` `module`, or `global` for entries typed `global`.
107
+ - `overloadOf` When several sibling headings document one callable, the `id`
108
+ of the first on the second and later ones; otherwise `null`.
109
+ - `children` The headings nested under it.
110
+
111
+ ## Signatures and types
112
+
113
+ ```json
114
+ "signature": {
115
+ "parameters": [
116
+ {
117
+ "name": "options",
118
+ "type": { "text": "Object | string", "links": [{ "name": "Object", "href": "https://developer.mozilla.org/…", "start": 0, "end": 6 }] },
119
+ "description": "",
120
+ "default": null,
121
+ "optional": true,
122
+ "rest": false,
123
+ "properties": [
124
+ { "name": "encoding", "type": { "text": "string | null", "links": [] }, "description": "", "default": "null", "optional": true, "rest": false, "properties": [] }
125
+ ]
126
+ }
127
+ ],
128
+ "returns": { "type": { "text": "Promise", "links": [] }, "description": "Fulfills upon success." }
129
+ }
130
+ ```
131
+
132
+ - A signature's `parameters` are the ones the heading declares,
133
+ described by the typed list under it. `optional` is set for parameters
134
+ bracketed in the heading or documented with a default; `rest` for
135
+ `...args`. `properties` are the nested list items: the properties of an
136
+ options object, or the arguments of a callback.
137
+ - `returns` is the `Returns:` item, or `null`.
138
+ - A `Type` is the annotation's TypeScript text, normalised to one line with
139
+ `|` between union members, plus the names in it that resolved to
140
+ documentation, with their character offsets. A type that was not
141
+ documented is `null`, never guessed.
142
+ - An event's `parameters` are the arguments its listeners receive.
143
+
144
+ ## The schema
145
+
146
+ `schema.json` is the source of truth. After changing it, bump its `$id` and
147
+ `SCHEMA_VERSION` in `constants.mjs` together, and regenerate the types:
148
+
149
+ ```sh
150
+ node scripts/generate-json-types.mjs
151
+ ```
@@ -0,0 +1,57 @@
1
+ 'use strict';
2
+
3
+ // See the `version` in schema.json. These values should be in sync.
4
+ export const SCHEMA_VERSION = '1.0.1';
5
+
6
+ // Where a schema version is published.
7
+ export const SCHEMA_URL =
8
+ 'https://doc-kit.nodejs.org/schemas/api-doc/{schemaVersion}.json';
9
+
10
+ // The heading classifications the metadata generator assigns, and the node
11
+ // kind each one becomes.
12
+ export const KINDS = {
13
+ class: 'class',
14
+ ctor: 'constructor',
15
+ method: 'method',
16
+ classMethod: 'staticMethod',
17
+ property: 'property',
18
+ event: 'event',
19
+ };
20
+
21
+ // The kind of a heading that documents no API entry
22
+ export const SECTION_KIND = 'section';
23
+
24
+ // The kinds whose leading typed list is lifted out of the body as data
25
+ export const KINDS_WITH_TYPED_LIST = new Set([
26
+ 'class',
27
+ 'constructor',
28
+ 'method',
29
+ 'staticMethod',
30
+ 'property',
31
+ 'event',
32
+ ]);
33
+
34
+ // The kinds whose heading declares the parameters of a signature
35
+ export const CALLABLE_KINDS = new Set([
36
+ 'constructor',
37
+ 'method',
38
+ 'staticMethod',
39
+ ]);
40
+
41
+ // The document-level `type` classifications
42
+ export const DOCUMENT_TYPES = new Set(['module', 'misc', 'global']);
43
+
44
+ // The `displayName="..."` attribute of a fenced code block's info string
45
+ export const DISPLAY_NAME = /displayName="([^"]*)"/;
46
+
47
+ // A rest parameter's marker
48
+ export const REST_MARKER = /^\.\.\./;
49
+
50
+ // The code span around a default value
51
+ export const CODE_SPAN = /^`([^]*)`$/;
52
+
53
+ // The `=` a default value declared in a heading starts with
54
+ export const DECLARED_DEFAULT = /^=\s*/;
55
+
56
+ // The `extends` clause a class heading may carry: `Class: \`Foo extends Bar\``
57
+ export const EXTENDS_CLAUSE = / extends +/;
@@ -0,0 +1,65 @@
1
+ 'use strict';
2
+
3
+ import { join } from 'node:path';
4
+
5
+ import getConfig from '#utils/configuration/index.mjs';
6
+ import { GITHUB_BLOB_URL, populate } from '#utils/configuration/templates.mjs';
7
+ import { withExt, writeJSON } from '#utils/file.mjs';
8
+ import { groupNodesByModule } from '#utils/generators.mjs';
9
+
10
+ import { buildDocument } from './utils/document.mjs';
11
+ import { resolveSchemaURL } from './utils/schema.mjs';
12
+
13
+ /**
14
+ * Builds the documents of a chunk of modules in a worker thread.
15
+ *
16
+ * @type {import('./types').Generator['processChunk']}
17
+ */
18
+ export async function processChunk(slicedInput, itemIndices, dependencies) {
19
+ return itemIndices.map(idx => {
20
+ const { head, entries } = slicedInput[idx];
21
+
22
+ return buildDocument(head, entries, dependencies);
23
+ });
24
+ }
25
+
26
+ /**
27
+ * Generates one JSON document per input file.
28
+ *
29
+ * @type {import('./types').Generator['generate']}
30
+ */
31
+ export async function* generate(input, worker) {
32
+ const config = getConfig('json');
33
+
34
+ /** @type {import('./types').Dependencies} */
35
+ const dependencies = {
36
+ schemaURL: resolveSchemaURL(config),
37
+ // Source links resolve against the repository, when one is configured
38
+ sourceURL: config.repository ? populate(GITHUB_BLOB_URL, config) : null,
39
+ };
40
+
41
+ // Pages other generators added to the pipeline are theirs to render
42
+ const entries = input.filter(entry => !entry.synthetic && !entry.chunk);
43
+
44
+ // One item per module, so a worker gets everything a document needs
45
+ const modules = [...groupNodesByModule(entries).values()].map(nodes => ({
46
+ head: nodes.find(({ heading }) => heading.depth === 1) ?? nodes[0],
47
+ entries: nodes,
48
+ }));
49
+
50
+ for await (const chunk of worker.stream(modules, dependencies)) {
51
+ if (config.output) {
52
+ await Promise.all(
53
+ chunk.map(document =>
54
+ writeJSON(
55
+ join(config.output, withExt(document.path, 'json')),
56
+ document,
57
+ config.minify
58
+ )
59
+ )
60
+ );
61
+ }
62
+
63
+ yield chunk;
64
+ }
65
+ }