1
1
/**
2
- * @typedef {import('hast').Text } Text
3
- * @typedef {import('hast').Root } Root
4
- * @typedef {import('hast').Element } Element
5
- * @typedef {import('hast').Content } Content
6
2
* @typedef {import('hast').Nodes } Nodes
3
+ * @typedef {import('hast').Parents } Parents
4
+ * @typedef {import('hast').Root } Root
5
+ * @typedef {import('hast').RootContent } RootContent
6
+ * @typedef {import('hast').Text } Text
7
7
* @typedef {import('hast-util-is-element').Test } Test
8
8
* @typedef {import('unist-util-visit-parents').VisitorResult } VisitorResult
9
9
*/
10
10
11
11
/**
12
+ * @typedef {RegExp | string } Find
13
+ * Pattern to find.
14
+ *
15
+ * Strings are escaped and then turned into global expressions.
16
+ *
17
+ * @typedef {Array<FindAndReplaceTuple> } FindAndReplaceList
18
+ * Several find and replaces, in array form.
19
+ *
20
+ * @typedef {Record<string, Replace> } FindAndReplaceSchema
21
+ * Several find and replaces, in object form.
22
+ *
23
+ * @typedef {[Find, Replace] } FindAndReplaceTuple
24
+ * Find and replace in tuple form.
25
+ *
12
26
* @typedef RegExpMatchObject
13
27
* Info on the match.
14
28
* @property {number } index
15
29
* The index of the search at which the result was found.
16
30
* @property {string } input
17
31
* A copy of the search string in the text node.
18
- * @property {[Root, ...Array<Element >, Text] } stack
32
+ * @property {[...Array<Parents >, Text] } stack
19
33
* All ancestors of the text node, where the last node is the text itself.
20
34
*
35
+ * @typedef {ReplaceFunction | string } Replace
36
+ * Thing to replace with.
37
+ *
21
38
* @callback ReplaceFunction
22
39
* Callback called when a search matches.
23
40
* @param {...any } parameters
26
43
* * `value` (`string`) — whole match
27
44
* * `...capture` (`Array<string>`) — matches from regex capture groups
28
45
* * `match` (`RegExpMatchObject`) — info on the match
29
- * @returns {Array<Content > | Content | string | false | undefined | null }
46
+ * @returns {Array<RootContent > | RootContent | string | false | null | undefined }
30
47
* Thing to replace with.
31
48
*
32
49
* * when `null`, `undefined`, `''`, remove the match
33
50
* * …or when `false`, do not replace at all
34
51
* * …or when `string`, replace with a text node of that value
35
52
* * …or when `Node` or `Array<Node>`, replace with those nodes
36
53
*
37
- * @typedef {string | RegExp } Find
38
- * Pattern to find.
39
- *
40
- * Strings are escaped and then turned into global expressions.
41
- *
42
- * @typedef {Array<FindAndReplaceTuple> } FindAndReplaceList
43
- * Several find and replaces, in array form.
44
- * @typedef {Record<string, Replace> } FindAndReplaceSchema
45
- * Several find and replaces, in object form.
46
- * @typedef {[Find, Replace] } FindAndReplaceTuple
47
- * Find and replace in tuple form.
48
- * @typedef {string | ReplaceFunction } Replace
49
- * Thing to replace with.
50
54
* @typedef {[RegExp, ReplaceFunction] } Pair
51
55
* Normalized find and replace.
52
56
* @typedef {Array<Pair> } Pairs
55
59
* @typedef Options
56
60
* Configuration.
57
61
* @property {Test | null | undefined } [ignore]
58
- * Test for which elements to ignore.
62
+ * Test for which elements to ignore (optional) .
59
63
*/
60
64
61
65
import { visitParents } from 'unist-util-visit-parents'
@@ -80,18 +84,29 @@ export const defaultIgnore = ['math', 'script', 'style', 'svg', 'title']
80
84
* nodes.
81
85
* Partial matches are not supported.
82
86
*
83
- * @template {Nodes} Tree
84
- * Node type.
85
- * @param {Tree } tree
87
+ * @overload
88
+ * @param {Nodes } tree
89
+ * @param {Find } find
90
+ * @param {Replace | null | undefined } [replace]
91
+ * @param {Options | null | undefined } [options]
92
+ * @returns {undefined }
93
+ *
94
+ * @overload
95
+ * @param {Nodes } tree
96
+ * @param {FindAndReplaceSchema | FindAndReplaceList } schema
97
+ * @param {Options | null | undefined } [options]
98
+ * @returns {undefined }
99
+ *
100
+ * @param {Nodes } tree
86
101
* Tree to change.
87
- * @param {Find | FindAndReplaceSchema | FindAndReplaceList } find
102
+ * @param {Find | FindAndReplaceList | FindAndReplaceSchema } find
88
103
* Patterns to find.
89
- * @param {Replace | Options | null | undefined } [replace]
104
+ * @param {Options | Replace | null | undefined } [replace]
90
105
* Things to replace with (when `find` is `Find`) or configuration.
91
106
* @param {Options | null | undefined } [options]
92
107
* Configuration (when `find` is not `Find`).
93
- * @returns {Tree }
94
- * Given, modified, tree .
108
+ * @returns {undefined }
109
+ * Nothing .
95
110
*/
96
111
export function findAndReplace ( tree , find , replace , options ) {
97
112
/** @type {Options | null | undefined } */
@@ -121,23 +136,24 @@ export function findAndReplace(tree, find, replace, options) {
121
136
visitParents ( tree , 'text' , visitor )
122
137
}
123
138
124
- // To do next major: don’t return the given tree.
139
+ // @ts -expect-error: To do next major: don’t return the given tree.
125
140
return tree
126
141
127
- /** @type {import('unist-util-visit-parents').BuildVisitor<Nodes , 'text'> } */
142
+ /** @type {import('unist-util-visit-parents').BuildVisitor<Root , 'text'> } */
128
143
function visitor ( node , parents ) {
129
144
let index = - 1
130
- /** @type {Root | Element | undefined } */
145
+ /** @type {Parents | undefined } */
131
146
let grandparent
132
147
133
148
while ( ++ index < parents . length ) {
134
149
const parent = parents [ index ]
150
+ /** @type {Array<Nodes> | undefined } */
151
+ const siblings = grandparent ? grandparent . children : undefined
135
152
136
153
if (
137
154
ignored (
138
155
parent ,
139
- // @ts -expect-error: TS doesn’t understand but it’s perfect.
140
- grandparent ? grandparent . children . indexOf ( parent ) : undefined ,
156
+ siblings ? siblings . indexOf ( parent ) : undefined ,
141
157
grandparent
142
158
)
143
159
) {
@@ -157,7 +173,7 @@ export function findAndReplace(tree, find, replace, options) {
157
173
*
158
174
* @param {Text } node
159
175
* Text node.
160
- * @param {Array<Root | Element > } parents
176
+ * @param {Array<Parents > } parents
161
177
* Parents.
162
178
* @returns {VisitorResult }
163
179
* Result.
@@ -167,9 +183,11 @@ export function findAndReplace(tree, find, replace, options) {
167
183
const find = pairs [ pairIndex ] [ 0 ]
168
184
const replace = pairs [ pairIndex ] [ 1 ]
169
185
let start = 0
170
- const index = parent . children . indexOf ( node )
186
+ /** @type {Array<Nodes> } */
187
+ const siblings = parent . children
188
+ const index = siblings . indexOf ( node )
171
189
let change = false
172
- /** @type {Array<Content > } */
190
+ /** @type {Array<RootContent > } */
173
191
let nodes = [ ]
174
192
175
193
find . lastIndex = 0
@@ -182,7 +200,6 @@ export function findAndReplace(tree, find, replace, options) {
182
200
const matchObject = {
183
201
index : match . index ,
184
202
input : match . input ,
185
- // @ts -expect-error: stack is fine.
186
203
stack : [ ...parents , node ]
187
204
}
188
205
let value = replace ( ...match , matchObject )
@@ -231,7 +248,7 @@ export function findAndReplace(tree, find, replace, options) {
231
248
/**
232
249
* Turn a schema into pairs.
233
250
*
234
- * @param {FindAndReplaceSchema | FindAndReplaceList } schema
251
+ * @param {FindAndReplaceList | FindAndReplaceSchema } schema
235
252
* Schema.
236
253
* @returns {Pairs }
237
254
* Clean pairs.
@@ -288,5 +305,9 @@ function toExpression(find) {
288
305
* Function.
289
306
*/
290
307
function toFunction ( replace ) {
291
- return typeof replace === 'function' ? replace : ( ) => replace
308
+ return typeof replace === 'function'
309
+ ? replace
310
+ : function ( ) {
311
+ return replace
312
+ }
292
313
}
0 commit comments