@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.
- package/CHANGELOG.md +16 -0
- package/README.md +2 -1
- package/package.json +9 -4
- package/src/generators/index.mjs +2 -0
- package/src/generators/json/README.md +151 -0
- package/src/generators/json/constants.mjs +57 -0
- package/src/generators/json/generate.mjs +65 -0
- package/src/generators/json/generated/schema.d.ts +351 -0
- package/src/generators/json/index.mjs +27 -0
- package/src/generators/json/schema.json +529 -0
- package/src/generators/json/types.d.ts +29 -0
- package/src/generators/json/utils/document.mjs +58 -0
- package/src/generators/json/utils/entry.mjs +87 -0
- package/src/generators/json/utils/lifecycle.mjs +61 -0
- package/src/generators/json/utils/markdown.mjs +57 -0
- package/src/generators/json/utils/node.mjs +153 -0
- package/src/generators/json/utils/schema.mjs +15 -0
- package/src/generators/json/utils/signature.mjs +185 -0
- package/src/generators/json/utils/types.mjs +28 -0
- package/src/generators/json-all/README.md +31 -0
- package/src/generators/json-all/constants.mjs +5 -0
- package/src/generators/json-all/generate.mjs +35 -0
- package/src/generators/json-all/index.mjs +25 -0
- package/src/generators/json-all/schema.json +22 -0
- package/src/generators/json-all/types.d.ts +20 -0
- package/src/generators/json-simple/generate.mjs +2 -7
- package/src/generators/metadata/maps/mdn.json +10 -2
- package/src/generators/metadata/types.d.ts +5 -0
- package/src/generators/metadata/utils/transformers.mjs +1 -1
- package/src/logger/logger.mjs +8 -0
- package/src/threading/chunk-worker.mjs +7 -0
- package/src/threading/index.mjs +1 -0
- package/src/utils/file.mjs +10 -0
- package/src/utils/hierarchy.mjs +50 -0
- package/src/utils/overloads.mjs +54 -0
- package/src/utils/queries/index.mjs +2 -0
- package/src/utils/queries/utils.mjs +15 -0
- package/src/utils/remark.mjs +1 -1
- package/src/utils/signature/constants.mjs +3 -0
- package/src/utils/signature/extractListItem.mjs +140 -0
- package/src/utils/stability.mjs +24 -0
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { getEntryDescription } from '#utils/generators.mjs';
|
|
4
|
+
import { splitTypedItems, UNIST } from '#utils/queries/index.mjs';
|
|
5
|
+
import { extractListItem } from '#utils/signature/extractListItem.mjs';
|
|
6
|
+
|
|
7
|
+
import { KINDS_WITH_TYPED_LIST } from '../constants.mjs';
|
|
8
|
+
import { toChanges, toNumbers, toStability, toVersions } from './lifecycle.mjs';
|
|
9
|
+
import { blocksToMarkdown, extractExamples } from './markdown.mjs';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Whether a node is a stability index the metadata generator recognised.
|
|
13
|
+
*
|
|
14
|
+
* @param {import('mdast').RootContent} node
|
|
15
|
+
*/
|
|
16
|
+
const isStabilityIndex = node =>
|
|
17
|
+
node.type === 'blockquote' && node.data?.index !== undefined;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* An entry's body: its content without its heading and, when the entry
|
|
21
|
+
* carries one, its stability index.
|
|
22
|
+
*
|
|
23
|
+
* @param {import('../../metadata/types').MetadataEntry} entry
|
|
24
|
+
* @returns {Array<import('mdast').RootContent>}
|
|
25
|
+
*/
|
|
26
|
+
export const entryBody = entry =>
|
|
27
|
+
entry.content.children.filter(
|
|
28
|
+
node =>
|
|
29
|
+
!UNIST.isHeading(node) && !(entry.stability && isStabilityIndex(node))
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Lifts the leading typed items of the body's first typed list out of the
|
|
34
|
+
* body, for the kinds that turn them into data.
|
|
35
|
+
*
|
|
36
|
+
* @param {Array<import('mdast').RootContent>} body
|
|
37
|
+
* @param {string} kind The node's kind
|
|
38
|
+
* @returns {{ body: Array<import('mdast').RootContent>, items: Array<import('mdast').ListItem> }}
|
|
39
|
+
*/
|
|
40
|
+
export const takeTypedItems = (body, kind) => {
|
|
41
|
+
const index = KINDS_WITH_TYPED_LIST.has(kind)
|
|
42
|
+
? body.findIndex(UNIST.isStronglyTypedList)
|
|
43
|
+
: -1;
|
|
44
|
+
|
|
45
|
+
if (index === -1) {
|
|
46
|
+
return { body, items: [] };
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const list = body[index];
|
|
50
|
+
const { typed: items, rest } = splitTypedItems(list);
|
|
51
|
+
|
|
52
|
+
if (
|
|
53
|
+
kind === 'class' &&
|
|
54
|
+
!items.some(item => extractListItem(item).prefix === 'Extends')
|
|
55
|
+
) {
|
|
56
|
+
return { body, items: [] };
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
return {
|
|
60
|
+
body: body.toSpliced(
|
|
61
|
+
index,
|
|
62
|
+
1,
|
|
63
|
+
...(rest.length ? [{ ...list, children: rest }] : [])
|
|
64
|
+
),
|
|
65
|
+
items,
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Builds an entry's metadata and body.
|
|
71
|
+
*
|
|
72
|
+
* @param {import('../../metadata/types').MetadataEntry} entry
|
|
73
|
+
* @param {Array<import('mdast').RootContent>} body The entry's body, minus anything lifted out of it
|
|
74
|
+
* @returns {import('../types').Entry}
|
|
75
|
+
*/
|
|
76
|
+
export const buildEntry = (entry, body) => ({
|
|
77
|
+
title: entry.heading.data.text,
|
|
78
|
+
stability: toStability(entry.stability, entry.mdx),
|
|
79
|
+
added: toVersions(entry.added),
|
|
80
|
+
deprecated: toVersions(entry.deprecated),
|
|
81
|
+
removed: toVersions(entry.removed),
|
|
82
|
+
napiVersion: toNumbers(entry.napiVersion),
|
|
83
|
+
changes: toChanges(entry.changes),
|
|
84
|
+
description: blocksToMarkdown(body, entry.mdx),
|
|
85
|
+
summary: getEntryDescription(entry),
|
|
86
|
+
examples: extractExamples(body),
|
|
87
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { enforceArray } from '#utils/array.mjs';
|
|
4
|
+
import { removeStabilityPrefix } from '#utils/stability.mjs';
|
|
5
|
+
|
|
6
|
+
import { blocksToMarkdown } from './markdown.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Normalises a YAML version field
|
|
10
|
+
*
|
|
11
|
+
* @param {unknown} value
|
|
12
|
+
* @returns {Array<string>}
|
|
13
|
+
*/
|
|
14
|
+
export const toVersions = value =>
|
|
15
|
+
value == null ? [] : enforceArray(value).map(String);
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Normalises a YAML number field
|
|
19
|
+
*
|
|
20
|
+
* @param {unknown} value
|
|
21
|
+
* @returns {Array<number>}
|
|
22
|
+
*/
|
|
23
|
+
export const toNumbers = value =>
|
|
24
|
+
value == null ? [] : enforceArray(value).map(Number);
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Normalises a YAML `changes` list
|
|
28
|
+
*
|
|
29
|
+
* @param {unknown} changes
|
|
30
|
+
* @returns {Array<import('../types').Change>}
|
|
31
|
+
*/
|
|
32
|
+
export const toChanges = changes =>
|
|
33
|
+
enforceArray(changes ?? []).map(change => ({
|
|
34
|
+
versions: toVersions(change.version),
|
|
35
|
+
prUrl: change['pr-url'] == null ? null : String(change['pr-url']),
|
|
36
|
+
commit: change.commit == null ? null : String(change.commit),
|
|
37
|
+
description: String(change.description ?? '').trim(),
|
|
38
|
+
}));
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Builds an entry's stability index
|
|
42
|
+
*
|
|
43
|
+
* @param {import('../../metadata/types').StabilityNode | undefined} node
|
|
44
|
+
* @param {boolean} [mdx] Whether the node comes from an MDX document
|
|
45
|
+
* @returns {import('../types').Stability | null}
|
|
46
|
+
*/
|
|
47
|
+
export const toStability = (node, mdx) => {
|
|
48
|
+
if (!node) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { index, description } = node.data;
|
|
53
|
+
const body = removeStabilityPrefix(node);
|
|
54
|
+
|
|
55
|
+
return {
|
|
56
|
+
index: String(index),
|
|
57
|
+
description: body?.children.length
|
|
58
|
+
? blocksToMarkdown(body.children, mdx)
|
|
59
|
+
: description,
|
|
60
|
+
};
|
|
61
|
+
};
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { u as createTree } from 'unist-builder';
|
|
4
|
+
import { visit } from 'unist-util-visit';
|
|
5
|
+
|
|
6
|
+
import { getRemark, getRemarkMdx } from '#utils/remark.mjs';
|
|
7
|
+
|
|
8
|
+
import { DISPLAY_NAME } from '../constants.mjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Serialises block nodes back to Markdown.
|
|
12
|
+
*
|
|
13
|
+
* @param {Array<import('mdast').RootContent>} nodes
|
|
14
|
+
* @param {boolean} [mdx] Whether the nodes come from an MDX document
|
|
15
|
+
* @returns {string}
|
|
16
|
+
*/
|
|
17
|
+
export const blocksToMarkdown = (nodes, mdx = false) => {
|
|
18
|
+
if (nodes.length === 0) {
|
|
19
|
+
return '';
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const processor = mdx ? getRemarkMdx() : getRemark();
|
|
23
|
+
|
|
24
|
+
return processor.stringify(createTree('root', nodes)).trim();
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Serialises phrasing (inline) nodes back to Markdown.
|
|
29
|
+
*
|
|
30
|
+
* @param {Array<import('mdast').PhrasingContent>} nodes
|
|
31
|
+
* @param {boolean} [mdx] Whether the nodes come from an MDX document
|
|
32
|
+
* @returns {string}
|
|
33
|
+
*/
|
|
34
|
+
export const inlineToMarkdown = (nodes, mdx) =>
|
|
35
|
+
nodes.length === 0
|
|
36
|
+
? ''
|
|
37
|
+
: blocksToMarkdown([createTree('paragraph', nodes)], mdx);
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Collects the fenced code blocks of a body
|
|
41
|
+
*
|
|
42
|
+
* @param {Array<import('mdast').RootContent>} nodes
|
|
43
|
+
* @returns {Array<import('../types').Example>}
|
|
44
|
+
*/
|
|
45
|
+
export const extractExamples = nodes => {
|
|
46
|
+
const examples = [];
|
|
47
|
+
|
|
48
|
+
visit(createTree('root', nodes), 'code', node => {
|
|
49
|
+
examples.push({
|
|
50
|
+
language: node.lang ?? null,
|
|
51
|
+
displayName: DISPLAY_NAME.exec(node.meta ?? '')?.[1] ?? null,
|
|
52
|
+
code: node.value,
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
|
|
56
|
+
return examples;
|
|
57
|
+
};
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { toString } from 'mdast-util-to-string';
|
|
4
|
+
|
|
5
|
+
import { transformNodeToHeading } from '#generators/metadata/utils/transformers.mjs';
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
CALLABLE_KINDS,
|
|
9
|
+
EXTENDS_CLAUSE,
|
|
10
|
+
KINDS,
|
|
11
|
+
SECTION_KIND,
|
|
12
|
+
} from '../constants.mjs';
|
|
13
|
+
import { buildEntry, entryBody, takeTypedItems } from './entry.mjs';
|
|
14
|
+
import {
|
|
15
|
+
buildEventParameters,
|
|
16
|
+
buildExtends,
|
|
17
|
+
buildPropertyType,
|
|
18
|
+
buildSignature,
|
|
19
|
+
} from './signature.mjs';
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Classifies an entry: the kind its heading documents and, when a `global`
|
|
23
|
+
* override replaced that classification, the scope it sets instead.
|
|
24
|
+
*
|
|
25
|
+
* @param {import('../../metadata/types').MetadataEntry} entry
|
|
26
|
+
* @returns {{ kind: string, scope?: 'global' }}
|
|
27
|
+
*/
|
|
28
|
+
export const classify = entry => {
|
|
29
|
+
const { type } = entry.heading.data;
|
|
30
|
+
|
|
31
|
+
if (type === 'global') {
|
|
32
|
+
const { type: structural } = transformNodeToHeading(entry.heading);
|
|
33
|
+
|
|
34
|
+
return { kind: KINDS[structural] ?? SECTION_KIND, scope: 'global' };
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
return { kind: KINDS[type] ?? SECTION_KIND };
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The bare identifier an entry documents
|
|
42
|
+
*
|
|
43
|
+
* @param {import('../../metadata/types').MetadataEntry} entry
|
|
44
|
+
* @param {string} kind The entry's kind
|
|
45
|
+
* @returns {string}
|
|
46
|
+
*/
|
|
47
|
+
export const nodeName = (entry, kind) => {
|
|
48
|
+
if (typeof entry.name === 'string') {
|
|
49
|
+
return entry.name;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
const { name } = entry.heading.data;
|
|
53
|
+
|
|
54
|
+
switch (kind) {
|
|
55
|
+
case SECTION_KIND:
|
|
56
|
+
return toString(entry.heading.children).trim();
|
|
57
|
+
case 'class':
|
|
58
|
+
case 'constructor':
|
|
59
|
+
// `http.Server`, `buffer.Blob`, `Foo extends Bar`
|
|
60
|
+
return name.split(EXTENDS_CLAUSE)[0].split('.').at(-1);
|
|
61
|
+
default:
|
|
62
|
+
return name;
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* The properties a node has on top of its entry, by kind.
|
|
68
|
+
*
|
|
69
|
+
* @param {string} kind
|
|
70
|
+
* @param {import('../../metadata/types').MetadataEntry} entry
|
|
71
|
+
* @param {Array<import('mdast').ListItem>} items The entry's typed list items
|
|
72
|
+
* @returns {{ properties: object, description?: string }}
|
|
73
|
+
*/
|
|
74
|
+
const kindProperties = (kind, entry, items) => {
|
|
75
|
+
if (CALLABLE_KINDS.has(kind)) {
|
|
76
|
+
return {
|
|
77
|
+
properties: {
|
|
78
|
+
signature: buildSignature(entry.heading, items, entry.mdx),
|
|
79
|
+
},
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
switch (kind) {
|
|
84
|
+
case 'class':
|
|
85
|
+
return { properties: { extends: buildExtends(entry.heading, items) } };
|
|
86
|
+
case 'property': {
|
|
87
|
+
const {
|
|
88
|
+
type,
|
|
89
|
+
default: value,
|
|
90
|
+
description,
|
|
91
|
+
} = buildPropertyType(items, entry.mdx);
|
|
92
|
+
|
|
93
|
+
return { properties: { type, default: value }, description };
|
|
94
|
+
}
|
|
95
|
+
case 'event':
|
|
96
|
+
return {
|
|
97
|
+
properties: { parameters: buildEventParameters(items, entry.mdx) },
|
|
98
|
+
};
|
|
99
|
+
default:
|
|
100
|
+
return { properties: {} };
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Builds a node and its subtree from a hierarchized entry.
|
|
106
|
+
*
|
|
107
|
+
* @param {import('#utils/hierarchy.mjs').HierarchizedEntry} node
|
|
108
|
+
* @param {'module' | 'global'} scope The document's scope
|
|
109
|
+
* @returns {import('../types').Node}
|
|
110
|
+
*/
|
|
111
|
+
export const buildNode = ({ entry, children }, scope) => {
|
|
112
|
+
const { kind, scope: entryScope = scope } = classify(entry);
|
|
113
|
+
const { body, items } = takeTypedItems(entryBody(entry), kind);
|
|
114
|
+
const { properties, description: typeDescription } = kindProperties(
|
|
115
|
+
kind,
|
|
116
|
+
entry,
|
|
117
|
+
items
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
const {
|
|
121
|
+
title,
|
|
122
|
+
stability,
|
|
123
|
+
added,
|
|
124
|
+
deprecated,
|
|
125
|
+
removed,
|
|
126
|
+
napiVersion,
|
|
127
|
+
changes,
|
|
128
|
+
description,
|
|
129
|
+
summary,
|
|
130
|
+
examples,
|
|
131
|
+
} = buildEntry(entry, body);
|
|
132
|
+
|
|
133
|
+
return {
|
|
134
|
+
kind,
|
|
135
|
+
id: entry.heading.data.slug,
|
|
136
|
+
name: nodeName(entry, kind),
|
|
137
|
+
title,
|
|
138
|
+
scope: entryScope,
|
|
139
|
+
overloadOf: entry.heading.data.overloadOf ?? null,
|
|
140
|
+
stability,
|
|
141
|
+
added,
|
|
142
|
+
deprecated,
|
|
143
|
+
removed,
|
|
144
|
+
napiVersion,
|
|
145
|
+
changes,
|
|
146
|
+
...properties,
|
|
147
|
+
// A property's type item may describe it; that comes first
|
|
148
|
+
description: [typeDescription, description].filter(Boolean).join('\n\n'),
|
|
149
|
+
summary,
|
|
150
|
+
examples,
|
|
151
|
+
children: children.map(child => buildNode(child, scope)),
|
|
152
|
+
};
|
|
153
|
+
};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { populate } from '#utils/configuration/templates.mjs';
|
|
4
|
+
|
|
5
|
+
import { SCHEMA_VERSION } from '../constants.mjs';
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* The `$schema` URL a generator's output carries: its `schemaURL` option with
|
|
9
|
+
* the schema version filled in.
|
|
10
|
+
*
|
|
11
|
+
* @param {{ schemaURL: string }} config The generator's configuration
|
|
12
|
+
* @returns {string}
|
|
13
|
+
*/
|
|
14
|
+
export const resolveSchemaURL = config =>
|
|
15
|
+
populate(config.schemaURL, { ...config, schemaVersion: SCHEMA_VERSION });
|
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { u as createTree } from 'unist-builder';
|
|
4
|
+
|
|
5
|
+
import {
|
|
6
|
+
extractListItem,
|
|
7
|
+
removeDefault,
|
|
8
|
+
} from '#utils/signature/extractListItem.mjs';
|
|
9
|
+
import parseSignature from '#utils/signature/parseSignature.mjs';
|
|
10
|
+
|
|
11
|
+
import {
|
|
12
|
+
CODE_SPAN,
|
|
13
|
+
DECLARED_DEFAULT,
|
|
14
|
+
EXTENDS_CLAUSE,
|
|
15
|
+
REST_MARKER,
|
|
16
|
+
} from '../constants.mjs';
|
|
17
|
+
import { blocksToMarkdown } from './markdown.mjs';
|
|
18
|
+
import { plainType, toType } from './types.mjs';
|
|
19
|
+
|
|
20
|
+
// What a parameter declared in a heading but absent from the typed list has
|
|
21
|
+
const EMPTY_ITEM = {
|
|
22
|
+
name: undefined,
|
|
23
|
+
prefix: undefined,
|
|
24
|
+
annotation: undefined,
|
|
25
|
+
text: [],
|
|
26
|
+
blocks: [],
|
|
27
|
+
default: undefined,
|
|
28
|
+
items: [],
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The Markdown of a list item's description
|
|
33
|
+
*
|
|
34
|
+
* @param {import('#utils/signature/extractListItem.mjs').ExtractedListItem} item
|
|
35
|
+
* @param {boolean} [mdx] Whether the item comes from an MDX document
|
|
36
|
+
* @returns {string}
|
|
37
|
+
*/
|
|
38
|
+
export const itemDescription = ({ text, blocks }, mdx) => {
|
|
39
|
+
const description = removeDefault(text);
|
|
40
|
+
|
|
41
|
+
return blocksToMarkdown(
|
|
42
|
+
[
|
|
43
|
+
...(description.length ? [createTree('paragraph', description)] : []),
|
|
44
|
+
...blocks,
|
|
45
|
+
],
|
|
46
|
+
mdx
|
|
47
|
+
);
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* A default value as authored, without the code span around it.
|
|
52
|
+
*
|
|
53
|
+
* @param {string | undefined} value
|
|
54
|
+
* @returns {string | null}
|
|
55
|
+
*/
|
|
56
|
+
const toDefault = value =>
|
|
57
|
+
value === undefined
|
|
58
|
+
? null
|
|
59
|
+
: value.replace(DECLARED_DEFAULT, '').replace(CODE_SPAN, '$1');
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Builds a parameter from its list item and, for a callable, its declaration
|
|
63
|
+
* in the heading.
|
|
64
|
+
*
|
|
65
|
+
* @param {import('#utils/signature/extractListItem.mjs').ExtractedListItem} item
|
|
66
|
+
* @param {import('#utils/signature/types').Parameter} [declared] The heading's declaration
|
|
67
|
+
* @param {boolean} [mdx] Whether the item comes from an MDX document
|
|
68
|
+
* @returns {import('../types').Parameter}
|
|
69
|
+
*/
|
|
70
|
+
export const toParameter = (item, declared = {}, mdx) => {
|
|
71
|
+
const name = declared.name ?? item.name ?? '';
|
|
72
|
+
const value = item.default ?? declared.default;
|
|
73
|
+
|
|
74
|
+
return {
|
|
75
|
+
name: name.replace(REST_MARKER, ''),
|
|
76
|
+
type: toType(item.annotation),
|
|
77
|
+
description: itemDescription(item, mdx),
|
|
78
|
+
default: toDefault(value),
|
|
79
|
+
optional: Boolean(declared.optional) || value !== undefined,
|
|
80
|
+
rest: REST_MARKER.test(name),
|
|
81
|
+
properties: item.items.map(nested =>
|
|
82
|
+
toParameter(extractListItem(nested), undefined, mdx)
|
|
83
|
+
),
|
|
84
|
+
};
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
/**
|
|
88
|
+
* Wraps an extracted item the way `parseSignature` matches parameters
|
|
89
|
+
* (by name, with the nested items as `options`)
|
|
90
|
+
*
|
|
91
|
+
* @param {import('#utils/signature/extractListItem.mjs').ExtractedListItem} item
|
|
92
|
+
*/
|
|
93
|
+
const toMarkdownParameter = item => ({
|
|
94
|
+
name: item.prefix
|
|
95
|
+
? item.prefix === 'Returns'
|
|
96
|
+
? 'return'
|
|
97
|
+
: item.prefix.toLowerCase()
|
|
98
|
+
: item.name,
|
|
99
|
+
options: item.items.map(nested =>
|
|
100
|
+
toMarkdownParameter(extractListItem(nested))
|
|
101
|
+
),
|
|
102
|
+
item,
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Builds a return value from its `Returns:` item.
|
|
107
|
+
*
|
|
108
|
+
* @param {import('#utils/signature/extractListItem.mjs').ExtractedListItem} item
|
|
109
|
+
* @param {boolean} [mdx] Whether the item comes from an MDX document
|
|
110
|
+
* @returns {import('../types').Return}
|
|
111
|
+
*/
|
|
112
|
+
const toReturn = (item, mdx) => ({
|
|
113
|
+
type: toType(item.annotation),
|
|
114
|
+
description: itemDescription(item, mdx),
|
|
115
|
+
});
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Builds the parameters a callable heading declares
|
|
119
|
+
*
|
|
120
|
+
* @param {import('../../metadata/types').HeadingNode} heading
|
|
121
|
+
* @param {Array<import('mdast').ListItem>} items The typed list's items
|
|
122
|
+
* @param {boolean} [mdx] Whether the items come from an MDX document
|
|
123
|
+
* @returns {import('../types').Signature}
|
|
124
|
+
*/
|
|
125
|
+
export const buildSignature = (heading, items, mdx) => {
|
|
126
|
+
const signature = parseSignature(
|
|
127
|
+
heading.data.text,
|
|
128
|
+
items.map(item => toMarkdownParameter(extractListItem(item)))
|
|
129
|
+
);
|
|
130
|
+
|
|
131
|
+
return {
|
|
132
|
+
parameters: signature.params.map(declared =>
|
|
133
|
+
toParameter(declared.item ?? EMPTY_ITEM, declared, mdx)
|
|
134
|
+
),
|
|
135
|
+
returns: signature.return ? toReturn(signature.return.item, mdx) : null,
|
|
136
|
+
};
|
|
137
|
+
};
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* @param {import('../../metadata/types').HeadingNode} heading
|
|
141
|
+
* @param {Array<import('mdast').ListItem>} items The typed list's items
|
|
142
|
+
* @returns {import('../types').Type | null}
|
|
143
|
+
*/
|
|
144
|
+
export const buildExtends = (heading, items) => {
|
|
145
|
+
const item = items
|
|
146
|
+
.map(extractListItem)
|
|
147
|
+
.find(({ prefix }) => prefix === 'Extends');
|
|
148
|
+
|
|
149
|
+
if (item) {
|
|
150
|
+
return toType(item.annotation);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
const [, base] = heading.data.name.split(EXTENDS_CLAUSE);
|
|
154
|
+
|
|
155
|
+
return base ? plainType(base) : null;
|
|
156
|
+
};
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* A property's basic metadata
|
|
160
|
+
*
|
|
161
|
+
* @param {Array<import('mdast').ListItem>} items The typed list's items
|
|
162
|
+
* @param {boolean} [mdx] Whether the items come from an MDX document
|
|
163
|
+
* @returns {{ type: import('../types').Type | null, default: string | null, description: string }}
|
|
164
|
+
*/
|
|
165
|
+
export const buildPropertyType = (items, mdx) => {
|
|
166
|
+
const [item] = items.map(extractListItem);
|
|
167
|
+
|
|
168
|
+
return item
|
|
169
|
+
? {
|
|
170
|
+
type: toType(item.annotation),
|
|
171
|
+
default: toDefault(item.default),
|
|
172
|
+
description: itemDescription(item, mdx),
|
|
173
|
+
}
|
|
174
|
+
: { type: null, default: null, description: '' };
|
|
175
|
+
};
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* The arguments an event's listeners receive.
|
|
179
|
+
*
|
|
180
|
+
* @param {Array<import('mdast').ListItem>} items The typed list's items
|
|
181
|
+
* @param {boolean} [mdx] Whether the items come from an MDX document
|
|
182
|
+
* @returns {Array<import('../types').Parameter>}
|
|
183
|
+
*/
|
|
184
|
+
export const buildEventParameters = (items, mdx) =>
|
|
185
|
+
items.map(item => toParameter(extractListItem(item), undefined, mdx));
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Builds a type from a resolved `typeAnnotation` node.
|
|
5
|
+
*
|
|
6
|
+
* @param {import('mdast').Node | undefined} node
|
|
7
|
+
* @returns {import('../types').Type | null}
|
|
8
|
+
*/
|
|
9
|
+
export const toType = node =>
|
|
10
|
+
node
|
|
11
|
+
? {
|
|
12
|
+
text: node.value,
|
|
13
|
+
links: (node.data?.links ?? []).map(({ text, href, start, end }) => ({
|
|
14
|
+
name: text,
|
|
15
|
+
href,
|
|
16
|
+
start,
|
|
17
|
+
end,
|
|
18
|
+
})),
|
|
19
|
+
}
|
|
20
|
+
: null;
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Builds a type from bare text, with nothing resolved.
|
|
24
|
+
*
|
|
25
|
+
* @param {string} text
|
|
26
|
+
* @returns {import('../types').Type}
|
|
27
|
+
*/
|
|
28
|
+
export const plainType = text => ({ text, links: [] });
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# `json-all` Generator
|
|
2
|
+
|
|
3
|
+
The `json-all` generator bundles the documents of the [`json`](./json.md)
|
|
4
|
+
generator into a single `all.json` file.
|
|
5
|
+
|
|
6
|
+
```sh
|
|
7
|
+
npx @doc-kit/cli generate -t json-all -i "doc/api/*.md" -o out --index doc/api/index.md
|
|
8
|
+
```
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"$schema": "https://doc-kit.nodejs.org/schemas/api-doc-all/1.0.0.json",
|
|
13
|
+
"documents": []
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
`documents` holds every document in the order of the configured `index`,
|
|
18
|
+
then the rest by `id`. The bundle's schema, shipped as
|
|
19
|
+
`@doc-kit/core/generators/json-all/schema.json`, refers to the `json`
|
|
20
|
+
generator's schema for the documents.
|
|
21
|
+
|
|
22
|
+
## Configuring
|
|
23
|
+
|
|
24
|
+
- `output` {string} The directory where `all.json` will be written.
|
|
25
|
+
- `minify` {boolean} Whether to minify the output. Inherited from `global`.
|
|
26
|
+
**Default:** `true`.
|
|
27
|
+
- `index` {Array} The `{ api }` objects defining the document order. Inherited
|
|
28
|
+
from `global`.
|
|
29
|
+
- `schemaURL` {string} Where the bundle's schema is published.
|
|
30
|
+
`{schemaVersion}` is filled in. **Default:**
|
|
31
|
+
`'https://doc-kit.nodejs.org/schemas/api-doc-all/{schemaVersion}.json'`.
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
|
|
5
|
+
import getConfig from '#utils/configuration/index.mjs';
|
|
6
|
+
import { writeJSON } from '#utils/file.mjs';
|
|
7
|
+
|
|
8
|
+
import { resolveSchemaURL } from '../json/utils/schema.mjs';
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* Bundles the `json` generator's documents into one `all.json` file.
|
|
12
|
+
*
|
|
13
|
+
* @type {import('./types').Generator['generate']}
|
|
14
|
+
*/
|
|
15
|
+
export async function generate(input) {
|
|
16
|
+
const config = getConfig('json-all');
|
|
17
|
+
|
|
18
|
+
// Documents follow the configured index; the rest go after it, by id
|
|
19
|
+
const order = new Map(config.index?.map(({ api }, i) => [api, i]));
|
|
20
|
+
|
|
21
|
+
const documents = input.toSorted(
|
|
22
|
+
(a, b) =>
|
|
23
|
+
(order.get(a.id) ?? Infinity) - (order.get(b.id) ?? Infinity) ||
|
|
24
|
+
a.id.localeCompare(b.id)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
/** @type {import('./types').Bundle} */
|
|
28
|
+
const bundle = { $schema: resolveSchemaURL(config), documents };
|
|
29
|
+
|
|
30
|
+
if (config.output) {
|
|
31
|
+
await writeJSON(join(config.output, 'all.json'), bundle, config.minify);
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return bundle;
|
|
35
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { SCHEMA_URL } from './constants.mjs';
|
|
4
|
+
import { generate } from './generate.mjs';
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* This generator bundles the documents of the `json` generator into a single
|
|
8
|
+
* `all.json` file
|
|
9
|
+
*
|
|
10
|
+
* @type {import('./types').Generator}
|
|
11
|
+
*/
|
|
12
|
+
export default {
|
|
13
|
+
name: 'json-all',
|
|
14
|
+
|
|
15
|
+
description:
|
|
16
|
+
'Bundles the documents of the `json` generator into a single `all.json` file',
|
|
17
|
+
|
|
18
|
+
dependsOn: '@doc-kit/core/json',
|
|
19
|
+
|
|
20
|
+
defaultConfiguration: {
|
|
21
|
+
schemaURL: SCHEMA_URL,
|
|
22
|
+
},
|
|
23
|
+
|
|
24
|
+
generate,
|
|
25
|
+
};
|