Unist Utility to Map Nodes
unist-util-map is a utility for the Unist syntax tree ecosystem designed to create a *new* Unist tree by applying a mapping function to every node. Unlike many tree manipulation utilities that mutate the tree in place, `unist-util-map` always returns a completely new, transformed tree, preserving the original structure. The package is currently at version 4.0.0, with a release cadence that includes minor patch updates for bug fixes, documentation improvements, and internal refactors. Major versions are released less frequently, typically when significant breaking changes occur, such as updates to required Node.js versions or shifts to modern module systems. A key differentiator and important consideration for developers is its tree-cloning behavior; while excellent for immutable transformations, this approach can lead to performance overhead on exceptionally large trees. For scenarios involving potentially large trees and relatively few modifications, developers are often advised to consider alternatives like `unist-util-visit` or `unist-util-filter`, which offer different performance characteristics depending on the use case.
Common errors
-
ERR_REQUIRE_ESM
cause Attempting to import `unist-util-map` using CommonJS `require()` in a project that expects ESM.fixUpdate your import statement to use ES Modules syntax: `import { map } from 'unist-util-map';`. Ensure your `package.json` has `"type": "module"` if it's a pure ESM project, or use dynamic import for mixed CJS/ESM projects. -
SyntaxError: Named export 'map' not found. The requested module 'unist-util-map' is a CommonJS module, which may not support named exports.
cause Incorrectly assuming `unist-util-map` is a CommonJS module or attempting a named import from a non-ESM source. This error message is misleading, as `unist-util-map` is ESM-only.fixVerify your project is configured for ES Modules. If you're in a CommonJS environment, you cannot directly import `unist-util-map`. Consider using a bundler or converting your project to ESM. Ensure you are using `import { map } from 'unist-util-map'`. -
Your current Node.js version (X.Y.Z) is not supported. Please upgrade to Node.js 16 or higher.
cause Running `unist-util-map` v4 or higher on an unsupported Node.js version.fixUpgrade your Node.js runtime to version 16 or newer. You can use a tool like `nvm` (Node Version Manager) to manage multiple Node.js versions. -
Argument of type 'Node<Data>' is not assignable to parameter of type 'Node'.
cause Type incompatibility often arises from differing versions of `@types/unist` or custom `Node` definitions not aligning with the library's expectations, especially after `unist-util-map` v4.0.0's type updates.fixEnsure your project's `@types/unist` version is compatible with `unist-util-map@4`. Update `@types/unist` to its latest version. If you have custom `Node` definitions, ensure they correctly extend or align with the `unist` types.
Warnings
- breaking `unist-util-map` became an ESM-only package in version 3.0.0. Attempting to `require()` it in CommonJS will result in an error.
- breaking Version 4.0.0 raised the minimum required Node.js version to 16.
- breaking The `@types/unist` dependency was updated in v4.0.0. While typically a development dependency, this might require users to update their own `@types/unist` package to match, especially if they rely on specific type definitions.
- gotcha `unist-util-map` creates a new object for *every* node in the tree. While ensuring immutability, this can lead to performance issues and increased memory usage when processing very large syntax trees. For scenarios with large trees and relatively few changes, alternatives like `unist-util-visit` (which mutates in place) or `unist-util-filter` (which also clones but is optimized for removal) might be more suitable.
- breaking Version 4.0.0 changed to use `exports` map in `package.json`, which affects how module resolution works. Directly accessing 'private' internal paths (e.g., `unist-util-map/lib/foo`) will likely break.
- breaking Version 2.0.0 introduced TypeScript types. While beneficial, this could be a breaking change for TypeScript users who had previously provided their own ambient type declarations or relied on implicit `any`.
Install
-
npm install unist-util-map -
yarn add unist-util-map -
pnpm add unist-util-map
Imports
- map
const map = require('unist-util-map')import { map } from 'unist-util-map' - MapFunction
import type { MapFunction } from 'unist-util-map' - MapFunction (inline)
import { map } from 'unist-util-map'; const myMapFn: (node: Node, index?: number, parent?: Node) => Node = (node) => { // ... return new node };
Quickstart
import {u} from 'unist-builder'
import {map} from 'unist-util-map'
const tree = u('tree', [
u('leaf', 'leaf 1'),
u('node', [u('leaf', 'leaf 2')]),
u('void'),
u('leaf', 'leaf 3')
])
const next = map(tree, function (node) {
return node.type === 'leaf'
? Object.assign({}, node, {value: 'CHANGED'}) // Return a new object for immutability
: node
})
// The original tree remains unchanged
console.log('Original tree:', JSON.stringify(tree, null, 2));
// The new tree has 'leaf' nodes with 'CHANGED' value
console.log('Mapped tree:', JSON.stringify(next, null, 2));
// Example using unist-builder for comparison (not a direct dependency)
// npm install unist-builder