Skip to content

Commit e61a88e

Browse files
authored
Merge pull request #1 from reshape/promise
modifyNodes can now work with promises
2 parents 40e6225 + f7574d8 commit e61a88e

File tree

4 files changed

+56
-21
lines changed

4 files changed

+56
-21
lines changed

README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ Output:
108108
<p>after</p>
109109
```
110110

111+
You can also return a promise from either function and it will work fine.
112+
111113
#### `validateNode(node)`
112114

113115
Given a single reshape AST node, checks it for formatting errors. Example:

lib/index.js

Lines changed: 34 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,43 @@
1+
const when = require('when')
12
const UtilError = require('./error')
23

34
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()
1210

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 })
2515
}
2616

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+
})
2841
}, [])
2942
}
3043

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,8 @@
2727
"coveralls": "nyc report --reporter=text-lcov | coveralls",
2828
"pretest": "standard | snazzy",
2929
"test": "nyc ava"
30+
},
31+
"dependencies": {
32+
"when": "^3.7.7"
3033
}
3134
}

test/index.js

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,23 @@ test('modifyNodes errors when invalid return node provided', (t) => {
4242
.catch((err) => t.truthy(err.toString() === 'Error: invalid replacement node\nFrom: plugin-util\n\nNode: "foo"'))
4343
})
4444

45+
test('modifyNodes works with promises', (t) => {
46+
function plugin (tree) {
47+
return util.modifyNodes(tree, (n) => {
48+
return new Promise((resolve) => resolve(n.name === 'p'))
49+
}, (node) => {
50+
return new Promise((resolve) => {
51+
node.content[0].content = 'replaced!'
52+
resolve(node)
53+
})
54+
})
55+
}
56+
57+
return reshape({ plugins: plugin })
58+
.process(readFileSync(path.join(fixtures, 'basic.html'), 'utf8'))
59+
.then((res) => t.truthy(res.output() === '<div class="wow">\n <p>replaced!</p>\n</div>\n'))
60+
})
61+
4562
test('validateNode', (t) => {
4663
util.validateNode({
4764
type: 'tag',

0 commit comments

Comments
 (0)