All checks were successful
Publish To Prod / deploy_and_publish (push) Successful in 35s
181 lines
3.6 KiB
JavaScript
181 lines
3.6 KiB
JavaScript
'use strict'
|
|
|
|
module.exports = findAndReplace
|
|
|
|
var visit = require('unist-util-visit-parents')
|
|
var convert = require('unist-util-is/convert')
|
|
var escape = require('escape-string-regexp')
|
|
|
|
var splice = [].splice
|
|
|
|
function findAndReplace(tree, find, replace, options) {
|
|
var settings
|
|
var schema
|
|
|
|
if (typeof find === 'string' || (find && typeof find.exec === 'function')) {
|
|
schema = [[find, replace]]
|
|
} else {
|
|
schema = find
|
|
options = replace
|
|
}
|
|
|
|
settings = options || {}
|
|
|
|
search(tree, settings, handlerFactory(toPairs(schema)))
|
|
|
|
return tree
|
|
|
|
function handlerFactory(pairs) {
|
|
var pair = pairs[0]
|
|
|
|
return handler
|
|
|
|
function handler(node, parent) {
|
|
var find = pair[0]
|
|
var replace = pair[1]
|
|
var nodes = []
|
|
var start = 0
|
|
var index = parent.children.indexOf(node)
|
|
var position
|
|
var match
|
|
var subhandler
|
|
var value
|
|
|
|
find.lastIndex = 0
|
|
|
|
match = find.exec(node.value)
|
|
|
|
while (match) {
|
|
position = match.index
|
|
value = replace.apply(
|
|
null,
|
|
[].concat(match, {index: match.index, input: match.input})
|
|
)
|
|
|
|
if (value !== false) {
|
|
if (start !== position) {
|
|
nodes.push({type: 'text', value: node.value.slice(start, position)})
|
|
}
|
|
|
|
if (typeof value === 'string' && value.length > 0) {
|
|
value = {type: 'text', value: value}
|
|
}
|
|
|
|
if (value) {
|
|
nodes = [].concat(nodes, value)
|
|
}
|
|
|
|
start = position + match[0].length
|
|
}
|
|
|
|
if (!find.global) {
|
|
break
|
|
}
|
|
|
|
match = find.exec(node.value)
|
|
}
|
|
|
|
if (position === undefined) {
|
|
nodes = [node]
|
|
index--
|
|
} else {
|
|
if (start < node.value.length) {
|
|
nodes.push({type: 'text', value: node.value.slice(start)})
|
|
}
|
|
|
|
nodes.unshift(index, 1)
|
|
splice.apply(parent.children, nodes)
|
|
}
|
|
|
|
if (pairs.length > 1) {
|
|
subhandler = handlerFactory(pairs.slice(1))
|
|
position = -1
|
|
|
|
while (++position < nodes.length) {
|
|
node = nodes[position]
|
|
|
|
if (node.type === 'text') {
|
|
subhandler(node, parent)
|
|
} else {
|
|
search(node, settings, subhandler)
|
|
}
|
|
}
|
|
}
|
|
|
|
return index + nodes.length + 1
|
|
}
|
|
}
|
|
}
|
|
|
|
function search(tree, settings, handler) {
|
|
var ignored = convert(settings.ignore || [])
|
|
var result = []
|
|
|
|
visit(tree, 'text', visitor)
|
|
|
|
return result
|
|
|
|
function visitor(node, parents) {
|
|
var index = -1
|
|
var parent
|
|
var grandparent
|
|
|
|
while (++index < parents.length) {
|
|
parent = parents[index]
|
|
|
|
if (
|
|
ignored(
|
|
parent,
|
|
grandparent ? grandparent.children.indexOf(parent) : undefined,
|
|
grandparent
|
|
)
|
|
) {
|
|
return
|
|
}
|
|
|
|
grandparent = parent
|
|
}
|
|
|
|
return handler(node, grandparent)
|
|
}
|
|
}
|
|
|
|
function toPairs(schema) {
|
|
var result = []
|
|
var key
|
|
var index
|
|
|
|
if (typeof schema !== 'object') {
|
|
throw new Error('Expected array or object as schema')
|
|
}
|
|
|
|
if ('length' in schema) {
|
|
index = -1
|
|
|
|
while (++index < schema.length) {
|
|
result.push([
|
|
toExpression(schema[index][0]),
|
|
toFunction(schema[index][1])
|
|
])
|
|
}
|
|
} else {
|
|
for (key in schema) {
|
|
result.push([toExpression(key), toFunction(schema[key])])
|
|
}
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
function toExpression(find) {
|
|
return typeof find === 'string' ? new RegExp(escape(find), 'g') : find
|
|
}
|
|
|
|
function toFunction(replace) {
|
|
return typeof replace === 'function' ? replace : returner
|
|
|
|
function returner() {
|
|
return replace
|
|
}
|
|
}
|