11/**
2- * @typedef {import('mdast').Content } Content
32 * @typedef {import('mdast').Heading } Heading
43 * @typedef {import('mdast').Root } Root
4+ * @typedef {import('unist').Node } UnistNode
55 * @typedef {import('unist').Parent } UnistParent
66 */
77
8- // To do: use `Nodes`, `Parents` from `mdast` when released.
98/**
10- * @typedef {Content | Root } Node
11- * @typedef {Extract<Node, UnistParent> } Parent
9+ * @typedef {0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 } Uint
10+ * Number; capped reasonably.
11+ */
12+
13+ /**
14+ * @typedef {I extends 0 ? 1 : I extends 1 ? 2 : I extends 2 ? 3 : I extends 3 ? 4 : I extends 4 ? 5 : I extends 5 ? 6 : I extends 6 ? 7 : I extends 7 ? 8 : I extends 8 ? 9 : 10 } Increment
15+ * Increment a number in the type system.
16+ * @template {Uint} [I=0]
17+ * Index.
18+ */
19+
20+ /**
21+ * @typedef {(
22+ * Tree extends UnistParent
23+ * ? Depth extends Max
24+ * ? Tree
25+ * : Tree | InclusiveDescendant<Tree['children'][number], Max, Increment<Depth>>
26+ * : Tree
27+ * )} InclusiveDescendant
28+ * Collect all (inclusive) descendants of `Tree`.
29+ *
30+ * > 👉 **Note**: for performance reasons, this seems to be the fastest way to
31+ * > recurse without actually running into an infinite loop, which the
32+ * > previous version did.
33+ * >
34+ * > Practically, a max of `2` is typically enough assuming a `Root` is
35+ * > passed, but it doesn’t improve performance.
36+ * > It gets higher with `List > ListItem > Table > TableRow > TableCell`.
37+ * > Using up to `10` doesn’t hurt or help either.
38+ * @template {UnistNode} Tree
39+ * Tree type.
40+ * @template {Uint} [Max=10]
41+ * Max; searches up to this depth.
42+ * @template {Uint} [Depth=0]
43+ * Current depth.
44+ */
45+
46+ /**
47+ * @typedef {(
48+ * Node extends {children: Array<infer Child>}
49+ * ? Child
50+ * : never
51+ * )} InternalChild
52+ * Collect nodes that can be parents of `Child`.
53+ * @template {UnistNode} Node
54+ * All node types in a tree.
55+ * @template {UnistNode} Parent
56+ * Node to search for.
57+ */
58+
59+ /**
60+ * @typedef {(
61+ * Node extends UnistParent
62+ * ? Node extends {children: Array<infer Children>}
63+ * ? Kind extends Children ? Node : never
64+ * : never
65+ * : never
66+ * )} InternalParent
67+ * Collect nodes that can be parents of `Child`.
68+ * @template {UnistNode} Node
69+ * All node types in a tree.
70+ * @template {UnistNode} Kind
71+ * Node to search for.
72+ */
73+
74+ /**
75+ * @typedef {InternalChild<InclusiveDescendant<Tree>, Kind> } Child
76+ * Collect nodes in `Tree` that can be parents of `Child`.
77+ * @template {UnistNode} Tree
78+ * All node types in a tree.
79+ * @template {UnistNode} Kind
80+ * Node to search for.
81+ */
82+
83+ /**
84+ * @typedef {InternalParent<InclusiveDescendant<Tree>, Kind> } Parent
85+ * Collect nodes in `Tree` that can be parents of `Child`.
86+ * @template {UnistNode} Tree
87+ * All node types in a tree.
88+ * @template {UnistNode} Kind
89+ * Node to search for.
90+ */
91+
92+ /**
93+ * @typedef {Child<Root, Parent<Root, Heading>> } Sibling
94+ * Collect nodes in `Tree` that can be parents of `Child`.
95+ * @template {UnistNode} Tree
96+ * All node types in a tree.
97+ * @template {UnistNode} Node
98+ * Node to search for.
1299 */
13100
14101/**
15102 * @callback Handler
16103 * Callback called when a section is found.
17104 * @param {Heading } start
18105 * Start of section (a heading node matching `test`).
19- * @param {Array<Node > } between
106+ * @param {Array<Sibling<Root, Heading> > } between
20107 * Nodes between `start` and `end`.
21- * @param {Node | undefined } end
108+ * @param {Sibling<Root, Heading> | undefined } end
22109 * End of section, if any.
23110 * @param {Info } scope
24111 * Extra info.
25- * @returns {Array<Node | null | undefined> | null | undefined | void }
112+ * @returns {Array<Sibling<Root, Heading> | null | undefined> | null | undefined | void }
26113 * Results.
27114 *
28115 * If nothing is returned, nothing will be changed.
31118 *
32119 * @typedef Info
33120 * Extra info.
34- * @property {Parent } parent
121+ * @property {Parent<Root, Heading> } parent
35122 * Parent of the section.
36123 * @property {number } start
37124 * Index of `start` in `parent`.
@@ -78,7 +165,7 @@ import {toString} from 'mdast-util-to-string'
78165 * If `ignoreFinalDefinitions: true`, final definitions “in” the section are
79166 * excluded.
80167 *
81- * @param {Node } tree
168+ * @param {Parent<Root, Heading> } tree
82169 * Tree to change.
83170 * @param {Options | Test } options
84171 * Configuration.
@@ -91,7 +178,7 @@ import {toString} from 'mdast-util-to-string'
91178export function headingRange ( tree , options , handler ) {
92179 let test = options
93180 // To do: smarter types to allow siblings of headings.
94- /** @type {Array<Node > } */
181+ /** @type {Array<Sibling<Root, Heading> > } */
95182 const children = 'children' in tree ? tree . children : [ ]
96183 let ignoreFinalDefinitions = false
97184
@@ -163,7 +250,9 @@ export function headingRange(tree, options, handler) {
163250 const parent = tree
164251 assert ( 'children' in parent , 'parent is a parent' )
165252
166- const nodes = handler ( head , children . slice ( start + 1 , end ) , children [ end ] , {
253+ const from = children . slice ( start + 1 , end )
254+
255+ const nodes = handler ( head , from , children [ end ] , {
167256 parent,
168257 start,
169258 end : children [ end ] ? end : null
@@ -172,7 +261,7 @@ export function headingRange(tree, options, handler) {
172261 if ( nodes ) {
173262 // Ensure no empty nodes are inserted.
174263 // This could be the case if `end` is in `nodes` but no `end` node exists.
175- /** @type {Array<Node > } */
264+ /** @type {Array<Sibling<Root, Heading> > } */
176265 const result = [ ]
177266 let index = - 1
178267
0 commit comments