From 02ce21582f586abe99479301e65e17a76868c867 Mon Sep 17 00:00:00 2001 From: Uday Sagar Date: Fri, 5 Jul 2024 19:23:06 +0530 Subject: [PATCH] mention style and strike through style --- src/Components/Common/MarkdownEditor.tsx | 58 +++++++---------------- src/Components/Common/MarkdownPreview.tsx | 20 ++++++++ 2 files changed, 38 insertions(+), 40 deletions(-) create mode 100644 src/Components/Common/MarkdownPreview.tsx diff --git a/src/Components/Common/MarkdownEditor.tsx b/src/Components/Common/MarkdownEditor.tsx index c41773d9511..7a5bbdeca39 100644 --- a/src/Components/Common/MarkdownEditor.tsx +++ b/src/Components/Common/MarkdownEditor.tsx @@ -12,8 +12,8 @@ import { import { GoMention } from "react-icons/go"; // import { MdAttachFile } from "react-icons/md"; import TurndownService from "turndown"; -import ReactMarkdown from "react-markdown"; import MentionsDropdown from "./MentionDropdown"; +import MarkdownPreview from "./MarkdownPreview"; interface RichTextEditorProps { markdown?: string; @@ -141,14 +141,13 @@ const RichTextEditor: React.FC = () => { return null; }; - const applyStyle = (style: "bold" | "italic" | "strikethrough") => { + const applyStyle = (style: "b" | "i" | "s") => { const selection = window.getSelection(); if (!selection || !selection.rangeCount) return; const range = selection.getRangeAt(0); - const tag = style === "bold" ? "strong" : style === "italic" ? "em" : "s"; - const node = document.createElement(tag); + const node = document.createElement(style); node.appendChild(range.cloneContents()); range.deleteContents(); range.insertNode(node); @@ -278,9 +277,10 @@ const RichTextEditor: React.FC = () => { range.setStart(range.startContainer, range.startOffset - 1); range.deleteContents(); - const mentionNode = document.createElement("span"); + const mentionNode = document.createElement("a"); mentionNode.contentEditable = "false"; - mentionNode.className = "bg-blue-100 px-1 rounded"; + mentionNode.className = + "bg-blue-100 px-1 rounded no-underline text-slate-800 font-normal hover:underline"; mentionNode.textContent = `@${user.username}`; mentionNode.setAttribute("data-user-id", user.id); @@ -301,33 +301,6 @@ const RichTextEditor: React.FC = () => { } }; - const handleKeyDown = (event: React.KeyboardEvent) => { - if (event.key === "Backspace") { - const selection = window.getSelection(); - if (selection && selection.rangeCount > 0) { - const range = selection.getRangeAt(0); - const startContainer = range.startContainer; - - if ( - startContainer.nodeType === Node.TEXT_NODE && - startContainer.textContent === "@" - ) { - const parentNode = startContainer.parentNode; - if ( - parentNode && - parentNode.nodeName === "SPAN" && - parentNode instanceof HTMLElement && - parentNode.hasAttribute("data-user-id") - ) { - event.preventDefault(); - parentNode.parentNode?.removeChild(parentNode); - saveState(); - } - } - } - } - }; - const saveState = () => { const turndownService = new TurndownService(); turndownService.addRule("strikethrough", { @@ -336,12 +309,18 @@ const RichTextEditor: React.FC = () => { }); turndownService.addRule("mentions", { filter: (node) => { - return node.nodeName === "SPAN" && node.hasAttribute("data-user-id"); + return node.nodeName === "A" && node.hasAttribute("data-user-id"); }, replacement: (content, node) => { const userId = (node as HTMLElement).getAttribute("data-user-id"); const username = content.replace("@", ""); - return `[mention_user](user_id:${userId}, username:${username})`; + return `![mention_user](user_id:${userId}, username:${username})`; + }, + }); + turndownService.addRule("div", { + filter: "div", + replacement: function (content) { + return content + "\n"; }, }); @@ -357,7 +336,7 @@ const RichTextEditor: React.FC = () => {
{showMentions && ( @@ -477,7 +455,7 @@ const RichTextEditor: React.FC = () => {

Markdown Preview:

- {markdown} +

Markdown Output:

diff --git a/src/Components/Common/MarkdownPreview.tsx b/src/Components/Common/MarkdownPreview.tsx new file mode 100644 index 00000000000..ee7222e193c --- /dev/null +++ b/src/Components/Common/MarkdownPreview.tsx @@ -0,0 +1,20 @@ +import ReactMarkdown from "react-markdown"; +import rehypeRaw from "rehype-raw"; + +const MarkdownPreview = ({ markdown }: { markdown: string }) => { + const processedMarkdown = markdown + .replace( + /!\[mention_user\]\(user_id:(\d+), username:([^)]+)\)/g, + (_, userId, username) => + `@${username}`, + ) + .replace(/~(.*?)~/g, (_, text) => `${text}`); + + return ( + + {processedMarkdown} + + ); +}; + +export default MarkdownPreview;