From 18bb005f7a41c4a37d43c791962d9c03fbe6e407 Mon Sep 17 00:00:00 2001 From: Julien Nahum Date: Fri, 6 Dec 2024 14:49:06 +0100 Subject: [PATCH] Enhance Mention Extension for Quill Editor - Introduced a custom Clipboard module to sanitize pasted content by removing invalid mention formatting. - Updated MentionBlot creation logic to ensure mentions are only created with valid data, specifically checking for 'nf_id'. - Improved attribute setting for mentions to prevent issues with invalid or missing data. These changes aim to improve the reliability and integrity of mentions within the Quill editor. --- client/lib/quill/quillMentionExtension.js | 46 +++++++++++++++++------ 1 file changed, 35 insertions(+), 11 deletions(-) diff --git a/client/lib/quill/quillMentionExtension.js b/client/lib/quill/quillMentionExtension.js index 49442ab7..04c8e3f0 100644 --- a/client/lib/quill/quillMentionExtension.js +++ b/client/lib/quill/quillMentionExtension.js @@ -1,31 +1,55 @@ import { reactive } from 'vue' import Quill from 'quill' const Inline = Quill.import('blots/inline') +const Delta = Quill.import('delta') +const Clipboard = Quill.import('modules/clipboard') export default function registerMentionExtension(Quill) { + // Extend Clipboard to handle pasted content + class MentionClipboard extends Clipboard { + convert(html) { + const delta = super.convert(html) + // Remove any mention formatting from pasted content + return delta.reduce((newDelta, op) => { + if (op.attributes && op.attributes.mention) { + // Only keep mentions that have valid field IDs + if (!op.attributes.mention['mention-field-id']) { + delete op.attributes.mention + } + } + newDelta.push(op) + return newDelta + }, new Delta()) + } + } + Quill.register('modules/clipboard', MentionClipboard, true) + class MentionBlot extends Inline { static blotName = 'mention' static tagName = 'SPAN' static create(data) { + // Only create mention if we have valid data + if (!data || !data.field || !data.field.nf_id) { + return null + } let node = super.create() MentionBlot.setAttributes(node, data) return node } static setAttributes(node, data) { + // Only set attributes if we have valid data + if (!data || !data.field || !data.field.nf_id) { + return + } + node.setAttribute('contenteditable', 'false') node.setAttribute('mention', 'true') - - if (data && typeof data === 'object') { - node.setAttribute('mention-field-id', data.field?.id || '') - node.setAttribute('mention-field-name', data.field?.name || '') - node.setAttribute('mention-fallback', data.fallback || '') - node.textContent = data.field?.name || '' - } else { - // Handle case where data is not an object (e.g., during undo) - node.textContent = data || '' - } + node.setAttribute('mention-field-id', data.field.nf_id || '') + node.setAttribute('mention-field-name', data.field.name || '') + node.setAttribute('mention-fallback', data.fallback || '') + node.textContent = data.field.name || '' } static formats(domNode) { @@ -53,7 +77,7 @@ export default function registerMentionExtension(Quill) { static value(domNode) { return { field: { - id: domNode.getAttribute('mention-field-id') || '', + nf_id: domNode.getAttribute('mention-field-id') || '', name: domNode.getAttribute('mention-field-name') || '' }, fallback: domNode.getAttribute('mention-fallback') || ''