'use strict' module.exports = visitParents var convert = require('unist-util-is/convert') var color = require('./color') 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 step var is if (typeof test === 'function' && typeof visitor !== 'function') { reverse = visitor visitor = test test = null } is = convert(test) step = reverse ? -1 : 1 factory(tree, null, [])() function factory(node, index, parents) { var value = typeof node === 'object' && node !== null ? node : {} var name if (typeof value.type === 'string') { name = typeof value.tagName === 'string' ? value.tagName : typeof value.name === 'string' ? value.name : undefined visit.displayName = 'node (' + color(value.type + (name ? '<' + name + '>' : '')) + ')' } return visit function visit() { var grandparents = parents.concat(node) var result = [] var subresult var offset 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) { offset = (reverse ? node.children.length : -1) + step while (offset > -1 && offset < node.children.length) { subresult = factory(node.children[offset], offset, grandparents)() if (subresult[0] === EXIT) { return subresult } offset = typeof subresult[1] === 'number' ? subresult[1] : offset + step } } return result } } } function toResult(value) { if (value !== null && typeof value === 'object' && 'length' in value) { return value } if (typeof value === 'number') { return [CONTINUE, value] } return [value] }