1 | const Node = require('./node');
|
---|
2 |
|
---|
3 | class Container extends Node {
|
---|
4 | walk(callback) {
|
---|
5 | return this.each((child, i) => {
|
---|
6 | let result = callback(child, i);
|
---|
7 | if (result !== false && child.walk) {
|
---|
8 | result = child.walk(callback);
|
---|
9 | }
|
---|
10 | return result;
|
---|
11 | });
|
---|
12 | }
|
---|
13 |
|
---|
14 | walkType(type, callback) {
|
---|
15 | if (!type || !callback) {
|
---|
16 | throw new Error('Parameters {type} and {callback} are required.');
|
---|
17 | }
|
---|
18 |
|
---|
19 | // allow users to pass a constructor, or node type string; eg. Word.
|
---|
20 | const isTypeCallable = typeof type === 'function';
|
---|
21 |
|
---|
22 | return this.walk((node, index) => {
|
---|
23 | if ((isTypeCallable && node instanceof type) || (!isTypeCallable && node.type === type)) {
|
---|
24 | return callback.call(this, node, index);
|
---|
25 | }
|
---|
26 | });
|
---|
27 | }
|
---|
28 | }
|
---|
29 |
|
---|
30 | Container.registerWalker = (constructor) => {
|
---|
31 | let walkerName = `walk${constructor.name}`;
|
---|
32 |
|
---|
33 | // plural sugar
|
---|
34 | if (walkerName.lastIndexOf('s') !== walkerName.length - 1) {
|
---|
35 | walkerName += 's';
|
---|
36 | }
|
---|
37 |
|
---|
38 | if (Container.prototype[walkerName]) {
|
---|
39 | return;
|
---|
40 | }
|
---|
41 |
|
---|
42 | // we need access to `this` so we can't use an arrow function
|
---|
43 | Container.prototype[walkerName] = function(callback) {
|
---|
44 | return this.walkType(constructor, callback);
|
---|
45 | };
|
---|
46 | };
|
---|
47 |
|
---|
48 | module.exports = Container;
|
---|