@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,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
|
+
"$id": "https://doc-kit.nodejs.org/schemas/api-doc-all/1.0.1.json",
|
|
4
|
+
"title": "Bundle",
|
|
5
|
+
"description": "Every document of a documentation set, as emitted by the doc-kit `json-all` generator",
|
|
6
|
+
"type": "object",
|
|
7
|
+
"properties": {
|
|
8
|
+
"$schema": {
|
|
9
|
+
"type": "string",
|
|
10
|
+
"description": "The URL of the schema this bundle conforms to. Its last path segment is the schema version."
|
|
11
|
+
},
|
|
12
|
+
"documents": {
|
|
13
|
+
"type": "array",
|
|
14
|
+
"items": {
|
|
15
|
+
"$ref": "https://doc-kit.nodejs.org/schemas/api-doc/1.0.1.json"
|
|
16
|
+
},
|
|
17
|
+
"description": "The documents, in the order of the configured index, then by id."
|
|
18
|
+
}
|
|
19
|
+
},
|
|
20
|
+
"required": ["$schema", "documents"],
|
|
21
|
+
"additionalProperties": false
|
|
22
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Document } from '../json/generated/schema';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Every document of a documentation set
|
|
5
|
+
*/
|
|
6
|
+
export interface Bundle {
|
|
7
|
+
/** The URL of the schema the bundle conforms to */
|
|
8
|
+
$schema: string;
|
|
9
|
+
documents: Array<Document>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface Configuration {
|
|
13
|
+
/** Where the schema is published; `{schemaVersion}` is filled in */
|
|
14
|
+
schemaURL: string;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export type Generator = GeneratorMetadata<
|
|
18
|
+
Configuration,
|
|
19
|
+
Generate<Array<Document>, Promise<Bundle>>
|
|
20
|
+
>;
|
|
@@ -5,7 +5,7 @@ import { join } from 'node:path';
|
|
|
5
5
|
import { remove } from 'unist-util-remove';
|
|
6
6
|
|
|
7
7
|
import getConfig from '#utils/configuration/index.mjs';
|
|
8
|
-
import {
|
|
8
|
+
import { writeJSON } from '#utils/file.mjs';
|
|
9
9
|
import { UNIST } from '#utils/queries/index.mjs';
|
|
10
10
|
|
|
11
11
|
/**
|
|
@@ -21,12 +21,7 @@ export async function generate(input) {
|
|
|
21
21
|
);
|
|
22
22
|
|
|
23
23
|
if (config.output) {
|
|
24
|
-
|
|
25
|
-
// Note: The full JSON generator in the future will create one JSON file per top-level API doc file
|
|
26
|
-
await writeFile(
|
|
27
|
-
join(config.output, 'api-docs.json'),
|
|
28
|
-
config.minify ? JSON.stringify(input) : JSON.stringify(input, null, 2)
|
|
29
|
-
);
|
|
24
|
+
await writeJSON(join(config.output, 'api-docs.json'), input, config.minify);
|
|
30
25
|
}
|
|
31
26
|
|
|
32
27
|
return input;
|
|
@@ -421,6 +421,7 @@
|
|
|
421
421
|
"idbkeyrange": "https://developer.mozilla.org/docs/Web/API/IDBKeyRange",
|
|
422
422
|
"idbobjectstore": "https://developer.mozilla.org/docs/Web/API/IDBObjectStore",
|
|
423
423
|
"idbopendbrequest": "https://developer.mozilla.org/docs/Web/API/IDBOpenDBRequest",
|
|
424
|
+
"idbrecord": "https://developer.mozilla.org/docs/Web/API/IDBRecord",
|
|
424
425
|
"idbrequest": "https://developer.mozilla.org/docs/Web/API/IDBRequest",
|
|
425
426
|
"idbtransaction": "https://developer.mozilla.org/docs/Web/API/IDBTransaction",
|
|
426
427
|
"idbversionchangeevent": "https://developer.mozilla.org/docs/Web/API/IDBVersionChangeEvent",
|
|
@@ -442,6 +443,7 @@
|
|
|
442
443
|
"inputdeviceinfo": "https://developer.mozilla.org/docs/Web/API/InputDeviceInfo",
|
|
443
444
|
"inputevent": "https://developer.mozilla.org/docs/Web/API/InputEvent",
|
|
444
445
|
"installevent": "https://developer.mozilla.org/docs/Web/API/InstallEvent",
|
|
446
|
+
"interactioncontentfulpaint": "https://developer.mozilla.org/docs/Web/API/InteractionContentfulPaint",
|
|
445
447
|
"interestevent": "https://developer.mozilla.org/docs/Web/API/InterestEvent",
|
|
446
448
|
"intersectionobserver": "https://developer.mozilla.org/docs/Web/API/IntersectionObserver",
|
|
447
449
|
"intersectionobserverentry": "https://developer.mozilla.org/docs/Web/API/IntersectionObserverEntry",
|
|
@@ -452,6 +454,7 @@
|
|
|
452
454
|
"keyboardlayoutmap": "https://developer.mozilla.org/docs/Web/API/KeyboardLayoutMap",
|
|
453
455
|
"keyframeeffect": "https://developer.mozilla.org/docs/Web/API/KeyframeEffect",
|
|
454
456
|
"languagedetector": "https://developer.mozilla.org/docs/Web/API/LanguageDetector",
|
|
457
|
+
"languagemodel": "https://developer.mozilla.org/docs/Web/API/LanguageModel",
|
|
455
458
|
"largestcontentfulpaint": "https://developer.mozilla.org/docs/Web/API/LargestContentfulPaint",
|
|
456
459
|
"launchparams": "https://developer.mozilla.org/docs/Web/API/LaunchParams",
|
|
457
460
|
"launchqueue": "https://developer.mozilla.org/docs/Web/API/LaunchQueue",
|
|
@@ -472,6 +475,7 @@
|
|
|
472
475
|
"magnetometer": "https://developer.mozilla.org/docs/Web/API/Magnetometer",
|
|
473
476
|
"managedmediasource": "https://developer.mozilla.org/docs/Web/API/ManagedMediaSource",
|
|
474
477
|
"managedsourcebuffer": "https://developer.mozilla.org/docs/Web/API/ManagedSourceBuffer",
|
|
478
|
+
"mathmlanchorelement": "https://developer.mozilla.org/docs/Web/API/MathMLAnchorElement",
|
|
475
479
|
"mathmlelement": "https://developer.mozilla.org/docs/Web/API/MathMLElement",
|
|
476
480
|
"mediacapabilities": "https://developer.mozilla.org/docs/Web/API/MediaCapabilities",
|
|
477
481
|
"mediadeviceinfo": "https://developer.mozilla.org/docs/Web/API/MediaDeviceInfo",
|
|
@@ -589,7 +593,9 @@
|
|
|
589
593
|
"performanceresourcetiming": "https://developer.mozilla.org/docs/Web/API/PerformanceResourceTiming",
|
|
590
594
|
"performancescripttiming": "https://developer.mozilla.org/docs/Web/API/PerformanceScriptTiming",
|
|
591
595
|
"performanceservertiming": "https://developer.mozilla.org/docs/Web/API/PerformanceServerTiming",
|
|
596
|
+
"performancesoftnavigation": "https://developer.mozilla.org/docs/Web/API/PerformanceSoftNavigation",
|
|
592
597
|
"performancetiming": "https://developer.mozilla.org/docs/Web/API/PerformanceTiming",
|
|
598
|
+
"performancetimingconfidence": "https://developer.mozilla.org/docs/Web/API/PerformanceTimingConfidence",
|
|
593
599
|
"periodicsyncevent": "https://developer.mozilla.org/docs/Web/API/PeriodicSyncEvent",
|
|
594
600
|
"periodicsyncmanager": "https://developer.mozilla.org/docs/Web/API/PeriodicSyncManager",
|
|
595
601
|
"periodicwave": "https://developer.mozilla.org/docs/Web/API/PeriodicWave",
|
|
@@ -636,6 +642,7 @@
|
|
|
636
642
|
"rtcerror": "https://developer.mozilla.org/docs/Web/API/RTCError",
|
|
637
643
|
"rtcerrorevent": "https://developer.mozilla.org/docs/Web/API/RTCErrorEvent",
|
|
638
644
|
"rtcicecandidate": "https://developer.mozilla.org/docs/Web/API/RTCIceCandidate",
|
|
645
|
+
"rtcicecandidatepair": "https://developer.mozilla.org/docs/Web/API/RTCIceCandidatePair",
|
|
639
646
|
"rtcicetransport": "https://developer.mozilla.org/docs/Web/API/RTCIceTransport",
|
|
640
647
|
"rtcidentityassertion": "https://developer.mozilla.org/docs/Web/API/RTCIdentityAssertion",
|
|
641
648
|
"rtcpeerconnection": "https://developer.mozilla.org/docs/Web/API/RTCPeerConnection",
|
|
@@ -672,7 +679,6 @@
|
|
|
672
679
|
"restrictiontarget": "https://developer.mozilla.org/docs/Web/API/RestrictionTarget",
|
|
673
680
|
"svgaelement": "https://developer.mozilla.org/docs/Web/API/SVGAElement",
|
|
674
681
|
"svgangle": "https://developer.mozilla.org/docs/Web/API/SVGAngle",
|
|
675
|
-
"svganimatecolorelement": "https://developer.mozilla.org/docs/Web/API/SVGAnimateColorElement",
|
|
676
682
|
"svganimateelement": "https://developer.mozilla.org/docs/Web/API/SVGAnimateElement",
|
|
677
683
|
"svganimatemotionelement": "https://developer.mozilla.org/docs/Web/API/SVGAnimateMotionElement",
|
|
678
684
|
"svganimatetransformelement": "https://developer.mozilla.org/docs/Web/API/SVGAnimateTransformElement",
|
|
@@ -749,7 +755,6 @@
|
|
|
749
755
|
"svgradialgradientelement": "https://developer.mozilla.org/docs/Web/API/SVGRadialGradientElement",
|
|
750
756
|
"svgrect": "https://developer.mozilla.org/docs/Web/API/SVGRect",
|
|
751
757
|
"svgrectelement": "https://developer.mozilla.org/docs/Web/API/SVGRectElement",
|
|
752
|
-
"svgrenderingintent": "https://developer.mozilla.org/docs/Web/API/SVGRenderingIntent",
|
|
753
758
|
"svgsvgelement": "https://developer.mozilla.org/docs/Web/API/SVGSVGElement",
|
|
754
759
|
"svgscriptelement": "https://developer.mozilla.org/docs/Web/API/SVGScriptElement",
|
|
755
760
|
"svgsetelement": "https://developer.mozilla.org/docs/Web/API/SVGSetElement",
|
|
@@ -947,8 +952,10 @@
|
|
|
947
952
|
"webtransport": "https://developer.mozilla.org/docs/Web/API/WebTransport",
|
|
948
953
|
"webtransportbidirectionalstream": "https://developer.mozilla.org/docs/Web/API/WebTransportBidirectionalStream",
|
|
949
954
|
"webtransportdatagramduplexstream": "https://developer.mozilla.org/docs/Web/API/WebTransportDatagramDuplexStream",
|
|
955
|
+
"webtransportdatagramswritable": "https://developer.mozilla.org/docs/Web/API/WebTransportDatagramsWritable",
|
|
950
956
|
"webtransporterror": "https://developer.mozilla.org/docs/Web/API/WebTransportError",
|
|
951
957
|
"webtransportreceivestream": "https://developer.mozilla.org/docs/Web/API/WebTransportReceiveStream",
|
|
958
|
+
"webtransportsendgroup": "https://developer.mozilla.org/docs/Web/API/WebTransportSendGroup",
|
|
952
959
|
"webtransportsendstream": "https://developer.mozilla.org/docs/Web/API/WebTransportSendStream",
|
|
953
960
|
"wheelevent": "https://developer.mozilla.org/docs/Web/API/WheelEvent",
|
|
954
961
|
"window": "https://developer.mozilla.org/docs/Web/API/Window",
|
|
@@ -1014,6 +1021,7 @@
|
|
|
1014
1021
|
"xrview": "https://developer.mozilla.org/docs/Web/API/XRView",
|
|
1015
1022
|
"xrviewerpose": "https://developer.mozilla.org/docs/Web/API/XRViewerPose",
|
|
1016
1023
|
"xrviewport": "https://developer.mozilla.org/docs/Web/API/XRViewport",
|
|
1024
|
+
"xrvisibilitymaskchangeevent": "https://developer.mozilla.org/docs/Web/API/XRVisibilityMaskChangeEvent",
|
|
1017
1025
|
"xrwebglbinding": "https://developer.mozilla.org/docs/Web/API/XRWebGLBinding",
|
|
1018
1026
|
"xrwebgldepthinformation": "https://developer.mozilla.org/docs/Web/API/XRWebGLDepthInformation",
|
|
1019
1027
|
"xrwebgllayer": "https://developer.mozilla.org/docs/Web/API/XRWebGLLayer",
|
|
@@ -97,6 +97,11 @@ export interface HeadingData extends Data {
|
|
|
97
97
|
* from the ToC while still rendering on the page.
|
|
98
98
|
*/
|
|
99
99
|
isOverload?: boolean;
|
|
100
|
+
/**
|
|
101
|
+
* The slug of the first heading of the overloaded function this heading is
|
|
102
|
+
* an overload of. Set alongside `isOverload`.
|
|
103
|
+
*/
|
|
104
|
+
overloadOf?: string;
|
|
100
105
|
}
|
|
101
106
|
|
|
102
107
|
/**
|
|
@@ -72,7 +72,7 @@ export const resolveTypeReference = (name, typeMap) => {
|
|
|
72
72
|
// Transform Node.js types like 'vm.Something'.
|
|
73
73
|
if (MODULE_QUALIFIED_NAME.test(name)) {
|
|
74
74
|
const [mod, ...pieces] = name.split('.');
|
|
75
|
-
const isClass = pieces.at(-1).match(/^[A-Z][a-z]/);
|
|
75
|
+
const isClass = pieces.at(-1).match(/^[A-Z](?=.*[a-z])/);
|
|
76
76
|
|
|
77
77
|
return `${mod}.html#${isClass ? 'class-' : ''}${slug(name)}`;
|
|
78
78
|
}
|
package/src/logger/logger.mjs
CHANGED
|
@@ -165,6 +165,13 @@ export const createLogger = (
|
|
|
165
165
|
}
|
|
166
166
|
};
|
|
167
167
|
|
|
168
|
+
/**
|
|
169
|
+
* Gets the current log level for this logger instance.
|
|
170
|
+
*
|
|
171
|
+
* @returns {number} The current numeric log level
|
|
172
|
+
*/
|
|
173
|
+
const getLogLevel = () => currentLevel;
|
|
174
|
+
|
|
168
175
|
return {
|
|
169
176
|
info,
|
|
170
177
|
warn,
|
|
@@ -173,5 +180,6 @@ export const createLogger = (
|
|
|
173
180
|
debug,
|
|
174
181
|
child,
|
|
175
182
|
setLogLevel,
|
|
183
|
+
getLogLevel,
|
|
176
184
|
};
|
|
177
185
|
};
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
+
import { workerData } from 'node:worker_threads';
|
|
2
|
+
|
|
1
3
|
import { loadGenerator } from '#generators/loader.mjs';
|
|
4
|
+
import logger from '#logger/index.mjs';
|
|
2
5
|
import { setConfig } from '#utils/configuration/index.mjs';
|
|
3
6
|
|
|
7
|
+
if (workerData?.logLevel !== undefined) {
|
|
8
|
+
logger.setLogLevel(workerData.logLevel);
|
|
9
|
+
}
|
|
10
|
+
|
|
4
11
|
/**
|
|
5
12
|
* Processes a chunk of items using the specified generator's processChunk method.
|
|
6
13
|
* This is the worker entry point for Piscina.
|
package/src/threading/index.mjs
CHANGED
package/src/utils/file.mjs
CHANGED
|
@@ -18,3 +18,13 @@ export const writeFile = (file, ...args) =>
|
|
|
18
18
|
fs
|
|
19
19
|
.mkdir(dirname(file), { recursive: true })
|
|
20
20
|
.then(() => fs.writeFile(file, ...args));
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Writes a value as JSON
|
|
24
|
+
*
|
|
25
|
+
* @param {string} file
|
|
26
|
+
* @param {unknown} value
|
|
27
|
+
* @param {boolean} [minify]
|
|
28
|
+
*/
|
|
29
|
+
export const writeJSON = (file, value, minify = false) =>
|
|
30
|
+
writeFile(file, JSON.stringify(value, null, minify ? 0 : 2));
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* A node in the entry hierarchy.
|
|
5
|
+
*
|
|
6
|
+
* @typedef {object} HierarchizedEntry
|
|
7
|
+
* @property {import('../generators/metadata/types').MetadataEntry} entry The metadata entry this node wraps
|
|
8
|
+
* @property {Array<HierarchizedEntry>} children Entries nested under this one, by heading depth
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Finds the closest preceding node whose heading is shallower than the
|
|
13
|
+
* entry's, which is the entry's parent.
|
|
14
|
+
*
|
|
15
|
+
* @param {import('../generators/metadata/types').MetadataEntry} entry The entry to find a parent for
|
|
16
|
+
* @param {Array<HierarchizedEntry>} nodes Wrapper nodes, index-aligned with the entries
|
|
17
|
+
* @param {number} startIdx The index to search backwards from
|
|
18
|
+
* @returns {HierarchizedEntry | undefined} The parent, or `undefined` when no shallower entry precedes it
|
|
19
|
+
*/
|
|
20
|
+
export const findParent = (entry, nodes, startIdx) => {
|
|
21
|
+
for (let i = startIdx; i >= 0; i--) {
|
|
22
|
+
if (nodes[i].entry.heading.depth < entry.heading.depth) {
|
|
23
|
+
return nodes[i];
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return undefined;
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* @param {Array<import('../generators/metadata/types').MetadataEntry>} entries Entries in document order
|
|
32
|
+
* @returns {Array<HierarchizedEntry>} The root nodes
|
|
33
|
+
*/
|
|
34
|
+
export const buildHierarchy = entries => {
|
|
35
|
+
const roots = [];
|
|
36
|
+
|
|
37
|
+
// Wrapper nodes, index-aligned with `entries`
|
|
38
|
+
const nodes = entries.map(entry => ({ entry, children: [] }));
|
|
39
|
+
|
|
40
|
+
nodes.forEach((node, i) => {
|
|
41
|
+
const parent =
|
|
42
|
+
node.entry.heading.depth <= 1
|
|
43
|
+
? undefined
|
|
44
|
+
: findParent(node.entry, nodes, i - 1);
|
|
45
|
+
|
|
46
|
+
(parent?.children ?? roots).push(node);
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
return roots;
|
|
50
|
+
};
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// Heading types that document a callable and therefore may appear several times
|
|
4
|
+
// in a row as overloaded signatures of the same function.
|
|
5
|
+
const OVERLOADABLE_TYPES = new Set(['method', 'ctor', 'classMethod']);
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Two headings document the same function (i.e. are overloads of one another)
|
|
9
|
+
* when they sit at the same depth and share the same resolved name and type.
|
|
10
|
+
*
|
|
11
|
+
* @param {import('../generators/metadata/types').HeadingNode} a
|
|
12
|
+
* @param {import('../generators/metadata/types').HeadingNode} b
|
|
13
|
+
*/
|
|
14
|
+
const isSameFunction = (a, b) =>
|
|
15
|
+
a.depth === b.depth &&
|
|
16
|
+
a.data.type === b.data.type &&
|
|
17
|
+
a.data.name === b.data.name;
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Flags overloaded function headings so consumers can present a single entry
|
|
21
|
+
* per function.
|
|
22
|
+
*
|
|
23
|
+
* Node.js documents each overload of a function as its own heading (e.g. the
|
|
24
|
+
* five `new Buffer(...)` signatures). This marks the 2nd..nth heading of each
|
|
25
|
+
* such run with `isOverload`, and with `overloadOf` pointing at the slug of
|
|
26
|
+
* the run's first heading. The first (most stable) heading is left as-is.
|
|
27
|
+
*
|
|
28
|
+
* @param {Array<import('../generators/metadata/types').MetadataEntry>} entries - Entries, in document order.
|
|
29
|
+
* @returns {Array<import('../generators/metadata/types').MetadataEntry>} The same entries (mutated).
|
|
30
|
+
*/
|
|
31
|
+
export const annotateOverloads = entries => {
|
|
32
|
+
for (let i = 0; i < entries.length; i++) {
|
|
33
|
+
const { heading } = entries[i];
|
|
34
|
+
|
|
35
|
+
if (!OVERLOADABLE_TYPES.has(heading.data.type)) {
|
|
36
|
+
continue;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Flag each following heading that overloads the same function.
|
|
40
|
+
let end = i + 1;
|
|
41
|
+
while (
|
|
42
|
+
end < entries.length &&
|
|
43
|
+
isSameFunction(entries[end].heading, heading)
|
|
44
|
+
) {
|
|
45
|
+
entries[end].heading.data.isOverload = true;
|
|
46
|
+
entries[end].heading.data.overloadOf = heading.data.slug;
|
|
47
|
+
end++;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
i = end - 1;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
return entries;
|
|
54
|
+
};
|
|
@@ -4,6 +4,8 @@ import { transformNodesToString } from '#utils/unist.mjs';
|
|
|
4
4
|
|
|
5
5
|
import { isTypedListItem, isTypedList } from './utils.mjs';
|
|
6
6
|
|
|
7
|
+
export { splitTypedItems } from './utils.mjs';
|
|
8
|
+
|
|
7
9
|
// This defines the actual REGEX Queries
|
|
8
10
|
export const QUERIES = {
|
|
9
11
|
// Fixes the references to Markdown pages into the API documentation
|
|
@@ -67,3 +67,18 @@ export const isTypedList = list => {
|
|
|
67
67
|
|
|
68
68
|
return getTypedConfidence(list.children?.[0]?.children?.[0]?.children?.[0]);
|
|
69
69
|
};
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* Splits a typed list's items into the leading typed ones and the rest:
|
|
73
|
+
* prose bullets that happen to share the list in the source markdown.
|
|
74
|
+
*
|
|
75
|
+
* @param {import('@types/mdast').List} list
|
|
76
|
+
* @returns {{ typed: Array<import('@types/mdast').ListItem>, rest: Array<import('@types/mdast').ListItem> }}
|
|
77
|
+
*/
|
|
78
|
+
export const splitTypedItems = ({ children }) => {
|
|
79
|
+
const end = children.findIndex(item => !isTypedListItem(item));
|
|
80
|
+
|
|
81
|
+
return end === -1
|
|
82
|
+
? { typed: children, rest: [] }
|
|
83
|
+
: { typed: children.slice(0, end), rest: children.slice(end) };
|
|
84
|
+
};
|
package/src/utils/remark.mjs
CHANGED
|
@@ -76,7 +76,7 @@ export const getRemark = lazy(() =>
|
|
|
76
76
|
* `{` for type annotations that MDX would otherwise try to parse.
|
|
77
77
|
*/
|
|
78
78
|
export const getRemarkMdx = lazy(() =>
|
|
79
|
-
unified().use(remarkParse).use(remarkMdx).use(remarkGfm)
|
|
79
|
+
unified().use(remarkParse).use(remarkMdx).use(remarkGfm).use(remarkStringify)
|
|
80
80
|
);
|
|
81
81
|
|
|
82
82
|
/**
|
|
@@ -4,6 +4,9 @@ export const NAME_EXPRESSION = /^['`"]?([^'`": {]+)['`"]?\s*:?\s*/;
|
|
|
4
4
|
// Checks if there's a leading hyphen
|
|
5
5
|
export const LEADING_HYPHEN = /^-\s*/;
|
|
6
6
|
|
|
7
|
+
// The separators between a parameter's type and its description
|
|
8
|
+
export const TRIMMABLE_PADDING_REGEX = /^[\s:-]+/;
|
|
9
|
+
|
|
7
10
|
// Grabs the default value if present
|
|
8
11
|
export const DEFAULT_EXPRESSION = /\s*\*\*Default:\*\*\s*([^]+)$/i;
|
|
9
12
|
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { QUERIES, UNIST } from '#utils/queries/index.mjs';
|
|
4
|
+
import { transformNodesToString } from '#utils/unist.mjs';
|
|
5
|
+
|
|
6
|
+
import { DEFAULT_EXPRESSION, TRIMMABLE_PADDING_REGEX } from './constants.mjs';
|
|
7
|
+
|
|
8
|
+
// The text of the `**Default:**` marker introducing a default value
|
|
9
|
+
const DEFAULT_MARKER = /^default:$/i;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* A typed list item taken apart into its parts, none of them stringified, so
|
|
13
|
+
* each consumer can render the description its own way.
|
|
14
|
+
*
|
|
15
|
+
* @typedef {object} ExtractedListItem
|
|
16
|
+
* @property {string | undefined} name The parameter name (the leading code span), if any
|
|
17
|
+
* @property {'Returns' | 'Extends' | 'Type' | undefined} prefix The special prefix the item starts with, if any
|
|
18
|
+
* @property {import('mdast').Node | undefined} annotation The leading `typeAnnotation` node, if any
|
|
19
|
+
* @property {Array<import('mdast').PhrasingContent>} text The rest of the first paragraph: the description,
|
|
20
|
+
* with leading separators trimmed and any `**Default:**` marker still in place
|
|
21
|
+
* @property {Array<import('mdast').BlockContent>} blocks The item's further block content, excluding its nested typed list
|
|
22
|
+
* @property {string | undefined} default The `**Default:**` value as written (code span included), if any
|
|
23
|
+
* @property {Array<import('mdast').ListItem>} items The items of the nested typed list, if any
|
|
24
|
+
*/
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Replaces the first node's text, or drops the node when nothing is left.
|
|
28
|
+
*
|
|
29
|
+
* @param {Array<import('mdast').PhrasingContent>} nodes
|
|
30
|
+
* @param {string} value The new text of the first node
|
|
31
|
+
*/
|
|
32
|
+
const replaceLeadingText = (nodes, value) => {
|
|
33
|
+
if (value.trim()) {
|
|
34
|
+
nodes[0] = { ...nodes[0], value };
|
|
35
|
+
} else {
|
|
36
|
+
nodes.shift();
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Takes a typed list item apart: `` `name` {Type} Description. **Default:** `value` ``,
|
|
42
|
+
* or one of the `Returns:`, `Extends:` and `Type:` forms.
|
|
43
|
+
*
|
|
44
|
+
* @param {import('mdast').ListItem} item
|
|
45
|
+
* @returns {ExtractedListItem}
|
|
46
|
+
*/
|
|
47
|
+
export const extractListItem = item => {
|
|
48
|
+
const [paragraph, ...rest] = item.children ?? [];
|
|
49
|
+
const text = [...(paragraph?.children ?? [])];
|
|
50
|
+
|
|
51
|
+
const result = {
|
|
52
|
+
name: undefined,
|
|
53
|
+
prefix: undefined,
|
|
54
|
+
annotation: undefined,
|
|
55
|
+
text,
|
|
56
|
+
blocks: [],
|
|
57
|
+
default: undefined,
|
|
58
|
+
items: [],
|
|
59
|
+
};
|
|
60
|
+
|
|
61
|
+
const [first] = text;
|
|
62
|
+
|
|
63
|
+
if (first?.type === 'inlineCode') {
|
|
64
|
+
result.name = first.value.trimEnd();
|
|
65
|
+
text.shift();
|
|
66
|
+
} else if (first?.type === 'text') {
|
|
67
|
+
const match = first.value.match(QUERIES.typedListStarters);
|
|
68
|
+
|
|
69
|
+
if (match) {
|
|
70
|
+
result.prefix = match[1];
|
|
71
|
+
replaceLeadingText(text, first.value.slice(match[0].length));
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// The whitespace between the name and the type
|
|
76
|
+
if (text[0]?.type === 'text' && !text[0].value.trim()) {
|
|
77
|
+
text.shift();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (text[0]?.type === 'typeAnnotation') {
|
|
81
|
+
result.annotation = text.shift();
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// Leading separators: `- description`, `: description`
|
|
85
|
+
if (text[0]?.type === 'text') {
|
|
86
|
+
replaceLeadingText(
|
|
87
|
+
text,
|
|
88
|
+
text[0].value.replace(TRIMMABLE_PADDING_REGEX, '')
|
|
89
|
+
);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
result.default = DEFAULT_EXPRESSION.exec(transformNodesToString(text))?.[1]
|
|
93
|
+
.trim()
|
|
94
|
+
.replace(/\.$/, '');
|
|
95
|
+
|
|
96
|
+
for (const node of rest) {
|
|
97
|
+
if (result.items.length === 0 && UNIST.isLooselyTypedList(node)) {
|
|
98
|
+
result.items = node.children;
|
|
99
|
+
} else {
|
|
100
|
+
result.blocks.push(node);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
return result;
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
/**
|
|
108
|
+
* Drops the `**Default:**` marker, and everything after it, from an item's
|
|
109
|
+
* description.
|
|
110
|
+
*
|
|
111
|
+
* @param {Array<import('mdast').PhrasingContent>} nodes The item's description
|
|
112
|
+
* @returns {Array<import('mdast').PhrasingContent>} The description without its default value
|
|
113
|
+
*/
|
|
114
|
+
export const removeDefault = nodes => {
|
|
115
|
+
const index = nodes.findIndex(
|
|
116
|
+
node =>
|
|
117
|
+
node.type === 'strong' &&
|
|
118
|
+
DEFAULT_MARKER.test(transformNodesToString(node.children).trim())
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
if (index === -1) {
|
|
122
|
+
return nodes;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const kept = nodes.slice(0, index);
|
|
126
|
+
const last = kept.at(-1);
|
|
127
|
+
|
|
128
|
+
// The whitespace that separated the description from its default
|
|
129
|
+
if (last?.type === 'text') {
|
|
130
|
+
const value = last.value.trimEnd();
|
|
131
|
+
|
|
132
|
+
kept.pop();
|
|
133
|
+
|
|
134
|
+
if (value) {
|
|
135
|
+
kept.push({ ...last, value });
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return kept;
|
|
140
|
+
};
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import { slice } from 'mdast-util-slice-markdown';
|
|
4
|
+
import { toString } from 'mdast-util-to-string';
|
|
5
|
+
|
|
6
|
+
import { QUERIES } from './queries/index.mjs';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* The content of a stability blockquote without its `Stability: N - `
|
|
10
|
+
* prefix, as a copy of the blockquote. The prefix may have been turned into a
|
|
11
|
+
* link by the AST stage; the separator goes with it.
|
|
12
|
+
*
|
|
13
|
+
* @param {import('../generators/metadata/types').StabilityNode} node
|
|
14
|
+
* @returns {import('mdast').Blockquote | null} The copy, or `null` when nothing follows the prefix
|
|
15
|
+
*/
|
|
16
|
+
export const removeStabilityPrefix = node => {
|
|
17
|
+
const text = toString(node.children[0]);
|
|
18
|
+
const match = QUERIES.stabilityIndex.exec(text);
|
|
19
|
+
const start = match ? text.length - match[2].length : 0;
|
|
20
|
+
|
|
21
|
+
return slice(node, start, undefined, {
|
|
22
|
+
textHandling: { boundaries: 'preserve' },
|
|
23
|
+
}).node;
|
|
24
|
+
};
|