UNPKG

2.42 kBJavaScriptView Raw
1/**
2 * @author Titus Wormer
3 * @copyright 2015 Titus Wormer. All rights reserved.
4 * @module unist:util:visit
5 * @fileoverview Utility to recursively walk over unist nodes.
6 */
7
8'use strict';
9
10/**
11 * Walk forwards.
12 *
13 * @param {Array.<*>} values - Things to iterate over,
14 * forwards.
15 * @param {function(*, number): boolean} callback - Function
16 * to invoke.
17 * @return {boolean} - False if iteration stopped.
18 */
19function forwards(values, callback) {
20 var index = -1;
21 var length = values.length;
22
23 while (++index < length) {
24 if (callback(values[index], index) === false) {
25 return false;
26 }
27 }
28
29 return true;
30}
31
32/**
33 * Walk backwards.
34 *
35 * @param {Array.<*>} values - Things to iterate over,
36 * backwards.
37 * @param {function(*, number): boolean} callback - Function
38 * to invoke.
39 * @return {boolean} - False if iteration stopped.
40 */
41function backwards(values, callback) {
42 var index = values.length;
43 var length = -1;
44
45 while (--index > length) {
46 if (callback(values[index], index) === false) {
47 return false;
48 }
49 }
50
51 return true;
52}
53
54/**
55 * Visit.
56 *
57 * @param {Node} tree - Root node
58 * @param {string} [type] - Node type.
59 * @param {function(node): boolean?} callback - Invoked
60 * with each found node. Can return `false` to stop.
61 * @param {boolean} [reverse] - By default, `visit` will
62 * walk forwards, when `reverse` is `true`, `visit`
63 * walks backwards.
64 */
65function visit(tree, type, callback, reverse) {
66 var iterate;
67 var one;
68 var all;
69
70 if (typeof type === 'function') {
71 reverse = callback;
72 callback = type;
73 type = null;
74 }
75
76 iterate = reverse ? backwards : forwards;
77
78 /**
79 * Visit `children` in `parent`.
80 */
81 all = function (children, parent) {
82 return iterate(children, function (child, index) {
83 return child && one(child, index, parent);
84 });
85 };
86
87 /**
88 * Visit a single node.
89 */
90 one = function (node, index, parent) {
91 var result;
92
93 index = index || (parent ? 0 : null);
94
95 if (!type || node.type === type) {
96 result = callback(node, index, parent || null);
97 }
98
99 if (node.children && result !== false) {
100 return all(node.children, node);
101 }
102
103 return result;
104 };
105
106 one(tree);
107}
108
109/*
110 * Expose.
111 */
112
113module.exports = visit;