Skip to content

Commit 6599827

Browse files
committed
Add support for returning false to not replace
* Add support for returning `false` to not replace * Fix to not recurse into replacements * Refactor to improve bundle size
1 parent 09271c3 commit 6599827

File tree

3 files changed

+54
-53
lines changed

3 files changed

+54
-53
lines changed

Diff for: index.js

+44-49
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@ var escape = require('escape-string-regexp')
66

77
var defaultIgnore = ['title', 'script', 'style', 'svg', 'math']
88

9+
var splice = [].splice
10+
911
module.exports = findAndReplace
1012

1113
findAndReplace.ignore = defaultIgnore
@@ -36,82 +38,78 @@ function findAndReplace(tree, find, replace, options) {
3638
return handler
3739

3840
function handler(node, parent) {
39-
var siblings = parent.children
40-
var pos = siblings.indexOf(node)
41-
var value = node.value
4241
var find = pair[0]
4342
var replace = pair[1]
44-
var lastIndex = 0
4543
var nodes = []
46-
var subvalue
47-
var index
48-
var length
44+
var start = 0
45+
var index = parent.children.indexOf(node)
46+
var position
4947
var match
5048
var subhandler
49+
var value
5150

5251
find.lastIndex = 0
5352

54-
match = find.exec(value)
53+
match = find.exec(node.value)
5554

5655
while (match) {
57-
index = match.index
58-
subvalue = value.slice(lastIndex, index)
56+
position = match.index
57+
value = replace.apply(
58+
null,
59+
[].concat(match, {index: match.index, input: match.input})
60+
)
5961

60-
if (subvalue) {
61-
nodes.push({type: 'text', value: subvalue})
62-
}
62+
if (value !== false) {
63+
if (start !== position) {
64+
nodes.push({type: 'text', value: node.value.slice(start, position)})
65+
}
6366

64-
subvalue = replace.apply(null, match)
67+
if (typeof value === 'string' && value.length > 0) {
68+
value = {type: 'text', value: value}
69+
}
6570

66-
if (subvalue) {
67-
if (typeof subvalue === 'string') {
68-
subvalue = {type: 'text', value: subvalue}
71+
if (value) {
72+
nodes.push(value)
6973
}
7074

71-
nodes.push(subvalue)
75+
start = position + match[0].length
7276
}
7377

74-
lastIndex = index + match[0].length
75-
7678
if (!find.global) {
7779
break
7880
}
7981

80-
match = find.exec(value)
82+
match = find.exec(node.value)
8183
}
8284

83-
if (index === undefined) {
85+
if (position === undefined) {
8486
nodes = [node]
87+
index--
8588
} else {
86-
subvalue = value.slice(lastIndex)
87-
88-
if (subvalue) {
89-
nodes.push({type: 'text', value: subvalue})
89+
if (start < node.value.length) {
90+
nodes.push({type: 'text', value: node.value.slice(start)})
9091
}
9192

92-
parent.children = siblings
93-
.slice(0, pos)
94-
.concat(nodes)
95-
.concat(siblings.slice(pos + 1))
96-
}
97-
98-
if (pairs.length <= 1) {
99-
return
93+
nodes.unshift(index, 1)
94+
splice.apply(parent.children, nodes)
10095
}
10196

102-
length = nodes.length
103-
index = -1
104-
subhandler = handlerFactory(pairs.slice(1))
97+
if (pairs.length > 1) {
98+
subhandler = handlerFactory(pairs.slice(1))
99+
position = -1
105100

106-
while (++index < length) {
107-
node = nodes[index]
101+
while (++position < nodes.length) {
102+
node = nodes[position]
108103

109-
if (node.type === 'text') {
110-
subhandler(node, parent)
111-
} else {
112-
search(node, settings, subhandler)
104+
if (node.type === 'text') {
105+
subhandler(node, parent)
106+
} else {
107+
search(node, settings, subhandler)
108+
}
113109
}
114110
}
111+
112+
return index + nodes.length + 1
115113
}
116114
}
117115
}
@@ -125,12 +123,11 @@ function search(tree, options, handler) {
125123
return result
126124

127125
function visitor(node, parents) {
128-
var length = parents.length
129126
var index = -1
130127
var parent
131128
var grandparent
132129

133-
while (++index < length) {
130+
while (++index < parents.length) {
134131
parent = parents[index]
135132

136133
if (
@@ -146,25 +143,23 @@ function search(tree, options, handler) {
146143
grandparent = parent
147144
}
148145

149-
handler(node, grandparent)
146+
return handler(node, grandparent)
150147
}
151148
}
152149

153150
function toPairs(schema) {
154151
var result = []
155152
var key
156-
var length
157153
var index
158154

159155
if (typeof schema !== 'object') {
160156
throw new Error('Expected array or object as schema')
161157
}
162158

163159
if ('length' in schema) {
164-
length = schema.length
165160
index = -1
166161

167-
while (++index < length) {
162+
while (++index < schema.length) {
168163
result.push([
169164
toExpression(schema[index][0]),
170165
toFunction(schema[index][1])

Diff for: readme.md

+4-4
Original file line numberDiff line numberDiff line change
@@ -91,11 +91,11 @@ Partial matches are not supported.
9191
* `replace` (`string` or `Function`)
9292
— Value to insert.
9393
When `string`, turned into a [`Text`][text] node.
94-
When `Function`, invoked with the results of calling `RegExp.exec` as
95-
arguments, in which case it can return a [`Node`][node] or a `string`, which
96-
is in the latter case wrapped in a [`Text`][text] node
94+
When `Function`, called with the results of calling `RegExp.exec` as
95+
arguments, in which case it can return a [`Node`][node] or a `string` (which
96+
is wrapped in a [`Text`][text] node), or `false` to not replace
9797
* `search` (`Object` or `Array`)
98-
— Perform multiple find-and-replace’s.
98+
— Perform multiple find-and-replaces.
9999
When `Array`, each entry is a tuple (`Array`) of a `find` (at `0`) and
100100
`replace` (at `1`).
101101
When `Object`, each key is a `find` (in string form) and each value is a

Diff for: test.js

+6
Original file line numberDiff line numberDiff line change
@@ -166,6 +166,12 @@ test('findAndReplace', function (t) {
166166
'should ignore from options'
167167
)
168168

169+
t.deepEqual(
170+
findAndReplace(create(), 'emphasis', () => false),
171+
create(),
172+
'should not replace when returning `false`'
173+
)
174+
169175
t.deepEqual(
170176
findAndReplace(h('p', 'Some emphasis, importance, and code.'), {
171177
importance: function (match) {

0 commit comments

Comments
 (0)