hast-util-find-and-replace
The `hast-util-find-and-replace` package is a utility within the unifiedjs ecosystem designed to efficiently find and replace patterns (strings or regular expressions) within a HAST (HTML Abstract Syntax Tree). It operates by traversing the tree in a preorder fashion and applying replacements specifically within `Text` nodes. A key feature is its awareness of HTML structure, allowing it to ignore certain tags like `<script>`, `<style>`, `<iframe>`, `<img>`, and `<a>` by default, preventing unintended modifications. The current stable version is 5.0.1. The package maintains an active release cadence, with frequent patch and minor updates, and significant breaking changes between major versions. Its primary differentiator is its tight integration with HAST, offering a robust and context-aware solution for HTML tree manipulation.
Common errors
-
ERR_REQUIRE_ESM
cause Attempting to import `hast-util-find-and-replace` using `require()` syntax in a CommonJS context, but the package is ESM-only.fixConvert your consuming file or project to use ES modules by setting `"type": "module"` in `package.json` or by using `.mjs` file extensions, and update `require()` calls to `import` statements. -
TypeError: (0 , _hast_util_find_and_replace__WEBPACK_IMPORTED_MODULE_0__.findAndReplace) is not a function
cause This error typically indicates an incorrect import statement, where `findAndReplace` is being treated as a default import when it is a named export.fixEnsure you are using a named import: `import { findAndReplace } from 'hast-util-find-and-replace'`. -
TypeError: The 'list' argument must be a tuple or a list of tuples
cause In `hast-util-find-and-replace` v5.x, the `list` argument for `findAndReplace` must be an array of `[find, replace]` tuples or a single `[find, replace]` tuple. Passing an object is deprecated and no longer supported.fixRefactor the `list` argument. Instead of `{ 'pattern': 'replacement' }`, use `[['pattern', 'replacement']]` or `['pattern', 'replacement']`.
Warnings
- breaking The package transitioned to ESM-only and requires Node.js 16 or newer for version 5.x. Older Node.js versions or CommonJS environments are not supported.
- breaking The API for `findAndReplace` changed to accept only a tuple `[Find, Replace]` or a list of tuples `[[Find, Replace], ...]`. Directly passing an object for `list` is no longer supported.
- breaking The `findAndReplace` function now yields `undefined` (returns nothing). It mutates the provided `tree` node directly. If you need to keep a reference to the modified tree, you must pass the original tree object and expect it to be modified in place.
- gotcha The utility only finds patterns within `Text` nodes and processes complete matches. It does not handle partial matches that span across multiple HAST nodes (e.g., a word broken by an HTML tag).
- gotcha By default, `findAndReplace` ignores content within `<math>`, `<script>`, `<style>`, `<svg>`, and `<title>` elements to prevent unintended modifications to code or metadata. This default can be overridden.
Install
-
npm install hast-util-find-and-replace -
yarn add hast-util-find-and-replace -
pnpm add hast-util-find-and-replace
Imports
- findAndReplace
const findAndReplace = require('hast-util-find-and-replace')import { findAndReplace } from 'hast-util-find-and-replace' - defaultIgnore
import defaultIgnore from 'hast-util-find-and-replace'
import { defaultIgnore } from 'hast-util-find-and-replace' - FindAndReplaceList
import type { FindAndReplaceList } from 'hast-util-find-and-replace'
Quickstart
import { h } from 'hastscript';
import { findAndReplace } from 'hast-util-find-and-replace';
import { inspect } from 'unist-util-inspect'; // For visualizing the tree
const tree = h('p', [
'Some ',
h('em', 'emphasis'),
', ',
h('strong', 'importance'),
', and ',
h('code', 'code'),
'.'
]);
// Apply find and replace operations
findAndReplace(
tree,
[
[/and/gi, 'or'], // Replace 'and' with 'or' (case-insensitive)
[/emphasis/gi, 'em'], // Replace 'emphasis' with 'em'
[/importance/gi, 'strong'], // Replace 'importance' with 'strong'
[
/code/gi,
function ($0) {
return h('a', {href: '//example.com#' + $0}, $0) // Replace 'code' with a link
}
],
['Some', (match, node, index, parent) => {
// Example of custom replacement logic, accessing node context
console.log(`Found "${match}" at index ${index} in parent:`, parent.type);
return 'Any'; // Replace "Some" with "Any"
}]
],
{
ignore: ['code'] // Also ignore 'code' tags in addition to defaults like script/style
}
);
console.log(inspect(tree));