@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.
Files changed (127) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +32 -9
  3. package/dist/docsTypes/index.d.ts +1 -1
  4. package/dist/document/documentBuilder.core.d.ts +15 -5
  5. package/dist/document/documentBuilder.core.js +27 -15
  6. package/dist/document/index.d.ts +1 -1
  7. package/dist/errors/index.d.ts +16 -0
  8. package/dist/errors/index.js +18 -0
  9. package/dist/examples/examples.core.d.ts +4 -0
  10. package/dist/examples/examples.core.js +16 -7
  11. package/dist/frontmatter/frontmatter.core.d.ts +1 -1
  12. package/dist/frontmatter/frontmatter.parser.d.ts +15 -2
  13. package/dist/frontmatter/frontmatter.parser.js +202 -39
  14. package/dist/frontmatter/frontmatter.serializer.d.ts +13 -1
  15. package/dist/frontmatter/frontmatter.serializer.js +89 -4
  16. package/dist/frontmatter/frontmatter.types.d.ts +10 -1
  17. package/dist/frontmatter/index.d.ts +1 -1
  18. package/dist/generator/generator.types.d.ts +18 -0
  19. package/dist/generator/generatorJson.core.d.ts +8 -3
  20. package/dist/generator/generatorJson.core.js +16 -4
  21. package/dist/generator/generatorMarkdown.core.d.ts +4 -0
  22. package/dist/generator/generatorMarkdown.core.js +32 -13
  23. package/dist/generator/generatorMarkdownNodes.d.ts +20 -0
  24. package/dist/generator/generatorMarkdownNodes.js +87 -17
  25. package/dist/generator/index.d.ts +2 -2
  26. package/dist/generator/index.js +1 -1
  27. package/dist/index.d.ts +1 -0
  28. package/dist/index.js +2 -0
  29. package/dist/navigation/index.d.ts +1 -1
  30. package/dist/navigation/index.js +1 -1
  31. package/dist/navigation/navigation.core.d.ts +25 -6
  32. package/dist/navigation/navigation.core.js +93 -25
  33. package/dist/registry/index.d.ts +2 -1
  34. package/dist/registry/index.js +1 -1
  35. package/dist/registry/registry.core.d.ts +29 -3
  36. package/dist/registry/registry.core.js +32 -6
  37. package/dist/utils/index.d.ts +2 -1
  38. package/dist/utils/index.js +2 -1
  39. package/dist/utils/utils.freeze.d.ts +16 -0
  40. package/dist/utils/utils.freeze.js +53 -0
  41. package/dist/utils/utils.helper.d.ts +27 -4
  42. package/dist/utils/utils.helper.js +108 -21
  43. package/dist/validator/index.d.ts +4 -1
  44. package/dist/validator/index.js +2 -1
  45. package/dist/validator/validator.types.d.ts +8 -0
  46. package/dist/validator/validator.types.js +10 -1
  47. package/dist/validator/validatorAll/validatorAll.core.d.ts +11 -2
  48. package/dist/validator/validatorAll/validatorAll.core.js +19 -7
  49. package/dist/validator/validatorAll/validatorNavigation.core.d.ts +8 -1
  50. package/dist/validator/validatorAll/validatorNavigation.core.js +64 -10
  51. package/dist/validator/validatorDocument.core.d.ts +3 -2
  52. package/dist/validator/validatorDocument.core.js +197 -15
  53. package/dist/validator/validatorDuplicates.core.d.ts +1 -1
  54. package/dist/validator/validatorDuplicates.core.js +4 -6
  55. package/dist/validator/validatorLinks.core.d.ts +22 -4
  56. package/dist/validator/validatorLinks.core.js +80 -44
  57. package/package.json +24 -15
  58. package/dist/docsTypes/documentationContent.d.ts.map +0 -1
  59. package/dist/docsTypes/documentationContent.js.map +0 -1
  60. package/dist/docsTypes/documentationDocument.d.ts.map +0 -1
  61. package/dist/docsTypes/documentationDocument.js.map +0 -1
  62. package/dist/docsTypes/documentationMetadata.d.ts.map +0 -1
  63. package/dist/docsTypes/documentationMetadata.js.map +0 -1
  64. package/dist/docsTypes/documentationNavigation.d.ts.map +0 -1
  65. package/dist/docsTypes/documentationNavigation.js.map +0 -1
  66. package/dist/docsTypes/documentationProvider.d.ts.map +0 -1
  67. package/dist/docsTypes/documentationProvider.js.map +0 -1
  68. package/dist/docsTypes/index.d.ts.map +0 -1
  69. package/dist/docsTypes/index.js.map +0 -1
  70. package/dist/document/documentBuilder.core.d.ts.map +0 -1
  71. package/dist/document/documentBuilder.core.js.map +0 -1
  72. package/dist/document/index.d.ts.map +0 -1
  73. package/dist/document/index.js.map +0 -1
  74. package/dist/examples/examples.core.d.ts.map +0 -1
  75. package/dist/examples/examples.core.js.map +0 -1
  76. package/dist/examples/index.d.ts.map +0 -1
  77. package/dist/examples/index.js.map +0 -1
  78. package/dist/frontmatter/frontmatter.core.d.ts.map +0 -1
  79. package/dist/frontmatter/frontmatter.core.js.map +0 -1
  80. package/dist/frontmatter/frontmatter.parser.d.ts.map +0 -1
  81. package/dist/frontmatter/frontmatter.parser.js.map +0 -1
  82. package/dist/frontmatter/frontmatter.serializer.d.ts.map +0 -1
  83. package/dist/frontmatter/frontmatter.serializer.js.map +0 -1
  84. package/dist/frontmatter/frontmatter.types.d.ts.map +0 -1
  85. package/dist/frontmatter/frontmatter.types.js.map +0 -1
  86. package/dist/frontmatter/index.d.ts.map +0 -1
  87. package/dist/frontmatter/index.js.map +0 -1
  88. package/dist/generator/generator.types.d.ts.map +0 -1
  89. package/dist/generator/generator.types.js.map +0 -1
  90. package/dist/generator/generatorJson.core.d.ts.map +0 -1
  91. package/dist/generator/generatorJson.core.js.map +0 -1
  92. package/dist/generator/generatorMarkdown.core.d.ts.map +0 -1
  93. package/dist/generator/generatorMarkdown.core.js.map +0 -1
  94. package/dist/generator/generatorMarkdownNodes.d.ts.map +0 -1
  95. package/dist/generator/generatorMarkdownNodes.js.map +0 -1
  96. package/dist/generator/index.d.ts.map +0 -1
  97. package/dist/generator/index.js.map +0 -1
  98. package/dist/index.d.ts.map +0 -1
  99. package/dist/index.js.map +0 -1
  100. package/dist/navigation/index.d.ts.map +0 -1
  101. package/dist/navigation/index.js.map +0 -1
  102. package/dist/navigation/navigation.core.d.ts.map +0 -1
  103. package/dist/navigation/navigation.core.js.map +0 -1
  104. package/dist/registry/index.d.ts.map +0 -1
  105. package/dist/registry/index.js.map +0 -1
  106. package/dist/registry/registry.core.d.ts.map +0 -1
  107. package/dist/registry/registry.core.js.map +0 -1
  108. package/dist/utils/index.d.ts.map +0 -1
  109. package/dist/utils/index.js.map +0 -1
  110. package/dist/utils/utils.helper.d.ts.map +0 -1
  111. package/dist/utils/utils.helper.js.map +0 -1
  112. package/dist/validator/index.d.ts.map +0 -1
  113. package/dist/validator/index.js.map +0 -1
  114. package/dist/validator/validator.types.d.ts.map +0 -1
  115. package/dist/validator/validator.types.js.map +0 -1
  116. package/dist/validator/validatorAll/index.d.ts.map +0 -1
  117. package/dist/validator/validatorAll/index.js.map +0 -1
  118. package/dist/validator/validatorAll/validatorAll.core.d.ts.map +0 -1
  119. package/dist/validator/validatorAll/validatorAll.core.js.map +0 -1
  120. package/dist/validator/validatorAll/validatorNavigation.core.d.ts.map +0 -1
  121. package/dist/validator/validatorAll/validatorNavigation.core.js.map +0 -1
  122. package/dist/validator/validatorDocument.core.d.ts.map +0 -1
  123. package/dist/validator/validatorDocument.core.js.map +0 -1
  124. package/dist/validator/validatorDuplicates.core.d.ts.map +0 -1
  125. package/dist/validator/validatorDuplicates.core.js.map +0 -1
  126. package/dist/validator/validatorLinks.core.d.ts.map +0 -1
  127. 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: readonly DocumentationNavigationItem[]): readonly DocumentationBreadcrumb[];
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: readonly DocumentationNavigationItem[]): readonly string[];
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: readonly DocumentationNavigationItem[]): DocumentationNavigationItem | undefined;
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 sibling document IDs for a given document.
37
+ * Gets the previous and next document IDs at the same navigation level.
23
38
  */
24
- export declare function getSiblings(documentId: string, items: readonly DocumentationNavigationItem[]): readonly string[];
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
- function walk(nodes) {
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({ title: node.title, documentId: node.documentId });
30
+ path.push(toBreadcrumb(node));
17
31
  return true;
18
32
  }
19
33
  if (node.children) {
20
- path.push({ title: node.title });
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
- function walk(nodes) {
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.documentId) {
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
- for (const node of items) {
55
- if (node.documentId === documentId) {
56
- return node;
57
- }
58
- if (node.children) {
59
- const found = findNavigationItem(documentId, node.children);
60
- if (found)
61
- return found;
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 undefined;
101
+ return walk(items, 0);
65
102
  }
66
103
  /**
67
- * Gets sibling document IDs for a given document.
104
+ * Returns the list of document IDs at the same level as `documentId`,
105
+ * including the document itself, in navigation order.
68
106
  */
69
- export function getSiblings(documentId, items) {
70
- function walk(nodes) {
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.filter((n) => n.documentId).map((n) => n.documentId);
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 Object.freeze(walk(items) ?? []);
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
@@ -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
@@ -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. Throws if the ID is already registered.
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. Throws if the ID is already registered.
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 Error(`Duplicate document ID: "${document.id}".`);
35
+ throw new DuplicateDocumentError(document.id);
18
36
  }
19
- this.documents.set(document.id, Object.freeze(document));
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
- return Object.freeze([...this.documents.values()]);
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
  */
@@ -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
@@ -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
- * Strips leading/trailing dots, collapses consecutive dots.
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
- * Extracts the title from markdown content (first heading).
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;