119 lines
3.7 KiB
JavaScript
119 lines
3.7 KiB
JavaScript
|
import { isTag, hasChildren } from "domhandler";
|
||
|
/**
|
||
|
* Search a node and its children for nodes passing a test function.
|
||
|
*
|
||
|
* @category Querying
|
||
|
* @param test Function to test nodes on.
|
||
|
* @param node Node to search. Will be included in the result set if it matches.
|
||
|
* @param recurse Also consider child nodes.
|
||
|
* @param limit Maximum number of nodes to return.
|
||
|
* @returns All nodes passing `test`.
|
||
|
*/
|
||
|
export function filter(test, node, recurse = true, limit = Infinity) {
|
||
|
if (!Array.isArray(node))
|
||
|
node = [node];
|
||
|
return find(test, node, recurse, limit);
|
||
|
}
|
||
|
/**
|
||
|
* Search an array of node and its children for nodes passing a test function.
|
||
|
*
|
||
|
* @category Querying
|
||
|
* @param test Function to test nodes on.
|
||
|
* @param nodes Array of nodes to search.
|
||
|
* @param recurse Also consider child nodes.
|
||
|
* @param limit Maximum number of nodes to return.
|
||
|
* @returns All nodes passing `test`.
|
||
|
*/
|
||
|
export function find(test, nodes, recurse, limit) {
|
||
|
const result = [];
|
||
|
for (const elem of nodes) {
|
||
|
if (test(elem)) {
|
||
|
result.push(elem);
|
||
|
if (--limit <= 0)
|
||
|
break;
|
||
|
}
|
||
|
if (recurse && hasChildren(elem) && elem.children.length > 0) {
|
||
|
const children = find(test, elem.children, recurse, limit);
|
||
|
result.push(...children);
|
||
|
limit -= children.length;
|
||
|
if (limit <= 0)
|
||
|
break;
|
||
|
}
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
/**
|
||
|
* Finds the first element inside of an array that matches a test function.
|
||
|
*
|
||
|
* @category Querying
|
||
|
* @param test Function to test nodes on.
|
||
|
* @param nodes Array of nodes to search.
|
||
|
* @returns The first node in the array that passes `test`.
|
||
|
* @deprecated Use `Array.prototype.find` directly.
|
||
|
*/
|
||
|
export function findOneChild(test, nodes) {
|
||
|
return nodes.find(test);
|
||
|
}
|
||
|
/**
|
||
|
* Finds one element in a tree that passes a test.
|
||
|
*
|
||
|
* @category Querying
|
||
|
* @param test Function to test nodes on.
|
||
|
* @param nodes Array of nodes to search.
|
||
|
* @param recurse Also consider child nodes.
|
||
|
* @returns The first child node that passes `test`.
|
||
|
*/
|
||
|
export function findOne(test, nodes, recurse = true) {
|
||
|
let elem = null;
|
||
|
for (let i = 0; i < nodes.length && !elem; i++) {
|
||
|
const checked = nodes[i];
|
||
|
if (!isTag(checked)) {
|
||
|
continue;
|
||
|
}
|
||
|
else if (test(checked)) {
|
||
|
elem = checked;
|
||
|
}
|
||
|
else if (recurse && checked.children.length > 0) {
|
||
|
elem = findOne(test, checked.children, true);
|
||
|
}
|
||
|
}
|
||
|
return elem;
|
||
|
}
|
||
|
/**
|
||
|
* @category Querying
|
||
|
* @param test Function to test nodes on.
|
||
|
* @param nodes Array of nodes to search.
|
||
|
* @returns Whether a tree of nodes contains at least one node passing the test.
|
||
|
*/
|
||
|
export function existsOne(test, nodes) {
|
||
|
return nodes.some((checked) => isTag(checked) &&
|
||
|
(test(checked) ||
|
||
|
(checked.children.length > 0 &&
|
||
|
existsOne(test, checked.children))));
|
||
|
}
|
||
|
/**
|
||
|
* Search and array of nodes and its children for elements passing a test function.
|
||
|
*
|
||
|
* Same as `find`, but limited to elements and with less options, leading to reduced complexity.
|
||
|
*
|
||
|
* @category Querying
|
||
|
* @param test Function to test nodes on.
|
||
|
* @param nodes Array of nodes to search.
|
||
|
* @returns All nodes passing `test`.
|
||
|
*/
|
||
|
export function findAll(test, nodes) {
|
||
|
var _a;
|
||
|
const result = [];
|
||
|
const stack = nodes.filter(isTag);
|
||
|
let elem;
|
||
|
while ((elem = stack.shift())) {
|
||
|
const children = (_a = elem.children) === null || _a === void 0 ? void 0 : _a.filter(isTag);
|
||
|
if (children && children.length > 0) {
|
||
|
stack.unshift(...children);
|
||
|
}
|
||
|
if (test(elem))
|
||
|
result.push(elem);
|
||
|
}
|
||
|
return result;
|
||
|
}
|
||
|
//# sourceMappingURL=querying.js.map
|