1
1
/**
2
- * @typedef {import('mdast').Content } Content
3
2
* @typedef {import('mdast').Heading } Heading
4
3
* @typedef {import('mdast').Root } Root
4
+ * @typedef {import('unist').Node } UnistNode
5
5
* @typedef {import('unist').Parent } UnistParent
6
6
*/
7
7
8
- // To do: use `Nodes`, `Parents` from `mdast` when released.
9
8
/**
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.
12
99
*/
13
100
14
101
/**
15
102
* @callback Handler
16
103
* Callback called when a section is found.
17
104
* @param {Heading } start
18
105
* Start of section (a heading node matching `test`).
19
- * @param {Array<Node > } between
106
+ * @param {Array<Sibling<Root, Heading> > } between
20
107
* Nodes between `start` and `end`.
21
- * @param {Node | undefined } end
108
+ * @param {Sibling<Root, Heading> | undefined } end
22
109
* End of section, if any.
23
110
* @param {Info } scope
24
111
* Extra info.
25
- * @returns {Array<Node | null | undefined> | null | undefined | void }
112
+ * @returns {Array<Sibling<Root, Heading> | null | undefined> | null | undefined | void }
26
113
* Results.
27
114
*
28
115
* If nothing is returned, nothing will be changed.
31
118
*
32
119
* @typedef Info
33
120
* Extra info.
34
- * @property {Parent } parent
121
+ * @property {Parent<Root, Heading> } parent
35
122
* Parent of the section.
36
123
* @property {number } start
37
124
* Index of `start` in `parent`.
@@ -78,7 +165,7 @@ import {toString} from 'mdast-util-to-string'
78
165
* If `ignoreFinalDefinitions: true`, final definitions “in” the section are
79
166
* excluded.
80
167
*
81
- * @param {Node } tree
168
+ * @param {Parent<Root, Heading> } tree
82
169
* Tree to change.
83
170
* @param {Options | Test } options
84
171
* Configuration.
@@ -91,7 +178,7 @@ import {toString} from 'mdast-util-to-string'
91
178
export function headingRange ( tree , options , handler ) {
92
179
let test = options
93
180
// To do: smarter types to allow siblings of headings.
94
- /** @type {Array<Node > } */
181
+ /** @type {Array<Sibling<Root, Heading> > } */
95
182
const children = 'children' in tree ? tree . children : [ ]
96
183
let ignoreFinalDefinitions = false
97
184
@@ -163,7 +250,9 @@ export function headingRange(tree, options, handler) {
163
250
const parent = tree
164
251
assert ( 'children' in parent , 'parent is a parent' )
165
252
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 ] , {
167
256
parent,
168
257
start,
169
258
end : children [ end ] ? end : null
@@ -172,7 +261,7 @@ export function headingRange(tree, options, handler) {
172
261
if ( nodes ) {
173
262
// Ensure no empty nodes are inserted.
174
263
// 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> > } */
176
265
const result = [ ]
177
266
let index = - 1
178
267
0 commit comments