|
| 1 | +const when = require('when') |
1 | 2 | const UtilError = require('./error') |
2 | 3 |
|
3 | 4 | exports.modifyNodes = function modifyNodes (tree, criteria, transform) { |
4 | | - return tree.reduce((m, node) => { |
5 | | - // bottom-up recurse |
6 | | - if (node.type === 'tag' && node.content) { |
7 | | - node.content = modifyNodes(node.content, criteria, transform) |
8 | | - } |
9 | | - |
10 | | - // if it doesn't match the criteria, move on |
11 | | - if (!criteria(node)) { m.push(node); return m } |
| 5 | + return when.reduce(tree, (m, node) => { |
| 6 | + // this will resolve immediately unless the node has children and needs to |
| 7 | + // recurse, in which case it will wait for the recursion to finish before |
| 8 | + // resolving |
| 9 | + let maybeRecurse = when.resolve() |
12 | 10 |
|
13 | | - // if it does, run the user transform |
14 | | - const output = transform(node) |
15 | | - |
16 | | - // push the output into the tree if it's a valid type |
17 | | - if (Array.isArray(output)) { |
18 | | - m = m.concat(output) |
19 | | - } else if (typeof output === 'object') { |
20 | | - m.push(output) |
21 | | - } else if (!output) { |
22 | | - // no node added |
23 | | - } else { |
24 | | - throw new UtilError('invalid replacement node', output) |
| 11 | + // bottom-up recurse if there is a tag with contents |
| 12 | + if (node.type === 'tag' && node.content) { |
| 13 | + maybeRecurse = modifyNodes(node.content, criteria, transform) |
| 14 | + .tap((content) => { node.content = content }) |
25 | 15 | } |
26 | 16 |
|
27 | | - return m |
| 17 | + // after the recurse has finished if applicable, test the node for the user |
| 18 | + // criteria and modify if applicable |
| 19 | + return maybeRecurse.then(() => { |
| 20 | + // run the criteria function (can be a promise) |
| 21 | + return when.resolve(criteria(node)).then((processNode) => { |
| 22 | + // if it doesn't match the criteria, move on |
| 23 | + if (!processNode) { m.push(node); return m } |
| 24 | + |
| 25 | + // if it does, run the user transform (can be a promise) |
| 26 | + return when.resolve(transform(node)).then((output) => { |
| 27 | + // push the output into the tree if it's a valid type |
| 28 | + if (Array.isArray(output)) { |
| 29 | + m.push(...output) |
| 30 | + } else if (typeof output === 'object') { |
| 31 | + m.push(output) |
| 32 | + } else if (!output) { |
| 33 | + // no node added |
| 34 | + } else { |
| 35 | + throw new UtilError('invalid replacement node', output) |
| 36 | + } |
| 37 | + return m |
| 38 | + }) |
| 39 | + }) |
| 40 | + }) |
28 | 41 | }, []) |
29 | 42 | } |
30 | 43 |
|
|
0 commit comments