Using Custom Selector Functions
Relevant source files
The following files were used as context for generating this wiki page:
cheerio-select provides a flexible interface for querying DOM structures, extending beyond standard CSS selectors and jQuery-like positionals. One of its most powerful features is the ability to use Custom Selector Functions. This allows developers to pass a programmatic predicate function instead of a CSS selector string to filter or find elements within a domhandler document.
This capability is integrated into the core entry points of the library, including select, is, and some. By providing a function that evaluates an Element, users can implement complex logic that standard CSS syntax cannot easily express, such as filtering based on the number of children or specific node properties not reflected in attributes.
Sources: src/index.ts:251-255, README.md:43-45
Functional Selector Architecture
The library treats selector functions as first-class citizens alongside string-based selectors. When a function is provided, the engine bypasses the standard CSS parsing and compilation pipeline (handled by css-what and css-select) and instead uses the function directly as a predicate for node traversal.
Data Flow for Functional Selectors
When a user calls a core function like select or is with a function, the logic branches early to execute the predicate against candidate nodes.
The diagram above illustrates the early branching logic when a functional selector is detected.
Sources: src/index.ts:57-61, src/index.ts:251-255
Supported API Entry Points
Custom selector functions can be used in several key exported functions. The signature for these functions generally follows the pattern: (element: Element) => boolean.
| Function | Parameter | Role of Selector Function |
|---|---|---|
select | selector | Used to traverse the DOM and return all elements for which the function returns true. |
is | selector | Checks if a single specific Element satisfies the function. |
some | selector | Checks if at least one element in a provided list satisfies the function. |
The select Function
In select, if the selector argument is a function, it triggers the internal find helper. This helper uses domutils to perform a deep search starting from the provided root, applying the custom function to every node.
Sources: src/index.ts:251-255, src/index.ts:358-369
The is and some Functions
The is function is a wrapper around some. When some receives a function, it directly applies Array.prototype.some(selector) to the input elements, providing a highly efficient path for validation.
Sources: src/index.ts:57-58, src/index.ts:74-75
Implementation Details
The core logic for functional selection is handled by the find function in src/index.ts.
function find(
root: AnyNode | AnyNode[],
query: CompiledQuery,
limit = Number.POSITIVE_INFINITY,
): Element[] {
const elements = prepareContext<AnyNode, Element>(
root,
DomUtils,
query.shouldTestNextSiblings,
);
return DomUtils.find(
(node: AnyNode) => DomUtils.isTag(node) && query(node),
elements,
true,
limit,
) as Element[];
}
Sources: src/index.ts:373-390
Key Components
CompiledQueryInterface: This interface represents the function used for matching. While custom functions provided by users are simple predicates, the internal system treats them asCompiledQueryobjects that may optionally include metadata likeshouldTestNextSiblings.domutils.find: The library leverages the underlyingdomutilspackage to perform the actual recursive traversal of the tree.isTagCheck: The engine ensures that the custom function is only applied to nodes that are actual tags (Elements), preventing errors when encountering text or comment nodes during traversal.
Sources: src/index.ts:365-371, src/index.ts:385
Usage Examples
Finding Elements by Property
A common use case is finding elements based on internal DOM properties, such as the number of children, which is not possible with standard CSS selectors.
// Find all divs that have more than one child
const result = select(
(element) => element.name === "div" && element.children.length > 1,
dom
);
Sources: src/index.spec.ts:114-114, README.md:44-45
Complex Logic in is Checks
Custom functions allow for sophisticated validation of specific nodes within a context.
// Check if an element is a 'p' tag
expect(is(p1, (element) => element.name === "p")).toBe(true);
Sources: src/index.spec.ts:11-14, src/index.spec.ts:109-109
Conclusion
Custom selector functions in cheerio-select provide a programmatic escape hatch for complex DOM queries. By integrating this functionality directly into the core select, is, and some APIs, the library allows developers to combine the ease of CSS selectors with the power of arbitrary JavaScript logic, ensuring that any structural or property-based query can be satisfied efficiently.
Sources: src/index.ts:1-20, README.md:43-48