Skip to content

Commit

Permalink
feat: nextSearchResult & previousSearchResul
Browse files Browse the repository at this point in the history
  • Loading branch information
sereneinserenade committed Jan 27, 2024
1 parent 5ddc4d3 commit b5f27a1
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 26 deletions.
20 changes: 16 additions & 4 deletions demos/vue/src/components/Tiptap.vue
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,13 @@
>
Clear
</button>
<button
@click="previous"
type="button"
class="relative inline-flex items-center px-4 py-2 -ml-px text-sm font-medium text-gray-700 bg-white border border-gray-300 hover:bg-gray-50 focus:z-10 focus:border-indigo-500 focus:outline-none focus:ring-1 focus:ring-indigo-500"
>
Previous
</button>
<button
@click="next"
type="button"
Expand All @@ -101,7 +108,7 @@
</button>

<div class="block text-sm font-medium text-gray-700 py-2 px-4">
Results: {{ editor?.storage?.searchAndReplace?.results.length }}
Results: {{ editor?.storage?.searchAndReplace?.resultIndex + 1 }} / {{ editor?.storage?.searchAndReplace?.results.length }}
</div>
</span>
</div>
Expand All @@ -115,8 +122,8 @@ import StarterKit from "@tiptap/starter-kit";
import Link from "@tiptap/extension-link";
import { onMounted, ref, watch } from "vue";
import SearchAndReplace from "@sereneinserenade/tiptap-search-and-replace";
// import { SearchAndReplace } from '../../../../src/searchAndReplace'
// import SearchAndReplace from "@sereneinserenade/tiptap-search-and-replace";
import { SearchAndReplace } from '../../../../src/searchAndReplace'
import GithubIcon from "../assets/github.svg";
Expand Down Expand Up @@ -191,7 +198,12 @@ const replace = () => {
};
const next = () => {
editor.value?.commands.next();
editor.value?.commands.nextSearchResult();
goToSelection();
};
const previous = () => {
editor.value?.commands.previousSearchResult();
goToSelection();
};
Expand Down
77 changes: 55 additions & 22 deletions src/searchAndReplace.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// MIT License

// Copyright (c) 2023 Jeet Mandaliya (Github Username: sereneinserenade)
// Copyright (c) 2023 - 2024 Jeet Mandaliya (Github Username: sereneinserenade)

// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
Expand All @@ -22,7 +22,12 @@

import { Extension, Range, type Dispatch } from "@tiptap/core";
import { Decoration, DecorationSet } from "@tiptap/pm/view";
import { Plugin, PluginKey, type EditorState, type Transaction } from "@tiptap/pm/state";
import {
Plugin,
PluginKey,
type EditorState,
type Transaction,
} from "@tiptap/pm/state";
import { Node as PMNode } from "@tiptap/pm/model";

declare module "@tiptap/core" {
Expand All @@ -47,7 +52,11 @@ declare module "@tiptap/core" {
/**
* @description Find next instance of search result.
*/
next: () => ReturnType;
nextSearchResult: () => ReturnType;
/**
* @description Find previous instance of search result.
*/
previousSearchResult: () => ReturnType;
/**
* @description Replace first instance of search result with given replace term.
*/
Expand Down Expand Up @@ -88,12 +97,17 @@ function processSearches(
resultIndex: number,
): ProcessedSearches {
const decorations: Decoration[] = [];
let textNodesWithPosition: TextNodesWithPosition[] = [];
const results: Range[] = [];

let textNodesWithPosition: TextNodesWithPosition[] = [];
let index = 0;

if (!searchTerm)
return { decorationsToReturn: DecorationSet.empty, results: [] };
if (!searchTerm) {
return {
decorationsToReturn: DecorationSet.empty,
results: [],
};
}

doc?.descendants((node, pos) => {
if (node.isText) {
Expand Down Expand Up @@ -150,21 +164,20 @@ function processSearches(
decorationsToReturn: DecorationSet.create(doc, decorations),
results,
};
};
}

const replace = (
replaceTerm: string,
results: Range[],
index: number,
{ state, dispatch }: { state: EditorState; dispatch: Dispatch },
) => {
const firstResult = results[index]
const firstResult = results[0];

if (!firstResult) return ``
if (!firstResult) return;

const { from, to } = results[index]
const { from, to } = results[0];

dispatch?.(state.tr.insertText(replaceTerm, from, to))
if (dispatch) dispatch(state.tr.insertText(replaceTerm, from, to));
};

const rebaseNextResult = (
Expand Down Expand Up @@ -196,13 +209,14 @@ const replaceAll = (
results: Range[],
{ tr, dispatch }: { tr: Transaction; dispatch: Dispatch },
) => {
let offset = 0
let resultsCopy = results.slice()
let offset = 0;

let resultsCopy = results.slice();

if (!resultsCopy.length) return;

for (let i = 0; i < resultsCopy.length; i += 1) {
const { from, to } = resultsCopy[i]
const { from, to } = resultsCopy[i];

tr.insertText(replaceTerm, from, to);

Expand All @@ -219,7 +233,7 @@ const replaceAll = (
resultsCopy = rebaseNextResultResponse[1];
}

dispatch?.(tr)
dispatch(tr);
};

export const searchAndReplacePluginKey = new PluginKey(
Expand Down Expand Up @@ -298,23 +312,42 @@ export const SearchAndReplace = Extension.create<

return false;
},
next:
nextSearchResult:
() =>
({ editor }) => {
const { results, resultIndex } = editor.storage.searchAndReplace;

if (results[resultIndex + 1]) {
editor.storage.searchAndReplace.resultIndex = resultIndex + 1;
const nextIndex = resultIndex + 1;

if (results[nextIndex]) {
editor.storage.searchAndReplace.resultIndex = nextIndex;
} else {
editor.storage.searchAndReplace.resultIndex = 0;
}

return false;
},
previousSearchResult:
() =>
({ editor }) => {
const { results, resultIndex } = editor.storage.searchAndReplace;

const prevIndex = resultIndex - 1;

if (results[prevIndex]) {
editor.storage.searchAndReplace.resultIndex = prevIndex;
} else {
editor.storage.searchAndReplace.resultIndex = results.length - 1;
}

return false;
},
replace:
() =>
({ editor, state, dispatch }) => {
const { replaceTerm, results, resultIndex } = editor.storage.searchAndReplace;
const { replaceTerm, results } = editor.storage.searchAndReplace;

replace(replaceTerm, results, resultIndex, { state, dispatch });
replace(replaceTerm, results, { state, dispatch });

return false;
},
Expand Down Expand Up @@ -377,7 +410,7 @@ export const SearchAndReplace = Extension.create<
doc,
getRegex(searchTerm, disableRegex, caseSensitive),
searchResultClass,
resultIndex
resultIndex,
);

editor.storage.searchAndReplace.results = results;
Expand Down

0 comments on commit b5f27a1

Please sign in to comment.