Skip to content

Commit 9bf44ad

Browse files
committed
Refactor code-style
1 parent 662165f commit 9bf44ad

File tree

2 files changed

+523
-447
lines changed

2 files changed

+523
-447
lines changed

lib/index.js

Lines changed: 168 additions & 160 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,23 @@
1818
* @property {[...Array<Parents>, Text]} stack
1919
* All ancestors of the text node, where the last node is the text itself.
2020
*
21+
* @typedef {RegExp | string} Find
22+
* Pattern to find.
23+
*
24+
* Strings are escaped and then turned into global expressions.
25+
*
26+
* @typedef {Array<FindAndReplaceTuple>} FindAndReplaceList
27+
* Several find and replaces, in array form.
28+
*
29+
* @typedef {Record<string, Replace>} FindAndReplaceSchema
30+
* Several find and replaces, in object form.
31+
*
32+
* @typedef {[Find, Replace]} FindAndReplaceTuple
33+
* Find and replace in tuple form.
34+
*
35+
* @typedef {ReplaceFunction | string} Replace
36+
* Thing to replace with.
37+
*
2138
* @callback ReplaceFunction
2239
* Callback called when a search matches.
2340
* @param {...any} parameters
@@ -26,36 +43,24 @@
2643
* * `value` (`string`) — whole match
2744
* * `...capture` (`Array<string>`) — matches from regex capture groups
2845
* * `match` (`RegExpMatchObject`) — info on the match
29-
* @returns {Array<PhrasingContent> | PhrasingContent | string | false | undefined | null}
46+
* @returns {Array<PhrasingContent> | PhrasingContent | string | false | null | undefined}
3047
* Thing to replace with.
3148
*
3249
* * when `null`, `undefined`, `''`, remove the match
3350
* * …or when `false`, do not replace at all
3451
* * …or when `string`, replace with a text node of that value
3552
* * …or when `Node` or `Array<Node>`, replace with those nodes
3653
*
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.
5054
* @typedef {[RegExp, ReplaceFunction]} Pair
5155
* Normalized find and replace.
56+
*
5257
* @typedef {Array<Pair>} Pairs
5358
* All find and replaced.
5459
*
5560
* @typedef Options
5661
* Configuration.
5762
* @property {Test | null | undefined} [ignore]
58-
* Test for which nodes to ignore.
63+
* Test for which nodes to ignore (optional).
5964
*/
6065

6166
import escape from 'escape-string-regexp'
@@ -71,176 +76,175 @@ const own = {}.hasOwnProperty
7176
* nodes.
7277
* Partial matches are not supported.
7378
*
74-
* @param tree
79+
* @overload
80+
* @param {Nodes} tree
81+
* @param {Find} find
82+
* @param {Replace | null | undefined} [replace]
83+
* @param {Options | null | undefined} [options]
84+
* @returns {undefined}
85+
*
86+
* @overload
87+
* @param {Nodes} tree
88+
* @param {FindAndReplaceSchema | FindAndReplaceList} schema
89+
* @param {Options | null | undefined} [options]
90+
* @returns {undefined}
91+
*
92+
* @param {Nodes} tree
7593
* Tree to change.
76-
* @param find
94+
* @param {Find | FindAndReplaceList | FindAndReplaceSchema} find
7795
* Patterns to find.
78-
* @param replace
96+
* @param {Options | Replace | null | undefined} [replace]
7997
* Things to replace with (when `find` is `Find`) or configuration.
80-
* @param options
98+
* @param {Options | null | undefined} [options]
8199
* Configuration (when `find` is not `Find`).
82-
* @returns
100+
* @returns {undefined}
83101
* Given, modified, tree.
84102
*/
85103
// To do: next major: remove `find` & `replace` combo, remove schema.
86-
export const findAndReplace =
87-
/**
88-
* @type {(
89-
* ((tree: Nodes, find: Find, replace?: Replace | null | undefined, options?: Options | null | undefined) => undefined) &
90-
* ((tree: Nodes, schema: FindAndReplaceSchema | FindAndReplaceList, options?: Options | null | undefined) => undefined)
91-
* )}
92-
**/
93-
(
94-
/**
95-
* @param {Nodes} tree
96-
* @param {Find | FindAndReplaceSchema | FindAndReplaceList} find
97-
* @param {Replace | Options | null | undefined} [replace]
98-
* @param {Options | null | undefined} [options]
99-
* @returns {undefined}
100-
*/
101-
function (tree, find, replace, options) {
102-
/** @type {Options | null | undefined} */
103-
let settings
104-
/** @type {FindAndReplaceSchema|FindAndReplaceList} */
105-
let schema
106-
107-
if (typeof find === 'string' || find instanceof RegExp) {
108-
// @ts-expect-error don’t expect options twice.
109-
schema = [[find, replace]]
110-
settings = options
111-
} else {
112-
schema = find
113-
// @ts-expect-error don’t expect replace twice.
114-
settings = replace
115-
}
104+
export function findAndReplace(tree, find, replace, options) {
105+
/** @type {Options | null | undefined} */
106+
let settings
107+
/** @type {FindAndReplaceList | FindAndReplaceSchema} */
108+
let schema
109+
110+
if (typeof find === 'string' || find instanceof RegExp) {
111+
// @ts-expect-error don’t expect options twice.
112+
schema = [[find, replace]]
113+
settings = options
114+
} else {
115+
schema = find
116+
// @ts-expect-error don’t expect replace twice.
117+
settings = replace
118+
}
116119

117-
if (!settings) {
118-
settings = {}
120+
if (!settings) {
121+
settings = {}
122+
}
123+
124+
const ignored = convert(settings.ignore || [])
125+
const pairs = toPairs(schema)
126+
let pairIndex = -1
127+
128+
while (++pairIndex < pairs.length) {
129+
visitParents(tree, 'text', visitor)
130+
}
131+
132+
// @ts-expect-error: To do: remove.
133+
return tree
134+
135+
/** @type {import('unist-util-visit-parents').BuildVisitor<Root, 'text'>} */
136+
function visitor(node, parents) {
137+
let index = -1
138+
/** @type {Parents | undefined} */
139+
let grandparent
140+
141+
while (++index < parents.length) {
142+
const parent = parents[index]
143+
/** @type {Array<Nodes> | undefined} */
144+
const siblings = grandparent ? grandparent.children : undefined
145+
146+
if (
147+
ignored(
148+
parent,
149+
siblings ? siblings.indexOf(parent) : undefined,
150+
grandparent
151+
)
152+
) {
153+
return
119154
}
120155

121-
const ignored = convert(settings.ignore || [])
122-
const pairs = toPairs(schema)
123-
let pairIndex = -1
156+
grandparent = parent
157+
}
158+
159+
if (grandparent) {
160+
return handler(node, parents)
161+
}
162+
}
163+
164+
/**
165+
* Handle a text node which is not in an ignored parent.
166+
*
167+
* @param {Text} node
168+
* Text node.
169+
* @param {Array<Parents>} parents
170+
* Parents.
171+
* @returns {VisitorResult}
172+
* Result.
173+
*/
174+
function handler(node, parents) {
175+
const parent = parents[parents.length - 1]
176+
const find = pairs[pairIndex][0]
177+
const replace = pairs[pairIndex][1]
178+
let start = 0
179+
/** @type {Array<Nodes>} */
180+
const siblings = parent.children
181+
const index = siblings.indexOf(node)
182+
let change = false
183+
/** @type {Array<PhrasingContent>} */
184+
let nodes = []
185+
186+
find.lastIndex = 0
187+
188+
let match = find.exec(node.value)
189+
190+
while (match) {
191+
const position = match.index
192+
/** @type {RegExpMatchObject} */
193+
const matchObject = {
194+
index: match.index,
195+
input: match.input,
196+
stack: [...parents, node]
197+
}
198+
let value = replace(...match, matchObject)
124199

125-
while (++pairIndex < pairs.length) {
126-
visitParents(tree, 'text', visitor)
200+
if (typeof value === 'string') {
201+
value = value.length > 0 ? {type: 'text', value} : undefined
127202
}
128203

129-
// @ts-expect-error: To do: remove.
130-
return tree
131-
132-
/** @type {import('unist-util-visit-parents').BuildVisitor<Root, 'text'>} */
133-
function visitor(node, parents) {
134-
let index = -1
135-
/** @type {Parents | undefined} */
136-
let grandparent
137-
138-
while (++index < parents.length) {
139-
const parent = parents[index]
140-
141-
if (
142-
ignored(
143-
parent,
144-
// @ts-expect-error: TS doesn’t understand but it’s perfect.
145-
grandparent ? grandparent.children.indexOf(parent) : undefined,
146-
grandparent
147-
)
148-
) {
149-
return
150-
}
151-
152-
grandparent = parent
204+
// It wasn’t a match after all.
205+
if (value !== false) {
206+
if (start !== position) {
207+
nodes.push({
208+
type: 'text',
209+
value: node.value.slice(start, position)
210+
})
153211
}
154212

155-
if (grandparent) {
156-
return handler(node, parents)
213+
if (Array.isArray(value)) {
214+
nodes.push(...value)
215+
} else if (value) {
216+
nodes.push(value)
157217
}
158-
}
159218

160-
/**
161-
* Handle a text node which is not in an ignored parent.
162-
*
163-
* @param {Text} node
164-
* Text node.
165-
* @param {Array<Parents>} parents
166-
* Parents.
167-
* @returns {VisitorResult}
168-
* Result.
169-
*/
170-
function handler(node, parents) {
171-
const parent = parents[parents.length - 1]
172-
const find = pairs[pairIndex][0]
173-
const replace = pairs[pairIndex][1]
174-
let start = 0
175-
// @ts-expect-error: TS is wrong, some of these children can be text.
176-
const index = parent.children.indexOf(node)
177-
let change = false
178-
/** @type {Array<PhrasingContent>} */
179-
let nodes = []
180-
181-
find.lastIndex = 0
182-
183-
let match = find.exec(node.value)
184-
185-
while (match) {
186-
const position = match.index
187-
/** @type {RegExpMatchObject} */
188-
const matchObject = {
189-
index: match.index,
190-
input: match.input,
191-
stack: [...parents, node]
192-
}
193-
let value = replace(...match, matchObject)
194-
195-
if (typeof value === 'string') {
196-
value = value.length > 0 ? {type: 'text', value} : undefined
197-
}
198-
199-
// It wasn’t a match after all.
200-
if (value !== false) {
201-
if (start !== position) {
202-
nodes.push({
203-
type: 'text',
204-
value: node.value.slice(start, position)
205-
})
206-
}
207-
208-
if (Array.isArray(value)) {
209-
nodes.push(...value)
210-
} else if (value) {
211-
nodes.push(value)
212-
}
213-
214-
start = position + match[0].length
215-
change = true
216-
}
217-
218-
if (!find.global) {
219-
break
220-
}
221-
222-
match = find.exec(node.value)
223-
}
219+
start = position + match[0].length
220+
change = true
221+
}
224222

225-
if (change) {
226-
if (start < node.value.length) {
227-
nodes.push({type: 'text', value: node.value.slice(start)})
228-
}
223+
if (!find.global) {
224+
break
225+
}
229226

230-
parent.children.splice(index, 1, ...nodes)
231-
} else {
232-
nodes = [node]
233-
}
227+
match = find.exec(node.value)
228+
}
234229

235-
return index + nodes.length
230+
if (change) {
231+
if (start < node.value.length) {
232+
nodes.push({type: 'text', value: node.value.slice(start)})
236233
}
234+
235+
parent.children.splice(index, 1, ...nodes)
236+
} else {
237+
nodes = [node]
237238
}
238-
)
239+
240+
return index + nodes.length
241+
}
242+
}
239243

240244
/**
241245
* Turn a schema into pairs.
242246
*
243-
* @param {FindAndReplaceSchema | FindAndReplaceList} schema
247+
* @param {FindAndReplaceList | FindAndReplaceSchema} schema
244248
* Schema.
245249
* @returns {Pairs}
246250
* Clean pairs.
@@ -297,5 +301,9 @@ function toExpression(find) {
297301
* Function.
298302
*/
299303
function toFunction(replace) {
300-
return typeof replace === 'function' ? replace : () => replace
304+
return typeof replace === 'function'
305+
? replace
306+
: function () {
307+
return replace
308+
}
301309
}

0 commit comments

Comments
 (0)