unist-util-filter

Create a new unist tree containing only the nodes that pass a test, with optional parent cascading.

Library
npm
v5.0.1
20stars
MIT License

Repository Health

Pre-computed score based on development activity, maintenance, community, maturity, and trend momentum.How we score it →
27/100Needs Attention
Development Activity0
Maintenance20
Community16
Maturity60
Momentum12

Technical Analysis

AI-assessed by reading the actual repository — architecture, code quality, innovation, and documentation.How we score it →
73/100Good
Architecture80
Code Quality92
Innovation75
Learning Curve45

unist-util-filter is a small, focused utility for the unist ecosystem that builds a new syntax tree containing only the nodes matching a given test, leaving the original tree untouched. It walks the tree in preorder, cloning each node that passes the test and reassembling matched children under their surviving parents, so consumers get an immutable, test-driven view of a tree without mutating the source AST.

It plugs directly into the unist-util-is test format (type strings, partial node objects, or predicate functions) used across the entire syntax-tree/unified ecosystem, and exposes a single cascade option that controls whether parent nodes with no surviving children are dropped or kept. Because it returns a new tree instead of mutating in place, it’s the safe choice when working with remark/rehype pipelines that expect the original AST to remain intact for further processing.

What You Get

  • A single filter(tree[, options][, test]) function with full TypeScript types.
  • unist-util-is compatible test support — type strings, partial objects, or predicate functions.
  • A cascade option to control whether empty parent nodes are dropped or preserved.
  • An immutable operation that always returns a new tree, leaving the source untouched.

Common Use Cases

  • Stripping unwanted node types (e.g. comments, HTML nodes) from a remark/rehype AST before rendering.
  • Producing a read-only filtered view of a syntax tree for analysis without touching the original.
  • Building custom unified plugins that need to select a subtree matching specific criteria.

Under The Hood

Architecture unist-util-filter is a minimal single-purpose module: the public entry point (index.js) re-exports a single filter function implemented in lib/index.js, with a separate lib/complex-types.d.ts file dedicated purely to the type-level machinery needed to infer the filtered node’s shape from the test given. The core algorithm is a recursive preorder (NLR) walk: each node is checked with a unist-util-is-derived predicate, and if it passes, a shallow clone is built by copying every enumerable property while recursively filtering children for parent-shaped nodes; when cascade is enabled, a parent whose children were reduced to zero survives only if it had none to begin with. There’s no persistent state, class hierarchy, or dependency injection — the whole module is one closure-returning function, which keeps the blast radius of any change to the traversal logic tightly contained to a single file.

Tech Stack The package targets ESM-only Node.js 16+ and TypeScript consumers via hand-written JSDoc types compiled with tsc --build, validated end-to-end with tsd and enforced to full type coverage via type-coverage. Its only runtime dependency is unist-util-is (for test-to-predicate conversion), with @types/unist present as a supporting dev dependency. Formatting and linting run through xo (an ESLint preset) and prettier, docs are auto-formatted via remark-preset-wooorm, and CI runs the full build/format/test-coverage pipeline on every push — a standard-issue setup shared across the entire syntax-tree/unified organization’s utility packages.

Code Quality Testing uses Node’s built-in test runner against a single test file, covering cascade on/off, root-node rejection, index/parent callback arguments, and the exact README example, with full statement coverage enforced as a hard CI gate — there’s no room for untested branches to ship. Every function and type is documented with JSDoc, including generic overloads that model the three call signatures (test only, options plus test, or neither), and the xo/prettier combination enforces consistent style automatically. No error handling beyond the predicate/cascade logic is needed given the module’s narrow scope, and there are no swallowed exceptions or defensive over-engineering — the code trusts its inputs and lets unist-util-is validate the test argument.

API Design The API surface is intentionally tiny: one named export, filter(tree[, options][, test]), that accepts the same unist-util-is-style test (a type string, partial node, or predicate) used across every other syntax-tree utility, so developers already familiar with unist-util-visit or unist-util-is incur zero new learning cost. The single cascade option covers the one meaningful behavioral fork (drop vs. keep emptied parents), and calling filter(tree) with no arguments at all still works as a full clone — there’s no required configuration object, no builder pattern, and no boilerplate beyond the import itself.

Join founders buildingwith open source

Opinionated takes, migration guides, cost-saving tips, and insights from the open source ecosystem.

Subscribe on Substack
Join 750+ subscribers

Search