API: filter() Function
Relevant source files
The following files were used as context for generating this wiki page:
The filter() function is a core utility in the cheerio-select library designed to refine a list of existing DOM nodes based on a CSS selector. Unlike the select() function, which searches for descendants, filter() evaluates the provided set of elements against the selector and returns only those that match.
It serves as a thin wrapper around css-select, extending it with support for jQuery-style positional pseudo-selectors such as :first, :last, :eq(), and :not(). This makes it particularly useful for manipulating DOM collections in environments that require jQuery-like selection behavior.
Sources: src/index.ts:133-140, README.md:1-20
Architecture and Data Flow
The filter() function operates by parsing the selector and splitting it into "plain" selectors (standard CSS) and "filtered" selectors (those containing positional pseudos). This categorization allows the engine to optimize performance by using standard CSS matching where possible and falling back to positional logic only when necessary.
Logical Segmentation
The following diagram illustrates how the filter() function processes an input selector and a set of elements:
The implementation ensures that the final result set preserves the original document order of the input elements, regardless of the order in which selectors matched.
Sources: src/index.ts:149-211, src/helpers.ts:22-38
API Definition
filter(selector, elements, options)
Filters a list of nodes by a selector string.
| Parameter | Type | Description |
|---|---|---|
selector | string | The CSS selector to match against the elements. |
elements | AnyNode[] | An array of nodes to be filtered. |
options | Options | Optional configuration including xmlMode and root reference. |
Returns: Element[] - A list of elements from the input that match the selector.
Sources: src/index.ts:133-140
Positional Pseudo-Selectors
A primary feature of cheerio-select's filtering logic is the handling of positional filters. When filter() encounters these, it routes the logic through filterByPosition.
Supported Positional Filters
| Filter | Description | Logic Implementation |
|---|---|---|
:first | Selects the first element. | Returns the input set (limit handled earlier). |
:last | Selects the last element. | elements[elements.length - 1] |
:eq(n) | Selects element at index n. | Supports negative offsets (e.g., -1 for last). |
:gt(n) | Elements with index > n. | elements.slice(position + 1) |
:lt(n) | Elements with index < n. | Returns input set (limit handled earlier). |
:even | Even-indexed elements. | index % 2 === 0 |
:odd | Odd-indexed elements. | index % 2 === 1 |
:not(sel) | Excludes matches. | Uses a Set for efficient exclusion. |
Sources: src/index.ts:63-111, src/positionals.ts:8-25
Positional Processing Flow
The internal findFilterElements function manages the complexity of selectors that mix standard CSS and positionals.
Sources: src/index.ts:258-290, src/positionals.ts:56-96
Internal Implementation Details
Selector Grouping
The groupSelectors helper is critical for determining the execution path. It iterates through parsed selector groups and checks if any token in the group satisfies isFilter.
Sources: src/helpers.ts:22-38
// src/helpers.ts:22-38
export function groupSelectors(
selectors: Selector[][],
): [plain: Selector[][], filtered: Selector[][]] {
const filteredSelectors: Selector[][] = [];
const plainSelectors: Selector[][] = [];
for (const selector of selectors) {
if (selector.some(isFilter)) {
filteredSelectors.push(selector);
} else {
plainSelectors.push(selector);
}
}
return [plainSelectors, filteredSelectors];
}
Traversal Handling
If a selector passed to filter() contains traversal tokens (like > or +), the engine treats the selection as relative to a root. It uses SCOPE_PSEUDO to ensure matches are restricted to the context of the provided elements.
Sources: src/index.ts:213-238
Usage Examples
The following examples demonstrate how filter() is used to process arrays of elements.
import { parseDocument } from "htmlparser2";
import { select, filter } from "cheerio-select";
const dom = parseDocument("<div><p>First<p>Second");
const ps = select("p", dom); // Returns both <p> elements
// Filter for only the first <p>
const firstP = filter(":first", ps);
// Filter with standard CSS
const namedP = filter("p:contains(First)", ps);
Sources: src/index.spec.ts:66-80, README.md:46-47
Summary
The filter() function provides a high-performance bridge between standard CSS selection and jQuery-style collection filtering. By intelligently grouping selectors and applying positional limits early, it minimizes DOM traversal while supporting complex features like negative indices in :eq() and recursive :not() selectors.
Sources: src/index.ts:149-160, src/positionals.ts:68-75