@zudojs/docs 0.1.0 → 1.0.0
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/LICENSE +21 -0
- package/README.md +32 -9
- package/dist/docsTypes/index.d.ts +1 -1
- package/dist/document/documentBuilder.core.d.ts +15 -5
- package/dist/document/documentBuilder.core.js +27 -15
- package/dist/document/index.d.ts +1 -1
- package/dist/errors/index.d.ts +16 -0
- package/dist/errors/index.js +18 -0
- package/dist/examples/examples.core.d.ts +4 -0
- package/dist/examples/examples.core.js +16 -7
- package/dist/frontmatter/frontmatter.core.d.ts +1 -1
- package/dist/frontmatter/frontmatter.parser.d.ts +15 -2
- package/dist/frontmatter/frontmatter.parser.js +202 -39
- package/dist/frontmatter/frontmatter.serializer.d.ts +13 -1
- package/dist/frontmatter/frontmatter.serializer.js +89 -4
- package/dist/frontmatter/frontmatter.types.d.ts +10 -1
- package/dist/frontmatter/index.d.ts +1 -1
- package/dist/generator/generator.types.d.ts +18 -0
- package/dist/generator/generatorJson.core.d.ts +8 -3
- package/dist/generator/generatorJson.core.js +16 -4
- package/dist/generator/generatorMarkdown.core.d.ts +4 -0
- package/dist/generator/generatorMarkdown.core.js +32 -13
- package/dist/generator/generatorMarkdownNodes.d.ts +20 -0
- package/dist/generator/generatorMarkdownNodes.js +87 -17
- package/dist/generator/index.d.ts +2 -2
- package/dist/generator/index.js +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/navigation/index.d.ts +1 -1
- package/dist/navigation/index.js +1 -1
- package/dist/navigation/navigation.core.d.ts +25 -6
- package/dist/navigation/navigation.core.js +93 -25
- package/dist/registry/index.d.ts +2 -1
- package/dist/registry/index.js +1 -1
- package/dist/registry/registry.core.d.ts +29 -3
- package/dist/registry/registry.core.js +32 -6
- package/dist/utils/index.d.ts +2 -1
- package/dist/utils/index.js +2 -1
- package/dist/utils/utils.freeze.d.ts +16 -0
- package/dist/utils/utils.freeze.js +53 -0
- package/dist/utils/utils.helper.d.ts +27 -4
- package/dist/utils/utils.helper.js +108 -21
- package/dist/validator/index.d.ts +4 -1
- package/dist/validator/index.js +2 -1
- package/dist/validator/validator.types.d.ts +8 -0
- package/dist/validator/validator.types.js +10 -1
- package/dist/validator/validatorAll/validatorAll.core.d.ts +11 -2
- package/dist/validator/validatorAll/validatorAll.core.js +19 -7
- package/dist/validator/validatorAll/validatorNavigation.core.d.ts +8 -1
- package/dist/validator/validatorAll/validatorNavigation.core.js +64 -10
- package/dist/validator/validatorDocument.core.d.ts +3 -2
- package/dist/validator/validatorDocument.core.js +197 -15
- package/dist/validator/validatorDuplicates.core.d.ts +1 -1
- package/dist/validator/validatorDuplicates.core.js +4 -6
- package/dist/validator/validatorLinks.core.d.ts +22 -4
- package/dist/validator/validatorLinks.core.js +80 -44
- package/package.json +24 -15
- package/dist/docsTypes/documentationContent.d.ts.map +0 -1
- package/dist/docsTypes/documentationContent.js.map +0 -1
- package/dist/docsTypes/documentationDocument.d.ts.map +0 -1
- package/dist/docsTypes/documentationDocument.js.map +0 -1
- package/dist/docsTypes/documentationMetadata.d.ts.map +0 -1
- package/dist/docsTypes/documentationMetadata.js.map +0 -1
- package/dist/docsTypes/documentationNavigation.d.ts.map +0 -1
- package/dist/docsTypes/documentationNavigation.js.map +0 -1
- package/dist/docsTypes/documentationProvider.d.ts.map +0 -1
- package/dist/docsTypes/documentationProvider.js.map +0 -1
- package/dist/docsTypes/index.d.ts.map +0 -1
- package/dist/docsTypes/index.js.map +0 -1
- package/dist/document/documentBuilder.core.d.ts.map +0 -1
- package/dist/document/documentBuilder.core.js.map +0 -1
- package/dist/document/index.d.ts.map +0 -1
- package/dist/document/index.js.map +0 -1
- package/dist/examples/examples.core.d.ts.map +0 -1
- package/dist/examples/examples.core.js.map +0 -1
- package/dist/examples/index.d.ts.map +0 -1
- package/dist/examples/index.js.map +0 -1
- package/dist/frontmatter/frontmatter.core.d.ts.map +0 -1
- package/dist/frontmatter/frontmatter.core.js.map +0 -1
- package/dist/frontmatter/frontmatter.parser.d.ts.map +0 -1
- package/dist/frontmatter/frontmatter.parser.js.map +0 -1
- package/dist/frontmatter/frontmatter.serializer.d.ts.map +0 -1
- package/dist/frontmatter/frontmatter.serializer.js.map +0 -1
- package/dist/frontmatter/frontmatter.types.d.ts.map +0 -1
- package/dist/frontmatter/frontmatter.types.js.map +0 -1
- package/dist/frontmatter/index.d.ts.map +0 -1
- package/dist/frontmatter/index.js.map +0 -1
- package/dist/generator/generator.types.d.ts.map +0 -1
- package/dist/generator/generator.types.js.map +0 -1
- package/dist/generator/generatorJson.core.d.ts.map +0 -1
- package/dist/generator/generatorJson.core.js.map +0 -1
- package/dist/generator/generatorMarkdown.core.d.ts.map +0 -1
- package/dist/generator/generatorMarkdown.core.js.map +0 -1
- package/dist/generator/generatorMarkdownNodes.d.ts.map +0 -1
- package/dist/generator/generatorMarkdownNodes.js.map +0 -1
- package/dist/generator/index.d.ts.map +0 -1
- package/dist/generator/index.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/navigation/index.d.ts.map +0 -1
- package/dist/navigation/index.js.map +0 -1
- package/dist/navigation/navigation.core.d.ts.map +0 -1
- package/dist/navigation/navigation.core.js.map +0 -1
- package/dist/registry/index.d.ts.map +0 -1
- package/dist/registry/index.js.map +0 -1
- package/dist/registry/registry.core.d.ts.map +0 -1
- package/dist/registry/registry.core.js.map +0 -1
- package/dist/utils/index.d.ts.map +0 -1
- package/dist/utils/index.js.map +0 -1
- package/dist/utils/utils.helper.d.ts.map +0 -1
- package/dist/utils/utils.helper.js.map +0 -1
- package/dist/validator/index.d.ts.map +0 -1
- package/dist/validator/index.js.map +0 -1
- package/dist/validator/validator.types.d.ts.map +0 -1
- package/dist/validator/validator.types.js.map +0 -1
- package/dist/validator/validatorAll/index.d.ts.map +0 -1
- package/dist/validator/validatorAll/index.js.map +0 -1
- package/dist/validator/validatorAll/validatorAll.core.d.ts.map +0 -1
- package/dist/validator/validatorAll/validatorAll.core.js.map +0 -1
- package/dist/validator/validatorAll/validatorNavigation.core.d.ts.map +0 -1
- package/dist/validator/validatorAll/validatorNavigation.core.js.map +0 -1
- package/dist/validator/validatorDocument.core.d.ts.map +0 -1
- package/dist/validator/validatorDocument.core.js.map +0 -1
- package/dist/validator/validatorDuplicates.core.d.ts.map +0 -1
- package/dist/validator/validatorDuplicates.core.js.map +0 -1
- package/dist/validator/validatorLinks.core.d.ts.map +0 -1
- package/dist/validator/validatorLinks.core.js.map +0 -1
|
@@ -3,23 +3,42 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides breadcrumb generation, tree flattening, and
|
|
5
5
|
* link resolution for documentation navigation structures.
|
|
6
|
+
*
|
|
7
|
+
* Every walker tolerates shared or cyclic nodes (a node is visited at
|
|
8
|
+
* most once) and stops at `MAX_NAVIGATION_DEPTH`, so malformed trees
|
|
9
|
+
* never overflow the stack.
|
|
6
10
|
*/
|
|
7
11
|
import type { DocumentationBreadcrumb, DocumentationNavigationItem } from "../docsTypes/index.js";
|
|
12
|
+
/** Maximum nesting depth any walker will descend. */
|
|
13
|
+
export declare const MAX_NAVIGATION_DEPTH = 64;
|
|
14
|
+
type Nodes = readonly DocumentationNavigationItem[];
|
|
8
15
|
/**
|
|
9
16
|
* Generates breadcrumbs for a given document ID
|
|
10
|
-
* by walking the navigation tree.
|
|
17
|
+
* by walking the navigation tree. Intermediate section nodes keep
|
|
18
|
+
* their `documentId` when they have one, so section landing pages
|
|
19
|
+
* stay linkable.
|
|
11
20
|
*/
|
|
12
|
-
export declare function getBreadcrumbs(documentId: string, items:
|
|
21
|
+
export declare function getBreadcrumbs(documentId: string, items: Nodes): readonly DocumentationBreadcrumb[];
|
|
13
22
|
/**
|
|
14
23
|
* Flattens a navigation tree into a list of all document IDs in order.
|
|
24
|
+
* A document referenced more than once appears once, at its first position.
|
|
15
25
|
*/
|
|
16
|
-
export declare function flattenNavigation(items:
|
|
26
|
+
export declare function flattenNavigation(items: Nodes): readonly string[];
|
|
17
27
|
/**
|
|
18
28
|
* Finds a navigation item by document ID.
|
|
19
29
|
*/
|
|
20
|
-
export declare function findNavigationItem(documentId: string, items:
|
|
30
|
+
export declare function findNavigationItem(documentId: string, items: Nodes): DocumentationNavigationItem | undefined;
|
|
31
|
+
/**
|
|
32
|
+
* Gets sibling document IDs for a given document (the other documents
|
|
33
|
+
* at the same navigation level, excluding the document itself).
|
|
34
|
+
*/
|
|
35
|
+
export declare function getSiblings(documentId: string, items: Nodes): readonly string[];
|
|
21
36
|
/**
|
|
22
|
-
* Gets
|
|
37
|
+
* Gets the previous and next document IDs at the same navigation level.
|
|
23
38
|
*/
|
|
24
|
-
export declare function
|
|
39
|
+
export declare function getAdjacent(documentId: string, items: Nodes): {
|
|
40
|
+
readonly previous?: string;
|
|
41
|
+
readonly next?: string;
|
|
42
|
+
};
|
|
43
|
+
export {};
|
|
25
44
|
//# sourceMappingURL=navigation.core.d.ts.map
|
|
@@ -3,22 +3,36 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Provides breadcrumb generation, tree flattening, and
|
|
5
5
|
* link resolution for documentation navigation structures.
|
|
6
|
+
*
|
|
7
|
+
* Every walker tolerates shared or cyclic nodes (a node is visited at
|
|
8
|
+
* most once) and stops at `MAX_NAVIGATION_DEPTH`, so malformed trees
|
|
9
|
+
* never overflow the stack.
|
|
6
10
|
*/
|
|
11
|
+
/** Maximum nesting depth any walker will descend. */
|
|
12
|
+
export const MAX_NAVIGATION_DEPTH = 64;
|
|
7
13
|
/**
|
|
8
14
|
* Generates breadcrumbs for a given document ID
|
|
9
|
-
* by walking the navigation tree.
|
|
15
|
+
* by walking the navigation tree. Intermediate section nodes keep
|
|
16
|
+
* their `documentId` when they have one, so section landing pages
|
|
17
|
+
* stay linkable.
|
|
10
18
|
*/
|
|
11
19
|
export function getBreadcrumbs(documentId, items) {
|
|
12
20
|
const path = [];
|
|
13
|
-
|
|
21
|
+
const seen = new WeakSet();
|
|
22
|
+
function walk(nodes, depth) {
|
|
23
|
+
if (depth > MAX_NAVIGATION_DEPTH)
|
|
24
|
+
return false;
|
|
14
25
|
for (const node of nodes) {
|
|
26
|
+
if (seen.has(node))
|
|
27
|
+
continue;
|
|
28
|
+
seen.add(node);
|
|
15
29
|
if (node.documentId === documentId) {
|
|
16
|
-
path.push(
|
|
30
|
+
path.push(toBreadcrumb(node));
|
|
17
31
|
return true;
|
|
18
32
|
}
|
|
19
33
|
if (node.children) {
|
|
20
|
-
path.push(
|
|
21
|
-
if (walk(node.children)) {
|
|
34
|
+
path.push(toBreadcrumb(node));
|
|
35
|
+
if (walk(node.children, depth + 1)) {
|
|
22
36
|
return true;
|
|
23
37
|
}
|
|
24
38
|
path.pop();
|
|
@@ -26,60 +40,114 @@ export function getBreadcrumbs(documentId, items) {
|
|
|
26
40
|
}
|
|
27
41
|
return false;
|
|
28
42
|
}
|
|
29
|
-
walk(items);
|
|
43
|
+
walk(items, 0);
|
|
30
44
|
return Object.freeze(path);
|
|
31
45
|
}
|
|
46
|
+
function toBreadcrumb(node) {
|
|
47
|
+
return node.documentId === undefined
|
|
48
|
+
? { title: node.title }
|
|
49
|
+
: { title: node.title, documentId: node.documentId };
|
|
50
|
+
}
|
|
32
51
|
/**
|
|
33
52
|
* Flattens a navigation tree into a list of all document IDs in order.
|
|
53
|
+
* A document referenced more than once appears once, at its first position.
|
|
34
54
|
*/
|
|
35
55
|
export function flattenNavigation(items) {
|
|
36
56
|
const result = [];
|
|
37
|
-
|
|
57
|
+
const ids = new Set();
|
|
58
|
+
const seen = new WeakSet();
|
|
59
|
+
function walk(nodes, depth) {
|
|
60
|
+
if (depth > MAX_NAVIGATION_DEPTH)
|
|
61
|
+
return;
|
|
38
62
|
for (const node of nodes) {
|
|
39
|
-
if (node
|
|
63
|
+
if (seen.has(node))
|
|
64
|
+
continue;
|
|
65
|
+
seen.add(node);
|
|
66
|
+
if (node.documentId && !ids.has(node.documentId)) {
|
|
67
|
+
ids.add(node.documentId);
|
|
40
68
|
result.push(node.documentId);
|
|
41
69
|
}
|
|
42
70
|
if (node.children) {
|
|
43
|
-
walk(node.children);
|
|
71
|
+
walk(node.children, depth + 1);
|
|
44
72
|
}
|
|
45
73
|
}
|
|
46
74
|
}
|
|
47
|
-
walk(items);
|
|
75
|
+
walk(items, 0);
|
|
48
76
|
return Object.freeze(result);
|
|
49
77
|
}
|
|
50
78
|
/**
|
|
51
79
|
* Finds a navigation item by document ID.
|
|
52
80
|
*/
|
|
53
81
|
export function findNavigationItem(documentId, items) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
82
|
+
const seen = new WeakSet();
|
|
83
|
+
function walk(nodes, depth) {
|
|
84
|
+
if (depth > MAX_NAVIGATION_DEPTH)
|
|
85
|
+
return undefined;
|
|
86
|
+
for (const node of nodes) {
|
|
87
|
+
if (seen.has(node))
|
|
88
|
+
continue;
|
|
89
|
+
seen.add(node);
|
|
90
|
+
if (node.documentId === documentId) {
|
|
91
|
+
return node;
|
|
92
|
+
}
|
|
93
|
+
if (node.children) {
|
|
94
|
+
const found = walk(node.children, depth + 1);
|
|
95
|
+
if (found)
|
|
96
|
+
return found;
|
|
97
|
+
}
|
|
62
98
|
}
|
|
99
|
+
return undefined;
|
|
63
100
|
}
|
|
64
|
-
return
|
|
101
|
+
return walk(items, 0);
|
|
65
102
|
}
|
|
66
103
|
/**
|
|
67
|
-
*
|
|
104
|
+
* Returns the list of document IDs at the same level as `documentId`,
|
|
105
|
+
* including the document itself, in navigation order.
|
|
68
106
|
*/
|
|
69
|
-
|
|
70
|
-
|
|
107
|
+
function getLevel(documentId, items) {
|
|
108
|
+
const seen = new WeakSet();
|
|
109
|
+
function walk(nodes, depth) {
|
|
110
|
+
if (depth > MAX_NAVIGATION_DEPTH)
|
|
111
|
+
return undefined;
|
|
71
112
|
for (const node of nodes) {
|
|
113
|
+
if (seen.has(node))
|
|
114
|
+
continue;
|
|
115
|
+
seen.add(node);
|
|
72
116
|
if (node.documentId === documentId) {
|
|
73
|
-
return nodes
|
|
117
|
+
return nodes
|
|
118
|
+
.map((n) => n.documentId)
|
|
119
|
+
.filter((id) => typeof id === "string");
|
|
74
120
|
}
|
|
75
121
|
if (node.children) {
|
|
76
|
-
const result = walk(node.children);
|
|
122
|
+
const result = walk(node.children, depth + 1);
|
|
77
123
|
if (result)
|
|
78
124
|
return result;
|
|
79
125
|
}
|
|
80
126
|
}
|
|
81
127
|
return undefined;
|
|
82
128
|
}
|
|
83
|
-
return
|
|
129
|
+
return walk(items, 0) ?? [];
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Gets sibling document IDs for a given document (the other documents
|
|
133
|
+
* at the same navigation level, excluding the document itself).
|
|
134
|
+
*/
|
|
135
|
+
export function getSiblings(documentId, items) {
|
|
136
|
+
return Object.freeze(getLevel(documentId, items).filter((id) => id !== documentId));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Gets the previous and next document IDs at the same navigation level.
|
|
140
|
+
*/
|
|
141
|
+
export function getAdjacent(documentId, items) {
|
|
142
|
+
const level = getLevel(documentId, items);
|
|
143
|
+
const index = level.indexOf(documentId);
|
|
144
|
+
if (index === -1)
|
|
145
|
+
return Object.freeze({});
|
|
146
|
+
const previous = level[index - 1];
|
|
147
|
+
const next = level[index + 1];
|
|
148
|
+
return Object.freeze({
|
|
149
|
+
...(previous !== undefined ? { previous } : {}),
|
|
150
|
+
...(next !== undefined ? { next } : {}),
|
|
151
|
+
});
|
|
84
152
|
}
|
|
85
153
|
//# sourceMappingURL=navigation.core.js.map
|
package/dist/registry/index.d.ts
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Document registry for storing, retrieving, and filtering documentation.
|
|
5
5
|
*/
|
|
6
|
-
export { DocumentRegistry, createDocumentRegistry } from "./registry.core.js";
|
|
6
|
+
export { DocumentRegistry, createDocumentRegistry, matchesVisibility, } from "./registry.core.js";
|
|
7
|
+
export type { DocumentVisibilityFilter, GetAllOptions, } from "./registry.core.js";
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/registry/index.js
CHANGED
|
@@ -3,5 +3,5 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Document registry for storing, retrieving, and filtering documentation.
|
|
5
5
|
*/
|
|
6
|
-
export { DocumentRegistry, createDocumentRegistry } from "./registry.core.js";
|
|
6
|
+
export { DocumentRegistry, createDocumentRegistry, matchesVisibility, } from "./registry.core.js";
|
|
7
7
|
//# sourceMappingURL=index.js.map
|
|
@@ -5,13 +5,34 @@
|
|
|
5
5
|
* documentation documents. Prevents duplicate IDs.
|
|
6
6
|
*/
|
|
7
7
|
import type { DocumentationDocument, DocumentationProvider } from "../docsTypes/index.js";
|
|
8
|
+
/** Visibility filter accepted by `getAll` and the generators. */
|
|
9
|
+
export type DocumentVisibilityFilter = "SERVER" | "CLIENT" | "ALL";
|
|
10
|
+
/** Options for `DocumentRegistry.getAll`. */
|
|
11
|
+
export interface GetAllOptions {
|
|
12
|
+
/**
|
|
13
|
+
* Which documents to return. `"CLIENT"` returns documents whose
|
|
14
|
+
* `visibility` is `"CLIENT"` or unset; `"SERVER"` returns only
|
|
15
|
+
* server-only documents; `"ALL"` (default) returns everything.
|
|
16
|
+
*/
|
|
17
|
+
readonly visibility?: DocumentVisibilityFilter;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Returns true when `document` should be included for the given filter.
|
|
21
|
+
*/
|
|
22
|
+
export declare function matchesVisibility(document: DocumentationDocument, filter?: DocumentVisibilityFilter): boolean;
|
|
8
23
|
/**
|
|
9
24
|
* Registry for managing documentation documents.
|
|
25
|
+
*
|
|
26
|
+
* Registered documents are stored as deep-frozen copies, so the
|
|
27
|
+
* caller's object is never mutated and later changes to it do not
|
|
28
|
+
* leak into the registry.
|
|
10
29
|
*/
|
|
11
30
|
export declare class DocumentRegistry implements DocumentationProvider {
|
|
12
31
|
private readonly documents;
|
|
13
32
|
/**
|
|
14
|
-
* Registers a document.
|
|
33
|
+
* Registers a document.
|
|
34
|
+
*
|
|
35
|
+
* @throws {DuplicateDocumentError} if the ID is already registered.
|
|
15
36
|
*/
|
|
16
37
|
register(document: DocumentationDocument): void;
|
|
17
38
|
/**
|
|
@@ -23,9 +44,9 @@ export declare class DocumentRegistry implements DocumentationProvider {
|
|
|
23
44
|
*/
|
|
24
45
|
get(id: string): DocumentationDocument | undefined;
|
|
25
46
|
/**
|
|
26
|
-
* Returns all registered documents.
|
|
47
|
+
* Returns all registered documents, optionally filtered by visibility.
|
|
27
48
|
*/
|
|
28
|
-
getAll(): readonly DocumentationDocument[];
|
|
49
|
+
getAll(options?: GetAllOptions): readonly DocumentationDocument[];
|
|
29
50
|
/**
|
|
30
51
|
* Returns the number of registered documents.
|
|
31
52
|
*/
|
|
@@ -46,6 +67,11 @@ export declare class DocumentRegistry implements DocumentationProvider {
|
|
|
46
67
|
* Returns all document IDs.
|
|
47
68
|
*/
|
|
48
69
|
ids(): readonly string[];
|
|
70
|
+
/**
|
|
71
|
+
* Returns the registered IDs as a set, suitable for `validateLinks`
|
|
72
|
+
* and `validateNavigation`.
|
|
73
|
+
*/
|
|
74
|
+
idSet(): ReadonlySet<string>;
|
|
49
75
|
/**
|
|
50
76
|
* Filters documents by category.
|
|
51
77
|
*/
|
|
@@ -4,19 +4,37 @@
|
|
|
4
4
|
* Provides registration, retrieval, and iteration over
|
|
5
5
|
* documentation documents. Prevents duplicate IDs.
|
|
6
6
|
*/
|
|
7
|
+
import { DuplicateDocumentError } from "@zudojs/errors";
|
|
8
|
+
import { deepFreezeClone } from "../utils/utils.freeze.js";
|
|
9
|
+
/**
|
|
10
|
+
* Returns true when `document` should be included for the given filter.
|
|
11
|
+
*/
|
|
12
|
+
export function matchesVisibility(document, filter = "ALL") {
|
|
13
|
+
if (filter === "ALL")
|
|
14
|
+
return true;
|
|
15
|
+
if (filter === "SERVER")
|
|
16
|
+
return document.visibility === "SERVER";
|
|
17
|
+
return document.visibility !== "SERVER";
|
|
18
|
+
}
|
|
7
19
|
/**
|
|
8
20
|
* Registry for managing documentation documents.
|
|
21
|
+
*
|
|
22
|
+
* Registered documents are stored as deep-frozen copies, so the
|
|
23
|
+
* caller's object is never mutated and later changes to it do not
|
|
24
|
+
* leak into the registry.
|
|
9
25
|
*/
|
|
10
26
|
export class DocumentRegistry {
|
|
11
27
|
documents = new Map();
|
|
12
28
|
/**
|
|
13
|
-
* Registers a document.
|
|
29
|
+
* Registers a document.
|
|
30
|
+
*
|
|
31
|
+
* @throws {DuplicateDocumentError} if the ID is already registered.
|
|
14
32
|
*/
|
|
15
33
|
register(document) {
|
|
16
34
|
if (this.documents.has(document.id)) {
|
|
17
|
-
throw new
|
|
35
|
+
throw new DuplicateDocumentError(document.id);
|
|
18
36
|
}
|
|
19
|
-
this.documents.set(document.id,
|
|
37
|
+
this.documents.set(document.id, deepFreezeClone(document));
|
|
20
38
|
}
|
|
21
39
|
/**
|
|
22
40
|
* Registers multiple documents.
|
|
@@ -33,10 +51,11 @@ export class DocumentRegistry {
|
|
|
33
51
|
return this.documents.get(id);
|
|
34
52
|
}
|
|
35
53
|
/**
|
|
36
|
-
* Returns all registered documents.
|
|
54
|
+
* Returns all registered documents, optionally filtered by visibility.
|
|
37
55
|
*/
|
|
38
|
-
getAll() {
|
|
39
|
-
|
|
56
|
+
getAll(options = {}) {
|
|
57
|
+
const filter = options.visibility ?? "ALL";
|
|
58
|
+
return Object.freeze([...this.documents.values()].filter((doc) => matchesVisibility(doc, filter)));
|
|
40
59
|
}
|
|
41
60
|
/**
|
|
42
61
|
* Returns the number of registered documents.
|
|
@@ -68,6 +87,13 @@ export class DocumentRegistry {
|
|
|
68
87
|
ids() {
|
|
69
88
|
return Object.freeze([...this.documents.keys()]);
|
|
70
89
|
}
|
|
90
|
+
/**
|
|
91
|
+
* Returns the registered IDs as a set, suitable for `validateLinks`
|
|
92
|
+
* and `validateNavigation`.
|
|
93
|
+
*/
|
|
94
|
+
idSet() {
|
|
95
|
+
return new Set(this.documents.keys());
|
|
96
|
+
}
|
|
71
97
|
/**
|
|
72
98
|
* Filters documents by category.
|
|
73
99
|
*/
|
package/dist/utils/index.d.ts
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Utility helpers for document ID normalization, link resolution, and markdown parsing.
|
|
5
5
|
*/
|
|
6
|
-
export { normalizeDocumentId, documentIdFromPath, resolveDocumentLink, extractTitleFromMarkdown, extractHeadings, stripMarkdown, } from "./utils.helper.js";
|
|
6
|
+
export { isValidDocumentId, normalizeDocumentId, documentIdFromPath, resolveDocumentLink, stripLinkDecorations, stripFencedCodeBlocks, extractTitleFromMarkdown, extractHeadings, stripMarkdown, } from "./utils.helper.js";
|
|
7
|
+
export { deepFreeze, deepFreezeClone } from "./utils.freeze.js";
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/utils/index.js
CHANGED
|
@@ -3,5 +3,6 @@
|
|
|
3
3
|
*
|
|
4
4
|
* Utility helpers for document ID normalization, link resolution, and markdown parsing.
|
|
5
5
|
*/
|
|
6
|
-
export { normalizeDocumentId, documentIdFromPath, resolveDocumentLink, extractTitleFromMarkdown, extractHeadings, stripMarkdown, } from "./utils.helper.js";
|
|
6
|
+
export { isValidDocumentId, normalizeDocumentId, documentIdFromPath, resolveDocumentLink, stripLinkDecorations, stripFencedCodeBlocks, extractTitleFromMarkdown, extractHeadings, stripMarkdown, } from "./utils.helper.js";
|
|
7
|
+
export { deepFreeze, deepFreezeClone } from "./utils.freeze.js";
|
|
7
8
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-freeze helpers for immutable value objects.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Recursively freezes a value in place. Cycles are tolerated.
|
|
6
|
+
* Only plain objects and arrays are traversed; class instances such
|
|
7
|
+
* as `Date` are frozen but not walked.
|
|
8
|
+
*/
|
|
9
|
+
export declare function deepFreeze<T>(value: T, seen?: WeakSet<object>): T;
|
|
10
|
+
/**
|
|
11
|
+
* Returns a deep-frozen copy of `value`, leaving the caller's object
|
|
12
|
+
* untouched. Falls back to freezing a shallow copy when the value
|
|
13
|
+
* cannot be structurally cloned (e.g. contains functions).
|
|
14
|
+
*/
|
|
15
|
+
export declare function deepFreezeClone<T>(value: T): T;
|
|
16
|
+
//# sourceMappingURL=utils.freeze.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deep-freeze helpers for immutable value objects.
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Recursively freezes a value in place. Cycles are tolerated.
|
|
6
|
+
* Only plain objects and arrays are traversed; class instances such
|
|
7
|
+
* as `Date` are frozen but not walked.
|
|
8
|
+
*/
|
|
9
|
+
export function deepFreeze(value, seen = new WeakSet()) {
|
|
10
|
+
if (typeof value !== "object" || value === null)
|
|
11
|
+
return value;
|
|
12
|
+
if (seen.has(value))
|
|
13
|
+
return value;
|
|
14
|
+
seen.add(value);
|
|
15
|
+
if (Array.isArray(value)) {
|
|
16
|
+
for (const item of value)
|
|
17
|
+
deepFreeze(item, seen);
|
|
18
|
+
}
|
|
19
|
+
else if (isPlainObject(value)) {
|
|
20
|
+
for (const item of Object.values(value))
|
|
21
|
+
deepFreeze(item, seen);
|
|
22
|
+
}
|
|
23
|
+
return Object.freeze(value);
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Returns a deep-frozen copy of `value`, leaving the caller's object
|
|
27
|
+
* untouched. Falls back to freezing a shallow copy when the value
|
|
28
|
+
* cannot be structurally cloned (e.g. contains functions).
|
|
29
|
+
*/
|
|
30
|
+
export function deepFreezeClone(value) {
|
|
31
|
+
let copy;
|
|
32
|
+
try {
|
|
33
|
+
copy = structuredClone(value);
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
copy = shallowCopy(value);
|
|
37
|
+
}
|
|
38
|
+
return deepFreeze(copy);
|
|
39
|
+
}
|
|
40
|
+
function shallowCopy(value) {
|
|
41
|
+
if (Array.isArray(value))
|
|
42
|
+
return [...value];
|
|
43
|
+
if (isPlainObject(value))
|
|
44
|
+
return { ...value };
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
function isPlainObject(value) {
|
|
48
|
+
if (typeof value !== "object" || value === null)
|
|
49
|
+
return false;
|
|
50
|
+
const proto = Object.getPrototypeOf(value);
|
|
51
|
+
return proto === Object.prototype || proto === null;
|
|
52
|
+
}
|
|
53
|
+
//# sourceMappingURL=utils.freeze.js.map
|
|
@@ -1,27 +1,50 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Utility helpers for the documentation package.
|
|
3
3
|
*/
|
|
4
|
+
/**
|
|
5
|
+
* Returns true when `id` is a stable dot-separated identifier such as
|
|
6
|
+
* `guides.http.routing`: non-empty segments of letters, digits, `_`
|
|
7
|
+
* and `-`, with no whitespace or empty segments.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isValidDocumentId(id: string): boolean;
|
|
4
10
|
/**
|
|
5
11
|
* Normalizes a document ID to a consistent format.
|
|
6
|
-
*
|
|
12
|
+
* Trims whitespace, collapses consecutive dots and strips leading/trailing dots.
|
|
7
13
|
*/
|
|
8
14
|
export declare function normalizeDocumentId(id: string): string;
|
|
9
15
|
/**
|
|
10
16
|
* Generates a document ID from a file path.
|
|
11
|
-
* Converts path separators to dots and removes extension
|
|
17
|
+
* Converts path separators to dots and removes the extension of the
|
|
18
|
+
* final segment only (`guides/v1.2/routing.md` → `guides.v1.2.routing`).
|
|
19
|
+
* Returns an empty string when the path has no usable segment
|
|
20
|
+
* (e.g. `.gitignore`).
|
|
12
21
|
*/
|
|
13
22
|
export declare function documentIdFromPath(path: string): string;
|
|
14
23
|
/**
|
|
15
24
|
* Resolves a relative document link against a base ID.
|
|
16
25
|
* "guides.http" + "./routing" → "guides.http.routing"
|
|
26
|
+
*
|
|
27
|
+
* Fragments (`#section`), `.md`/`.mdx` extensions and Windows
|
|
28
|
+
* separators are stripped before resolving.
|
|
17
29
|
*/
|
|
18
30
|
export declare function resolveDocumentLink(baseId: string, link: string): string;
|
|
19
31
|
/**
|
|
20
|
-
*
|
|
32
|
+
* Removes a `#fragment`, a trailing `.md`/`.mdx` extension and
|
|
33
|
+
* converts `\` to `/` in a link target.
|
|
34
|
+
*/
|
|
35
|
+
export declare function stripLinkDecorations(link: string): string;
|
|
36
|
+
/**
|
|
37
|
+
* Removes fenced code blocks (``` or ~~~) from markdown so that
|
|
38
|
+
* headings and links inside them are not interpreted.
|
|
39
|
+
*/
|
|
40
|
+
export declare function stripFencedCodeBlocks(markdown: string): string;
|
|
41
|
+
/**
|
|
42
|
+
* Extracts the title from markdown content (first level-1 heading
|
|
43
|
+
* outside fenced code blocks).
|
|
21
44
|
*/
|
|
22
45
|
export declare function extractTitleFromMarkdown(markdown: string): string | undefined;
|
|
23
46
|
/**
|
|
24
|
-
* Extracts headings from markdown content.
|
|
47
|
+
* Extracts headings from markdown content (outside fenced code blocks).
|
|
25
48
|
*/
|
|
26
49
|
export declare function extractHeadings(markdown: string): readonly {
|
|
27
50
|
level: number;
|