diff --git a/src/ui/MentionUserLabel/__tests__/__snapshots__/MentionUserLabel.spec.js.snap b/src/ui/MentionUserLabel/__tests__/__snapshots__/MentionUserLabel.spec.js.snap
index 41c7db5ee..c14293da5 100644
--- a/src/ui/MentionUserLabel/__tests__/__snapshots__/MentionUserLabel.spec.js.snap
+++ b/src/ui/MentionUserLabel/__tests__/__snapshots__/MentionUserLabel.spec.js.snap
@@ -5,6 +5,7 @@ exports[`ui/MentionUserLabel should do a snapshot test of the MentionUserLabel D
`;
diff --git a/src/ui/MentionUserLabel/__tests__/renderToString.spec.js b/src/ui/MentionUserLabel/__tests__/renderToString.spec.js
new file mode 100644
index 000000000..d7c76ebb2
--- /dev/null
+++ b/src/ui/MentionUserLabel/__tests__/renderToString.spec.js
@@ -0,0 +1,11 @@
+import renderToString from "../renderToString";
+
+describe("ui/MentionUserLabel/renderToString", () => {
+ it("should render userId and nickname as expected", () => {
+ const userId = "me";
+ const nickname = "nickname";
+ const expected = `nickname`;
+ const result = renderToString({ userId, nickname });
+ expect(result).toEqual(expected);
+ });
+});
diff --git a/src/ui/MentionUserLabel/consts.ts b/src/ui/MentionUserLabel/consts.ts
new file mode 100644
index 000000000..c3e2ab763
--- /dev/null
+++ b/src/ui/MentionUserLabel/consts.ts
@@ -0,0 +1 @@
+export const MENTION_USER_LABEL_CLASSNAME = 'sendbird-mention-user-label';
diff --git a/src/ui/MentionUserLabel/index.tsx b/src/ui/MentionUserLabel/index.tsx
index 3ed14cec2..50e03d236 100644
--- a/src/ui/MentionUserLabel/index.tsx
+++ b/src/ui/MentionUserLabel/index.tsx
@@ -1,6 +1,8 @@
-import React from 'react';
import './index.scss';
+import React from 'react';
+import { MENTION_USER_LABEL_CLASSNAME } from './consts';
+
interface MentionUserLabelProps {
className?: string
children?: string;
@@ -18,9 +20,10 @@ export default function MentionUserLabel({
}: MentionUserLabelProps): JSX.Element {
return (
{children}
diff --git a/src/ui/MentionUserLabel/renderToString.ts b/src/ui/MentionUserLabel/renderToString.ts
new file mode 100644
index 000000000..ebfd129ae
--- /dev/null
+++ b/src/ui/MentionUserLabel/renderToString.ts
@@ -0,0 +1,20 @@
+// cretes a sanitized string from a mention user label
+import DOMPurify from 'dompurify';
+import { MENTION_USER_LABEL_CLASSNAME } from './consts';
+
+type renderToStringParams = {
+ userId: string;
+ nickname: string;
+};
+
+export default function renderToString({ userId, nickname }: renderToStringParams): string {
+ // donot change this template, it wont work
+ const el = `${nickname}`;
+ const purifier = DOMPurify(window);
+ const sanitized_ = purifier.sanitize(el);
+ const token = sanitized_.split(' ');
+ const [spanTag, ...rest] = token;
+ // we do this because DOMPurify removes the contenteditable attribute
+ const sanitized = [spanTag, 'contenteditable="false"', ...rest].join(' ');
+ return sanitized;
+}
diff --git a/src/ui/MessageInput/hooks/usePaste/insertTemplate.tsx b/src/ui/MessageInput/hooks/usePaste/insertTemplate.ts
similarity index 58%
rename from src/ui/MessageInput/hooks/usePaste/insertTemplate.tsx
rename to src/ui/MessageInput/hooks/usePaste/insertTemplate.ts
index 9d14decc8..74c0b4782 100644
--- a/src/ui/MessageInput/hooks/usePaste/insertTemplate.tsx
+++ b/src/ui/MessageInput/hooks/usePaste/insertTemplate.ts
@@ -1,23 +1,12 @@
-import React from 'react';
-import { renderToString } from 'react-dom/server';
-
import { Word } from './types';
import { sanitizeString } from '../../utils';
-import MentionUserLabel from '../../../MentionUserLabel';
+import renderMentionLabelToString from '../../../MentionUserLabel/renderToString';
export function inserTemplateToDOM(templateList: Word[]): void {
const nodes = templateList.map((template) => {
const { text, userId } = template;
if (userId) {
- return (
- renderToString(
- <>
-
- {text}
-
- >
- )
- );
+ return renderMentionLabelToString({ userId, nickname: text });
}
return sanitizeString(text);
})
diff --git a/src/ui/MessageInput/index.jsx b/src/ui/MessageInput/index.jsx
index 64ef25a88..c6af70938 100644
--- a/src/ui/MessageInput/index.jsx
+++ b/src/ui/MessageInput/index.jsx
@@ -6,7 +6,6 @@ import React, {
useCallback,
useContext,
} from 'react';
-import { renderToString } from 'react-dom/server';
import PropTypes from 'prop-types';
import './index.scss';
@@ -15,7 +14,7 @@ import { MessageInputKeys, NodeNames, NodeTypes } from './const';
import { USER_MENTION_TEMP_CHAR } from '../../smart-components/Channel/context/const';
import IconButton from '../IconButton';
import Button, { ButtonTypes, ButtonSizes } from '../Button';
-import MentionUserLabel from '../MentionUserLabel';
+import renderMentionLabelToString from '../MentionUserLabel/renderToString';
import Icon, { IconTypes, IconColors } from '../Icon';
import Label, { LabelTypography, LabelColors } from '../Label';
import { LocalizationContext } from '../../lib/LocalizationContext';
@@ -161,16 +160,11 @@ const MessageInput = React.forwardRef((props, ref) => {
convertWordToStringObj(word, mentionedUsers).map((stringObj) => {
const { type, value, userId } = stringObj;
if (type === StringObjType.mention && mentionedUsers.some((user) => user?.userId === userId)) {
- return renderToString(
-
- {
- `${USER_MENTION_TEMP_CHAR}${mentionedUsers.find((user) => user?.userId === userId)?.nickname
- || value
- || stringSet.MENTION_NAME__NO_NAME
- }`
- }
- ,
- );
+ const nickname = `${USER_MENTION_TEMP_CHAR}${mentionedUsers.find((user) => user?.userId === userId)?.nickname
+ || value
+ || stringSet.MENTION_NAME__NO_NAME
+ }`
+ return renderMentionLabelToString({ userId, nickname });
}
return sanitizeString(value);
}).join('')
@@ -220,11 +214,10 @@ const MessageInput = React.forwardRef((props, ref) => {
const backTextNode = document?.createTextNode(
`\u00A0${childNodes[endNodeIndex]?.textContent.slice(endOffsetIndex)}`,
);
- const mentionLabel = renderToString(
-
- {`${USER_MENTION_TEMP_CHAR}${mentionSelectedUser?.nickname || stringSet.MENTION_NAME__NO_NAME}`}
- ,
- );
+ const mentionLabel = renderMentionLabelToString({
+ userId: mentionSelectedUser?.userId,
+ nickname: `${USER_MENTION_TEMP_CHAR}${mentionSelectedUser?.nickname || stringSet.MENTION_NAME__NO_NAME}`,
+ });
const div = document.createElement('div');
div.innerHTML = mentionLabel;
const newNodes = [