From 15a2cf54c09860344f98378efbd5e9e576f885e5 Mon Sep 17 00:00:00 2001 From: Alun Turner Date: Thu, 11 May 2023 18:10:45 +0100 Subject: [PATCH] make it able to deal with inserting in middle of blank lines --- .../wysiwyg_composer/hooks/useSuggestion.ts | 42 ++++++++++--------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/src/components/views/rooms/wysiwyg_composer/hooks/useSuggestion.ts b/src/components/views/rooms/wysiwyg_composer/hooks/useSuggestion.ts index f9b083c6ed85..f76269e51864 100644 --- a/src/components/views/rooms/wysiwyg_composer/hooks/useSuggestion.ts +++ b/src/components/views/rooms/wysiwyg_composer/hooks/useSuggestion.ts @@ -157,26 +157,28 @@ export function processMention( const { node } = suggestionData; // create an element with the required attributes to allow us to interpret the mention as being a pill - const link = document.createElement("a"); - const linkText = document.createTextNode(displayName); - link.setAttribute("href", href); - link.setAttribute("contenteditable", "false"); - Object.entries(attributes).forEach(([attr, value]) => isNotUndefined(value) && link.setAttribute(attr, value)); - link.appendChild(linkText); - - // create a text node that will follow the inserted link (as we may be inserting into the middle of a node) - const endNode = document.createTextNode(` ${node.textContent?.slice(suggestionData.endOffset) ?? ""}`); - - // now amend the current node text content to be only the text from start up to the suggestion startOffset - // (default to a zwsp if we'd have no preceding text to allow cursor positioning before a lone pill) - node.textContent = node.textContent?.slice(0, suggestionData.startOffset) || "\u200b"; - - // then append the newly created link and the ending text node containing the space that follows the link - node.parentNode?.appendChild(link); - node.parentNode?.appendChild(endNode); - - // move the selection to after the space that follows the link - document.getSelection()?.setBaseAndExtent(endNode, 1, endNode, 1); + const linkElement = document.createElement("a"); + const linkTextNode = document.createTextNode(displayName); + linkElement.setAttribute("href", href); + linkElement.setAttribute("contenteditable", "false"); + Object.entries(attributes).forEach( + ([attr, value]) => isNotUndefined(value) && linkElement.setAttribute(attr, value), + ); + linkElement.appendChild(linkTextNode); + + // create text nodes to go before and after the link + const leadingTextNode = document.createTextNode(node.textContent?.slice(0, suggestionData.startOffset) || "\u200b"); + const trailingTextNode = document.createTextNode(` ${node.textContent?.slice(suggestionData.endOffset) ?? ""}`); + + // now add the leading node, link element and trailing node before removing the node we are replacing + const parentNode = node.parentNode; + parentNode.insertBefore(leadingTextNode, node); + parentNode.insertBefore(linkElement, node); + parentNode.insertBefore(trailingTextNode, node); + parentNode.removeChild(node); + + // move the selection to the trailing text node + document.getSelection()?.setBaseAndExtent(trailingTextNode, 1, trailingTextNode, 1); // set the text content to be the innerHTML of the current editor ref and clear the suggestion state setText();