@cudoment/cudoc 0.1.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 (111) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +58 -0
  3. package/dist/ast.d.ts +2 -0
  4. package/dist/ast.d.ts.map +1 -0
  5. package/dist/ast.js +2 -0
  6. package/dist/ast.js.map +1 -0
  7. package/dist/embed.d.ts +5 -0
  8. package/dist/embed.d.ts.map +1 -0
  9. package/dist/embed.js +5 -0
  10. package/dist/embed.js.map +1 -0
  11. package/dist/index.d.ts +3 -0
  12. package/dist/index.d.ts.map +1 -0
  13. package/dist/index.js +3 -0
  14. package/dist/index.js.map +1 -0
  15. package/dist/internal/core/ast/guards.d.ts +13 -0
  16. package/dist/internal/core/ast/guards.d.ts.map +1 -0
  17. package/dist/internal/core/ast/guards.js +21 -0
  18. package/dist/internal/core/ast/guards.js.map +1 -0
  19. package/dist/internal/core/ast/index.d.ts +6 -0
  20. package/dist/internal/core/ast/index.d.ts.map +1 -0
  21. package/dist/internal/core/ast/index.js +4 -0
  22. package/dist/internal/core/ast/index.js.map +1 -0
  23. package/dist/internal/core/ast/types.d.ts +49 -0
  24. package/dist/internal/core/ast/types.d.ts.map +1 -0
  25. package/dist/internal/core/ast/types.js +25 -0
  26. package/dist/internal/core/ast/types.js.map +1 -0
  27. package/dist/internal/core/ast/validate.d.ts +16 -0
  28. package/dist/internal/core/ast/validate.d.ts.map +1 -0
  29. package/dist/internal/core/ast/validate.js +90 -0
  30. package/dist/internal/core/ast/validate.js.map +1 -0
  31. package/dist/internal/core/index.d.ts +9 -0
  32. package/dist/internal/core/index.d.ts.map +1 -0
  33. package/dist/internal/core/index.js +7 -0
  34. package/dist/internal/core/index.js.map +1 -0
  35. package/dist/internal/core/mdx/index.d.ts +2 -0
  36. package/dist/internal/core/mdx/index.d.ts.map +1 -0
  37. package/dist/internal/core/mdx/index.js +2 -0
  38. package/dist/internal/core/mdx/index.js.map +1 -0
  39. package/dist/internal/core/mdx/jsx.d.ts +25 -0
  40. package/dist/internal/core/mdx/jsx.d.ts.map +1 -0
  41. package/dist/internal/core/mdx/jsx.js +43 -0
  42. package/dist/internal/core/mdx/jsx.js.map +1 -0
  43. package/dist/internal/core/query/index.d.ts +7 -0
  44. package/dist/internal/core/query/index.d.ts.map +1 -0
  45. package/dist/internal/core/query/index.js +4 -0
  46. package/dist/internal/core/query/index.js.map +1 -0
  47. package/dist/internal/core/query/nodes.d.ts +61 -0
  48. package/dist/internal/core/query/nodes.d.ts.map +1 -0
  49. package/dist/internal/core/query/nodes.js +151 -0
  50. package/dist/internal/core/query/nodes.js.map +1 -0
  51. package/dist/internal/core/query/sections.d.ts +72 -0
  52. package/dist/internal/core/query/sections.d.ts.map +1 -0
  53. package/dist/internal/core/query/sections.js +178 -0
  54. package/dist/internal/core/query/sections.js.map +1 -0
  55. package/dist/internal/core/query/tables.d.ts +32 -0
  56. package/dist/internal/core/query/tables.d.ts.map +1 -0
  57. package/dist/internal/core/query/tables.js +46 -0
  58. package/dist/internal/core/query/tables.js.map +1 -0
  59. package/dist/internal/core/selectors.d.ts +41 -0
  60. package/dist/internal/core/selectors.d.ts.map +1 -0
  61. package/dist/internal/core/selectors.js +87 -0
  62. package/dist/internal/core/selectors.js.map +1 -0
  63. package/dist/internal/core/syntax/delimiters.d.ts +45 -0
  64. package/dist/internal/core/syntax/delimiters.d.ts.map +1 -0
  65. package/dist/internal/core/syntax/delimiters.js +81 -0
  66. package/dist/internal/core/syntax/delimiters.js.map +1 -0
  67. package/dist/internal/core/syntax/heading-metadata.d.ts +59 -0
  68. package/dist/internal/core/syntax/heading-metadata.d.ts.map +1 -0
  69. package/dist/internal/core/syntax/heading-metadata.js +178 -0
  70. package/dist/internal/core/syntax/heading-metadata.js.map +1 -0
  71. package/dist/internal/core/syntax/index.d.ts +5 -0
  72. package/dist/internal/core/syntax/index.d.ts.map +1 -0
  73. package/dist/internal/core/syntax/index.js +3 -0
  74. package/dist/internal/core/syntax/index.js.map +1 -0
  75. package/dist/internal/core/walk.d.ts +40 -0
  76. package/dist/internal/core/walk.d.ts.map +1 -0
  77. package/dist/internal/core/walk.js +53 -0
  78. package/dist/internal/core/walk.js.map +1 -0
  79. package/dist/mdx.d.ts +2 -0
  80. package/dist/mdx.d.ts.map +1 -0
  81. package/dist/mdx.js +2 -0
  82. package/dist/mdx.js.map +1 -0
  83. package/dist/node/export-ast.d.ts +52 -0
  84. package/dist/node/export-ast.d.ts.map +1 -0
  85. package/dist/node/export-ast.js +117 -0
  86. package/dist/node/export-ast.js.map +1 -0
  87. package/dist/node/index.d.ts +7 -0
  88. package/dist/node/index.d.ts.map +1 -0
  89. package/dist/node/index.js +4 -0
  90. package/dist/node/index.js.map +1 -0
  91. package/dist/node/load-ast-file.d.ts +9 -0
  92. package/dist/node/load-ast-file.d.ts.map +1 -0
  93. package/dist/node/load-ast-file.js +32 -0
  94. package/dist/node/load-ast-file.js.map +1 -0
  95. package/dist/node/load-ast.d.ts +11 -0
  96. package/dist/node/load-ast.d.ts.map +1 -0
  97. package/dist/node/load-ast.js +17 -0
  98. package/dist/node/load-ast.js.map +1 -0
  99. package/dist/node/paths.d.ts +31 -0
  100. package/dist/node/paths.d.ts.map +1 -0
  101. package/dist/node/paths.js +54 -0
  102. package/dist/node/paths.js.map +1 -0
  103. package/dist/query.d.ts +2 -0
  104. package/dist/query.d.ts.map +1 -0
  105. package/dist/query.js +2 -0
  106. package/dist/query.js.map +1 -0
  107. package/dist/syntax.d.ts +2 -0
  108. package/dist/syntax.d.ts.map +1 -0
  109. package/dist/syntax.js +2 -0
  110. package/dist/syntax.js.map +1 -0
  111. package/package.json +94 -0
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Reading a stored tree.
3
+ *
4
+ * Exporting the AST is only half of what it is for. The other half is a page
5
+ * that pulls a table, a paragraph or a whole section out of another document
6
+ * and renders it in place — and that side needs to locate things in a tree it
7
+ * did not build, without re-parsing the source it came from.
8
+ *
9
+ * These are the primitives for that: they answer "which node is next", "where
10
+ * does this section end", "what does this subtree say". What counts as the
11
+ * right node for a particular embed stays with the caller, because that is a
12
+ * documentation-set convention rather than something cudoc can know.
13
+ */
14
+ import type { Node, Parent } from "unist";
15
+ /** Reading order, not tree depth: `before` walks towards the start. */
16
+ export type Direction = "before" | "after";
17
+ export type FindSiblingOptions = {
18
+ direction: Direction;
19
+ /** Node type to accept, such as `"table"`. Any type when omitted. */
20
+ type?: string;
21
+ /**
22
+ * Index the search stops at, exclusive. Usually a section boundary, so a
23
+ * lookup cannot quietly reach into the next section and return its table.
24
+ */
25
+ boundary?: number;
26
+ /** Further condition, evaluated only on nodes that passed `type`. */
27
+ accept?: (node: Node) => boolean;
28
+ };
29
+ /**
30
+ * The nearest sibling in one direction that matches.
31
+ *
32
+ * `boundary` is what keeps an embed honest: without it, "the table after this
33
+ * heading" silently becomes "the next table in the document", and a section
34
+ * with no table of its own borrows the following section's.
35
+ */
36
+ export declare const findSiblingNode: <T extends Node = Node>(parent: Parent, index: number, { accept, boundary, direction, type }: FindSiblingOptions) => T | undefined;
37
+ export type NodeTextOptions = {
38
+ /**
39
+ * Descend into node types this does not know, such as a host's own JSX
40
+ * element. On by default, because a stored tree is full of them and dropping
41
+ * their text silently loses content.
42
+ */
43
+ includeUnknown?: boolean;
44
+ /**
45
+ * Placed between two blocks. Inline nodes are always joined directly, so a
46
+ * badge in the middle of a sentence does not split it.
47
+ */
48
+ blockSeparator?: string;
49
+ /** Separates columns when reading a whole Markdown or HTML table row. */
50
+ tableCellSeparator?: string;
51
+ };
52
+ /**
53
+ * The visible text of a subtree.
54
+ *
55
+ * Blocks are included, unlike `getInlineText`, which stops at phrasing content:
56
+ * an embed usually wants what a section says, and a section is blocks. They are
57
+ * separated rather than concatenated, so a heading does not run into the
58
+ * paragraph beneath it.
59
+ */
60
+ export declare const getNodeText: (nodes: readonly Node[], options?: NodeTextOptions) => string;
61
+ //# sourceMappingURL=nodes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodes.d.ts","sourceRoot":"","sources":["../../../../src/internal/core/query/nodes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,OAAO,CAAA;AAEzC,uEAAuE;AACvE,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,CAAA;AAE1C,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,SAAS,CAAA;IACpB,qEAAqE;IACrE,IAAI,CAAC,EAAE,MAAM,CAAA;IACb;;;OAGG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAA;IACjB,qEAAqE;IACrE,MAAM,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,OAAO,CAAA;CACjC,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAAI,CAAC,SAAS,IAAI,GAAG,IAAI,EACnD,QAAQ,MAAM,EACd,OAAO,MAAM,EACb,uCAAuC,kBAAkB,KACxD,CAAC,GAAG,SAoBN,CAAA;AASD,MAAM,MAAM,eAAe,GAAG;IAC5B;;;;OAIG;IACH,cAAc,CAAC,EAAE,OAAO,CAAA;IACxB;;;OAGG;IACH,cAAc,CAAC,EAAE,MAAM,CAAA;IACvB,yEAAyE;IACzE,kBAAkB,CAAC,EAAE,MAAM,CAAA;CAC5B,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,WAAW,GACtB,OAAO,SAAS,IAAI,EAAE,EACtB,UAAS,eAAoB,KAC5B,MAgBF,CAAA"}
@@ -0,0 +1,151 @@
1
+ /**
2
+ * Reading a stored tree.
3
+ *
4
+ * Exporting the AST is only half of what it is for. The other half is a page
5
+ * that pulls a table, a paragraph or a whole section out of another document
6
+ * and renders it in place — and that side needs to locate things in a tree it
7
+ * did not build, without re-parsing the source it came from.
8
+ *
9
+ * These are the primitives for that: they answer "which node is next", "where
10
+ * does this section end", "what does this subtree say". What counts as the
11
+ * right node for a particular embed stays with the caller, because that is a
12
+ * documentation-set convention rather than something cudoc can know.
13
+ */
14
+ /**
15
+ * The nearest sibling in one direction that matches.
16
+ *
17
+ * `boundary` is what keeps an embed honest: without it, "the table after this
18
+ * heading" silently becomes "the next table in the document", and a section
19
+ * with no table of its own borrows the following section's.
20
+ */
21
+ export const findSiblingNode = (parent, index, { accept, boundary, direction, type }) => {
22
+ const step = direction === "before" ? -1 : 1;
23
+ const limit = direction === "before"
24
+ ? Math.max(boundary ?? -1, -1)
25
+ : Math.min(boundary ?? parent.children.length, parent.children.length);
26
+ for (let i = index + step; direction === "before" ? i > limit : i < limit; i += step) {
27
+ const node = parent.children[i];
28
+ if (!node)
29
+ continue;
30
+ if (type !== undefined && node.type !== type)
31
+ continue;
32
+ if (accept && !accept(node))
33
+ continue;
34
+ return node;
35
+ }
36
+ return undefined;
37
+ };
38
+ const LINE_BREAK_ELEMENTS = new Set(["br"]);
39
+ const isLineBreak = (node) => node.type === "break" ||
40
+ ((node.type === "mdxJsxTextElement" || node.type === "mdxJsxFlowElement") &&
41
+ LINE_BREAK_ELEMENTS.has(String(node.name)));
42
+ /**
43
+ * The visible text of a subtree.
44
+ *
45
+ * Blocks are included, unlike `getInlineText`, which stops at phrasing content:
46
+ * an embed usually wants what a section says, and a section is blocks. They are
47
+ * separated rather than concatenated, so a heading does not run into the
48
+ * paragraph beneath it.
49
+ */
50
+ export const getNodeText = (nodes, options = {}) => {
51
+ const { blockSeparator = "\n" } = options;
52
+ let text = "";
53
+ let previousWasBlock = false;
54
+ for (const node of nodes) {
55
+ const part = textOfNode(node, options);
56
+ if (!part)
57
+ continue;
58
+ const block = isBlock(node);
59
+ if (text && (block || previousWasBlock))
60
+ text += blockSeparator;
61
+ text += part;
62
+ previousWasBlock = block;
63
+ }
64
+ return text;
65
+ };
66
+ const textOfNode = (node, options) => {
67
+ const { includeUnknown = true } = options;
68
+ if (node.type === "text" ||
69
+ node.type === "inlineCode" ||
70
+ node.type === "code") {
71
+ return String(node.value ?? "");
72
+ }
73
+ if (isLineBreak(node))
74
+ return "\n";
75
+ if (!hasChildren(node))
76
+ return "";
77
+ if (!KNOWN_PARENTS.has(node.type) && !includeUnknown)
78
+ return "";
79
+ if (node.type === "tableRow" || elementName(node) === "tr") {
80
+ return node.children
81
+ .map((child) => textOfNode(child, options))
82
+ .join(options.tableCellSeparator ?? "\t");
83
+ }
84
+ return getNodeText(node.children, options);
85
+ };
86
+ /** Node types whose children are always part of the text. */
87
+ const KNOWN_PARENTS = new Set([
88
+ "root",
89
+ "blockquote",
90
+ "delete",
91
+ "emphasis",
92
+ "heading",
93
+ "link",
94
+ "linkReference",
95
+ "list",
96
+ "listItem",
97
+ "paragraph",
98
+ "strong",
99
+ "table",
100
+ "tableCell",
101
+ "tableRow",
102
+ ]);
103
+ /**
104
+ * Types that occupy a line of their own. Only used to decide where a separator
105
+ * goes, so an unknown element counts as inline and stays in its sentence.
106
+ */
107
+ const BLOCK_TYPES = new Set([
108
+ "blockquote",
109
+ "code",
110
+ "definition",
111
+ "footnoteDefinition",
112
+ "heading",
113
+ "html",
114
+ "list",
115
+ "listItem",
116
+ "mdxJsxFlowElement",
117
+ "mdxjsEsm",
118
+ "paragraph",
119
+ "table",
120
+ "tableRow",
121
+ "thematicBreak",
122
+ ]);
123
+ const BLOCK_ELEMENTS = new Set([
124
+ "p",
125
+ "div",
126
+ "section",
127
+ "article",
128
+ "aside",
129
+ "blockquote",
130
+ "pre",
131
+ "ul",
132
+ "ol",
133
+ "li",
134
+ "table",
135
+ "thead",
136
+ "tbody",
137
+ "tfoot",
138
+ "tr",
139
+ "h1",
140
+ "h2",
141
+ "h3",
142
+ "h4",
143
+ "h5",
144
+ "h6",
145
+ ]);
146
+ const elementName = (node) => node.type === "mdxJsxTextElement" || node.type === "mdxJsxFlowElement"
147
+ ? node.name
148
+ : undefined;
149
+ const isBlock = (node) => BLOCK_TYPES.has(node.type) || BLOCK_ELEMENTS.has(elementName(node) ?? "");
150
+ const hasChildren = (node) => "children" in node && Array.isArray(node.children);
151
+ //# sourceMappingURL=nodes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nodes.js","sourceRoot":"","sources":["../../../../src/internal/core/query/nodes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,72 @@
1
+ /**
2
+ * Locating and slicing the section a heading introduces.
3
+ *
4
+ * This is what an embed is usually after: a page links to
5
+ * `guide/limits#rate-limits` and wants that section's content, not the whole
6
+ * document. The anchor id is the right key for it — an author chose it, and it
7
+ * survives the heading being reworded, which is the entire reason cudoc has
8
+ * explicit anchors.
9
+ */
10
+ import type { Heading, Root } from "mdast";
11
+ import type { Parent } from "unist";
12
+ export type AnchorLookupOptions = {
13
+ /** Element name the id is read from. Matches the heading metadata options. */
14
+ anchorName?: string;
15
+ /** Attribute the id is read from. */
16
+ idAttribute?: string;
17
+ /** Attribute the badge is read from. */
18
+ badgeAttribute?: string;
19
+ };
20
+ /**
21
+ * An id as written in a link: a leading `#` is dropped and percent-encoding is
22
+ * undone, so `#rate%20limits` and `rate limits` find the same heading.
23
+ */
24
+ export declare const normalizeAnchorId: (anchorId: string | undefined) => string | undefined;
25
+ /** Reads the anchor id a heading carries, if it has one. */
26
+ export declare const getHeadingAnchorId: (heading: Heading, options?: AnchorLookupOptions) => string | undefined;
27
+ /**
28
+ * Reads the badge a heading carries.
29
+ *
30
+ * It sits in an attribute rather than in the heading's children, so collecting
31
+ * the heading's text does not find it — which is usually what you want for a
32
+ * title, and never what you want when the badge is the point.
33
+ */
34
+ export declare const getHeadingBadge: (heading: Heading, options?: AnchorLookupOptions) => string | undefined;
35
+ export type HeadingLocation = {
36
+ heading: Heading;
37
+ parent: Parent;
38
+ index: number;
39
+ };
40
+ /** Finds the heading carrying `anchorId`, with enough context to slice from. */
41
+ export declare const findHeadingByAnchorId: (tree: Root, anchorId: string, options?: AnchorLookupOptions) => HeadingLocation | undefined;
42
+ /**
43
+ * The index the section starting at `index` ends at, exclusive.
44
+ *
45
+ * A section ends at the next heading of the same depth or shallower, which is
46
+ * how a reader sees it: an `h3` closes an `h3`, an `h2` closes both.
47
+ */
48
+ export declare const findSectionEnd: (parent: Parent, index: number, depth: number) => number;
49
+ /** The heading that introduces the section containing the one at `index`. */
50
+ export declare const findParentHeading: (parent: Parent, index: number, depth: number) => Heading | undefined;
51
+ export type SliceSectionOptions = AnchorLookupOptions & {
52
+ /** Retain the link, image and footnote definitions used by the slice. On by default. */
53
+ includeDefinitions?: boolean;
54
+ /**
55
+ * Prepend the enclosing heading when the target is at this depth or deeper.
56
+ *
57
+ * A deep section is often meaningless alone — "Requirements" says nothing
58
+ * without the API name above it — so an embed can ask for that context. Off
59
+ * unless a depth is given.
60
+ */
61
+ contextHeadingFromDepth?: number;
62
+ };
63
+ /**
64
+ * The section a heading introduces, as a tree of its own.
65
+ *
66
+ * The result keeps the root's `data`, so a stored tree's schema version travels
67
+ * with the slice and a consumer can still validate what it was handed.
68
+ * Returns `undefined` when no heading carries the id; the caller knows what a
69
+ * broken embed reference should do, and it is rarely "throw".
70
+ */
71
+ export declare const sliceSectionByAnchorId: (tree: Root, anchorId: string, options?: SliceSectionOptions) => Root | undefined;
72
+ //# sourceMappingURL=sections.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sections.d.ts","sourceRoot":"","sources":["../../../../src/internal/core/query/sections.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAGV,OAAO,EACP,IAAI,EAEL,MAAM,OAAO,CAAA;AACd,OAAO,KAAK,EAAQ,MAAM,EAAE,MAAM,OAAO,CAAA;AASzC,MAAM,MAAM,mBAAmB,GAAG;IAChC,8EAA8E;IAC9E,UAAU,CAAC,EAAE,MAAM,CAAA;IACnB,qCAAqC;IACrC,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,wCAAwC;IACxC,cAAc,CAAC,EAAE,MAAM,CAAA;CACxB,CAAA;AAED;;;GAGG;AACH,eAAO,MAAM,iBAAiB,GAC5B,UAAU,MAAM,GAAG,SAAS,KAC3B,MAAM,GAAG,SAUX,CAAA;AAED,4DAA4D;AAC5D,eAAO,MAAM,kBAAkB,GAC7B,SAAS,OAAO,EAChB,UAAS,mBAAwB,KAChC,MAAM,GAAG,SAUX,CAAA;AAED;;;;;;GAMG;AACH,eAAO,MAAM,eAAe,GAC1B,SAAS,OAAO,EAChB,UAAS,mBAAwB,KAChC,MAAM,GAAG,SAIT,CAAA;AAEH,MAAM,MAAM,eAAe,GAAG;IAC5B,OAAO,EAAE,OAAO,CAAA;IAChB,MAAM,EAAE,MAAM,CAAA;IACd,KAAK,EAAE,MAAM,CAAA;CACd,CAAA;AAED,gFAAgF;AAChF,eAAO,MAAM,qBAAqB,GAChC,MAAM,IAAI,EACV,UAAU,MAAM,EAChB,UAAS,mBAAwB,KAChC,eAAe,GAAG,SAgBpB,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,GACzB,QAAQ,MAAM,EACd,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,MAMF,CAAA;AAED,6EAA6E;AAC7E,eAAO,MAAM,iBAAiB,GAC5B,QAAQ,MAAM,EACd,OAAO,MAAM,EACb,OAAO,MAAM,KACZ,OAAO,GAAG,SAQZ,CAAA;AAED,MAAM,MAAM,mBAAmB,GAAG,mBAAmB,GAAG;IACtD,wFAAwF;IACxF,kBAAkB,CAAC,EAAE,OAAO,CAAA;IAC5B;;;;;;OAMG;IACH,uBAAuB,CAAC,EAAE,MAAM,CAAA;CACjC,CAAA;AAED;;;;;;;GAOG;AACH,eAAO,MAAM,sBAAsB,GACjC,MAAM,IAAI,EACV,UAAU,MAAM,EAChB,UAAS,mBAAwB,KAChC,IAAI,GAAG,SA2BT,CAAA"}
@@ -0,0 +1,178 @@
1
+ /**
2
+ * Locating and slicing the section a heading introduces.
3
+ *
4
+ * This is what an embed is usually after: a page links to
5
+ * `guide/limits#rate-limits` and wants that section's content, not the whole
6
+ * document. The anchor id is the right key for it — an author chose it, and it
7
+ * survives the heading being reworded, which is the entire reason cudoc has
8
+ * explicit anchors.
9
+ */
10
+ import { visit } from "unist-util-visit";
11
+ import { extractAnchorId, findAnchorNode, DEFAULT_ANCHOR_NAME, } from "../syntax/heading-metadata.js";
12
+ import { readStringAttribute } from "../mdx/jsx.js";
13
+ /**
14
+ * An id as written in a link: a leading `#` is dropped and percent-encoding is
15
+ * undone, so `#rate%20limits` and `rate limits` find the same heading.
16
+ */
17
+ export const normalizeAnchorId = (anchorId) => {
18
+ const trimmed = anchorId?.trim().replace(/^#/, "");
19
+ if (!trimmed)
20
+ return undefined;
21
+ try {
22
+ return decodeURIComponent(trimmed);
23
+ }
24
+ catch {
25
+ // A malformed escape is not worth failing over; compare it as written.
26
+ return trimmed;
27
+ }
28
+ };
29
+ /** Reads the anchor id a heading carries, if it has one. */
30
+ export const getHeadingAnchorId = (heading, options = {}) => {
31
+ // Hosts and heading-ids put the rendered id here. Prefer it if another
32
+ // plugin supplied an id that differs from the metadata anchor.
33
+ const id = heading.data
34
+ ?.hProperties?.id;
35
+ if (typeof id === "string" && id)
36
+ return id;
37
+ return extractAnchorId(findAnchorNode(heading.children, options.anchorName ?? DEFAULT_ANCHOR_NAME), options.idAttribute ?? "id");
38
+ };
39
+ /**
40
+ * Reads the badge a heading carries.
41
+ *
42
+ * It sits in an attribute rather than in the heading's children, so collecting
43
+ * the heading's text does not find it — which is usually what you want for a
44
+ * title, and never what you want when the badge is the point.
45
+ */
46
+ export const getHeadingBadge = (heading, options = {}) => readStringAttribute(findAnchorNode(heading.children, options.anchorName ?? DEFAULT_ANCHOR_NAME), options.badgeAttribute ?? "badge");
47
+ /** Finds the heading carrying `anchorId`, with enough context to slice from. */
48
+ export const findHeadingByAnchorId = (tree, anchorId, options = {}) => {
49
+ const target = normalizeAnchorId(anchorId);
50
+ if (!target)
51
+ return undefined;
52
+ let found;
53
+ visit(tree, "heading", (node, index, parent) => {
54
+ if (found || typeof index !== "number" || !parent)
55
+ return;
56
+ const heading = node;
57
+ if (normalizeAnchorId(getHeadingAnchorId(heading, options)) !== target) {
58
+ return;
59
+ }
60
+ found = { heading, index, parent: parent };
61
+ });
62
+ return found;
63
+ };
64
+ /**
65
+ * The index the section starting at `index` ends at, exclusive.
66
+ *
67
+ * A section ends at the next heading of the same depth or shallower, which is
68
+ * how a reader sees it: an `h3` closes an `h3`, an `h2` closes both.
69
+ */
70
+ export const findSectionEnd = (parent, index, depth) => {
71
+ for (let i = index + 1; i < parent.children.length; i += 1) {
72
+ const node = parent.children[i];
73
+ if (node?.type === "heading" && node.depth <= depth)
74
+ return i;
75
+ }
76
+ return parent.children.length;
77
+ };
78
+ /** The heading that introduces the section containing the one at `index`. */
79
+ export const findParentHeading = (parent, index, depth) => {
80
+ for (let i = index - 1; i >= 0; i -= 1) {
81
+ const node = parent.children[i];
82
+ if (node?.type === "heading" && node.depth < depth) {
83
+ return node;
84
+ }
85
+ }
86
+ return undefined;
87
+ };
88
+ /**
89
+ * The section a heading introduces, as a tree of its own.
90
+ *
91
+ * The result keeps the root's `data`, so a stored tree's schema version travels
92
+ * with the slice and a consumer can still validate what it was handed.
93
+ * Returns `undefined` when no heading carries the id; the caller knows what a
94
+ * broken embed reference should do, and it is rarely "throw".
95
+ */
96
+ export const sliceSectionByAnchorId = (tree, anchorId, options = {}) => {
97
+ const location = findHeadingByAnchorId(tree, anchorId, options);
98
+ if (!location)
99
+ return undefined;
100
+ const { heading, index, parent } = location;
101
+ const { contextHeadingFromDepth } = options;
102
+ const contextHeading = contextHeadingFromDepth !== undefined &&
103
+ heading.depth >= contextHeadingFromDepth
104
+ ? findParentHeading(parent, index, heading.depth)
105
+ : undefined;
106
+ const section = parent.children.slice(index, findSectionEnd(parent, index, heading.depth));
107
+ const children = contextHeading ? [contextHeading, ...section] : section;
108
+ if (options.includeDefinitions !== false) {
109
+ appendReferencedDefinitions(tree, children);
110
+ }
111
+ return {
112
+ ...tree,
113
+ children,
114
+ };
115
+ };
116
+ // Definitions are document-scoped. A reference inside the slice may be
117
+ // resolved by a definition after the next heading, including a footnote that
118
+ // itself refers to a link or another footnote. Keep only those dependencies.
119
+ const appendReferencedDefinitions = (tree, children) => {
120
+ const definitions = new Map();
121
+ const key = (type, identifier) => `${type}:${identifier.toUpperCase()}`;
122
+ visit(tree, (node) => {
123
+ if (node.type !== "definition" && node.type !== "footnoteDefinition")
124
+ return;
125
+ const id = key(node.type, node.identifier);
126
+ if (!definitions.has(id))
127
+ definitions.set(id, node);
128
+ });
129
+ // Markdown resolves duplicate definitions to the first one in the full
130
+ // document. Remove later duplicates from the slice so they cannot take over
131
+ // when the original first definition is appended below. Clone only affected
132
+ // parents; never edit the source tree's children.
133
+ const removeShadowed = (node) => {
134
+ if (node.type === "definition" || node.type === "footnoteDefinition") {
135
+ const definition = node;
136
+ if (definitions.get(key(node.type, definition.identifier)) !== definition)
137
+ return undefined;
138
+ }
139
+ if (!("children" in node) || !Array.isArray(node.children))
140
+ return node;
141
+ const original = node.children;
142
+ const kept = original.flatMap((child) => {
143
+ const next = removeShadowed(child);
144
+ return next ? [next] : [];
145
+ });
146
+ return kept.length === original.length &&
147
+ kept.every((child, index) => child === original[index])
148
+ ? node
149
+ : { ...node, children: kept };
150
+ };
151
+ const retained = children.flatMap((child) => {
152
+ const next = removeShadowed(child);
153
+ return next ? [next] : [];
154
+ });
155
+ children.splice(0, children.length, ...retained);
156
+ const included = new Set();
157
+ visit({ type: "root", children }, (node) => {
158
+ if (node.type === "definition" || node.type === "footnoteDefinition")
159
+ included.add(node);
160
+ });
161
+ // Appended definitions are visited on later iterations; `included` also
162
+ // makes cyclic footnote references finite.
163
+ for (let index = 0; index < children.length; index += 1) {
164
+ visit(children[index], (node) => {
165
+ if (node.type !== "linkReference" &&
166
+ node.type !== "imageReference" &&
167
+ node.type !== "footnoteReference")
168
+ return;
169
+ const type = node.type === "footnoteReference" ? "footnoteDefinition" : "definition";
170
+ const definition = definitions.get(key(type, node.identifier));
171
+ if (definition && !included.has(definition)) {
172
+ included.add(definition);
173
+ children.push(definition);
174
+ }
175
+ });
176
+ }
177
+ };
178
+ //# sourceMappingURL=sections.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sections.js","sourceRoot":"","sources":["../../../../src/internal/core/query/sections.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Reading values out of a table.
3
+ *
4
+ * An embed that shows "the method and the endpoint for this API" is reading two
5
+ * cells of a table in another document. Addressing them by row and column is
6
+ * blunt, but it is what the document actually offers: a Markdown table has no
7
+ * field names.
8
+ */
9
+ import type { CudocTable } from "../ast/types.js";
10
+ import type { Node } from "unist";
11
+ /** A `[row, column]` pair, both zero-based, with the header row as row 0. */
12
+ export type CellPosition = readonly [row: number, column: number];
13
+ /**
14
+ * The children of each addressed cell, in the order asked for.
15
+ *
16
+ * A missing cell yields an empty array rather than throwing: a table that is
17
+ * one column short is a document problem, and the caller is the one that can
18
+ * say what to do about it.
19
+ */
20
+ export declare const getTableCellNodes: (table: CudocTable, positions: readonly CellPosition[]) => Node[][];
21
+ /** The text of each addressed cell, or `undefined` where the cell is empty. */
22
+ export declare const getTableCellText: (table: CudocTable, positions: readonly CellPosition[]) => (string | undefined)[];
23
+ /** The header row's text, for matching a column by name rather than index. */
24
+ export declare const getTableHeaderTexts: (table: CudocTable) => string[];
25
+ /**
26
+ * The index of the column whose header matches, or -1.
27
+ *
28
+ * Comparison collapses whitespace, so a header wrapped across lines in the
29
+ * source still matches what the author sees.
30
+ */
31
+ export declare const findTableColumnIndex: (table: CudocTable, headerTexts: readonly string[]) => number;
32
+ //# sourceMappingURL=tables.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.d.ts","sourceRoot":"","sources":["../../../../src/internal/core/query/tables.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAA;AACjD,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,OAAO,CAAA;AAGjC,6EAA6E;AAC7E,MAAM,MAAM,YAAY,GAAG,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,CAAC,CAAA;AAEjE;;;;;;GAMG;AACH,eAAO,MAAM,iBAAiB,GAC5B,OAAO,UAAU,EACjB,WAAW,SAAS,YAAY,EAAE,KACjC,IAAI,EAAE,EAIL,CAAA;AAEJ,+EAA+E;AAC/E,eAAO,MAAM,gBAAgB,GAC3B,OAAO,UAAU,EACjB,WAAW,SAAS,YAAY,EAAE,KACjC,CAAC,MAAM,GAAG,SAAS,CAAC,EAInB,CAAA;AAEJ,8EAA8E;AAC9E,eAAO,MAAM,mBAAmB,GAAI,OAAO,UAAU,KAAG,MAAM,EAQ7D,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB,GAC/B,OAAO,UAAU,EACjB,aAAa,SAAS,MAAM,EAAE,KAC7B,MAIF,CAAA"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Reading values out of a table.
3
+ *
4
+ * An embed that shows "the method and the endpoint for this API" is reading two
5
+ * cells of a table in another document. Addressing them by row and column is
6
+ * blunt, but it is what the document actually offers: a Markdown table has no
7
+ * field names.
8
+ */
9
+ import { getNodeText } from "./nodes.js";
10
+ /**
11
+ * The children of each addressed cell, in the order asked for.
12
+ *
13
+ * A missing cell yields an empty array rather than throwing: a table that is
14
+ * one column short is a document problem, and the caller is the one that can
15
+ * say what to do about it.
16
+ */
17
+ export const getTableCellNodes = (table, positions) => positions.map(([row, column]) => {
18
+ const cell = table.children[row]?.children[column];
19
+ return cell ? [...cell.children] : [];
20
+ });
21
+ /** The text of each addressed cell, or `undefined` where the cell is empty. */
22
+ export const getTableCellText = (table, positions) => getTableCellNodes(table, positions).map((children) => {
23
+ const text = getNodeText(children).trim();
24
+ return text || undefined;
25
+ });
26
+ /** The header row's text, for matching a column by name rather than index. */
27
+ export const getTableHeaderTexts = (table) => {
28
+ const header = table.children[0];
29
+ if (!header)
30
+ return [];
31
+ return header.children.map((cell) => getNodeText(cell.children)
32
+ .replace(/\s+/g, " ")
33
+ .trim());
34
+ };
35
+ /**
36
+ * The index of the column whose header matches, or -1.
37
+ *
38
+ * Comparison collapses whitespace, so a header wrapped across lines in the
39
+ * source still matches what the author sees.
40
+ */
41
+ export const findTableColumnIndex = (table, headerTexts) => {
42
+ const headers = getTableHeaderTexts(table);
43
+ const wanted = headerTexts.map((text) => text.replace(/\s+/g, " ").trim());
44
+ return headers.findIndex((header) => wanted.includes(header));
45
+ };
46
+ //# sourceMappingURL=tables.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tables.js","sourceRoot":"","sources":["../../../../src/internal/core/query/tables.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAIH,OAAO,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAKxC;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAC/B,KAAiB,EACjB,SAAkC,EACxB,EAAE,CACZ,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,MAAM,CAAC,EAAE,EAAE;IAC9B,MAAM,IAAI,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,CAAA;IAClD,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,GAAI,IAAI,CAAC,QAAmB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;AACnD,CAAC,CAAC,CAAA;AAEJ,+EAA+E;AAC/E,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAC9B,KAAiB,EACjB,SAAkC,EACV,EAAE,CAC1B,iBAAiB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE;IACnD,MAAM,IAAI,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAA;IACzC,OAAO,IAAI,IAAI,SAAS,CAAA;AAC1B,CAAC,CAAC,CAAA;AAEJ,8EAA8E;AAC9E,MAAM,CAAC,MAAM,mBAAmB,GAAG,CAAC,KAAiB,EAAY,EAAE;IACjE,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAA;IAChC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAA;IACtB,OAAO,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAClC,WAAW,CAAC,IAAI,CAAC,QAAkB,CAAC;SACjC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,IAAI,EAAE,CACV,CAAA;AACH,CAAC,CAAA;AAED;;;;;GAKG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,CAClC,KAAiB,EACjB,WAA8B,EACtB,EAAE;IACV,MAAM,OAAO,GAAG,mBAAmB,CAAC,KAAK,CAAC,CAAA;IAC1C,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC,CAAA;IAC1E,OAAO,OAAO,CAAC,SAAS,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAA;AAC/D,CAAC,CAAA"}
@@ -0,0 +1,41 @@
1
+ /**
2
+ * Declarative selectors.
3
+ *
4
+ * A caller cannot pass a predicate function through a bundler config, so the
5
+ * conditions a transform needs are described as plain data and evaluated here.
6
+ */
7
+ import type { Heading, Parent, PhrasingContent } from "mdast";
8
+ import type { AncestorLocation } from "./walk.js";
9
+ /** Concatenates the text of a phrasing subtree, ignoring node kinds. */
10
+ export declare const getInlineText: (nodes: readonly PhrasingContent[]) => string;
11
+ /** Collapses runs of whitespace and lowercases, for tolerant comparison. */
12
+ export declare const normalizeTitle: (value: string) => string;
13
+ /** Drops every space, so a title written with or without one still matches. */
14
+ export declare const compactTitle: (value: string) => string;
15
+ /** Collapses whitespace but keeps case, for exact header matching. */
16
+ export declare const normalizeHeaderText: (value: string) => string;
17
+ /** Identifies a section by the heading that introduces it. */
18
+ export type SectionSelector = {
19
+ /** Accepted heading depth, or depths. Any depth when omitted. */
20
+ depth?: number | number[];
21
+ /** Accepted heading titles. Compared case-insensitively, spacing-tolerant. */
22
+ titles: string[];
23
+ };
24
+ export declare const assertSectionSelector: (value: unknown, optionPath: string) => SectionSelector;
25
+ /**
26
+ * Tests a heading against a selector.
27
+ *
28
+ * Both a whitespace-normalized and a space-free comparison are accepted, so an
29
+ * author writing the title with or without an internal space still matches.
30
+ */
31
+ export declare const matchesSectionHeading: (heading: Heading, selector: SectionSelector,
32
+ /** Text extractor, so a caller can strip generated nodes first. */
33
+ readText?: (heading: Heading) => string) => boolean;
34
+ /**
35
+ * Finds the heading that introduces the node at `index`.
36
+ *
37
+ * The search continues through ancestors, because a table may sit inside a
38
+ * container whose own siblings hold the heading.
39
+ */
40
+ export declare const findPreviousHeading: (parent: Parent, index: number, ancestors?: AncestorLocation[]) => Heading | undefined;
41
+ //# sourceMappingURL=selectors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selectors.d.ts","sourceRoot":"","sources":["../../../src/internal/core/selectors.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,OAAO,CAAA;AAC7D,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAA;AAEjD,wEAAwE;AACxE,eAAO,MAAM,aAAa,GAAI,OAAO,SAAS,eAAe,EAAE,KAAG,MACP,CAAA;AAW3D,4EAA4E;AAC5E,eAAO,MAAM,cAAc,GAAI,OAAO,MAAM,KAAG,MACE,CAAA;AAEjD,+EAA+E;AAC/E,eAAO,MAAM,YAAY,GAAI,OAAO,MAAM,KAAG,MACH,CAAA;AAE1C,sEAAsE;AACtE,eAAO,MAAM,mBAAmB,GAAI,OAAO,MAAM,KAAG,MACjB,CAAA;AAEnC,8DAA8D;AAC9D,MAAM,MAAM,eAAe,GAAG;IAC5B,iEAAiE;IACjE,KAAK,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAA;IACzB,8EAA8E;IAC9E,MAAM,EAAE,MAAM,EAAE,CAAA;CACjB,CAAA;AAED,eAAO,MAAM,qBAAqB,GAChC,OAAO,OAAO,EACd,YAAY,MAAM,KACjB,eAwBF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,GAChC,SAAS,OAAO,EAChB,UAAU,eAAe;AACzB,mEAAmE;AACnE,WAAU,CAAC,OAAO,EAAE,OAAO,KAAK,MACF,KAC7B,OAeF,CAAA;AAED;;;;;GAKG;AACH,eAAO,MAAM,mBAAmB,GAC9B,QAAQ,MAAM,EACd,OAAO,MAAM,EACb,YAAW,gBAAgB,EAAO,KACjC,OAAO,GAAG,SAqBZ,CAAA"}