| '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] |
| } |