---
title: "Find and Replace extension"
description: "Search, highlight, navigate, and replace text in a Tiptap editor with the Find and Replace extension."
canonical_url: "https://tiptap-docs.lin52025i.qzz.io/editor/extensions/functionality/find-and-replace"
---

# Find and Replace extension

Search, highlight, navigate, and replace text in a Tiptap editor with the Find and Replace extension.

The Find and Replace extension searches the document, highlights matches, and provides commands for navigation and replacement. It is headless, so you can build the controls and place them anywhere in your application.

> **Interactive demo:** [FindAndReplace](https://embed.tiptap.dev/preview/Extensions/FindAndReplace)

## Install

```bash
npm install @tiptap/extension-find-and-replace
```

## Usage

```js
import { Editor } from '@tiptap/core'
import FindAndReplace from '@tiptap/extension-find-and-replace'
import StarterKit from '@tiptap/starter-kit'

new Editor({
  extensions: [StarterKit, FindAndReplace],
})
```

See the [custom UI guide](https://tiptap-docs.lin52025i.qzz.io/guides/find-and-replace.md) for complete React and Vue examples.

## Settings

These options set the initial state. Use the commands below to update the search while the editor is running.

### searchTerm

The initial text to search for. In regex mode, this is the regular expression source.

Default: `''`

```js
FindAndReplace.configure({
  searchTerm: 'Tiptap',
})
```

### replaceTerm

The initial text used by the replace commands. When regex mode is enabled, the replacement can
reuse the complete match or capture groups.

Default: `''`

```js
FindAndReplace.configure({
  useRegex: true,
  searchTerm: '(color|colour)',
  replaceTerm: '[$1]',
})
```

### caseSensitive

Whether the search matches case exactly.

Default: `false`

```js
FindAndReplace.configure({
  caseSensitive: true,
})
```

### useRegex

Whether `searchTerm` is treated as a regular expression.

Default: `false`

```js
FindAndReplace.configure({
  useRegex: true,
  searchTerm: 'colou?r',
})
```

Regex mode can be combined with `caseSensitive` and `wholeWord`. Invalid patterns and patterns
rejected as unsafe return no results. Regex mode uses RE2-compatible syntax, so lookarounds and
backreferences in the search pattern are not supported.

### wholeWord

Whether to require matches to have a Unicode word boundary on both sides. This works for literal
and regex searches. Unicode word characters include letters, combining marks, numbers, and
connector punctuation such as `_`.

Default: `false`

```js
FindAndReplace.configure({
  caseSensitive: true,
  useRegex: true,
  wholeWord: true,
  searchTerm: 'cat|catalog',
})
```

For example, this configuration matches `cat` and `catalog`, but not `cats` or `Catalog`. The regex
engine can try a later alternative or a longer match when an earlier result does not satisfy the
whole-word boundary.

### searchDebounceMs

The delay, in milliseconds, before `setSearchTerm()` updates the search results. Set this to `0` to update results immediately.

Default: `250`

```js
FindAndReplace.configure({
  searchDebounceMs: 0,
})
```

### injectCSS

Whether to inject the default result highlight styles. Disable this option to provide your own styles.

Default: `true`

```js
FindAndReplace.configure({
  injectCSS: false,
})
```

### injectNonce

The nonce applied to the injected style element. Set this when your Content Security Policy requires a nonce.

Default: `undefined`

```js
FindAndReplace.configure({
  injectNonce: 'your-nonce-here',
})
```

## Commands

### setSearchTerm()

Set the search term and highlight every match.

```js
editor.commands.setSearchTerm('Tiptap')
```

### setReplaceTerm()

Set the text used by `replace()` and `replaceAll()`. In regex mode, the replacement can include
capture-group substitutions.

```js
editor.commands.setReplaceTerm('[$1]')
```

#### Regex replacement tokens

When regex mode is enabled, replacement terms support these JavaScript-style tokens:

| Token      | Replacement                              |
| ---------- | ---------------------------------------- |
| `$$`       | A literal `$`                            |
| `$&`       | The complete match                       |
| `$1`–`$99` | The corresponding numbered capture group |
| `$<name>`  | The corresponding named capture group    |

Unmatched groups insert an empty string. A one-digit numbered reference that exceeds the pattern's
capture count remains unchanged. For a two-digit reference, JavaScript-style fallback applies: if
the complete number does not exist but its first digit names a capture, that capture is inserted
followed by the second digit. For example, `$12` with one capture inserts capture 1 followed by `2`.
Zero-padded references such as `$01` also follow JavaScript semantics and address capture 1. An
unknown named reference inserts an empty string when the pattern contains named groups, and remains
unchanged when it does not.

Other `$` sequences remain unchanged. The JavaScript before-match token (`$` followed by a
backtick) and after-match token (`$'`) are not expanded. When regex mode is disabled, every
replacement term is inserted literally.

In regex mode, escape the leading dollar sign with `$$` to preserve a supported token literally.
For example, `$$1` inserts `$1`.

```js
editor.commands.setUseRegex(true)
editor.commands.setSearchTerm('(color|colour)')
editor.commands.setReplaceTerm('[$1]')
editor.commands.replaceAll()
// "color and colour" becomes "[color] and [colour]"
```

### setCaseSensitive()

Enable or disable case-sensitive matching. This works in literal and regex modes.

```js
editor.commands.setCaseSensitive(true)
```

### setUseRegex()

Enable or disable regular expression matching. Regex mode can be enabled together with Match case
and Whole word.

```js
editor.commands.setUseRegex(true)
```

### setWholeWord()

Enable or disable Unicode-aware whole-word matching for literal or regex searches.

```js
editor.commands.setWholeWord(true)
```

### goToNextResult()

Select the next result. Navigation wraps from the final result to the first result.

```js
editor.commands.goToNextResult()
```

### goToPreviousResult()

Select the previous result. Navigation wraps from the first result to the final result.

```js
editor.commands.goToPreviousResult()
```

### replace()

Replace the selected result and select the next available result.

```js
editor.commands.replace()
```

### replaceAll()

Replace every result in the current result set.

```js
editor.commands.replaceAll()
```

### clearSearch()

Clear the search term and remove every result highlight.

```js
editor.commands.clearSearch()
```

## Storage

The extension keeps its current state in `editor.storage.findAndReplace`.

### searchTerm

The current search term.

```js
editor.storage.findAndReplace.searchTerm
```

### replaceTerm

The current replacement text.

```js
editor.storage.findAndReplace.replaceTerm
```

### caseSensitive, useRegex, and wholeWord

The current matching options.

```js
editor.storage.findAndReplace.caseSensitive
editor.storage.findAndReplace.useRegex
editor.storage.findAndReplace.wholeWord
```

### results

The matches in document order. Every result has `from` and `to` ProseMirror positions.

```js
editor.storage.findAndReplace.results
```

### currentIndex

The index of the selected result, or `null` when no result is selected.

```js
editor.storage.findAndReplace.currentIndex
```

## Search behavior

Matches update when the document or a search option changes. A match can span text nodes with different marks, but never crosses a textblock or a non-text inline node such as a hard break or mention.

Match case, Regex, and Whole word are independent options and can be enabled together. In regex
whole-word mode, the boundary is checked around the final regex result. This allows alternatives and
quantifiers to continue until they produce a complete word. Consecutive matches can share a
punctuation boundary, so a whole-word regex for `cat` finds all three matches in `cat-cat.cat`.

`replaceAll()` replaces the matches that exist when the command runs. If the replacement text also matches the search, those new matches remain in storage after the transaction.

## Styling results

By default, results have a yellow highlight and the selected result has an orange highlight. Disable `injectCSS` to replace these styles.

```css
.find-and-replace-result {
  background-color: rgb(255 225 0 / 0.4);
}

.find-and-replace-result-current {
  background-color: rgb(255 165 0 / 0.55);
}
```

## Source code

[packages/extension-find-and-replace/](https://github.com/ueberdosis/tiptap/tree/main/packages/extension-find-and-replace/)
