@veltdev/lexical-velt-comments 1.0.0

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.
@@ -0,0 +1,384 @@
1
+ import { LexicalEditor, LexicalNode, RangeSelection, TextNode } from 'lexical';
2
+ import { CommentNode } from './comment-node';
3
+ import type { Plugin } from './plugin';
4
+ import { AnnotationData } from './types';
5
+ interface TextMatch {
6
+ start: number;
7
+ end: number;
8
+ startNode?: LexicalNode;
9
+ endNode?: LexicalNode;
10
+ }
11
+ /**
12
+ * Interface for tracking annotation data during processing
13
+ */
14
+ interface AnnotationToCheck {
15
+ id: string;
16
+ multiThreadAnnotationId?: string;
17
+ annotation: AnnotationData;
18
+ nodes: {
19
+ node: {
20
+ text?: string;
21
+ nodeSize?: number;
22
+ };
23
+ pos: number;
24
+ }[];
25
+ originalText: string;
26
+ originalOccurrence: number;
27
+ targetTextNodeId: string;
28
+ }
29
+ /**
30
+ * Interface for tracking annotation changes during a transaction
31
+ */
32
+ interface AnnotationChange {
33
+ annotationId: string;
34
+ multiThreadAnnotationId?: string;
35
+ originalText: string;
36
+ currentText: string;
37
+ originalOccurrence: number;
38
+ currentOccurrence: number;
39
+ originalTargetTextNodeId: string;
40
+ newTargetTextNodeId: string;
41
+ annotation: any;
42
+ contentChanged: boolean;
43
+ occurrenceChanged: boolean;
44
+ targetTextNodeIdChanged: boolean;
45
+ }
46
+ export declare class EditorService {
47
+ plugin: Plugin;
48
+ private editorUpdateListenerRemover?;
49
+ constructor(plugin: Plugin);
50
+ static getEditorId: (editor: LexicalEditor) => string | null;
51
+ /**
52
+ * Initialize the transaction listener (equivalent to TipTap's onTransaction)
53
+ * Call this method when setting up the plugin
54
+ */
55
+ initializeTransactionListener(editor: LexicalEditor): void;
56
+ /**
57
+ * Clean up the transaction listener
58
+ */
59
+ destroyTransactionListener(): void;
60
+ /**
61
+ * Check if the document content has actually changed
62
+ */
63
+ private hasDocumentChanged;
64
+ /**
65
+ * Process editor changes
66
+ */
67
+ onTransaction(editor: LexicalEditor): void;
68
+ /**
69
+ * Extract text from a CommentNode while preserving paragraph structure.
70
+ * This method ensures that text extracted from existing comment nodes maintains
71
+ * the same newline characters that were present during initial selection.
72
+ *
73
+ * @param commentNode - The CommentNode to extract text from
74
+ * @returns Text content with preserved paragraph breaks (newlines)
75
+ */
76
+ private getCommentNodeTextWithStructure;
77
+ /**
78
+ * Collect all annotations present in the document for processing
79
+ */
80
+ collectDocumentAnnotations(editor: LexicalEditor): Map<string, AnnotationToCheck>;
81
+ /**
82
+ * Process annotation changes
83
+ */
84
+ processAnnotationChanges(editor: LexicalEditor, data: AnnotationToCheck): AnnotationChange | null;
85
+ /**
86
+ * Detect content changes while preserving paragraph structure.
87
+ * When multiple CommentNodes represent different paragraphs of the same annotation,
88
+ * we need to join them with newlines to match the original text format.
89
+ */
90
+ detectContentChanges(nodes: AnnotationToCheck['nodes'], originalText: string): {
91
+ currentText: string;
92
+ contentChanged: boolean;
93
+ };
94
+ /**
95
+ * Detect container changes
96
+ */
97
+ detectContainerChanges(editor: LexicalEditor, params: {
98
+ annotationId?: string;
99
+ currentText: string;
100
+ targetTextNodeId: string;
101
+ nodes: AnnotationToCheck['nodes'];
102
+ }): {
103
+ targetTextNodeIdChanged: boolean;
104
+ newTargetTextNodeId: string;
105
+ searchResults: TextMatch[];
106
+ };
107
+ /**
108
+ * Process container changes
109
+ */
110
+ processContainerChanges(editor: LexicalEditor, params: {
111
+ annotationId?: string;
112
+ currentText: string;
113
+ targetTextNodeId: string;
114
+ nodes: {
115
+ node: {
116
+ text?: string;
117
+ nodeSize?: number;
118
+ };
119
+ pos: number;
120
+ }[];
121
+ }): {
122
+ changed: boolean;
123
+ newId: string;
124
+ searchResults: TextMatch[];
125
+ } | null;
126
+ /**
127
+ * Find new container for moved content
128
+ */
129
+ findNewContainer(editor: LexicalEditor, currentText: string): HTMLElement | null;
130
+ /**
131
+ * Calculate new occurrence
132
+ */
133
+ calculateNewOccurrence(editor: LexicalEditor, params: {
134
+ searchResults: TextMatch[];
135
+ nodes: {
136
+ node: {
137
+ text?: string;
138
+ nodeSize?: number;
139
+ };
140
+ pos: number;
141
+ }[];
142
+ contentChanged: boolean;
143
+ currentText: string;
144
+ targetTextNodeId: string | null;
145
+ originalOccurrence: number;
146
+ }): number;
147
+ /**
148
+ * Create annotation change object
149
+ */
150
+ createAnnotationChange(data: AnnotationToCheck, changes: {
151
+ currentText: string;
152
+ contentChanged: boolean;
153
+ currentOccurrence: number;
154
+ occurrenceChanged: boolean;
155
+ targetTextNodeIdChanged: boolean;
156
+ newTargetTextNodeId: string;
157
+ }): AnnotationChange;
158
+ /**
159
+ * Update Velt comments
160
+ */
161
+ updateVeltComments(commentElement: {
162
+ updateContext: (id: string, context: unknown) => void;
163
+ }, changes: Map<string, AnnotationChange>, editor: LexicalEditor): Promise<void>;
164
+ getSelectedText(editor: LexicalEditor): string;
165
+ /**
166
+ * Find occurrence index of selected text in Lexical editor.
167
+ * This method determines which occurrence of a text pattern the current selection represents,
168
+ * which is crucial for multi-paragraph text selections that span across different paragraphs.
169
+ *
170
+ * @param editor - The Lexical editor instance
171
+ * @param selectedText - The text that is currently selected (may include newlines for multi-paragraph selections)
172
+ * @param targetContainer - Optional container element to limit search scope
173
+ * @returns The 1-indexed occurrence number of the selected text
174
+ */
175
+ findOccurrenceIndex(editor: LexicalEditor, selectedText: string, targetContainer: HTMLElement | null): number;
176
+ /**
177
+ * Get the text range of current selection, accounting for paragraph breaks.
178
+ * This method maps Lexical selection positions to text offsets in the combined text
179
+ * representation that includes newline characters between paragraphs.
180
+ *
181
+ * @param editor - The Lexical editor instance
182
+ * @param selection - The current range selection
183
+ * @returns Object with start and end positions in the combined text
184
+ */
185
+ getSelectionTextRange(editor: LexicalEditor, selection: RangeSelection): {
186
+ start: number;
187
+ end: number;
188
+ };
189
+ /**
190
+ * Collect all text content including paragraph breaks.
191
+ * This method creates a combined text representation of the entire document,
192
+ * inserting newline characters between paragraphs to maintain text structure
193
+ * for accurate multi-paragraph text matching.
194
+ *
195
+ * @param root - The root Lexical node to traverse
196
+ * @returns Object containing:
197
+ * - combinedText: Complete text with newlines between paragraphs
198
+ * - nodeMap: Array mapping each text node and paragraph break to its position
199
+ */
200
+ collectTextContent(root: LexicalNode): {
201
+ combinedText: string;
202
+ nodeMap: {
203
+ node: TextNode | null;
204
+ start: number;
205
+ end: number;
206
+ isParagraphBreak?: boolean;
207
+ }[];
208
+ };
209
+ /**
210
+ * Find all text occurrences in the entire Lexical editor.
211
+ * This method supports multi-paragraph text search by using the combined text
212
+ * representation that includes newline characters between paragraphs.
213
+ *
214
+ * @param editor - The Lexical editor instance
215
+ * @param searchText - The text to search for (may include newlines for multi-paragraph searches)
216
+ * @returns Array of TextMatch objects with start and end positions
217
+ */
218
+ findTextInEditor(editor: LexicalEditor, searchText: string): TextMatch[];
219
+ /**
220
+ * Find text occurrences within a specific DOM container (Updated to handle paragraph breaks)
221
+ */
222
+ findTextInContainer(editor: LexicalEditor, searchText: string, containerId: string): TextMatch[];
223
+ /**
224
+ * Get text content for a specific container
225
+ */
226
+ getContainerTextContent(containerElement: HTMLElement, editor: LexicalEditor, nodeMap: {
227
+ node: TextNode | null;
228
+ start: number;
229
+ end: number;
230
+ isParagraphBreak?: boolean;
231
+ }[], combinedText: string): {
232
+ text: string;
233
+ startOffset: number;
234
+ } | null;
235
+ /**
236
+ * Filter text nodes that are within a specific DOM container
237
+ */
238
+ filterNodesInContainer(textNodes: any[], containerElement: HTMLElement, editor: LexicalEditor): any[];
239
+ /**
240
+ * Collect all text nodes with their cumulative text offsets (helper method)
241
+ */
242
+ collectTextNodes(root: LexicalNode): {
243
+ node: TextNode;
244
+ text: string;
245
+ textOffset: number;
246
+ }[];
247
+ /**
248
+ * Get text nodes within a specific character range (Updated to handle paragraph breaks)
249
+ */
250
+ getTextNodesInRange(root: LexicalNode, fromPos: number, toPos: number, excludeAnnotationId?: string): {
251
+ node: TextNode;
252
+ startOffset: number;
253
+ endOffset: number;
254
+ isPartial: boolean;
255
+ }[];
256
+ /**
257
+ * Check if a text range is already wrapped (Updated to handle paragraph breaks)
258
+ */
259
+ isRangeAlreadyWrapped(root: LexicalNode, fromPos: number, toPos: number, annotationId: string): boolean;
260
+ /**
261
+ * Collect text nodes within a specific range
262
+ */
263
+ collectTextNodesInRange(root: LexicalNode, range: {
264
+ start: number;
265
+ end: number;
266
+ }): {
267
+ node: TextNode;
268
+ text: string;
269
+ start: number;
270
+ end: number;
271
+ }[];
272
+ /**
273
+ * Get the text range for a specific DOM container
274
+ */
275
+ getContainerRange(editor: LexicalEditor, containerElement: HTMLElement): {
276
+ start: number;
277
+ end: number;
278
+ } | null;
279
+ /**
280
+ * KMP Search implementation
281
+ */
282
+ kmpSearch(text: string, pattern: string, startPos?: number, maxOccurrences?: number): number[];
283
+ /**
284
+ * Compute KMP failure function
285
+ */
286
+ computeKMPTable(pattern: string): number[];
287
+ findParentContainerWithId(selection: RangeSelection, editor: LexicalEditor): HTMLElement | null;
288
+ /**
289
+ * Highlights text in the editor with a Velt comment annotation.
290
+ * This method supports multi-paragraph text highlighting by preserving paragraph structure
291
+ * and creating separate comment nodes for each paragraph when necessary.
292
+ *
293
+ * @param editor - The Lexical editor instance
294
+ * @param textToFind - The text to highlight (may include newlines for multi-paragraph selections)
295
+ * @param commentOptions - Configuration options for the comment annotation
296
+ */
297
+ highlightTextWithVeltComment(editor: LexicalEditor, textToFind: string, commentOptions: {
298
+ annotationId?: string;
299
+ multiThreadAnnotationId?: string;
300
+ occurrence?: number;
301
+ targetTextNodeId?: string;
302
+ originalAnnotation?: any;
303
+ }): void;
304
+ /**
305
+ * Find text within a specific DOM element
306
+ */
307
+ findTextInDomElement(editor: LexicalEditor, text: string, domElementId: string, desiredOccurrence?: number): TextMatch[];
308
+ /**
309
+ * Find text in the entire document with support for multi-paragraph searches.
310
+ * This method is used by the highlighting system to locate text that needs to be wrapped
311
+ * with comment annotations, including text that spans across multiple paragraphs.
312
+ *
313
+ * @param editor - The Lexical editor instance
314
+ * @param text - The text to search for (may include newlines for multi-paragraph searches)
315
+ * @param desiredOccurrence - Optional limit on the number of occurrences to find
316
+ * @returns Array of TextMatch objects with start and end positions
317
+ */
318
+ findTextInDocument(editor: LexicalEditor, text: string, desiredOccurrence?: number): TextMatch[];
319
+ /**
320
+ * Creates a Velt comment highlight at the specified range.
321
+ * This method intelligently handles different scenarios including single text nodes,
322
+ * partial text nodes, and multi-paragraph selections while preserving document structure.
323
+ *
324
+ * @param editor - The Lexical editor instance
325
+ * @param annotationId - The annotation ID for the comment
326
+ * @param multiThreadAnnotationId - Optional multi-thread annotation ID
327
+ * @param fromPos - Start position in the combined text representation
328
+ * @param toPos - End position in the combined text representation
329
+ */
330
+ setVeltComment(editor: LexicalEditor, annotationId: string, multiThreadAnnotationId: string | undefined, fromPos: number, toPos: number): void;
331
+ /**
332
+ * Wrap a partial text node (when selection is within the node) - PRESERVING FORMATTING
333
+ */
334
+ wrapPartialTextNode(textNode: TextNode, startOffset: number, endOffset: number, commentNode: CommentNode): void;
335
+ /**
336
+ * Wrap an entire text node - PRESERVING FORMATTING
337
+ */
338
+ wrapEntireTextNode(textNode: TextNode, commentNode: CommentNode): void;
339
+ /**
340
+ * Wrap multiple text nodes while preserving formatting and paragraph structure.
341
+ * This method groups text nodes by their paragraph parent and creates separate
342
+ * comment nodes for each paragraph to maintain document structure integrity.
343
+ *
344
+ * @param textNodesToWrap - Array of text nodes with their offset information
345
+ * @param commentNode - The base comment node to use (additional nodes will be created for other paragraphs)
346
+ */
347
+ wrapMultipleTextNodesWithFormatting(textNodesToWrap: {
348
+ node: TextNode;
349
+ startOffset: number;
350
+ endOffset: number;
351
+ isPartial: boolean;
352
+ }[], commentNode: CommentNode): void;
353
+ /**
354
+ * Find the paragraph parent of a text node.
355
+ * Traverses up the node hierarchy to find the paragraph element that contains this text node.
356
+ *
357
+ * @param node - The text node to find the paragraph parent for
358
+ * @returns The paragraph node or null if not found
359
+ */
360
+ findParagraphParent(node: TextNode): LexicalNode | null;
361
+ /**
362
+ * Wrap multiple text nodes within the same paragraph.
363
+ * This method handles complex scenarios where multiple text nodes need to be wrapped
364
+ * while maintaining their original formatting and order within the paragraph.
365
+ *
366
+ * @param nodesInParagraph - Array of text nodes within the same paragraph
367
+ * @param commentNode - The comment node to wrap the text nodes with
368
+ */
369
+ wrapMultipleNodesInSameParagraph(nodesInParagraph: {
370
+ node: TextNode;
371
+ startOffset: number;
372
+ endOffset: number;
373
+ isPartial: boolean;
374
+ }[], commentNode: CommentNode): void;
375
+ /**
376
+ * Removes a Velt comment from the Lexical document
377
+ * @param editor - The Lexical editor instance
378
+ * @param annotationId - The ID of the annotation to remove
379
+ * @returns boolean - True if the annotation was successfully removed, false otherwise
380
+ * @throws Error if the stored data is invalid
381
+ */
382
+ removeVeltCommentFromEditor(editor: LexicalEditor, annotationId: string): boolean;
383
+ }
384
+ export {};
@@ -0,0 +1,24 @@
1
+ import { CommentAnnotation } from '@veltdev/types';
2
+ import { LexicalEditor } from 'lexical';
3
+ import { LexicalVeltCommentConfig } from "./types";
4
+ export * from './comment-node';
5
+ export * from './serializer';
6
+ export declare const triggerAddComment: (editor: LexicalEditor, config?: LexicalVeltCommentConfig) => Promise<void>;
7
+ export interface AddCommentRequest {
8
+ editorId?: string;
9
+ editor: LexicalEditor;
10
+ context?: unknown;
11
+ }
12
+ /**
13
+ * Creates a comment annotation for the currently selected text in the editor
14
+ * This function handles the entire flow from getting the selected text to creating
15
+ * the actual comment through the Velt service
16
+ */
17
+ export declare const addComment: ({ editorId, editor, context: clientContext, }: AddCommentRequest) => Promise<void>;
18
+ export declare function highlightComments(editor: LexicalEditor, commentAnnotations: CommentAnnotation[], editorId?: string): void;
19
+ export interface RenderCommentsRequest {
20
+ editor: LexicalEditor;
21
+ editorId?: string;
22
+ commentAnnotations?: CommentAnnotation[];
23
+ }
24
+ export declare const renderComments: ({ editor, editorId, commentAnnotations }: RenderCommentsRequest) => void;
@@ -0,0 +1,14 @@
1
+ import { LexicalEditor } from 'lexical';
2
+ import { EditorService } from './editor';
3
+ import { StoreService } from './store';
4
+ export declare class Plugin {
5
+ editorId: string;
6
+ editor: LexicalEditor | undefined;
7
+ editorService: EditorService;
8
+ storeService: StoreService;
9
+ constructor(editorId: string, editor?: LexicalEditor);
10
+ static getInstance(config?: {
11
+ editorId?: string | null;
12
+ editor?: LexicalEditor;
13
+ }): Plugin;
14
+ }
@@ -0,0 +1,9 @@
1
+ import { LexicalEditor } from "lexical";
2
+ /**
3
+ * Enhanced export function with multiple strategies
4
+ */
5
+ export declare const exportCleanEditorContent: (editor: LexicalEditor) => string;
6
+ /**
7
+ * Deserializes editor state from clean JSON
8
+ */
9
+ export declare function deserializeCleanState(editor: LexicalEditor, jsonString: string): void;
@@ -0,0 +1,39 @@
1
+ import type { CommentAnnotation } from '@veltdev/types';
2
+ import { LexicalEditor } from 'lexical';
3
+ import type { Plugin } from './plugin';
4
+ import type { AnnotationData, PluginReference } from './types';
5
+ type GlobalStore = {
6
+ editor?: LexicalEditor | null;
7
+ comments?: CommentAnnotation[];
8
+ filteredComments?: CommentAnnotation[];
9
+ selectedCommentsMap?: Map<string, boolean>;
10
+ };
11
+ /**
12
+ * Interface for annotation store entry
13
+ */
14
+ interface AnnotationStoreEntry {
15
+ annotation: AnnotationData;
16
+ pluginReference: PluginReference;
17
+ }
18
+ export declare class StoreService {
19
+ static storeInstanceMap: Map<string, StoreService>;
20
+ plugin: Plugin;
21
+ isSubscribed: boolean;
22
+ globalStore: GlobalStore;
23
+ globalAnnotationStore: Map<string, AnnotationStoreEntry>;
24
+ /**
25
+ * Helper to get and set annotations with debug messages
26
+ */
27
+ annotationStore: {
28
+ get: (id: string) => AnnotationStoreEntry | undefined;
29
+ set: (id: string, data: AnnotationStoreEntry) => void;
30
+ getAll: () => Map<string, AnnotationStoreEntry>;
31
+ clear: () => void;
32
+ remove: (id: string) => void;
33
+ hasAnnotationTextChanged: (annotationId: string, currentAnnotation: AnnotationData) => boolean;
34
+ };
35
+ constructor(plugin: Plugin);
36
+ updateGlobalStore: (store: GlobalStore) => void;
37
+ highlightCommentsFromGlobalStore: () => void;
38
+ }
39
+ export {};
@@ -0,0 +1,40 @@
1
+ export type CommentAnnotationContext = {
2
+ textEditorConfig?: {
3
+ text: string;
4
+ occurrence: number;
5
+ editorId?: string;
6
+ targetTextNodeId?: string;
7
+ };
8
+ } & Record<string, unknown>;
9
+ export interface LexicalVeltCommentConfig {
10
+ context?: any;
11
+ }
12
+ /**
13
+ * Interface for annotation data
14
+ */
15
+ export interface AnnotationData {
16
+ annotationId?: string;
17
+ multiThreadAnnotationId?: string;
18
+ text?: string;
19
+ context?: AnnotationContext;
20
+ }
21
+ /**
22
+ * Interface for annotation context
23
+ */
24
+ export interface AnnotationContext {
25
+ textEditorConfig?: {
26
+ text?: string;
27
+ occurrence?: number;
28
+ targetTextNodeId?: string;
29
+ };
30
+ }
31
+ /**
32
+ * Interface for plugin reference in annotation store
33
+ */
34
+ export interface PluginReference {
35
+ node: HTMLElement;
36
+ position: {
37
+ from: number;
38
+ to: number;
39
+ };
40
+ }
@@ -0,0 +1,21 @@
1
+ import type { Location } from '@veltdev/types';
2
+ import type { CommentAnnotationContext } from './types';
3
+ export declare class VeltService {
4
+ static selectedCommentsMap: Map<string, boolean>;
5
+ static subscribers: Map<string, (selectedCommentsMap: Map<string, boolean>) => void>;
6
+ static isSubscribed: boolean;
7
+ static getCommentElement: () => import("@veltdev/types").CommentElement | null;
8
+ static addManualComment: ({ context, location, }: {
9
+ context: CommentAnnotationContext;
10
+ location?: Location | undefined;
11
+ }) => Promise<any>;
12
+ static updateContext: ({ annotationId, context, }: {
13
+ annotationId: string;
14
+ context: CommentAnnotationContext;
15
+ }) => Promise<any> | undefined;
16
+ static subscribeToSelectedCommentsMap: (id: string, subscriber: (selectedCommentsMap: Map<string, boolean>) => void) => void;
17
+ static unsubscribeFromSelectedCommentsMap: (id: string) => void;
18
+ static catchError: (message: string, otherProperties?: any) => void;
19
+ static subscribeToSelectedAnnotationsMapSingleton: () => Map<any, any> | undefined;
20
+ private static updateSelectedCommentsMap;
21
+ }
package/esm/index.js ADDED
@@ -0,0 +1,2 @@
1
+ import{ElementNode as t,$getRoot as e,$isTextNode as n,$isElementNode as r,$getSelection as o,$isRangeSelection as i,$createTextNode as a,createEditor as c}from"lexical";class s extends t{static getType(){return"comment"}static clone(t){return new s(t.__annotationId,t.__multiThreadAnnotationId,t.__key)}constructor(t,e,n){super(n),this.__annotationId=t,this.__multiThreadAnnotationId=e}createDOM(t){const e=document.createElement("velt-comment-text");return this.__annotationId&&e.setAttribute("annotation-id",this.__annotationId),this.__multiThreadAnnotationId&&e.setAttribute("multi-thread-annotation-id",this.__multiThreadAnnotationId),e}updateDOM(t,e,n){return!1}static importJSON(t){return d(t.annotationId,t.multiThreadAnnotationId)}exportJSON(){return{...super.exportJSON(),annotationId:this.__annotationId,multiThreadAnnotationId:this.__multiThreadAnnotationId,type:"comment",version:1}}isInline(){return!0}}function d(t,e){return new s(t,e)}function l(t){return t instanceof s}var g;class h{}g=h,h.selectedCommentsMap=new Map,h.subscribers=new Map,h.isSubscribed=!1,h.getCommentElement=()=>{try{const t=window.Velt;return t?.getCommentElement?t.getCommentElement():null}catch(t){return g.catchError("Error getting comment element:",t),null}},h.addManualComment=({context:t,location:e})=>{try{const n=g.getCommentElement();return n?n.addManualComment({context:t,location:e}):Promise.resolve(null)}catch(t){return g.catchError("Error adding manual comment:",t),Promise.resolve(null)}},h.updateContext=({annotationId:t,context:e})=>{try{const n=g.getCommentElement();return n?n.updateContext(t,e):Promise.resolve(null)}catch(t){g.catchError("Error updating context:",t)}},h.subscribeToSelectedCommentsMap=(t,e)=>{try{g.subscribeToSelectedAnnotationsMapSingleton(),g.subscribers.set(t,e)}catch(t){g.catchError("Error subscribing to selected comments map:",t)}},h.unsubscribeFromSelectedCommentsMap=t=>{try{g.subscribers.delete(t)}catch(t){g.catchError("Error unsubscribing from selected comments map:",t)}},h.catchError=(t,e)=>{try{let n={};e&&"object"==typeof e&&(n={...n,...e}),t&&(n.message=t),n.sdkVersion=window.Velt?.version}catch(t){}},h.subscribeToSelectedAnnotationsMapSingleton=()=>{try{if(g.isSubscribed)return;const t=g.getCommentElement();t&&"function"==typeof t?.getSelectedComments&&(t?.getSelectedComments()?.subscribe(t=>{const e=new Map;t?.forEach(t=>{t?.annotationId&&e.set(t?.annotationId,!0)});((t,e)=>{if(t.size!==e.size)return!1;for(const[n,r]of t)if(e.get(n)!==r)return!1;return!0})(e,g.selectedCommentsMap||new Map)||g.updateSelectedCommentsMap(e)}),g.isSubscribed=!0)}catch(t){return new Map}},h.updateSelectedCommentsMap=t=>{try{g.selectedCommentsMap=t,g.subscribers.forEach(t=>{"function"==typeof t&&t(g.selectedCommentsMap)})}catch(t){g.catchError("Error updating selected comments map:",t)}};class u{constructor(t){this.plugin=t}initializeTransactionListener(t){try{this.editorUpdateListenerRemover&&this.editorUpdateListenerRemover(),this.editorUpdateListenerRemover=t.registerUpdateListener(({editorState:e,prevEditorState:n})=>{try{if(e===n||!this.hasDocumentChanged(e,n))return;this.onTransaction(t)}catch(t){}})}catch(t){h.catchError("Error initializing transaction listener:",t)}}destroyTransactionListener(){try{this.editorUpdateListenerRemover&&(this.editorUpdateListenerRemover(),this.editorUpdateListenerRemover=void 0)}catch(t){h.catchError("Error destroying transaction listener:",t)}}hasDocumentChanged(t,n){try{return t.read(()=>{const t=e().getTextContent();return n.read(()=>{const n=e().getTextContent();return t!==n})})}catch(t){return!0}}onTransaction(t){try{const e=new Map,n=this.collectDocumentAnnotations(t);for(const[r,o]of Array.from(n.entries())){const n=this.processAnnotationChanges(t,o);n&&e.set(r,n)}if(e.size>0){const n=h.getCommentElement();if(!n)return;this.updateVeltComments(n,e,t)}}catch(t){h.catchError("Error in onTransaction:",t)}}getCommentNodeTextWithStructure(t){try{let e="";const o=(t,i=0)=>{if(n(t))e+=t.getTextContent();else if(r(t)){const n=t.getChildren(),a=t.getType();for(let t=0;t<n.length;t++)o(n[t],i+1);if("paragraph"===a&&i>=0){const n=t.getParent();if(n&&r(n)){const r=n.getChildren();r.indexOf(t)<r.length-1&&(e+="\n")}}}};return o(t),e}catch(e){return t.getTextContent()}}collectDocumentAnnotations(t){try{const o=new Map,i=this;return t.getEditorState().read(()=>{const t=e();let a=0;const c=t=>{if(l(t)){const e=t.__annotationId;if(!e)return;const n=i.plugin.storeService.annotationStore.get(e);if(!n)return;const r=i.getCommentNodeTextWithStructure(t),c=r.length,s=o.get(e),d={node:{text:r,nodeSize:c},pos:a};s?s.nodes.push(d):o.set(e,{id:e,multiThreadAnnotationId:t.__multiThreadAnnotationId,annotation:n.annotation,nodes:[d],originalText:n.annotation.context?.textEditorConfig?.text||"",originalOccurrence:n.annotation.context?.textEditorConfig?.occurrence||1,targetTextNodeId:n.annotation.context?.textEditorConfig?.targetTextNodeId||""}),a+=c}else if(n(t))a+=t.getTextContent().length;else if(r(t)){const e=t.getChildren();for(const t of e)c(t)}};c(t)}),o}catch(t){return h.catchError("Error collecting document annotations:",t),new Map}}processAnnotationChanges(t,e){try{if(!t||!e)throw new Error("Invalid input: editor and data are required");if(!e.originalText||!e.annotation)return null;if(!Array.isArray(e.nodes)||0===e.nodes.length)return null;const{currentText:n,contentChanged:r}=this.detectContentChanges(e.nodes,e.originalText),{targetTextNodeIdChanged:o,newTargetTextNodeId:i,searchResults:a}=this.detectContainerChanges(t,{annotationId:e.id,currentText:n,targetTextNodeId:e.targetTextNodeId,nodes:e.nodes}),c=this.calculateNewOccurrence(t,{searchResults:a,nodes:e.nodes,contentChanged:r,currentText:n,targetTextNodeId:o?i:e.targetTextNodeId,originalOccurrence:e.originalOccurrence}),s=c!==e.originalOccurrence;return r||s||o?this.createAnnotationChange(e,{currentText:n,contentChanged:r,currentOccurrence:c,occurrenceChanged:s,targetTextNodeIdChanged:o,newTargetTextNodeId:i}):null}catch(t){return h.catchError("Error processing annotation changes:",t),null}}detectContentChanges(t,e){const n=[...t].sort((t,e)=>t.pos-e.pos),r=n.length>1&&e.includes("\n")?n.map(t=>t.node.text||"").join("\n"):n.map(t=>t.node.text||"").join("");return{currentText:r,contentChanged:r!==e}}detectContainerChanges(t,e){const{annotationId:n,currentText:r,targetTextNodeId:o,nodes:i}=e;let a=!1,c=o,s=[];const d=this.processContainerChanges(t,{annotationId:n,currentText:r,targetTextNodeId:o,nodes:i});return d?(a=d.changed,c=d.newId,s=d.searchResults):s=o?this.findTextInDomElement(t,r,o,void 0):this.findTextInDocument(t,r,void 0),{targetTextNodeIdChanged:a,newTargetTextNodeId:c,searchResults:s}}processContainerChanges(t,o){const{annotationId:i,currentText:a,targetTextNodeId:c}=o;if(!c)return null;let s=null;if(t.getEditorState().read(()=>{const t=e();let o=0;!function t(e){if(l(e)&&e.__annotationId===i)s=o;else if(n(e))o+=e.getTextContent().length;else if(r(e)){const n=e.getChildren();for(const e of n)if(t(e),null!==s)return}}(t)}),null!==s){const e=t.getRootElement();if(!e)return null;if(e.querySelector(`#${c}`)){if(0===this.findTextInDomElement(t,a,c,void 0).length){const e=this.findNewContainer(t,a);if(e&&e.id!==c){const n=this.findTextInDomElement(t,a,e.id,void 0);return{changed:!0,newId:e.id,searchResults:n}}}}}return null}findNewContainer(t,e){const n=t.getRootElement();if(!n)return null;const r=n.querySelectorAll("[id]");for(const t of Array.from(r))if(t.textContent?.includes(e))return t;return null}calculateNewOccurrence(t,e){if(0===e.searchResults.length)return e.originalOccurrence;const n=e.nodes[0],r=e.nodes[e.nodes.length-1],o=n.pos,i=r.pos+(r.node.nodeSize||0);for(let t=0;t<e.searchResults.length;t++){const n=e.searchResults[t];if(n.start<=o&&n.end>=o||n.start<=i&&n.end>=i||o<=n.start&&i>=n.end)return t+1}return e.originalOccurrence}createAnnotationChange(t,e){const{currentText:n,contentChanged:r,currentOccurrence:o,occurrenceChanged:i,targetTextNodeIdChanged:a,newTargetTextNodeId:c}=e;return{annotationId:t.id,multiThreadAnnotationId:t.multiThreadAnnotationId,originalText:t.originalText,currentText:r?n:t.originalText,originalOccurrence:t.originalOccurrence,currentOccurrence:o,originalTargetTextNodeId:t.targetTextNodeId,newTargetTextNodeId:a?c:t.targetTextNodeId,annotation:t.annotation,contentChanged:r,occurrenceChanged:i,targetTextNodeIdChanged:a}}async updateVeltComments(t,e,n){try{for(const[t,r]of Array.from(e.entries()))try{if(!r.annotation.context?.textEditorConfig)continue;const e=JSON.parse(JSON.stringify(r.annotation.context.textEditorConfig));r.contentChanged&&(e.text=r.currentText),r.occurrenceChanged&&(e.occurrence=r.currentOccurrence),r.targetTextNodeIdChanged&&(e.targetTextNodeId=r.newTargetTextNodeId);const o={...r.annotation.context,textEditorConfig:e};this.plugin.storeService.annotationStore.remove(t),this.removeVeltCommentFromEditor(n,t),await new Promise(t=>setTimeout(t,100)),h.updateContext({annotationId:t,context:o})}catch(t){h.catchError("Error updating individual Velt comment:",t)}}catch(t){h.catchError("Error updating Velt comments:",t)}}getSelectedText(t){return t.getEditorState().read(()=>{const t=o();return i(t)?t.getTextContent():""})}findOccurrenceIndex(t,e,n){try{if(!e.trim())return 1;let r=[],a=0,c=0;t.getEditorState().read(()=>{const s=o();if(i(s)){const o=this.getSelectionTextRange(t,s);a=o.start,c=o.end,r=n&&n.id?this.findTextInContainer(t,e,n.id):this.findTextInEditor(t,e)}});for(let t=0;t<r.length;t++)if(r[t].start===a&&r[t].end===c)return t+1;return 1}catch(t){return h.catchError("Error finding occurrence index:",t),1}}getSelectionTextRange(t,n){const r=e(),{nodeMap:o}=this.collectTextContent(r),i=n.anchor.getNode(),a=n.focus.getNode(),c=n.anchor.offset,s=n.focus.offset;let d=0,l=0;for(const t of o){if(t.isParagraphBreak||!t.node)continue;const e=t.node.getKey();e===i.getKey()&&(d=t.start+c),e===a.getKey()&&(l=t.start+s)}return{start:Math.min(d,l),end:Math.max(d,l)}}collectTextContent(t){try{const e=[];let o="",i=0;const a=(t,c=0)=>{if(n(t)){const n=t.getTextContent(),r=i,a=i+n.length;e.push({node:t,start:r,end:a}),o+=n,i+=n.length}else if(r(t)){const n=t.getChildren(),s=t.getType();for(let t=0;t<n.length;t++)a(n[t],c+1);if("paragraph"===s&&1===c){const n=t.getParent();if(n&&r(n)){const r=n.getChildren();if(r.indexOf(t)<r.length-1){const t=i,n=i+1;e.push({node:null,start:t,end:n,isParagraphBreak:!0}),o+="\n",i+=1}}}}};return a(t),{combinedText:o,nodeMap:e}}catch(t){return h.catchError("Error collecting text content:",t),{combinedText:"",nodeMap:[]}}}findTextInEditor(t,n){try{const r=[];return t.getEditorState().read(()=>{const t=e(),{combinedText:o}=this.collectTextContent(t),i=this.kmpSearch(o,n);for(const t of i)r.push({start:t,end:t+n.length})}),r}catch(t){return h.catchError("Error finding text in editor:",t),[]}}findTextInContainer(t,n,r){try{const o=[],i=document.getElementById(r);return i?(t.getEditorState().read(()=>{const r=e(),{combinedText:a,nodeMap:c}=this.collectTextContent(r),s=this.getContainerTextContent(i,t,c,a);if(!s)return;const d=this.kmpSearch(s.text,n);for(const t of d)o.push({start:s.startOffset+t,end:s.startOffset+t+n.length})}),o):o}catch(t){return h.catchError("Error finding text in container:",t),[]}}getContainerTextContent(t,e,n,r){try{let o=-1,i=-1;for(let r=0;r<n.length;r++){const a=n[r];if(!a.isParagraphBreak&&a.node)try{const n=a.node.getKey(),r=e.getElementByKey(n);r&&t.contains(r)&&(-1===o&&(o=a.start),i=a.end)}catch(t){continue}}if(-1===o||-1===i)return null;return{text:r.substring(o,i),startOffset:o}}catch(t){return null}}filterNodesInContainer(t,e,n){try{const r=[];for(const o of t)try{const t=o.node.getKey(),i=n.getElementByKey(t);i&&e.contains(i)&&r.push(o)}catch(t){continue}return r}catch(t){return[]}}collectTextNodes(t){try{const e=[];let o=0;const i=t=>{if(n(t)){const n=t.getTextContent();e.push({node:t,text:n,textOffset:o}),o+=n.length}else if(r(t)){const e=t.getChildren();for(const t of e)i(t)}};return i(t),e}catch(t){return[]}}getTextNodesInRange(t,e,n,r){try{const o=[],{combinedText:i,nodeMap:a}=this.collectTextContent(t);for(const t of a){if(t.isParagraphBreak||!t.node)continue;const i=t.node.getParent();if((!l(i)||!r||i.__annotationId!==r)&&(t.end>e&&t.start<n)){const r=Math.max(0,e-t.start),i=Math.min(t.node.getTextContent().length,n-t.start),a=r>0||i<t.node.getTextContent().length;o.push({node:t.node,startOffset:r,endOffset:i,isPartial:a})}}return o}catch(t){return h.catchError("Error getting text nodes in range:",t),[]}}isRangeAlreadyWrapped(t,e,o,i){try{let a=0,c=!1;const s=t=>{if(l(t)){if(t.__annotationId===i){const n=t.getTextContent(),r=a,i=a+n.length;if(r<=e&&i>=o)return c=!0,!0}const n=t.getTextContent();a+=n.length}else if(n(t)){const e=t.getTextContent();a+=e.length}else if(r(t)){const e=t.getChildren();for(const t of e)if(s(t))return!0;if("paragraph"===t.getType()){const e=t.getParent();if(e&&r(e)){const n=e.getChildren();n.indexOf(t)<n.length-1&&(a+=1)}}}return!1};return s(t),c}catch(t){return!0}}collectTextNodesInRange(t,e){try{const o=[];let i=0;const a=t=>{const c=i;if(n(t)){const n=t.getTextContent(),r=i+n.length;r>=e.start&&c<=e.end&&o.push({node:t,text:n,start:i,end:r}),i=r}else if(r(t)){const e=t.getChildren();for(const t of e)a(t)}};return a(t),o}catch(t){return[]}}getContainerRange(t,e){try{const n=t.getRootElement();if(!n||!n.contains(e))return null;const r=e.textContent||"",o=(n.textContent||"").indexOf(r);return-1===o?null:{start:o,end:o+r.length}}catch(t){return h.catchError("Error getting container range:",t),null}}kmpSearch(t,e,n=0,r){try{const o=[];if(!e||!t||e.length>t.length)return o;const i=this.computeKMPTable(e);let a=0,c=0;for(;a<t.length;)if(e[c]===t[a]&&(a++,c++),c===e.length){if(o.push(n+a-c),c=i[c-1],r&&o.length>=r)break}else a<t.length&&e[c]!==t[a]&&(0!==c?c=i[c-1]:a++);return o}catch(t){return[]}}computeKMPTable(t){try{const e=new Array(t.length).fill(0);let n=0,r=1;for(;r<t.length;)t[r]===t[n]?(n++,e[r]=n,r++):0!==n?n=e[n-1]:(e[r]=0,r++);return e}catch(t){return[]}}findParentContainerWithId(t,e){try{const n=t.anchor.getNode(),r=e.getElementByKey(n.getKey());if(!r)return null;let o=r;for(;o&&o!==document.body;){if(o.id)return o;o=o.parentElement}return null}catch(t){return null}}highlightTextWithVeltComment(t,n,r){try{const{targetTextNodeId:o}=r,i=r?.occurrence||1;if(r.annotationId){const e=this.plugin.storeService.annotationStore.get(r.annotationId);if(e){const n=e.annotation.context?.textEditorConfig,o=r.originalAnnotation?.context?.textEditorConfig;n&&o&&(n.text!==o.text||n.occurrence!==o.occurrence||n.targetTextNodeId!==o.targetTextNodeId)&&this.removeVeltCommentFromEditor(t,r.annotationId)}}if(!n||0===n.length)return;if(o){const t=document.getElementById(o);if(t){const e=t.closest("[data-velt-location-id]")?.getAttribute("data-velt-location-id");if(e!==r.originalAnnotation?.location?.id)return}}let a=[];if(a=o?this.findTextInDomElement(t,n,o,i):this.findTextInDocument(t,n,i),0===a.length)return;const c=a[Math.min(i,a.length)-1];if(c&&r.annotationId){if(t.getEditorState().read(()=>{const t=e();return this.isRangeAlreadyWrapped(t,c.start,c.end,r.annotationId)}))return;this.plugin.storeService.annotationStore.set(r.annotationId,{annotation:r.originalAnnotation||{annotationId:r.annotationId,multiThreadAnnotationId:r.multiThreadAnnotationId,text:n},pluginReference:{node:document.createElement("velt-comment-text"),position:{from:c.start,to:c.end}}}),this.setVeltComment(t,r.annotationId,r.multiThreadAnnotationId,c.start,c.end)}}catch(t){h.catchError("Error highlighting text with Velt comment:",t)}}findTextInDomElement(t,n,r,o){try{const i=[],a=document.getElementById(r);return a?(t.getEditorState().read(()=>{const r=e(),c=this.filterNodesInContainer(this.collectTextNodes(r),a,t);if(0===c.length)return;const s=c[0].textOffset,d=c.map(t=>t.text).join(""),l=this.kmpSearch(d,n,0,o);for(const t of l)i.push({start:s+t,end:s+t+n.length})}),i):i}catch(t){return[]}}findTextInDocument(t,n,r){try{const o=[];return t.getEditorState().read(()=>{const t=e(),{combinedText:i}=this.collectTextContent(t),a=this.kmpSearch(i,n,0,r);for(const t of a)o.push({start:t,end:t+n.length})}),o}catch(t){return h.catchError("Error finding text in document:",t),[]}}setVeltComment(t,n,r,o,i){try{t.update(()=>{const t=e();t.selectStart();const a=this.getTextNodesInRange(t,o,i,n);if(0===a.length)return;const c=d(n,r);if(1===a.length){const{node:t,startOffset:e,endOffset:n,isPartial:r}=a[0];r?this.wrapPartialTextNode(t,e,n,c):this.wrapEntireTextNode(t,c)}else this.wrapMultipleTextNodesWithFormatting(a,c)})}catch(t){h.catchError("Error setting Velt comment:",t)}}wrapPartialTextNode(t,e,n,r){try{const o=t.getWritable(),i=o.getTextContent(),c=i.substring(0,e),s=i.substring(e,n),d=i.substring(n),l=a(s);if(l.setFormat(o.getFormat()),l.setStyle(o.getStyle()),r.append(l),c){const t=a(c);t.setFormat(o.getFormat()),t.setStyle(o.getStyle()),o.insertBefore(t)}if(o.insertBefore(r),d){const t=a(d);t.setFormat(o.getFormat()),t.setStyle(o.getStyle()),o.insertBefore(t)}o.remove()}catch(t){}}wrapEntireTextNode(t,e){try{const n=t.getWritable();e.append(n);const r=n.getParent();if(r){const t=r.getWritable(),o=n.getIndexWithinParent();t.splice(o,1,[e])}}catch(t){}}wrapMultipleTextNodesWithFormatting(t,e){try{const n=new Map;for(const e of t){const t=this.findParagraphParent(e.node),r=t?t.getKey():"no-paragraph";n.has(r)||n.set(r,[]),n.get(r).push(e)}let r=!0;for(const[,t]of n.entries()){const n=r?e:d(e.__annotationId,e.__multiThreadAnnotationId);if(1===t.length){const e=t[0],{node:r,startOffset:o,endOffset:i,isPartial:a}=e;a?this.wrapPartialTextNode(r,o,i,n):this.wrapEntireTextNode(r,n)}else this.wrapMultipleNodesInSameParagraph(t,n);r=!1}}catch(t){h.catchError("Error in wrapMultipleTextNodesWithFormatting:",t)}}findParagraphParent(t){let e=t.getParent();for(;e;){if(r(e)&&"paragraph"===e.getType())return e;e=e.getParent()}return null}wrapMultipleNodesInSameParagraph(t,e){try{const n=[...t].sort((t,e)=>t.node.getIndexWithinParent()-e.node.getIndexWithinParent()),r=n[0],o=n[n.length-1],i=r.node.getWritable(),c=i.getParent();if(!c)return;const s=c.getWritable();let d=i.getIndexWithinParent();if(r.isPartial&&r.startOffset>0){const t=r.node.getTextContent().substring(0,r.startOffset),n=r.node.getTextContent().substring(r.startOffset),o=a(t);o.setFormat(i.getFormat()),o.setStyle(i.getStyle());const c=a(n);c.setFormat(i.getFormat()),c.setStyle(i.getStyle()),e.append(c),s.splice(d,1,[o,e])}else e.append(i),s.splice(d,1,[e]);for(let t=1;t<n.length-1;t++){const r=n[t].node.getWritable();e.append(r)}if(n.length>1){const t=o.node.getWritable();if(o.isPartial&&o.endOffset<o.node.getTextContent().length){const n=o.node.getTextContent().substring(0,o.endOffset),r=o.node.getTextContent().substring(o.endOffset),i=a(n);i.setFormat(t.getFormat()),i.setStyle(t.getStyle());const c=a(r);c.setFormat(t.getFormat()),c.setStyle(t.getStyle()),e.append(i),t.replace(c)}else e.append(t)}}catch(t){h.catchError("Error in wrapMultipleNodesInSameParagraph:",t)}}removeVeltCommentFromEditor(t,n){try{if(!t||!n)throw new Error("Invalid input: editor and annotationId are required");let o=!1;return t.update(()=>{const t=e(),i=[];!function t(e){if(l(e))e.__annotationId===n&&i.push(e);else if(r(e)){const n=e.getChildren();for(const e of n)t(e)}}(t);for(const t of i)try{const e=t.getWritable(),n=e.getChildren();if(n.length>0){const t=n[0];e.replace(t);let r=t;for(let t=1;t<n.length;t++)r.insertAfter(n[t]),r=n[t]}else{const t=e.getTextContent();if(t){const n=a(t);e.replace(n)}else e.remove()}o=!0}catch(t){h.catchError("Error removing individual comment node:",t)}}),o&&this.plugin.storeService.annotationStore.remove(n),o}catch(t){return!1}}}u.getEditorId=t=>{try{return t&&t._config?t._config.namespace:null}catch(t){return h.catchError("Error finding editor ID:",t),null}};class f{constructor(t){this.isSubscribed=!1,this.globalStore={editor:null,comments:[],filteredComments:[],selectedCommentsMap:new Map},this.globalAnnotationStore=new Map,this.annotationStore={get:t=>this.globalAnnotationStore.get(t),set:(t,e)=>{this.globalAnnotationStore.set(t,e)},getAll:()=>new Map(this.globalAnnotationStore),clear:()=>{this.globalAnnotationStore.clear()},remove:t=>{this.globalAnnotationStore.delete(t)},hasAnnotationTextChanged:(t,e)=>{try{const n=this.globalAnnotationStore.get(t);if(!n||!e)return!1;const r=n.annotation.text,o=e.context?.textEditorConfig?.text;return r!==o}catch(t){return!1}}},this.updateGlobalStore=t=>{try{const e=t?.comments||this.globalStore?.comments||[],n=t?.selectedCommentsMap||this.globalStore?.selectedCommentsMap||new Map,r=this.globalStore?.filteredComments||[],o=e.filter(t=>"terminal"!==t?.status?.type||n?.get(t?.annotationId)),i=new Set(o.map(t=>t?.annotationId));r.map(t=>t?.annotationId).filter(t=>t&&!i.has(t)).forEach(t=>{this.globalStore?.editor&&t&&this.plugin.editorService.removeVeltCommentFromEditor(this.globalStore?.editor,t)}),this.globalStore={...this.globalStore,...t,filteredComments:o},this.highlightCommentsFromGlobalStore()}catch(t){h.catchError("Error updating global store:",t)}},this.highlightCommentsFromGlobalStore=()=>{try{const{editor:t,filteredComments:e}=this.globalStore;if(!t||!e)return;for(const n of e){const e=n?.context?.textEditorConfig?.text,r=n?.context?.textEditorConfig?.occurrence;e&&this.plugin.editorService.highlightTextWithVeltComment(t,e,{annotationId:n?.annotationId,multiThreadAnnotationId:n?.multiThreadAnnotationId,occurrence:r,targetTextNodeId:n?.context?.textEditorConfig?.targetTextNodeId,originalAnnotation:n})}}catch(t){h.catchError("Error highlighting comments from global store:",t)}},this.plugin=t;try{h.subscribeToSelectedCommentsMap(this.plugin.editorId,t=>{try{this.updateGlobalStore({selectedCommentsMap:t})}catch(t){h.catchError("Error updating global store:",t)}})}catch(t){h.catchError("Error subscribing to selected comments map:",t)}}}f.storeInstanceMap=new Map;const m=new Map;class p{constructor(t,e){this.editorId=t,this.editor=e,this.editorService=new u(this),e&&this.editorService.initializeTransactionListener(e),this.storeService=new f(this)}static getInstance(t){let{editorId:e,editor:n}=t||{};return e||(e="default"),m.has(e)||m.set(e,new p(e,n)),m.get(e)}}function x(t){const n=function(t){const e=t._createEditorArgs,n={namespace:`shadow-editor-${Date.now()}`,nodes:e?.nodes||[],theme:{},onError:t=>{},editable:!1};return c(n)}(t);try{const o=t.getEditorState();n.setEditorState(o),n.update(()=>{!function(t){const e=[];function n(t){if(l(t))e.push(t);else if(r(t)){t.getChildren().forEach(n)}}n(t),e.forEach(t=>{try{const e=t.getParent();if(!e)return;const n=t.getChildren(),r=t.getIndexWithinParent();t.remove(),n.length>0&&e.splice(r,0,n)}catch(t){}}),t.markDirty()}(e())},{discrete:!0});const i=n.getEditorState().toJSON();return JSON.stringify(i)}catch(e){return function(t){return t.getEditorState().read(()=>{const e=C(T(t.getEditorState().toJSON()));return JSON.stringify(e)})}(t)}}function T(t){if(!t||"object"!=typeof t)return t;if(Array.isArray(t)){const e=[];for(const n of t)if(n&&"comment"===n.type){if(n.children&&Array.isArray(n.children))for(const t of n.children)e.push(T(t))}else e.push(T(n));return e}const e={...t};if("comment"===e.type)return e.children&&Array.isArray(e.children)?e.children.map(t=>T(t)):null;for(const[t,n]of Object.entries(e))("children"===t&&Array.isArray(n)||"object"==typeof n&&null!==n)&&(e[t]=T(n));return e}function C(t){if(!t||"object"!=typeof t)return t;if(Array.isArray(t))return t.map(t=>C(t));const e={...t};if(e.children&&Array.isArray(e.children)){const t=e.children.map(t=>C(t));e.children=function(t){if(!Array.isArray(t)||t.length<=1)return t;const e=[];let n=0;for(;n<t.length;){const r=t[n];if(r&&"text"===r.type){let o=r.text||"",i=n+1;for(;i<t.length;){const e=t[i];if(!e||"text"!==e.type||!y(r,e))break;o+=e.text||"",i++}e.push({...r,text:o}),n=i}else e.push(r),n++}return e}(t)}for(const[t,n]of Object.entries(e))"children"!==t&&"object"==typeof n&&null!==n&&(e[t]=C(n));return e}function y(t,e){return t.format===e.format&&t.style===e.style&&t.mode===e.mode&&t.detail===e.detail}const E=t=>{try{return x(t)}catch(n){return t.getEditorState().read(()=>{const t=e();return JSON.stringify({root:{children:[{children:[{detail:0,format:0,mode:"normal",style:"",text:t.getTextContent(),type:"text",version:1}],direction:"ltr",format:"",indent:0,type:"paragraph",version:1,textFormat:0,textStyle:""}],direction:"ltr",format:"",indent:0,type:"root",version:1}})})}};function I(t,n){try{const e=JSON.parse(n);t.setEditorState(t.parseEditorState(e))}catch(n){t.update(()=>{e().clear()})}}const S=async(t,e)=>{try{return b({editor:t,context:e?.context})}catch(t){h.catchError("Error triggering add comment",t)}},b=async({editorId:t,editor:e,context:n})=>{try{const r=h.getCommentElement();if(!r)return;await new Promise(t=>setTimeout(t,500)),t||(t=u.getEditorId(e)??void 0);const o=p.getInstance({editorId:t,editor:e}),i=o.editorService.getSelectedText(e);if(!i)return;let a;const c=o.editorService.findOccurrenceIndex(e,i,null);if(!c)return;let s,d={};n&&"object"==typeof n&&(d={...d,...n}),d.textEditorConfig={text:i,occurrence:c,targetTextNodeId:a},t&&(d.textEditorConfig.editorId=t),r?.addManualComment({context:d,location:s})?.then(t=>{})}catch(t){h.catchError("Error adding lexical-velt-comments",t)}};function N(t,e,n){try{A({editor:t,editorId:n,commentAnnotations:e})}catch(t){h.catchError("Error highlighting lexical-velt-comments",t)}}const A=({editor:t,editorId:e,commentAnnotations:n})=>{try{if(t){if(e||(e=u.getEditorId(t)??void 0),!Array.isArray(n))return;n=JSON.parse(JSON.stringify(n));const r=n?.filter(t=>!!t.context?.textEditorConfig&&t.context?.textEditorConfig?.editorId===e)||[];p.getInstance({editorId:e,editor:t}).storeService.updateGlobalStore({editor:t,comments:r}),h.subscribeToSelectedAnnotationsMapSingleton()}}catch(t){h.catchError("Error highlighting lexical-velt-comments",t)}};export{d as $createCommentNode,l as $isCommentNode,s as CommentNode,b as addComment,I as deserializeCleanState,E as exportCleanEditorContent,N as highlightComments,A as renderComments,S as triggerAddComment};
2
+ //# sourceMappingURL=index.js.map