Skip to content

Commit 9f91522

Browse files
committed
add type and function predicates
Use unist-util-is for testing a node. BREAKING CHANGE: `opts` argument position is changed to better suit the function form of the predicate argument.
1 parent 013a343 commit 9f91522

File tree

5 files changed

+90
-20
lines changed

5 files changed

+90
-20
lines changed

README.md

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,12 +77,15 @@ remove(ast, ast)
7777

7878
## API
7979

80-
### `remove(ast, nodes, [opts])`
80+
### `remove(ast, [opts], predicate)`
8181

8282
- `ast`[Unist] tree.
83-
- `nodes`[Unist] node or array of nodes.
83+
- `predicate` — one of:
84+
- [Unist] node or array of nodes,
85+
- node type (string),
86+
- function invoked with arguments `(node, index?, parent?)`.
8487

85-
Removes `nodes` from `ast`. Returns a modified [Unist] tree.
88+
Iterates over `ast` in preorder traversal and removes all nodes matching `predicate` from `ast`. Returns a modified [Unist] tree.
8689

8790
##### `opts.cascade`
8891

index.js

Lines changed: 20 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,23 @@
11
'use strict';
22

3+
var is = require('unist-util-is');
34

4-
module.exports = function (ast, nodes, opts) {
5-
if (!Array.isArray(nodes)) {
6-
nodes = [nodes];
5+
6+
module.exports = function (ast, opts, predicate) {
7+
if (arguments.length == 2) {
8+
predicate = opts;
9+
opts = {};
710
}
811

9-
opts = opts || {};
12+
if (Array.isArray(predicate)) {
13+
predicate = arrayPredicate(predicate);
14+
}
1015
opts.cascade = opts.cascade || opts.cascade === undefined;
1116

1217
// Check and remove nodes recursively in preorder.
1318
// For each composite node, modify its children array in-place.
14-
return (function preorder (node) {
15-
if (nodes.indexOf(node) >= 0) {
19+
return (function preorder (node, nodeIndex, parent) {
20+
if (is(predicate, node, nodeIndex, parent)) {
1621
return null;
1722
}
1823
if (!node.children) {
@@ -24,7 +29,7 @@ module.exports = function (ast, nodes, opts) {
2429
var length = 0;
2530

2631
for (var index = 0; index < node.children.length; ++index) {
27-
var child = preorder(node.children[index]);
32+
var child = preorder(node.children[index], index, node);
2833

2934
if (child) {
3035
node.children[length++] = child;
@@ -38,5 +43,12 @@ module.exports = function (ast, nodes, opts) {
3843

3944
node.children.length = length;
4045
return node;
41-
}(ast));
46+
}(ast, null, null));
4247
};
48+
49+
50+
function arrayPredicate (nodes) {
51+
return function (node) {
52+
return nodes.indexOf(node) >= 0;
53+
};
54+
}

package.json

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@
2828
"unist",
2929
"util"
3030
],
31-
"dependencies": {},
31+
"dependencies": {
32+
"unist-util-is": "^1.0.0"
33+
},
3234
"devDependencies": {
3335
"tape": "^4.4.0",
3436
"unist-builder": "^1.0.0"

test/opts.js

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,10 @@ test('opts.cascade', function (t) {
1515
u('leaf', 2)
1616
]);
1717

18-
var newAst = remove(ast, [
18+
var newAst = remove(ast, { cascade: true }, [
1919
ast.children[0].children[0],
2020
ast.children[1]
21-
], {
22-
cascade: true
23-
});
21+
]);
2422

2523
t.equal(newAst, null);
2624
t.end();
@@ -37,12 +35,10 @@ test('opts.cascade', function (t) {
3735
var innerNode = ast.children[0];
3836
var grandChildren = ast.children[0].children;
3937

40-
var newAst = remove(ast, [
38+
var newAst = remove(ast, { cascade: false }, [
4139
ast.children[0].children[0],
4240
ast.children[1]
43-
], {
44-
cascade: false
45-
});
41+
]);
4642

4743
t.equal(newAst, ast);
4844
t.deepEqual(ast, u('root', [

test/test.js

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -118,3 +118,60 @@ it('should cascade remove parent nodes', function (t) {
118118
t.end();
119119
});
120120
});
121+
122+
123+
it('should support type tests and predicate functions', function (t) {
124+
t.test(function (t) {
125+
var ast = u('node', [
126+
u('node', [
127+
u('leaf', 1)
128+
]),
129+
u('leaf', 2)
130+
]);
131+
132+
ast = remove(ast, { cascade: false }, 'leaf');
133+
134+
t.deepEqual(ast, u('node', [
135+
u('node', [])
136+
]));
137+
t.end();
138+
});
139+
140+
t.test(function (t) {
141+
var ast = u('node', [
142+
u('node', [
143+
u('leaf', 1)
144+
]),
145+
u('leaf', 2)
146+
]);
147+
148+
ast = remove(ast, { cascade: false }, function (node) {
149+
return node.value == 1;
150+
});
151+
152+
t.deepEqual(ast, u('node', [
153+
u('node', []),
154+
u('leaf', 2)
155+
]));
156+
t.end();
157+
});
158+
159+
t.test(function (t) {
160+
var ast = u('node', [
161+
u('node', [
162+
u('leaf', 1)
163+
]),
164+
u('leaf', 2)
165+
]);
166+
167+
ast = remove(ast, { cascade: false }, function (node, index, parent) {
168+
return index == 0 && parent.children.length == 1;
169+
});
170+
171+
t.deepEqual(ast, u('node', [
172+
u('node', []),
173+
u('leaf', 2)
174+
]));
175+
t.end();
176+
});
177+
});

0 commit comments

Comments
 (0)