blob: c72635924f86d16d24695a88d345df0882c2430f [file] [log] [blame]
'use strict'
module.exports = visitParents
var convert = require('unist-util-is/convert')
var CONTINUE = true
var SKIP = 'skip'
var EXIT = false
visitParents.CONTINUE = CONTINUE
visitParents.SKIP = SKIP
visitParents.EXIT = EXIT
function visitParents(tree, test, visitor, reverse) {
var is
if (typeof test === 'function' && typeof visitor !== 'function') {
reverse = visitor
visitor = test
test = null
}
is = convert(test)
one(tree, null, [])
// Visit a single node.
function one(node, index, parents) {
var result = []
var subresult
if (!test || is(node, index, parents[parents.length - 1] || null)) {
result = toResult(visitor(node, parents))
if (result[0] === EXIT) {
return result
}
}
if (node.children && result[0] !== SKIP) {
subresult = toResult(all(node.children, parents.concat(node)))
return subresult[0] === EXIT ? subresult : result
}
return result
}
// Visit children in `parent`.
function all(children, parents) {
var min = -1
var step = reverse ? -1 : 1
var index = (reverse ? children.length : min) + step
var result
while (index > min && index < children.length) {
result = one(children[index], index, parents)
if (result[0] === EXIT) {
return result
}
index = typeof result[1] === 'number' ? result[1] : index + step
}
}
}
function toResult(value) {
if (value !== null && typeof value === 'object' && 'length' in value) {
return value
}
if (typeof value === 'number') {
return [CONTINUE, value]
}
return [value]
}