Skip to content

Commit df39f22

Browse files
committed
Refactor to externalise assertions
1 parent 980e34b commit df39f22

7 files changed

+157
-124
lines changed

component.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"util",
1717
"utility"
1818
],
19+
"dependencies": {
20+
"wooorm/unist-util-is": "^1.0.0"
21+
},
1922
"repository": "wooorm/unist-util-find-before",
2023
"scripts": [
2124
"index.js"

index.js

Lines changed: 5 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -10,50 +10,11 @@
1010

1111
/* eslint-env commonjs */
1212

13-
/**
14-
* Test.
15-
*
16-
* @typedef {Function} findBefore~test
17-
* @param {Node} node - Node to test.
18-
* @param {number} index - Position of `node` in `parent`.
19-
* @param {Node} parent - Parent of `node`.
20-
* @return {boolean?} - Whether this iteration passes.
21-
*/
22-
23-
/**
24-
* Utility to return true for the first node.
25-
*
26-
* @type {findBefore~test}
27-
*/
28-
function first() {
29-
return true;
30-
}
31-
32-
/**
33-
* Utility to convert a string into a function which checks
34-
* a given node’s type for said string.
35-
*
36-
* @param {string} test - Node type to test.
37-
* @return {findBefore~test} - Tester.
13+
/*
14+
* Dependencies.
3815
*/
39-
function typeFactory(test) {
40-
return function (node) {
41-
return Boolean(node && node.type === test);
42-
}
43-
}
4416

45-
/**
46-
* Utility to convert a node into a function which checks
47-
* a given node for strict equality.
48-
*
49-
* @param {Node} test - Node to test.
50-
* @return {findBefore~test} - Tester.
51-
*/
52-
function nodeFactory(test) {
53-
return function (node) {
54-
return Boolean(node && node === test);
55-
}
56-
}
17+
var is = require('unist-util-is');
5718

5819
/**
5920
* Find a node before `index` in `parent` which passes
@@ -62,7 +23,7 @@ function nodeFactory(test) {
6223
* @param {Node} parent - Parent to search in.
6324
* @param {number|Node} index - (Position of) node to
6425
* search before.
65-
* @param {string|Node|findBefore~test} test - Tester.
26+
* @param {*} test - See `wooorm/unist-util-is`.
6627
* @return {Node?} - A child node of `parent` which passes
6728
* `test`.
6829
*/
@@ -89,20 +50,10 @@ function findBefore(parent, index, test) {
8950
index = children.length;
9051
}
9152

92-
if (typeof test === 'string') {
93-
test = typeFactory(test);
94-
} else if (test && test.type) {
95-
test = nodeFactory(test);
96-
} else if (test === null || test === undefined) {
97-
test = first;
98-
} else if (typeof test !== 'function') {
99-
throw new Error('Expected function, string, or node as test');
100-
}
101-
10253
while (index--) {
10354
child = children[index];
10455

105-
if (test(child, index, parent)) {
56+
if (is(test, child, index, parent)) {
10657
return child;
10758
}
10859
}

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@
1616
"util",
1717
"utility"
1818
],
19+
"dependencies": {
20+
"unist-util-is": "^1.0.0"
21+
},
1922
"repository": {
2023
"type": "git",
2124
"url": "https://github.com/wooorm/unist-util-find-before.git"

readme.md

Lines changed: 2 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -75,31 +75,11 @@ given).
7575

7676
* `index` (`number`) — Position of child to search before;
7777

78-
* `test` ([`Function`](#function-testnode-index-parent), `string`, or
79-
`Node`, optional)
80-
— Invoked for each preceding child of `parent` before `node` or `position`.
81-
When `test` returns truthy for the first time on a `child`, that `child` is
82-
returned.
83-
84-
Passing a `string` is equal to passing
85-
`function (node) {return node.type === test}`.
86-
87-
Passing a `node` is equal to passing
88-
`function (node) {return node === test}`, useful when checking if `test`
89-
comes before `index` or `node` in `parent`.
78+
* `test` (`Function`, `string`, or `Node`; optional)
79+
— See [`is()`](https://github.com/wooorm/unist-util-is#istest-node-index-parent-context).
9080

9181
**Returns**: `node?`, when found. Child node of `parent` which passes `test`.
9282

93-
### function test(node, index, parent)
94-
95-
**Parameters**:
96-
97-
* `node` (`Node`) — Node to test;
98-
* `index` (`number`) — Position of `node` in `parent`.
99-
* `parent` (`Node`) — Parent of `node`.
100-
101-
**Returns**: `boolean?`, whether this iteration passes.
102-
10383
## License
10484

10585
[MIT](LICENSE) © [Titus Wormer](http://wooorm.com)

test.js

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -80,15 +80,19 @@ describe('unist-util-find-before', function () {
8080
assert.throws(function () {
8181
findBefore({
8282
'type': 'foo',
83-
'children': []
84-
}, 0, false);
83+
'children': [{
84+
'type': 'bar'
85+
}]
86+
}, 1, false);
8587
}, /Expected function, string, or node as test/);
8688

8789
assert.throws(function () {
8890
findBefore({
8991
'type': 'foo',
90-
'children': []
91-
}, 0, true);
92+
'children': [{
93+
'type': 'bar'
94+
}]
95+
}, 1, true);
9296
}, /Expected function, string, or node as test/);
9397
});
9498

unist-util-find-before.js

Lines changed: 135 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -11,20 +11,90 @@
1111

1212
/* eslint-env commonjs */
1313

14+
/*
15+
* Dependencies.
16+
*/
17+
18+
var is = require('unist-util-is');
19+
20+
/**
21+
* Find a node before `index` in `parent` which passes
22+
* `test`.
23+
*
24+
* @param {Node} parent - Parent to search in.
25+
* @param {number|Node} index - (Position of) node to
26+
* search before.
27+
* @param {*} test - See `wooorm/unist-util-is`.
28+
* @return {Node?} - A child node of `parent` which passes
29+
* `test`.
30+
*/
31+
function findBefore(parent, index, test) {
32+
var children;
33+
var child;
34+
35+
if (!parent || !parent.type || !parent.children) {
36+
throw new Error('Expected parent node');
37+
}
38+
39+
children = parent.children;
40+
41+
if (index && index.type) {
42+
index = children.indexOf(index);
43+
}
44+
45+
if (isNaN(index) || index < 0 || index === Infinity) {
46+
throw new Error('Expected positive finite index or child node');
47+
}
48+
49+
/* Performance. */
50+
if (index > children.length) {
51+
index = children.length;
52+
}
53+
54+
while (index--) {
55+
child = children[index];
56+
57+
if (is(test, child, index, parent)) {
58+
return child;
59+
}
60+
}
61+
62+
return null;
63+
}
64+
65+
/*
66+
* Expose.
67+
*/
68+
69+
module.exports = findBefore;
70+
71+
},{"unist-util-is":2}],2:[function(require,module,exports){
72+
/**
73+
* @author Titus Wormer
74+
* @copyright 2015 Titus Wormer
75+
* @license MIT
76+
* @module unist:util:is
77+
* @fileoverview Utility to check if a node passes a test.
78+
*/
79+
80+
'use strict';
81+
82+
/* eslint-env commonjs */
83+
1484
/**
1585
* Test.
1686
*
17-
* @typedef {Function} findBefore~test
87+
* @typedef {Function} is~test
1888
* @param {Node} node - Node to test.
1989
* @param {number} index - Position of `node` in `parent`.
2090
* @param {Node} parent - Parent of `node`.
2191
* @return {boolean?} - Whether this iteration passes.
2292
*/
2393

2494
/**
25-
* Utility to return true for the first node.
95+
* Utility to return true.
2696
*
27-
* @type {findBefore~test}
97+
* @type {is~test}
2898
*/
2999
function first() {
30100
return true;
@@ -35,7 +105,7 @@ function first() {
35105
* a given node’s type for said string.
36106
*
37107
* @param {string} test - Node type to test.
38-
* @return {findBefore~test} - Tester.
108+
* @return {is~test} - Tester.
39109
*/
40110
function typeFactory(test) {
41111
return function (node) {
@@ -48,47 +118,58 @@ function typeFactory(test) {
48118
* a given node for strict equality.
49119
*
50120
* @param {Node} test - Node to test.
51-
* @return {findBefore~test} - Tester.
121+
* @return {is~test} - Tester.
52122
*/
53123
function nodeFactory(test) {
54124
return function (node) {
55-
return Boolean(node && node === test);
125+
return node === test;
56126
}
57127
}
58128

59129
/**
60-
* Find a node before `index` in `parent` which passes
61-
* `test`.
130+
* Assert if `test` passes for `node`.
131+
* When a `parent` node is known the `index` of node
62132
*
63-
* @param {Node} parent - Parent to search in.
64-
* @param {number|Node} index - (Position of) node to
65-
* search before.
66-
* @param {string|Node|findBefore~test} test - Tester.
67-
* @return {Node?} - A child node of `parent` which passes
68-
* `test`.
133+
* @example
134+
* is(null, {type: 'strong'}); // true
135+
*
136+
* @example
137+
* is('strong', {type: 'strong'}); // true
138+
* is('emphasis', {type: 'strong'}); // false
139+
*
140+
* @example
141+
* var node = {type: 'strong'};
142+
* is(node, node) // true
143+
* is(node, {type: 'strong'}) // false
144+
*
145+
* @example
146+
* var node = {type: 'strong'};
147+
* var parent = {type: 'paragraph', children: [node]};
148+
* function test(node, n) {return n === 5};
149+
* is(test, {type: 'strong'}); // false
150+
* is(test, {type: 'strong'}, 4, parent); // false
151+
* is(test, {type: 'strong'}, 5, parent); // true
152+
*
153+
* @example
154+
* var node = {type: 'strong'};
155+
* var parent = {type: 'paragraph', children: [node]};
156+
* is('strong'); // throws
157+
* is('strong', node, 0) // throws
158+
* is('strong', node, null, parent) // throws
159+
* is('strong', node, 0, {type: 'paragraph'}) // throws
160+
* is('strong', node, -1, parent) // throws
161+
* is('strong', node, Infinity, parent) // throws
162+
*
163+
* @param {(string|Node|is~test)?} test - Tester.
164+
* @param {Node} node - Node to test.
165+
* @param {number?} [index] - Position of `node` in `parent`.
166+
* @param {Node?} [parent] - Parent of `node`.
167+
* @param {*} [context] - Context to invoke `test` with.
168+
* @return {boolean} - Whether `test` passes.
69169
*/
70-
function findBefore(parent, index, test) {
71-
var children;
72-
var child;
73-
74-
if (!parent || !parent.type || !parent.children) {
75-
throw new Error('Expected parent node');
76-
}
77-
78-
children = parent.children;
79-
80-
if (index && index.type) {
81-
index = children.indexOf(index);
82-
}
83-
84-
if (isNaN(index) || index < 0 || index === Infinity) {
85-
throw new Error('Expected positive finite index or child node');
86-
}
87-
88-
/* Performance. */
89-
if (index > children.length) {
90-
index = children.length;
91-
}
170+
function is(test, node, index, parent, context) {
171+
var hasParent = parent !== null && parent !== undefined;
172+
var hasIndex = index !== null && index !== undefined;
92173

93174
if (typeof test === 'string') {
94175
test = typeFactory(test);
@@ -100,22 +181,33 @@ function findBefore(parent, index, test) {
100181
throw new Error('Expected function, string, or node as test');
101182
}
102183

103-
while (index--) {
104-
child = children[index];
184+
if (!node || !node.type) {
185+
throw new Error('Expected node');
186+
}
105187

106-
if (test(child, index, parent)) {
107-
return child;
108-
}
188+
if (
189+
hasIndex &&
190+
(typeof index !== 'number' || index < 0 || index === Infinity)
191+
) {
192+
throw new Error('Expected positive finite index or child node');
109193
}
110194

111-
return null;
195+
if (hasParent && (!parent || !parent.type || !parent.children)) {
196+
throw new Error('Expected parent node');
197+
}
198+
199+
if (hasParent !== hasIndex) {
200+
throw new Error('Expected both parent and index');
201+
}
202+
203+
return Boolean(test.call(context, node, index, parent));
112204
}
113205

114206
/*
115207
* Expose.
116208
*/
117209

118-
module.exports = findBefore;
210+
module.exports = is;
119211

120212
},{}]},{},[1])(1)
121213
});

0 commit comments

Comments
 (0)