/** * TipTap mark extensions for track-changes suggestions. * * SuggestionInsert: wraps text that was inserted in suggesting mode (green underline). * SuggestionDelete: wraps text that was marked for deletion in suggesting mode (red strikethrough). * * Both marks are stored in the Yjs document and sync in real-time. * Accept/reject logic is handled by the suggestion-plugin. */ import { Mark, mergeAttributes } from '@tiptap/core'; export const SuggestionInsertMark = Mark.create({ name: 'suggestionInsert', addAttributes() { return { suggestionId: { default: null }, authorId: { default: null }, authorName: { default: null }, createdAt: { default: null }, }; }, parseHTML() { return [ { tag: 'span[data-suggestion-insert]', getAttrs: (el) => { const element = el as HTMLElement; return { suggestionId: element.getAttribute('data-suggestion-id'), authorId: element.getAttribute('data-author-id'), authorName: element.getAttribute('data-author-name'), createdAt: Number(element.getAttribute('data-created-at')) || null, }; }, }, ]; }, renderHTML({ HTMLAttributes }) { return [ 'span', mergeAttributes({ class: 'suggestion-insert', 'data-suggestion-insert': '', 'data-suggestion-id': HTMLAttributes.suggestionId, 'data-author-id': HTMLAttributes.authorId, 'data-author-name': HTMLAttributes.authorName, 'data-created-at': HTMLAttributes.createdAt, }), 0, ]; }, }); export const SuggestionDeleteMark = Mark.create({ name: 'suggestionDelete', addAttributes() { return { suggestionId: { default: null }, authorId: { default: null }, authorName: { default: null }, createdAt: { default: null }, }; }, parseHTML() { return [ { tag: 'span[data-suggestion-delete]', getAttrs: (el) => { const element = el as HTMLElement; return { suggestionId: element.getAttribute('data-suggestion-id'), authorId: element.getAttribute('data-author-id'), authorName: element.getAttribute('data-author-name'), createdAt: Number(element.getAttribute('data-created-at')) || null, }; }, }, ]; }, renderHTML({ HTMLAttributes }) { return [ 'span', mergeAttributes({ class: 'suggestion-delete', 'data-suggestion-delete': '', 'data-suggestion-id': HTMLAttributes.suggestionId, 'data-author-id': HTMLAttributes.authorId, 'data-author-name': HTMLAttributes.authorName, 'data-created-at': HTMLAttributes.createdAt, }), 0, ]; }, });