@tiptap/extension-find-and-replace 3.30.1 → 3.30.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs CHANGED
@@ -1,94 +1,48 @@
1
- "use strict";
2
- var __defProp = Object.defineProperty;
3
- var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
- var __getOwnPropNames = Object.getOwnPropertyNames;
5
- var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
9
- };
10
- var __copyProps = (to, from, except, desc) => {
11
- if (from && typeof from === "object" || typeof from === "function") {
12
- for (let key of __getOwnPropNames(from))
13
- if (!__hasOwnProp.call(to, key) && key !== except)
14
- __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
- }
16
- return to;
17
- };
18
- var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
-
20
- // src/index.ts
21
- var index_exports = {};
22
- __export(index_exports, {
23
- FindAndReplace: () => FindAndReplace,
24
- FindAndReplacePlugin: () => FindAndReplacePlugin,
25
- FindAndReplacePluginKey: () => FindAndReplacePluginKey,
26
- createSearchRegex: () => createSearchRegex,
27
- currentResultClass: () => currentResultClass,
28
- default: () => index_default,
29
- findNextIndex: () => findNextIndex,
30
- resultClass: () => resultClass,
31
- searchDocument: () => searchDocument,
32
- searchTextblocks: () => searchTextblocks
1
+ Object.defineProperties(exports, {
2
+ __esModule: { value: true },
3
+ [Symbol.toStringTag]: { value: "Module" }
33
4
  });
34
- module.exports = __toCommonJS(index_exports);
35
-
36
- // src/find-and-replace.ts
37
- var import_core = require("@tiptap/core");
38
- var import_state2 = require("@tiptap/pm/state");
39
-
40
- // src/state/debounced-search-state.ts
41
- var debouncedSearchState = /* @__PURE__ */ new WeakMap();
5
+ let _tiptap_core = require("@tiptap/core");
6
+ let _tiptap_pm_state = require("@tiptap/pm/state");
7
+ let re2js = require("re2js");
8
+ let _tiptap_pm_view = require("@tiptap/pm/view");
9
+ //#region src/state/debounced-search-state.ts
10
+ const debouncedSearchState = /* @__PURE__ */ new WeakMap();
42
11
  function getDebouncedSearchState(editor) {
43
- const existingState = debouncedSearchState.get(editor);
44
- if (existingState) {
45
- return existingState;
46
- }
47
- const nextState = {
48
- timeout: null,
49
- pendingTerm: null
50
- };
51
- debouncedSearchState.set(editor, nextState);
52
- return nextState;
12
+ const existingState = debouncedSearchState.get(editor);
13
+ if (existingState) return existingState;
14
+ const nextState = {
15
+ timeout: null,
16
+ pendingTerm: null
17
+ };
18
+ debouncedSearchState.set(editor, nextState);
19
+ return nextState;
53
20
  }
54
21
  function clearDebouncedSearchState(editor) {
55
- const state = debouncedSearchState.get(editor);
56
- if (!state) {
57
- return;
58
- }
59
- if (state.timeout !== null) {
60
- clearTimeout(state.timeout);
61
- }
62
- debouncedSearchState.delete(editor);
63
- }
64
-
65
- // src/plugin/plugin.ts
66
- var import_state = require("@tiptap/pm/state");
67
-
68
- // src/constants/constants.ts
69
- var resultClass = "find-and-replace-result";
70
- var currentResultClass = "find-and-replace-result-current";
71
-
72
- // src/style/create-style-tag.ts
73
- var createStyleTag = (style2, nonce) => {
74
- const existing = document.querySelector(
75
- "style[data-tiptap-extension-find-and-replace-style]"
76
- );
77
- if (existing !== null) {
78
- return existing;
79
- }
80
- const styleNode = document.createElement("style");
81
- if (nonce) {
82
- styleNode.setAttribute("nonce", nonce);
83
- }
84
- styleNode.setAttribute("data-tiptap-extension-find-and-replace-style", "");
85
- styleNode.textContent = style2;
86
- document.getElementsByTagName("head")[0].appendChild(styleNode);
87
- return styleNode;
22
+ const state = debouncedSearchState.get(editor);
23
+ if (!state) return;
24
+ if (state.timeout !== null) clearTimeout(state.timeout);
25
+ debouncedSearchState.delete(editor);
26
+ }
27
+ //#endregion
28
+ //#region src/constants/constants.ts
29
+ const resultClass = "find-and-replace-result";
30
+ const currentResultClass = "find-and-replace-result-current";
31
+ //#endregion
32
+ //#region src/style/create-style-tag.ts
33
+ const createStyleTag = (style, nonce) => {
34
+ const existing = document.querySelector("style[data-tiptap-extension-find-and-replace-style]");
35
+ if (existing !== null) return existing;
36
+ const styleNode = document.createElement("style");
37
+ if (nonce) styleNode.setAttribute("nonce", nonce);
38
+ styleNode.setAttribute("data-tiptap-extension-find-and-replace-style", "");
39
+ styleNode.textContent = style;
40
+ document.getElementsByTagName("head")[0].appendChild(styleNode);
41
+ return styleNode;
88
42
  };
89
-
90
- // src/style/style.ts
91
- var style = `.find-and-replace-result {
43
+ //#endregion
44
+ //#region src/style/style.ts
45
+ const style = `.find-and-replace-result {
92
46
  background-color: rgb(255 225 0 / 0.4);
93
47
  }
94
48
 
@@ -96,855 +50,769 @@ var style = `.find-and-replace-result {
96
50
  background-color: rgb(255 165 0 / 0.55);
97
51
  }
98
52
  `;
99
-
100
- // src/search/regex.ts
101
- var import_re2js = require("re2js");
102
- var escapeRegExp = (value) => {
103
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
53
+ //#endregion
54
+ //#region src/search/regex.ts
55
+ const escapeRegExp = (value) => {
56
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
104
57
  };
105
- var unicodeWordCharacter = "[\\p{L}\\p{M}\\p{N}\\p{Pc}]";
58
+ /** Unicode word characters like letters, accents, numbers, and underscore-like punctuation. */
59
+ const unicodeWordCharacter = "[\\p{L}\\p{M}\\p{N}\\p{Pc}]";
106
60
  function compileNativeRegex(source, caseSensitive) {
107
- try {
108
- return new RegExp(source, caseSensitive ? "gu" : "giu");
109
- } catch {
110
- return null;
111
- }
61
+ try {
62
+ return new RegExp(source, caseSensitive ? "gu" : "giu");
63
+ } catch {
64
+ return null;
65
+ }
112
66
  }
113
67
  function compileSafeRegex(source, caseSensitive) {
114
- try {
115
- const flags = caseSensitive ? 0 : import_re2js.RE2JS.CASE_INSENSITIVE;
116
- return import_re2js.RE2JS.compile(source, flags);
117
- } catch {
118
- return null;
119
- }
68
+ try {
69
+ const flags = caseSensitive ? 0 : re2js.RE2JS.CASE_INSENSITIVE;
70
+ return re2js.RE2JS.compile(source, flags);
71
+ } catch {
72
+ return null;
73
+ }
120
74
  }
121
75
  function compileRegex(source, options) {
122
- return options.useRegex ? compileSafeRegex(source, options.caseSensitive) : compileNativeRegex(source, options.caseSensitive);
123
- }
76
+ return options.useRegex ? compileSafeRegex(source, options.caseSensitive) : compileNativeRegex(source, options.caseSensitive);
77
+ }
78
+ /**
79
+ * Creates a search matcher for a term.
80
+ * Regex mode uses RE2-compatible syntax to avoid catastrophic backtracking.
81
+ * @param term The search term, treated as regex source when `useRegex` is enabled.
82
+ * @param options Case sensitivity, regex mode, and whole word matching.
83
+ * @returns A compiled matcher, or `null` when the term is invalid or unsupported.
84
+ */
124
85
  function createSearchRegex(term, options) {
125
- if (!term) {
126
- return null;
127
- }
128
- let source;
129
- if (options.useRegex) {
130
- source = term;
131
- } else {
132
- const escaped = escapeRegExp(term);
133
- source = options.wholeWord ? `(?<!${unicodeWordCharacter})${escaped}(?!${unicodeWordCharacter})` : escaped;
134
- }
135
- return compileRegex(source, options);
136
- }
137
-
138
- // src/search/matches.ts
86
+ if (!term) return null;
87
+ let source;
88
+ if (options.useRegex) source = term;
89
+ else {
90
+ const escaped = escapeRegExp(term);
91
+ source = options.wholeWord ? `(?<!${unicodeWordCharacter})${escaped}(?!${unicodeWordCharacter})` : escaped;
92
+ }
93
+ return compileRegex(source, options);
94
+ }
95
+ //#endregion
96
+ //#region src/search/matches.ts
139
97
  function* findNativeMatches(regex, text) {
140
- for (const match of text.matchAll(regex)) {
141
- yield { index: match.index, value: match[0] };
142
- }
98
+ for (const match of text.matchAll(regex)) yield {
99
+ index: match.index,
100
+ value: match[0]
101
+ };
143
102
  }
144
103
  function* findSafeMatches(regex, text) {
145
- var _a;
146
- const matcher = regex.matcher(text);
147
- while (matcher.find()) {
148
- yield { index: matcher.start(), value: (_a = matcher.group()) != null ? _a : "" };
149
- }
104
+ const matcher = regex.matcher(text);
105
+ while (matcher.find()) {
106
+ var _matcher$group;
107
+ yield {
108
+ index: matcher.start(),
109
+ value: (_matcher$group = matcher.group()) !== null && _matcher$group !== void 0 ? _matcher$group : ""
110
+ };
111
+ }
150
112
  }
151
113
  function findMatches(regex, text) {
152
- return regex instanceof RegExp ? findNativeMatches(regex, text) : findSafeMatches(regex, text);
114
+ return regex instanceof RegExp ? findNativeMatches(regex, text) : findSafeMatches(regex, text);
153
115
  }
154
-
155
- // src/search/text-segments.ts
116
+ //#endregion
117
+ //#region src/search/text-segments.ts
156
118
  function getTextSegments(textblock, pos) {
157
- const segments = [];
158
- let textOffset = 0;
159
- textblock.forEach((child, offset) => {
160
- var _a;
161
- const text = child.isText ? (_a = child.text) != null ? _a : "" : "\n";
162
- segments.push({
163
- isText: child.isText,
164
- pos: pos + 1 + offset,
165
- length: child.nodeSize,
166
- text,
167
- textOffset
168
- });
169
- textOffset += text.length;
170
- });
171
- return segments;
119
+ const segments = [];
120
+ let textOffset = 0;
121
+ textblock.forEach((child, offset) => {
122
+ var _child$text;
123
+ const text = child.isText ? (_child$text = child.text) !== null && _child$text !== void 0 ? _child$text : "" : "\n";
124
+ segments.push({
125
+ isText: child.isText,
126
+ pos: pos + 1 + offset,
127
+ length: child.nodeSize,
128
+ text,
129
+ textOffset
130
+ });
131
+ textOffset += text.length;
132
+ });
133
+ return segments;
172
134
  }
173
135
  function findOffsetSegment(segments, offset) {
174
- var _a;
175
- let low = 0;
176
- let high = segments.length;
177
- while (low < high) {
178
- const middle = Math.floor((low + high) / 2);
179
- const segment = segments[middle];
180
- const segmentEnd = segment.textOffset + segment.text.length;
181
- if (offset < segmentEnd) {
182
- high = middle;
183
- } else {
184
- low = middle + 1;
185
- }
186
- }
187
- return (_a = segments[low]) != null ? _a : segments.at(-1);
136
+ var _segments$low;
137
+ let low = 0;
138
+ let high = segments.length;
139
+ while (low < high) {
140
+ const middle = Math.floor((low + high) / 2);
141
+ const segment = segments[middle];
142
+ if (offset < segment.textOffset + segment.text.length) high = middle;
143
+ else low = middle + 1;
144
+ }
145
+ return (_segments$low = segments[low]) !== null && _segments$low !== void 0 ? _segments$low : segments.at(-1);
188
146
  }
189
147
  function offsetToPos(segments, offset) {
190
- const segment = findOffsetSegment(segments, offset);
191
- return segment ? segment.pos + Math.min(offset - segment.textOffset, segment.length) : 0;
148
+ const segment = findOffsetSegment(segments, offset);
149
+ return segment ? segment.pos + Math.min(offset - segment.textOffset, segment.length) : 0;
192
150
  }
193
151
  function overlapsNonTextSegment(segments, from, to) {
194
- return segments.some(
195
- (segment) => !segment.isText && from < segment.textOffset + segment.text.length && to > segment.textOffset
196
- );
152
+ return segments.some((segment) => !segment.isText && from < segment.textOffset + segment.text.length && to > segment.textOffset);
197
153
  }
198
-
199
- // src/search/textblock-search.ts
154
+ //#endregion
155
+ //#region src/search/textblock-search.ts
200
156
  function searchTextblock(regex, textblock, pos) {
201
- const segments = getTextSegments(textblock, pos);
202
- const text = segments.map((segment) => segment.text).join("");
203
- const results = [];
204
- for (const match of findMatches(regex, text)) {
205
- if (match.value.length === 0) {
206
- continue;
207
- }
208
- const matchEnd = match.index + match.value.length;
209
- if (overlapsNonTextSegment(segments, match.index, matchEnd)) {
210
- continue;
211
- }
212
- results.push({
213
- from: offsetToPos(segments, match.index),
214
- to: offsetToPos(segments, matchEnd)
215
- });
216
- }
217
- return results;
218
- }
219
-
220
- // src/search/search.ts
157
+ const segments = getTextSegments(textblock, pos);
158
+ const text = segments.map((segment) => segment.text).join("");
159
+ const results = [];
160
+ for (const match of findMatches(regex, text)) {
161
+ if (match.value.length === 0) continue;
162
+ const matchEnd = match.index + match.value.length;
163
+ if (overlapsNonTextSegment(segments, match.index, matchEnd)) continue;
164
+ results.push({
165
+ from: offsetToPos(segments, match.index),
166
+ to: offsetToPos(segments, matchEnd)
167
+ });
168
+ }
169
+ return results;
170
+ }
171
+ //#endregion
172
+ //#region src/search/search.ts
173
+ /**
174
+ * Searches textblocks for a term and returns their matched ranges.
175
+ * @param textblocks The textblocks and their document positions.
176
+ * @param term The search term, treated as regex source when `useRegex` is enabled.
177
+ * @param options Case sensitivity, regex mode, and whole word matching.
178
+ * @returns The list of matched ranges in textblock order.
179
+ */
221
180
  function searchTextblocks(textblocks, term, options) {
222
- const regex = createSearchRegex(term, options);
223
- if (!regex) {
224
- return [];
225
- }
226
- return textblocks.flatMap(({ node, pos }) => searchTextblock(regex, node, pos));
227
- }
181
+ const regex = createSearchRegex(term, options);
182
+ if (!regex) return [];
183
+ return textblocks.flatMap(({ node, pos }) => searchTextblock(regex, node, pos));
184
+ }
185
+ /**
186
+ * Searches all textblocks of a document for a term and returns the matched ranges.
187
+ * Matches may span multiple text nodes (e.g. across marks), but never leave a textblock.
188
+ * @param doc The document to search in.
189
+ * @param term The search term, treated as regex source when `useRegex` is enabled.
190
+ * @param options Case sensitivity, regex mode, and whole word matching.
191
+ * @returns The list of matched ranges in document order.
192
+ */
228
193
  function searchDocument(doc, term, options) {
229
- const textblocks = [];
230
- doc.descendants((node, pos) => {
231
- if (!node.isTextblock) {
232
- return true;
233
- }
234
- textblocks.push({ node, pos });
235
- return false;
236
- });
237
- return searchTextblocks(textblocks, term, options);
238
- }
194
+ const textblocks = [];
195
+ doc.descendants((node, pos) => {
196
+ if (!node.isTextblock) return true;
197
+ textblocks.push({
198
+ node,
199
+ pos
200
+ });
201
+ return false;
202
+ });
203
+ return searchTextblocks(textblocks, term, options);
204
+ }
205
+ /**
206
+ * Finds the index of the first result at or after a position, wrapping around
207
+ * to the first result when the position is behind the last result.
208
+ * @param results The current search results.
209
+ * @param from The position to search from.
210
+ * @returns The result index, or `null` when there are no results.
211
+ */
239
212
  function findNextIndex(results, from) {
240
- if (results.length === 0) {
241
- return null;
242
- }
243
- const index = results.findIndex((result) => result.from >= from);
244
- return index === -1 ? 0 : index;
213
+ if (results.length === 0) return null;
214
+ const index = results.findIndex((result) => result.from >= from);
215
+ return index === -1 ? 0 : index;
245
216
  }
246
-
247
- // src/utils/createDecorations.ts
248
- var import_view2 = require("@tiptap/pm/view");
249
-
250
- // src/utils/createDecoration.ts
251
- var import_view = require("@tiptap/pm/view");
217
+ //#endregion
218
+ //#region src/utils/createDecoration.ts
252
219
  function createDecoration(result, currentIndex, index) {
253
- const className = index === currentIndex ? `${resultClass} ${currentResultClass}` : resultClass;
254
- return import_view.Decoration.inline(result.from, result.to, { class: className });
220
+ const className = index === currentIndex ? `${resultClass} ${currentResultClass}` : resultClass;
221
+ return _tiptap_pm_view.Decoration.inline(result.from, result.to, { class: className });
255
222
  }
256
-
257
- // src/utils/createDecorations.ts
223
+ //#endregion
224
+ //#region src/utils/createDecorations.ts
258
225
  function createDecorations(doc, results, currentIndex) {
259
- const decorations = results.map((result, index) => createDecoration(result, currentIndex, index));
260
- return import_view2.DecorationSet.create(doc, decorations);
226
+ const decorations = results.map((result, index) => createDecoration(result, currentIndex, index));
227
+ return _tiptap_pm_view.DecorationSet.create(doc, decorations);
261
228
  }
262
-
263
- // src/utils/createState.ts
229
+ //#endregion
230
+ //#region src/utils/createState.ts
264
231
  function createState(doc, options) {
265
- const results = searchDocument(doc, options.searchTerm, options);
266
- const currentIndex = results.length > 0 ? 0 : null;
267
- return {
268
- searchTerm: options.searchTerm,
269
- replaceTerm: options.replaceTerm,
270
- caseSensitive: options.caseSensitive,
271
- useRegex: options.useRegex,
272
- wholeWord: options.wholeWord,
273
- results,
274
- currentIndex,
275
- decorations: createDecorations(doc, results, currentIndex)
276
- };
277
- }
278
-
279
- // src/utils/hasCurrentIndex.ts
232
+ const results = searchDocument(doc, options.searchTerm, options);
233
+ const currentIndex = results.length > 0 ? 0 : null;
234
+ return {
235
+ searchTerm: options.searchTerm,
236
+ replaceTerm: options.replaceTerm,
237
+ caseSensitive: options.caseSensitive,
238
+ useRegex: options.useRegex,
239
+ wholeWord: options.wholeWord,
240
+ results,
241
+ currentIndex,
242
+ decorations: createDecorations(doc, results, currentIndex)
243
+ };
244
+ }
245
+ //#endregion
246
+ //#region src/utils/hasCurrentIndex.ts
280
247
  function hasCurrentIndex(meta) {
281
- return !!meta && "currentIndex" in meta;
248
+ return !!meta && "currentIndex" in meta;
282
249
  }
283
-
284
- // src/utils/findDecorations.ts
250
+ //#endregion
251
+ //#region src/utils/findDecorations.ts
285
252
  function findDecorations(decorations, results, textblocks) {
286
- const found = /* @__PURE__ */ new Set();
287
- textblocks.forEach((textblock) => {
288
- decorations.find(textblock.from, textblock.to).forEach((decoration) => found.add(decoration));
289
- });
290
- results.forEach((result) => {
291
- decorations.find(result.from, result.to).filter((decoration) => {
292
- return decoration.from === result.from && decoration.to === result.to;
293
- }).forEach((decoration) => found.add(decoration));
294
- });
295
- return [...found];
296
- }
297
-
298
- // src/utils/sameResult.ts
253
+ const found = /* @__PURE__ */ new Set();
254
+ textblocks.forEach((textblock) => {
255
+ decorations.find(textblock.from, textblock.to).forEach((decoration) => found.add(decoration));
256
+ });
257
+ results.forEach((result) => {
258
+ decorations.find(result.from, result.to).filter((decoration) => {
259
+ return decoration.from === result.from && decoration.to === result.to;
260
+ }).forEach((decoration) => found.add(decoration));
261
+ });
262
+ return [...found];
263
+ }
264
+ //#endregion
265
+ //#region src/utils/sameResult.ts
299
266
  function sameResult(first, second) {
300
- return first.from === second.from && first.to === second.to;
267
+ return first.from === second.from && first.to === second.to;
301
268
  }
302
-
303
- // src/utils/isCurrentResult.ts
269
+ //#endregion
270
+ //#region src/utils/isCurrentResult.ts
304
271
  function isCurrentResult(result, current) {
305
- return current !== null && sameResult(result, current);
272
+ return current !== null && sameResult(result, current);
306
273
  }
307
-
308
- // src/utils/resultInTextblocks.ts
274
+ //#endregion
275
+ //#region src/utils/resultInTextblocks.ts
309
276
  function resultInTextblocks(result, textblocks) {
310
- let start = 0;
311
- let end = textblocks.length - 1;
312
- while (start <= end) {
313
- const index = Math.floor((start + end) / 2);
314
- const textblock = textblocks[index];
315
- if (result.from < textblock.from) {
316
- end = index - 1;
317
- continue;
318
- }
319
- if (result.to > textblock.to) {
320
- start = index + 1;
321
- continue;
322
- }
323
- return true;
324
- }
325
- return false;
326
- }
327
-
328
- // src/utils/shouldRefreshResult.ts
277
+ let start = 0;
278
+ let end = textblocks.length - 1;
279
+ while (start <= end) {
280
+ const index = Math.floor((start + end) / 2);
281
+ const textblock = textblocks[index];
282
+ if (result.from < textblock.from) {
283
+ end = index - 1;
284
+ continue;
285
+ }
286
+ if (result.to > textblock.to) {
287
+ start = index + 1;
288
+ continue;
289
+ }
290
+ return true;
291
+ }
292
+ return false;
293
+ }
294
+ //#endregion
295
+ //#region src/utils/shouldRefreshResult.ts
329
296
  function shouldRefreshResult(result, textblocks, previousCurrent, current) {
330
- return resultInTextblocks(result, textblocks) || isCurrentResult(result, previousCurrent) || isCurrentResult(result, current);
297
+ return resultInTextblocks(result, textblocks) || isCurrentResult(result, previousCurrent) || isCurrentResult(result, current);
331
298
  }
332
-
333
- // src/utils/getResultsToRefresh.ts
299
+ //#endregion
300
+ //#region src/utils/getResultsToRefresh.ts
334
301
  function getResultsToRefresh(results, textblocks, previousCurrent, currentIndex) {
335
- var _a;
336
- const current = currentIndex === null ? null : (_a = results[currentIndex]) != null ? _a : null;
337
- const refreshedResults = [];
338
- results.forEach((result, index) => {
339
- if (shouldRefreshResult(result, textblocks, previousCurrent, current)) {
340
- refreshedResults.push({ result, index });
341
- }
342
- });
343
- return refreshedResults;
344
- }
345
-
346
- // src/utils/refreshDecorations.ts
302
+ var _results$currentIndex;
303
+ const current = currentIndex === null ? null : (_results$currentIndex = results[currentIndex]) !== null && _results$currentIndex !== void 0 ? _results$currentIndex : null;
304
+ const refreshedResults = [];
305
+ results.forEach((result, index) => {
306
+ if (shouldRefreshResult(result, textblocks, previousCurrent, current)) refreshedResults.push({
307
+ result,
308
+ index
309
+ });
310
+ });
311
+ return refreshedResults;
312
+ }
313
+ //#endregion
314
+ //#region src/utils/refreshDecorations.ts
347
315
  function refreshDecorations(decorations, doc, results, currentIndex, textblocks, previousCurrent) {
348
- const resultsToRefresh = getResultsToRefresh(results, textblocks, previousCurrent, currentIndex);
349
- const refreshedResults = resultsToRefresh.map(({ result }) => result);
350
- const staleResults = previousCurrent ? [...refreshedResults, previousCurrent] : refreshedResults;
351
- const decorationsToRemove = findDecorations(decorations, staleResults, textblocks);
352
- const decorationsToAdd = resultsToRefresh.map(({ result, index }) => {
353
- return createDecoration(result, currentIndex, index);
354
- });
355
- return decorations.remove(decorationsToRemove).add(doc, decorationsToAdd);
356
- }
357
-
358
- // src/utils/normalizeCurrentIndex.ts
316
+ const resultsToRefresh = getResultsToRefresh(results, textblocks, previousCurrent, currentIndex);
317
+ const refreshedResults = resultsToRefresh.map(({ result }) => result);
318
+ const decorationsToRemove = findDecorations(decorations, previousCurrent ? [...refreshedResults, previousCurrent] : refreshedResults, textblocks);
319
+ const decorationsToAdd = resultsToRefresh.map(({ result, index }) => {
320
+ return createDecoration(result, currentIndex, index);
321
+ });
322
+ return decorations.remove(decorationsToRemove).add(doc, decorationsToAdd);
323
+ }
324
+ //#endregion
325
+ //#region src/utils/normalizeCurrentIndex.ts
359
326
  function normalizeCurrentIndex(currentIndex, length) {
360
- if (currentIndex === void 0 || currentIndex === null || length === 0) {
361
- return null;
362
- }
363
- return Math.max(0, Math.min(currentIndex, length - 1));
327
+ if (currentIndex === void 0 || currentIndex === null || length === 0) return null;
328
+ return Math.max(0, Math.min(currentIndex, length - 1));
364
329
  }
365
-
366
- // src/utils/getMetaCurrentIndex.ts
330
+ //#endregion
331
+ //#region src/utils/getMetaCurrentIndex.ts
367
332
  function getMetaCurrentIndex(meta, length) {
368
- if (!meta) {
369
- return void 0;
370
- }
371
- if (!hasCurrentIndex(meta)) {
372
- return void 0;
373
- }
374
- return normalizeCurrentIndex(meta.currentIndex, length);
333
+ if (!meta) return;
334
+ if (!hasCurrentIndex(meta)) return;
335
+ return normalizeCurrentIndex(meta.currentIndex, length);
375
336
  }
376
-
377
- // src/utils/getFallbackCurrentIndex.ts
337
+ //#endregion
338
+ //#region src/utils/getFallbackCurrentIndex.ts
378
339
  function getFallbackCurrentIndex(previousState, length) {
379
- return previousState.currentIndex === null ? 0 : Math.min(previousState.currentIndex, length - 1);
340
+ return previousState.currentIndex === null ? 0 : Math.min(previousState.currentIndex, length - 1);
380
341
  }
381
-
382
- // src/utils/getPreviousCurrentResult.ts
342
+ //#endregion
343
+ //#region src/utils/getPreviousCurrentResult.ts
383
344
  function getPreviousCurrentResult(previousState) {
384
- return previousState.currentIndex === null ? void 0 : previousState.results[previousState.currentIndex];
345
+ return previousState.currentIndex === null ? void 0 : previousState.results[previousState.currentIndex];
385
346
  }
386
-
387
- // src/utils/getMappedCurrentIndex.ts
347
+ //#endregion
348
+ //#region src/utils/getMappedCurrentIndex.ts
388
349
  function getMappedCurrentIndex(previousState, results, docChanged, mapping) {
389
- if (!docChanged) {
390
- return void 0;
391
- }
392
- if (!mapping) {
393
- return void 0;
394
- }
395
- const previousResult = getPreviousCurrentResult(previousState);
396
- if (!previousResult) {
397
- return void 0;
398
- }
399
- const mappedFrom = mapping.map(previousResult.from, 1);
400
- return findNextIndex(results, mappedFrom);
401
- }
402
-
403
- // src/utils/isNewSearch.ts
350
+ if (!docChanged) return;
351
+ if (!mapping) return;
352
+ const previousResult = getPreviousCurrentResult(previousState);
353
+ if (!previousResult) return;
354
+ return findNextIndex(results, mapping.map(previousResult.from, 1));
355
+ }
356
+ //#endregion
357
+ //#region src/utils/isNewSearch.ts
404
358
  function isNewSearch(meta) {
405
- return !!meta && "searchTerm" in meta;
359
+ return !!meta && "searchTerm" in meta;
406
360
  }
407
-
408
- // src/utils/getSearchCurrentIndex.ts
361
+ //#endregion
362
+ //#region src/utils/getSearchCurrentIndex.ts
409
363
  function getSearchCurrentIndex(previousState, results, meta, docChanged, mapping) {
410
- if (isNewSearch(meta)) {
411
- return 0;
412
- }
413
- const mappedIndex = getMappedCurrentIndex(previousState, results, docChanged, mapping);
414
- return mappedIndex != null ? mappedIndex : getFallbackCurrentIndex(previousState, results.length);
364
+ if (isNewSearch(meta)) return 0;
365
+ const mappedIndex = getMappedCurrentIndex(previousState, results, docChanged, mapping);
366
+ return mappedIndex !== null && mappedIndex !== void 0 ? mappedIndex : getFallbackCurrentIndex(previousState, results.length);
415
367
  }
416
-
417
- // src/utils/resolveCurrentIndex.ts
368
+ //#endregion
369
+ //#region src/utils/resolveCurrentIndex.ts
418
370
  function resolveCurrentIndex(previousState, results, meta, docChanged, mapping) {
419
- if (results.length === 0) {
420
- return null;
421
- }
422
- const metaIndex = getMetaCurrentIndex(meta, results.length);
423
- if (metaIndex !== void 0) {
424
- return metaIndex;
425
- }
426
- return getSearchCurrentIndex(previousState, results, meta, docChanged, mapping);
371
+ if (results.length === 0) return null;
372
+ const metaIndex = getMetaCurrentIndex(meta, results.length);
373
+ if (metaIndex !== void 0) return metaIndex;
374
+ return getSearchCurrentIndex(previousState, results, meta, docChanged, mapping);
427
375
  }
428
-
429
- // src/utils/refreshCurrentIndexState.ts
376
+ //#endregion
377
+ //#region src/utils/refreshCurrentIndexState.ts
430
378
  function refreshCurrentIndexState(previousState, state, doc, meta) {
431
- const currentIndex = resolveCurrentIndex(previousState, state.results, meta, false, void 0);
432
- const previousCurrent = previousState.currentIndex === null ? null : previousState.results[previousState.currentIndex];
433
- return {
434
- ...state,
435
- currentIndex,
436
- decorations: refreshDecorations(
437
- previousState.decorations,
438
- doc,
439
- state.results,
440
- currentIndex,
441
- [],
442
- previousCurrent
443
- )
444
- };
445
- }
446
-
447
- // src/utils/getChangedTextblocks.ts
379
+ const currentIndex = resolveCurrentIndex(previousState, state.results, meta, false, void 0);
380
+ const previousCurrent = previousState.currentIndex === null ? null : previousState.results[previousState.currentIndex];
381
+ return {
382
+ ...state,
383
+ currentIndex,
384
+ decorations: refreshDecorations(previousState.decorations, doc, state.results, currentIndex, [], previousCurrent)
385
+ };
386
+ }
387
+ //#endregion
388
+ //#region src/utils/getChangedTextblocks.ts
448
389
  function getChangedTextblocks(doc, mapping) {
449
- const textblocks = /* @__PURE__ */ new Map();
450
- mapping.maps.forEach((stepMap, index) => {
451
- const remaining = mapping.slice(index + 1);
452
- stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
453
- const from = Math.max(0, remaining.map(newStart, -1) - 1);
454
- const to = Math.min(doc.content.size, remaining.map(newEnd, 1) + 1);
455
- doc.nodesBetween(from, to, (node, pos) => {
456
- if (!node.isTextblock) {
457
- return true;
458
- }
459
- textblocks.set(pos, { node, pos, from: pos, to: pos + node.nodeSize });
460
- return false;
461
- });
462
- });
463
- });
464
- return [...textblocks.values()].sort((first, second) => first.pos - second.pos);
465
- }
466
-
467
- // src/utils/mapResult.ts
390
+ const textblocks = /* @__PURE__ */ new Map();
391
+ mapping.maps.forEach((stepMap, index) => {
392
+ const remaining = mapping.slice(index + 1);
393
+ stepMap.forEach((_oldStart, _oldEnd, newStart, newEnd) => {
394
+ const from = Math.max(0, remaining.map(newStart, -1) - 1);
395
+ const to = Math.min(doc.content.size, remaining.map(newEnd, 1) + 1);
396
+ doc.nodesBetween(from, to, (node, pos) => {
397
+ if (!node.isTextblock) return true;
398
+ textblocks.set(pos, {
399
+ node,
400
+ pos,
401
+ from: pos,
402
+ to: pos + node.nodeSize
403
+ });
404
+ return false;
405
+ });
406
+ });
407
+ });
408
+ return [...textblocks.values()].sort((first, second) => first.pos - second.pos);
409
+ }
410
+ //#endregion
411
+ //#region src/utils/mapResult.ts
468
412
  function mapResult(result, mapping) {
469
- const from = mapping.map(result.from, 1);
470
- const to = mapping.map(result.to, -1);
471
- return from < to ? { from, to } : null;
472
- }
473
-
474
- // src/utils/mapResults.ts
413
+ const from = mapping.map(result.from, 1);
414
+ const to = mapping.map(result.to, -1);
415
+ return from < to ? {
416
+ from,
417
+ to
418
+ } : null;
419
+ }
420
+ //#endregion
421
+ //#region src/utils/mapResults.ts
475
422
  function mapResults(results, mapping) {
476
- const mappedResults = [];
477
- results.forEach((result) => {
478
- const mapped = mapResult(result, mapping);
479
- if (mapped) {
480
- mappedResults.push(mapped);
481
- }
482
- });
483
- return mappedResults;
484
- }
485
-
486
- // src/utils/mergeResults.ts
423
+ const mappedResults = [];
424
+ results.forEach((result) => {
425
+ const mapped = mapResult(result, mapping);
426
+ if (mapped) mappedResults.push(mapped);
427
+ });
428
+ return mappedResults;
429
+ }
430
+ //#endregion
431
+ //#region src/utils/mergeResults.ts
487
432
  function mergeResults(first, second) {
488
- const results = [];
489
- let firstIndex = 0;
490
- let secondIndex = 0;
491
- while (firstIndex < first.length && secondIndex < second.length) {
492
- if (first[firstIndex].from < second[secondIndex].from) {
493
- results.push(first[firstIndex++]);
494
- continue;
495
- }
496
- results.push(second[secondIndex++]);
497
- }
498
- return results.concat(first.slice(firstIndex), second.slice(secondIndex));
499
- }
500
-
501
- // src/utils/refreshDocumentState.ts
433
+ const results = [];
434
+ let firstIndex = 0;
435
+ let secondIndex = 0;
436
+ while (firstIndex < first.length && secondIndex < second.length) {
437
+ if (first[firstIndex].from < second[secondIndex].from) {
438
+ results.push(first[firstIndex++]);
439
+ continue;
440
+ }
441
+ results.push(second[secondIndex++]);
442
+ }
443
+ return results.concat(first.slice(firstIndex), second.slice(secondIndex));
444
+ }
445
+ //#endregion
446
+ //#region src/utils/refreshDocumentState.ts
502
447
  function refreshDocumentState(previousState, state, doc, meta, mapping) {
503
- const textblocks = getChangedTextblocks(doc, mapping);
504
- const mappedResults = mapResults(previousState.results, mapping);
505
- const unaffectedResults = mappedResults.filter((result) => !resultInTextblocks(result, textblocks));
506
- const changedResults = searchTextblocks(textblocks, state.searchTerm, state);
507
- const results = mergeResults(unaffectedResults, changedResults);
508
- const currentIndex = resolveCurrentIndex(previousState, results, meta, true, mapping);
509
- const previousCurrent = previousState.currentIndex === null ? null : mapResult(previousState.results[previousState.currentIndex], mapping);
510
- const decorations = previousState.decorations.map(mapping, doc);
511
- return {
512
- ...state,
513
- results,
514
- currentIndex,
515
- decorations: refreshDecorations(
516
- decorations,
517
- doc,
518
- results,
519
- currentIndex,
520
- textblocks,
521
- previousCurrent
522
- )
523
- };
524
- }
525
-
526
- // src/utils/refreshState.ts
448
+ const textblocks = getChangedTextblocks(doc, mapping);
449
+ const results = mergeResults(mapResults(previousState.results, mapping).filter((result) => !resultInTextblocks(result, textblocks)), searchTextblocks(textblocks, state.searchTerm, state));
450
+ const currentIndex = resolveCurrentIndex(previousState, results, meta, true, mapping);
451
+ const previousCurrent = previousState.currentIndex === null ? null : mapResult(previousState.results[previousState.currentIndex], mapping);
452
+ const decorations = previousState.decorations.map(mapping, doc);
453
+ return {
454
+ ...state,
455
+ results,
456
+ currentIndex,
457
+ decorations: refreshDecorations(decorations, doc, results, currentIndex, textblocks, previousCurrent)
458
+ };
459
+ }
460
+ //#endregion
461
+ //#region src/utils/refreshState.ts
527
462
  function refreshState(previousState, state, doc, meta, docChanged, mapping) {
528
- const results = searchDocument(doc, state.searchTerm, state);
529
- const currentIndex = resolveCurrentIndex(previousState, results, meta, docChanged, mapping);
530
- return {
531
- ...state,
532
- results,
533
- currentIndex,
534
- decorations: createDecorations(doc, results, currentIndex)
535
- };
536
- }
537
-
538
- // src/utils/touchesSearch.ts
539
- var searchKeys = ["searchTerm", "caseSensitive", "useRegex", "wholeWord"];
463
+ const results = searchDocument(doc, state.searchTerm, state);
464
+ const currentIndex = resolveCurrentIndex(previousState, results, meta, docChanged, mapping);
465
+ return {
466
+ ...state,
467
+ results,
468
+ currentIndex,
469
+ decorations: createDecorations(doc, results, currentIndex)
470
+ };
471
+ }
472
+ //#endregion
473
+ //#region src/utils/touchesSearch.ts
474
+ const searchKeys = [
475
+ "searchTerm",
476
+ "caseSensitive",
477
+ "useRegex",
478
+ "wholeWord"
479
+ ];
540
480
  function touchesSearch(meta) {
541
- return !!meta && searchKeys.some((key) => key in meta);
481
+ return !!meta && searchKeys.some((key) => key in meta);
542
482
  }
543
-
544
- // src/utils/updateState.ts
483
+ //#endregion
484
+ //#region src/utils/updateState.ts
545
485
  function updateState(previousState, state, doc, meta, docChanged, mapping) {
546
- if (touchesSearch(meta)) {
547
- return refreshState(previousState, state, doc, meta, docChanged, mapping);
548
- }
549
- if (docChanged) {
550
- return refreshDocumentState(previousState, state, doc, meta, mapping);
551
- }
552
- if (hasCurrentIndex(meta)) {
553
- return refreshCurrentIndexState(previousState, state, doc, meta);
554
- }
555
- return state;
556
- }
557
-
558
- // src/plugin/plugin.ts
559
- var FindAndReplacePluginKey = new import_state.PluginKey("findAndReplace");
560
- var FindAndReplacePlugin = (options, onCreate) => {
561
- return new import_state.Plugin({
562
- key: FindAndReplacePluginKey,
563
- state: {
564
- init: (_config, state) => {
565
- if (options.injectCSS && typeof document !== "undefined") {
566
- createStyleTag(style, options.injectNonce);
567
- }
568
- const pluginState = createState(state.doc, options);
569
- onCreate(pluginState);
570
- return pluginState;
571
- },
572
- apply: (tr, state, _oldState, newState) => {
573
- const meta = tr.getMeta(FindAndReplacePluginKey);
574
- if (!meta && !tr.docChanged) {
575
- return state;
576
- }
577
- return updateState(
578
- state,
579
- { ...state, ...meta },
580
- newState.doc,
581
- meta,
582
- tr.docChanged,
583
- tr.mapping
584
- );
585
- }
586
- },
587
- props: {
588
- decorations(state) {
589
- var _a;
590
- return (_a = FindAndReplacePluginKey.getState(state)) == null ? void 0 : _a.decorations;
591
- }
592
- }
593
- });
486
+ if (touchesSearch(meta)) return refreshState(previousState, state, doc, meta, docChanged, mapping);
487
+ if (docChanged) return refreshDocumentState(previousState, state, doc, meta, mapping);
488
+ if (hasCurrentIndex(meta)) return refreshCurrentIndexState(previousState, state, doc, meta);
489
+ return state;
490
+ }
491
+ //#endregion
492
+ //#region src/plugin/plugin.ts
493
+ const FindAndReplacePluginKey = new _tiptap_pm_state.PluginKey("findAndReplace");
494
+ const FindAndReplacePlugin = (options, onCreate) => {
495
+ return new _tiptap_pm_state.Plugin({
496
+ key: FindAndReplacePluginKey,
497
+ state: {
498
+ init: (_config, state) => {
499
+ if (options.injectCSS && typeof document !== "undefined") createStyleTag(style, options.injectNonce);
500
+ const pluginState = createState(state.doc, options);
501
+ onCreate(pluginState);
502
+ return pluginState;
503
+ },
504
+ apply: (tr, state, _oldState, newState) => {
505
+ const meta = tr.getMeta(FindAndReplacePluginKey);
506
+ if (!meta && !tr.docChanged) return state;
507
+ return updateState(state, {
508
+ ...state,
509
+ ...meta
510
+ }, newState.doc, meta, tr.docChanged, tr.mapping);
511
+ }
512
+ },
513
+ props: { decorations(state) {
514
+ var _FindAndReplacePlugin;
515
+ return (_FindAndReplacePlugin = FindAndReplacePluginKey.getState(state)) === null || _FindAndReplacePlugin === void 0 ? void 0 : _FindAndReplacePlugin.decorations;
516
+ } }
517
+ });
594
518
  };
595
-
596
- // src/utils/getTextNodeResult.ts
519
+ //#endregion
520
+ //#region src/utils/getTextNodeResult.ts
597
521
  function getTextNodeResult(state, result) {
598
- const $from = state.doc.resolve(result.from);
599
- const node = $from.parent.child($from.index());
600
- if (!node.isText || !node.text) {
601
- return null;
602
- }
603
- const from = result.from - $from.textOffset;
604
- return result.to <= from + node.nodeSize ? { from, text: node.text } : null;
605
- }
606
-
607
- // src/utils/groupResults.ts
522
+ const $from = state.doc.resolve(result.from);
523
+ const node = $from.parent.child($from.index());
524
+ if (!node.isText || !node.text) return null;
525
+ const from = result.from - $from.textOffset;
526
+ return result.to <= from + node.nodeSize ? {
527
+ from,
528
+ text: node.text
529
+ } : null;
530
+ }
531
+ //#endregion
532
+ //#region src/utils/groupResults.ts
608
533
  function shouldMergeResult(group, textNode) {
609
- if (!group || !textNode) {
610
- return false;
611
- }
612
- return group.from === textNode.from && group.text !== null;
534
+ if (!group || !textNode) return false;
535
+ return group.from === textNode.from && group.text !== null;
613
536
  }
614
537
  function createTextResultGroup(result, textNode) {
615
- return {
616
- from: textNode.from,
617
- text: textNode.text,
618
- results: [result]
619
- };
538
+ return {
539
+ from: textNode.from,
540
+ text: textNode.text,
541
+ results: [result]
542
+ };
620
543
  }
621
544
  function createResultGroup(result) {
622
- return {
623
- from: result.from,
624
- text: null,
625
- results: [result]
626
- };
545
+ return {
546
+ from: result.from,
547
+ text: null,
548
+ results: [result]
549
+ };
627
550
  }
628
551
  function appendResult(groups, result, textNode) {
629
- const group = groups.at(-1);
630
- if (shouldMergeResult(group, textNode)) {
631
- group.results.push(result);
632
- return;
633
- }
634
- if (textNode) {
635
- groups.push(createTextResultGroup(result, textNode));
636
- return;
637
- }
638
- groups.push(createResultGroup(result));
552
+ const group = groups.at(-1);
553
+ if (shouldMergeResult(group, textNode)) {
554
+ group.results.push(result);
555
+ return;
556
+ }
557
+ if (textNode) {
558
+ groups.push(createTextResultGroup(result, textNode));
559
+ return;
560
+ }
561
+ groups.push(createResultGroup(result));
639
562
  }
640
563
  function groupResults(state, results) {
641
- const groups = [];
642
- for (const result of results) {
643
- appendResult(groups, result, getTextNodeResult(state, result));
644
- }
645
- return groups;
564
+ const groups = [];
565
+ for (const result of results) appendResult(groups, result, getTextNodeResult(state, result));
566
+ return groups;
646
567
  }
647
-
648
- // src/utils/replaceGroup.ts
568
+ //#endregion
569
+ //#region src/utils/replaceGroup.ts
649
570
  function replaceSeparateResults(tr, results, replaceTerm) {
650
- for (const result of [...results].reverse()) {
651
- tr.insertText(replaceTerm, result.from, result.to);
652
- }
571
+ for (const result of [...results].reverse()) tr.insertText(replaceTerm, result.from, result.to);
653
572
  }
654
573
  function createReplacement(group, text, firstResult, replaceTerm) {
655
- let offset = firstResult.from - group.from;
656
- const replacement = [];
657
- for (const result of group.results) {
658
- const from = result.from - group.from;
659
- const to = result.to - group.from;
660
- replacement.push(text.slice(offset, from), replaceTerm);
661
- offset = to;
662
- }
663
- return replacement.join("");
574
+ let offset = firstResult.from - group.from;
575
+ const replacement = [];
576
+ for (const result of group.results) {
577
+ const from = result.from - group.from;
578
+ const to = result.to - group.from;
579
+ replacement.push(text.slice(offset, from), replaceTerm);
580
+ offset = to;
581
+ }
582
+ return replacement.join("");
664
583
  }
665
584
  function replaceGroup(tr, group, replaceTerm) {
666
- const firstResult = group.results[0];
667
- const lastResult = group.results.at(-1);
668
- if (!lastResult) {
669
- return;
670
- }
671
- if (group.text === null) {
672
- replaceSeparateResults(tr, group.results, replaceTerm);
673
- return;
674
- }
675
- tr.insertText(
676
- createReplacement(group, group.text, firstResult, replaceTerm),
677
- firstResult.from,
678
- lastResult.to
679
- );
680
- }
681
-
682
- // src/utils/replaceAllResults.ts
585
+ const firstResult = group.results[0];
586
+ const lastResult = group.results.at(-1);
587
+ if (!lastResult) return;
588
+ if (group.text === null) {
589
+ replaceSeparateResults(tr, group.results, replaceTerm);
590
+ return;
591
+ }
592
+ tr.insertText(createReplacement(group, group.text, firstResult, replaceTerm), firstResult.from, lastResult.to);
593
+ }
594
+ //#endregion
595
+ //#region src/utils/replaceAllResults.ts
683
596
  function replaceAllResults(tr, state, results, replaceTerm) {
684
- const groups = groupResults(state, results);
685
- for (const group of groups.reverse()) {
686
- replaceGroup(tr, group, replaceTerm);
687
- }
597
+ const groups = groupResults(state, results);
598
+ for (const group of groups.reverse()) replaceGroup(tr, group, replaceTerm);
688
599
  }
689
-
690
- // src/find-and-replace.ts
600
+ //#endregion
601
+ //#region src/find-and-replace.ts
691
602
  function mergePluginMeta(tr, meta) {
692
- const currentMeta = tr.getMeta(FindAndReplacePluginKey);
693
- tr.setMeta(FindAndReplacePluginKey, { ...currentMeta, ...meta });
603
+ const currentMeta = tr.getMeta(FindAndReplacePluginKey);
604
+ tr.setMeta(FindAndReplacePluginKey, {
605
+ ...currentMeta,
606
+ ...meta
607
+ });
694
608
  }
695
609
  function setPluginMeta(meta) {
696
- return ({ tr, dispatch }) => {
697
- if (dispatch) {
698
- mergePluginMeta(tr, meta);
699
- }
700
- return true;
701
- };
610
+ return ({ tr, dispatch }) => {
611
+ if (dispatch) mergePluginMeta(tr, meta);
612
+ return true;
613
+ };
702
614
  }
703
615
  function applySearchTerm(editor, term) {
704
- const tr = editor.state.tr;
705
- mergePluginMeta(tr, { searchTerm: term });
706
- editor.view.dispatch(tr);
616
+ const tr = editor.state.tr;
617
+ mergePluginMeta(tr, { searchTerm: term });
618
+ editor.view.dispatch(tr);
707
619
  }
708
620
  function consumePendingSearch(editor) {
709
- const state = getDebouncedSearchState(editor);
710
- if (state.pendingTerm === null) {
711
- return null;
712
- }
713
- const pendingTerm = state.pendingTerm;
714
- state.pendingTerm = null;
715
- if (state.timeout !== null) {
716
- clearTimeout(state.timeout);
717
- state.timeout = null;
718
- }
719
- return pendingTerm;
621
+ const state = getDebouncedSearchState(editor);
622
+ if (state.pendingTerm === null) return null;
623
+ const pendingTerm = state.pendingTerm;
624
+ state.pendingTerm = null;
625
+ if (state.timeout !== null) {
626
+ clearTimeout(state.timeout);
627
+ state.timeout = null;
628
+ }
629
+ return pendingTerm;
720
630
  }
721
631
  function getPendingAwarePluginState(state, pendingTerm) {
722
- const pluginState = FindAndReplacePluginKey.getState(state);
723
- if (!pluginState) {
724
- return null;
725
- }
726
- if (pendingTerm === null) {
727
- return pluginState.results.length === 0 ? null : pluginState;
728
- }
729
- const results = searchDocument(state.doc, pendingTerm, {
730
- caseSensitive: pluginState.caseSensitive,
731
- useRegex: pluginState.useRegex,
732
- wholeWord: pluginState.wholeWord
733
- });
734
- if (results.length === 0) {
735
- return null;
736
- }
737
- return {
738
- ...pluginState,
739
- searchTerm: pendingTerm,
740
- results,
741
- currentIndex: 0
742
- };
632
+ const pluginState = FindAndReplacePluginKey.getState(state);
633
+ if (!pluginState) return null;
634
+ if (pendingTerm === null) return pluginState.results.length === 0 ? null : pluginState;
635
+ const results = searchDocument(state.doc, pendingTerm, {
636
+ caseSensitive: pluginState.caseSensitive,
637
+ useRegex: pluginState.useRegex,
638
+ wholeWord: pluginState.wholeWord
639
+ });
640
+ if (results.length === 0) return null;
641
+ return {
642
+ ...pluginState,
643
+ searchTerm: pendingTerm,
644
+ results,
645
+ currentIndex: 0
646
+ };
743
647
  }
744
648
  function currentResult(pluginState) {
745
- var _a;
746
- return pluginState.results[(_a = pluginState.currentIndex) != null ? _a : 0];
649
+ var _pluginState$currentI;
650
+ return pluginState.results[(_pluginState$currentI = pluginState.currentIndex) !== null && _pluginState$currentI !== void 0 ? _pluginState$currentI : 0];
747
651
  }
748
652
  function shiftIndex(currentIndex, length, direction) {
749
- if (currentIndex === null) {
750
- return direction === 1 ? 0 : length - 1;
751
- }
752
- return (currentIndex + direction + length) % length;
653
+ if (currentIndex === null) return direction === 1 ? 0 : length - 1;
654
+ return (currentIndex + direction + length) % length;
753
655
  }
754
656
  function selectResult(tr, result, index) {
755
- tr.setSelection(import_state2.TextSelection.create(tr.doc, result.from, result.to));
756
- mergePluginMeta(tr, { currentIndex: index });
757
- tr.scrollIntoView();
657
+ tr.setSelection(_tiptap_pm_state.TextSelection.create(tr.doc, result.from, result.to));
658
+ mergePluginMeta(tr, { currentIndex: index });
659
+ tr.scrollIntoView();
758
660
  }
759
661
  function replaceResult(tr, pluginState, result) {
760
- const { searchTerm, replaceTerm, caseSensitive, useRegex, wholeWord } = pluginState;
761
- tr.insertText(replaceTerm, result.from, result.to);
762
- const results = searchDocument(tr.doc, searchTerm, { caseSensitive, useRegex, wholeWord });
763
- const nextIndex = findNextIndex(results, result.from + replaceTerm.length);
764
- if (nextIndex === null) {
765
- mergePluginMeta(tr, { currentIndex: null });
766
- return;
767
- }
768
- selectResult(tr, results[nextIndex], nextIndex);
769
- }
770
- var FindAndReplace = import_core.Extension.create({
771
- name: "findAndReplace",
772
- addOptions() {
773
- return {
774
- searchTerm: "",
775
- replaceTerm: "",
776
- caseSensitive: false,
777
- useRegex: false,
778
- wholeWord: false,
779
- searchDebounceMs: 250,
780
- injectCSS: true,
781
- injectNonce: void 0
782
- };
783
- },
784
- addStorage() {
785
- return {
786
- searchTerm: this.options.searchTerm,
787
- replaceTerm: this.options.replaceTerm,
788
- caseSensitive: this.options.caseSensitive,
789
- useRegex: this.options.useRegex,
790
- wholeWord: this.options.wholeWord,
791
- results: [],
792
- currentIndex: null
793
- };
794
- },
795
- addProseMirrorPlugins() {
796
- return [
797
- FindAndReplacePlugin(this.options, (pluginState) => {
798
- this.storage.results = pluginState.results;
799
- this.storage.currentIndex = pluginState.currentIndex;
800
- })
801
- ];
802
- },
803
- onTransaction() {
804
- const pluginState = FindAndReplacePluginKey.getState(this.editor.state);
805
- if (!pluginState) {
806
- return;
807
- }
808
- this.storage.searchTerm = pluginState.searchTerm;
809
- this.storage.replaceTerm = pluginState.replaceTerm;
810
- this.storage.caseSensitive = pluginState.caseSensitive;
811
- this.storage.useRegex = pluginState.useRegex;
812
- this.storage.wholeWord = pluginState.wholeWord;
813
- this.storage.results = pluginState.results;
814
- this.storage.currentIndex = pluginState.currentIndex;
815
- },
816
- addCommands() {
817
- const scheduleSearchTerm = (term) => {
818
- const state = getDebouncedSearchState(this.editor);
819
- if (this.options.searchDebounceMs <= 0) {
820
- if (state.timeout !== null) {
821
- clearTimeout(state.timeout);
822
- state.timeout = null;
823
- }
824
- state.pendingTerm = null;
825
- applySearchTerm(this.editor, term);
826
- return true;
827
- }
828
- if (state.timeout !== null) {
829
- clearTimeout(state.timeout);
830
- }
831
- state.pendingTerm = term;
832
- state.timeout = setTimeout(() => {
833
- const debouncedState = getDebouncedSearchState(this.editor);
834
- debouncedState.timeout = null;
835
- if (debouncedState.pendingTerm === null) {
836
- return;
837
- }
838
- const pendingTerm = debouncedState.pendingTerm;
839
- debouncedState.pendingTerm = null;
840
- applySearchTerm(this.editor, pendingTerm);
841
- }, this.options.searchDebounceMs);
842
- return true;
843
- };
844
- return {
845
- setSearchTerm: (term) => ({ dispatch }) => {
846
- if (!dispatch) {
847
- return true;
848
- }
849
- return scheduleSearchTerm(term);
850
- },
851
- setReplaceTerm: (term) => setPluginMeta({ replaceTerm: term }),
852
- setCaseSensitive: (caseSensitive) => setPluginMeta({ caseSensitive }),
853
- setUseRegex: (useRegex) => setPluginMeta({ useRegex }),
854
- setWholeWord: (wholeWord) => setPluginMeta({ wholeWord }),
855
- clearSearch: () => ({ tr, dispatch }) => {
856
- const state = getDebouncedSearchState(this.editor);
857
- if (state.timeout !== null) {
858
- clearTimeout(state.timeout);
859
- state.timeout = null;
860
- }
861
- state.pendingTerm = null;
862
- if (dispatch) {
863
- mergePluginMeta(tr, { searchTerm: "" });
864
- }
865
- return true;
866
- },
867
- replace: () => ({ tr, state, dispatch }) => {
868
- const pendingTerm = dispatch ? consumePendingSearch(this.editor) : null;
869
- if (dispatch && pendingTerm !== null) {
870
- mergePluginMeta(tr, { searchTerm: pendingTerm });
871
- }
872
- const pluginState = getPendingAwarePluginState(state, pendingTerm);
873
- if (!pluginState) {
874
- return false;
875
- }
876
- const result = currentResult(pluginState);
877
- if (!result) {
878
- return false;
879
- }
880
- if (dispatch) {
881
- replaceResult(tr, pluginState, result);
882
- }
883
- return true;
884
- },
885
- replaceAll: () => ({ tr, state, dispatch }) => {
886
- const pendingTerm = dispatch ? consumePendingSearch(this.editor) : null;
887
- if (dispatch && pendingTerm !== null) {
888
- mergePluginMeta(tr, { searchTerm: pendingTerm });
889
- }
890
- const pluginState = getPendingAwarePluginState(state, pendingTerm);
891
- if (!pluginState) {
892
- return false;
893
- }
894
- if (dispatch) {
895
- replaceAllResults(tr, state, pluginState.results, pluginState.replaceTerm);
896
- }
897
- return true;
898
- },
899
- goToNextResult: () => ({ tr, state, dispatch }) => {
900
- const pendingTerm = dispatch ? consumePendingSearch(this.editor) : null;
901
- if (dispatch && pendingTerm !== null) {
902
- mergePluginMeta(tr, { searchTerm: pendingTerm });
903
- }
904
- const pluginState = getPendingAwarePluginState(state, pendingTerm);
905
- if (!pluginState) {
906
- return false;
907
- }
908
- const nextIndex = shiftIndex(pluginState.currentIndex, pluginState.results.length, 1);
909
- if (dispatch) {
910
- selectResult(tr, pluginState.results[nextIndex], nextIndex);
911
- }
912
- return true;
913
- },
914
- goToPreviousResult: () => ({ tr, state, dispatch }) => {
915
- const pendingTerm = dispatch ? consumePendingSearch(this.editor) : null;
916
- if (dispatch && pendingTerm !== null) {
917
- mergePluginMeta(tr, { searchTerm: pendingTerm });
918
- }
919
- const pluginState = getPendingAwarePluginState(state, pendingTerm);
920
- if (!pluginState) {
921
- return false;
922
- }
923
- const previousIndex = shiftIndex(pluginState.currentIndex, pluginState.results.length, -1);
924
- if (dispatch) {
925
- selectResult(tr, pluginState.results[previousIndex], previousIndex);
926
- }
927
- return true;
928
- }
929
- };
930
- },
931
- onDestroy() {
932
- clearDebouncedSearchState(this.editor);
933
- }
662
+ const { searchTerm, replaceTerm, caseSensitive, useRegex, wholeWord } = pluginState;
663
+ tr.insertText(replaceTerm, result.from, result.to);
664
+ const results = searchDocument(tr.doc, searchTerm, {
665
+ caseSensitive,
666
+ useRegex,
667
+ wholeWord
668
+ });
669
+ const nextIndex = findNextIndex(results, result.from + replaceTerm.length);
670
+ if (nextIndex === null) {
671
+ mergePluginMeta(tr, { currentIndex: null });
672
+ return;
673
+ }
674
+ selectResult(tr, results[nextIndex], nextIndex);
675
+ }
676
+ const FindAndReplace = _tiptap_core.Extension.create({
677
+ name: "findAndReplace",
678
+ addOptions() {
679
+ return {
680
+ searchTerm: "",
681
+ replaceTerm: "",
682
+ caseSensitive: false,
683
+ useRegex: false,
684
+ wholeWord: false,
685
+ searchDebounceMs: 250,
686
+ injectCSS: true,
687
+ injectNonce: void 0
688
+ };
689
+ },
690
+ addStorage() {
691
+ return {
692
+ searchTerm: this.options.searchTerm,
693
+ replaceTerm: this.options.replaceTerm,
694
+ caseSensitive: this.options.caseSensitive,
695
+ useRegex: this.options.useRegex,
696
+ wholeWord: this.options.wholeWord,
697
+ results: [],
698
+ currentIndex: null
699
+ };
700
+ },
701
+ addProseMirrorPlugins() {
702
+ return [FindAndReplacePlugin(this.options, (pluginState) => {
703
+ this.storage.results = pluginState.results;
704
+ this.storage.currentIndex = pluginState.currentIndex;
705
+ })];
706
+ },
707
+ onTransaction() {
708
+ const pluginState = FindAndReplacePluginKey.getState(this.editor.state);
709
+ if (!pluginState) return;
710
+ this.storage.searchTerm = pluginState.searchTerm;
711
+ this.storage.replaceTerm = pluginState.replaceTerm;
712
+ this.storage.caseSensitive = pluginState.caseSensitive;
713
+ this.storage.useRegex = pluginState.useRegex;
714
+ this.storage.wholeWord = pluginState.wholeWord;
715
+ this.storage.results = pluginState.results;
716
+ this.storage.currentIndex = pluginState.currentIndex;
717
+ },
718
+ addCommands() {
719
+ const scheduleSearchTerm = (term) => {
720
+ const state = getDebouncedSearchState(this.editor);
721
+ if (this.options.searchDebounceMs <= 0) {
722
+ if (state.timeout !== null) {
723
+ clearTimeout(state.timeout);
724
+ state.timeout = null;
725
+ }
726
+ state.pendingTerm = null;
727
+ applySearchTerm(this.editor, term);
728
+ return true;
729
+ }
730
+ if (state.timeout !== null) clearTimeout(state.timeout);
731
+ state.pendingTerm = term;
732
+ state.timeout = setTimeout(() => {
733
+ const debouncedState = getDebouncedSearchState(this.editor);
734
+ debouncedState.timeout = null;
735
+ if (debouncedState.pendingTerm === null) return;
736
+ const pendingTerm = debouncedState.pendingTerm;
737
+ debouncedState.pendingTerm = null;
738
+ applySearchTerm(this.editor, pendingTerm);
739
+ }, this.options.searchDebounceMs);
740
+ return true;
741
+ };
742
+ return {
743
+ setSearchTerm: (term) => ({ dispatch }) => {
744
+ if (!dispatch) return true;
745
+ return scheduleSearchTerm(term);
746
+ },
747
+ setReplaceTerm: (term) => setPluginMeta({ replaceTerm: term }),
748
+ setCaseSensitive: (caseSensitive) => setPluginMeta({ caseSensitive }),
749
+ setUseRegex: (useRegex) => setPluginMeta({ useRegex }),
750
+ setWholeWord: (wholeWord) => setPluginMeta({ wholeWord }),
751
+ clearSearch: () => ({ tr, dispatch }) => {
752
+ const state = getDebouncedSearchState(this.editor);
753
+ if (state.timeout !== null) {
754
+ clearTimeout(state.timeout);
755
+ state.timeout = null;
756
+ }
757
+ state.pendingTerm = null;
758
+ if (dispatch) mergePluginMeta(tr, { searchTerm: "" });
759
+ return true;
760
+ },
761
+ replace: () => ({ tr, state, dispatch }) => {
762
+ const pendingTerm = dispatch ? consumePendingSearch(this.editor) : null;
763
+ if (dispatch && pendingTerm !== null) mergePluginMeta(tr, { searchTerm: pendingTerm });
764
+ const pluginState = getPendingAwarePluginState(state, pendingTerm);
765
+ if (!pluginState) return false;
766
+ const result = currentResult(pluginState);
767
+ if (!result) return false;
768
+ if (dispatch) replaceResult(tr, pluginState, result);
769
+ return true;
770
+ },
771
+ replaceAll: () => ({ tr, state, dispatch }) => {
772
+ const pendingTerm = dispatch ? consumePendingSearch(this.editor) : null;
773
+ if (dispatch && pendingTerm !== null) mergePluginMeta(tr, { searchTerm: pendingTerm });
774
+ const pluginState = getPendingAwarePluginState(state, pendingTerm);
775
+ if (!pluginState) return false;
776
+ if (dispatch) replaceAllResults(tr, state, pluginState.results, pluginState.replaceTerm);
777
+ return true;
778
+ },
779
+ goToNextResult: () => ({ tr, state, dispatch }) => {
780
+ const pendingTerm = dispatch ? consumePendingSearch(this.editor) : null;
781
+ if (dispatch && pendingTerm !== null) mergePluginMeta(tr, { searchTerm: pendingTerm });
782
+ const pluginState = getPendingAwarePluginState(state, pendingTerm);
783
+ if (!pluginState) return false;
784
+ const nextIndex = shiftIndex(pluginState.currentIndex, pluginState.results.length, 1);
785
+ if (dispatch) selectResult(tr, pluginState.results[nextIndex], nextIndex);
786
+ return true;
787
+ },
788
+ goToPreviousResult: () => ({ tr, state, dispatch }) => {
789
+ const pendingTerm = dispatch ? consumePendingSearch(this.editor) : null;
790
+ if (dispatch && pendingTerm !== null) mergePluginMeta(tr, { searchTerm: pendingTerm });
791
+ const pluginState = getPendingAwarePluginState(state, pendingTerm);
792
+ if (!pluginState) return false;
793
+ const previousIndex = shiftIndex(pluginState.currentIndex, pluginState.results.length, -1);
794
+ if (dispatch) selectResult(tr, pluginState.results[previousIndex], previousIndex);
795
+ return true;
796
+ }
797
+ };
798
+ },
799
+ onDestroy() {
800
+ clearDebouncedSearchState(this.editor);
801
+ }
934
802
  });
803
+ //#endregion
804
+ //#region src/index.ts
805
+ var src_default = FindAndReplace;
806
+ //#endregion
807
+ exports.FindAndReplace = FindAndReplace;
808
+ exports.FindAndReplacePlugin = FindAndReplacePlugin;
809
+ exports.FindAndReplacePluginKey = FindAndReplacePluginKey;
810
+ exports.createSearchRegex = createSearchRegex;
811
+ exports.currentResultClass = currentResultClass;
812
+ exports.default = src_default;
813
+ exports.findNextIndex = findNextIndex;
814
+ exports.resultClass = resultClass;
815
+ exports.searchDocument = searchDocument;
816
+ exports.searchTextblocks = searchTextblocks;
935
817
 
936
- // src/index.ts
937
- var index_default = FindAndReplace;
938
- // Annotate the CommonJS export names for ESM import in node:
939
- 0 && (module.exports = {
940
- FindAndReplace,
941
- FindAndReplacePlugin,
942
- FindAndReplacePluginKey,
943
- createSearchRegex,
944
- currentResultClass,
945
- findNextIndex,
946
- resultClass,
947
- searchDocument,
948
- searchTextblocks
949
- });
950
818
  //# sourceMappingURL=index.cjs.map