diff --git a/examples/Components/Routes/Search/index.vue b/examples/Components/Routes/Search/index.vue
index 6c2bd4a70..2cb1f3c26 100644
--- a/examples/Components/Routes/Search/index.vue
+++ b/examples/Components/Routes/Search/index.vue
@@ -121,9 +121,16 @@
placeholder="Search..."
type="text"
v-model="searchTerm"
- >
+ >
+
+
@@ -168,6 +175,7 @@ export default {
return {
searching: false,
searchTerm: null,
+ replaceWith: null,
editor: new Editor({
extensions: [
new Blockquote(),
diff --git a/packages/tiptap-extensions/src/extensions/Search.js b/packages/tiptap-extensions/src/extensions/Search.js
index ab85ffec0..2fe57f35d 100644
--- a/packages/tiptap-extensions/src/extensions/Search.js
+++ b/packages/tiptap-extensions/src/extensions/Search.js
@@ -47,6 +47,8 @@ export default class Search extends Extension {
commands() {
return {
find: attrs => this.find(attrs),
+ replace: attrs => this.replace(attrs),
+ replaceAll: attrs => this.replaceAll(attrs),
clearSearch: () => this.clear(),
toggleSearch: () => this.toggleSearch(),
}
@@ -104,6 +106,40 @@ export default class Search extends Extension {
})
}
+ replace(replace) {
+ return (state, dispatch) => {
+ const { from, to } = this.results[0]
+
+ dispatch(state.tr.insertText(replace, from, to))
+ }
+ }
+
+ rebaseNextResult(replace, index) {
+ const nextIndex = index + 1
+ if (!this.results[nextIndex]) return
+
+ const nextStep = this.results[nextIndex]
+ const { from, to } = nextStep
+ const offset = (to - from - replace.length) * nextIndex
+
+ this.results[nextIndex] = {
+ to: to - offset,
+ from: from - offset,
+ }
+ }
+
+ replaceAll(replace) {
+ return ({ tr }, dispatch) => {
+ this.results.forEach(({ from, to }, index) => {
+ tr.insertText(replace, from, to)
+
+ this.rebaseNextResult(replace, index)
+ })
+
+ dispatch(tr)
+ }
+ }
+
find(searchTerm) {
return (state, dispatch) => {
this.searchTerm = (this.options.disableRegex) ? searchTerm.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&') : searchTerm