Skip to content

Commit 632c35c

Browse files
committed
Fix bug causing missed finds, multiple replaces
1 parent 83279aa commit 632c35c

File tree

1 file changed

+71
-113
lines changed

1 file changed

+71
-113
lines changed

Diff for: index.js

+71-113
Original file line numberDiff line numberDiff line change
@@ -26,13 +26,6 @@
2626
* @typedef {Array.<Pair>} Pairs
2727
*/
2828

29-
/**
30-
* @callback Handler
31-
* @param {Text} node
32-
* @param {Parent} parent
33-
* @returns {VisitorResult}
34-
*/
35-
3629
/**
3730
* @callback ReplaceFunction
3831
* @param {...unknown} parameters
@@ -73,115 +66,15 @@ export function findAndReplace(tree, find, replace, options) {
7366
settings = {}
7467
}
7568

76-
search(tree, settings, handlerFactory(toPairs(schema)))
77-
78-
return tree
79-
80-
/**
81-
* @param {Pairs} pairs
82-
* @returns {Handler}
83-
*/
84-
function handlerFactory(pairs) {
85-
var pair = pairs[0]
86-
87-
return handler
88-
89-
/**
90-
* @type {Handler}
91-
*/
92-
function handler(node, parent) {
93-
var find = pair[0]
94-
var replace = pair[1]
95-
/** @type {Array.<Content>} */
96-
var nodes = []
97-
var start = 0
98-
var index = parent.children.indexOf(node)
99-
/** @type {number} */
100-
var position
101-
/** @type {RegExpMatchArray} */
102-
var match
103-
/** @type {Handler} */
104-
var subhandler
105-
/** @type {Content} */
106-
var child
107-
/** @type {Array.<Content>|Content|string|false|undefined|null} */
108-
var value
109-
110-
find.lastIndex = 0
111-
112-
match = find.exec(node.value)
113-
114-
while (match) {
115-
position = match.index
116-
// @ts-expect-error this is perfectly fine, typescript.
117-
value = replace(...match, {index: match.index, input: match.input})
118-
119-
if (typeof value === 'string' && value.length > 0) {
120-
value = {type: 'text', value}
121-
}
122-
123-
if (value !== false) {
124-
if (start !== position) {
125-
nodes.push({type: 'text', value: node.value.slice(start, position)})
126-
}
127-
128-
if (value) {
129-
nodes = [].concat(nodes, value)
130-
}
131-
132-
start = position + match[0].length
133-
}
134-
135-
if (!find.global) {
136-
break
137-
}
138-
139-
match = find.exec(node.value)
140-
}
141-
142-
if (position === undefined) {
143-
nodes = [node]
144-
index--
145-
} else {
146-
if (start < node.value.length) {
147-
nodes.push({type: 'text', value: node.value.slice(start)})
148-
}
149-
150-
// @ts-expect-error This is a bug!
151-
nodes = [index, 1, ...nodes]
152-
;[].splice.call(parent.children, ...nodes)
153-
}
154-
155-
if (pairs.length > 1) {
156-
subhandler = handlerFactory(pairs.slice(1))
157-
position = -1
158-
159-
while (++position < nodes.length) {
160-
child = nodes[position]
161-
162-
if (child.type === 'text') {
163-
subhandler(child, parent)
164-
} else {
165-
search(child, settings, subhandler)
166-
}
167-
}
168-
}
69+
var ignored = convertElement(settings.ignore || defaultIgnore)
70+
var pairs = toPairs(schema)
71+
var pairIndex = -1
16972

170-
return index + nodes.length + 1
171-
}
73+
while (++pairIndex < pairs.length) {
74+
visitParents(tree, 'text', visitor)
17275
}
173-
}
174-
175-
/**
176-
* @param {Node} tree
177-
* @param {Options} options
178-
* @param {Handler} handler
179-
* @returns {void}
180-
*/
181-
function search(tree, options, handler) {
182-
var ignored = convertElement(options.ignore || defaultIgnore)
18376

184-
visitParents(tree, 'text', visitor)
77+
return tree
18578

18679
/** @type {import('unist-util-visit-parents').Visitor<Text>} */
18780
function visitor(node, parents) {
@@ -211,6 +104,71 @@ function search(tree, options, handler) {
211104

212105
return handler(node, grandparent)
213106
}
107+
108+
/**
109+
* @param {Text} node
110+
* @param {Parent} parent
111+
* @returns {VisitorResult}
112+
*/
113+
function handler(node, parent) {
114+
var find = pairs[pairIndex][0]
115+
var replace = pairs[pairIndex][1]
116+
/** @type {Array.<Content>} */
117+
var nodes = []
118+
var start = 0
119+
var index = parent.children.indexOf(node)
120+
/** @type {number} */
121+
var position
122+
/** @type {RegExpMatchArray} */
123+
var match
124+
/** @type {Array.<Content>|Content|string|false|undefined|null} */
125+
var value
126+
127+
find.lastIndex = 0
128+
129+
match = find.exec(node.value)
130+
131+
while (match) {
132+
position = match.index
133+
// @ts-expect-error this is perfectly fine, typescript.
134+
value = replace(...match, {index: match.index, input: match.input})
135+
136+
if (typeof value === 'string' && value.length > 0) {
137+
value = {type: 'text', value}
138+
}
139+
140+
if (value !== false) {
141+
if (start !== position) {
142+
nodes.push({type: 'text', value: node.value.slice(start, position)})
143+
}
144+
145+
if (value) {
146+
nodes = [].concat(nodes, value)
147+
}
148+
149+
start = position + match[0].length
150+
}
151+
152+
if (!find.global) {
153+
break
154+
}
155+
156+
match = find.exec(node.value)
157+
}
158+
159+
if (position === undefined) {
160+
nodes = [node]
161+
index--
162+
} else {
163+
if (start < node.value.length) {
164+
nodes.push({type: 'text', value: node.value.slice(start)})
165+
}
166+
167+
parent.children.splice(index, 1, ...nodes)
168+
}
169+
170+
return index + nodes.length + 1
171+
}
214172
}
215173

216174
/**

0 commit comments

Comments
 (0)