commit 61806d86dd2e468cf10104de32a8107aa9920f39
parent d563b153e63de281edf9b37a1d50dcfccb1b7147
Author: MTRNord <mtrnord1@gmail.com>
Date: Thu, 4 May 2023 21:43:26 +0200
Purify some of the html (attributes missing) and align avatars properly in text messages
Diffstat:
3 files changed, 66 insertions(+), 16 deletions(-)
diff --git a/package-lock.json b/package-lock.json
@@ -19,7 +19,6 @@
"@types/react-dom": "^18.0.11",
"dompurify": "^3.0.2",
"idb": "^7.1.1",
- "immer": "^10.0.1",
"lexical": "^0.10.0",
"linkify-react": "^4.1.1",
"linkifyjs": "^4.1.1",
@@ -43,6 +42,7 @@
"@storybook/react-vite": "^7.0.7",
"@storybook/testing-library": "^0.1.0",
"@tailwindcss/forms": "^0.5.3",
+ "@types/dompurify": "^3.0.2",
"@vitejs/plugin-react-swc": "^3.3.0",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
@@ -5401,6 +5401,15 @@
"integrity": "sha512-w5jZ0ee+HaPOaX25X2/2oGR/7rgAQSYII7X7pp0m9KgBfMP7uKfMfTvcpl5Dj+eDBbpxKGiqE+flqDr6XTd2RA==",
"dev": true
},
+ "node_modules/@types/dompurify": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/dompurify/-/dompurify-3.0.2.tgz",
+ "integrity": "sha512-YBL4ziFebbbfQfH5mlC+QTJsvh0oJUrWbmxKMyEdL7emlHJqGR2Qb34TEFKj+VCayBvjKy3xczMFNhugThUsfQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/trusted-types": "*"
+ }
+ },
"node_modules/@types/ejs": {
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/@types/ejs/-/ejs-3.1.2.tgz",
@@ -5656,6 +5665,12 @@
"@types/jest": "*"
}
},
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.3.tgz",
+ "integrity": "sha512-NfQ4gyz38SL8sDNrSixxU2Os1a5xcdFxipAFxYEuLUlvU2uDwS4NUpsImcf1//SlWItCVMMLiylsxbmNMToV/g==",
+ "dev": true
+ },
"node_modules/@types/unist": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@types/unist/-/unist-2.0.6.tgz",
@@ -8987,15 +9002,6 @@
"node": ">=0.10.0"
}
},
- "node_modules/immer": {
- "version": "10.0.1",
- "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.1.tgz",
- "integrity": "sha512-zg++jJLsKKTwXGeSYIw0HgChSYQGtu0UDTnbKx5aGLYgte4CwTmH9eJDYyQ6FheyUtBe+lQW9FrGxya1G+Dtmg==",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/immer"
- }
- },
"node_modules/immutable": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/immutable/-/immutable-4.3.0.tgz",
diff --git a/package.json b/package.json
@@ -15,7 +15,6 @@
"@types/react-dom": "^18.0.11",
"dompurify": "^3.0.2",
"idb": "^7.1.1",
- "immer": "^10.0.1",
"lexical": "^0.10.0",
"linkify-react": "^4.1.1",
"linkifyjs": "^4.1.1",
@@ -74,6 +73,7 @@
"@storybook/react-vite": "^7.0.7",
"@storybook/testing-library": "^0.1.0",
"@tailwindcss/forms": "^0.5.3",
+ "@types/dompurify": "^3.0.2",
"@vitejs/plugin-react-swc": "^3.3.0",
"autoprefixer": "^10.4.14",
"postcss": "^8.4.23",
diff --git a/src/components/events/messageEvent.tsx b/src/components/events/messageEvent.tsx
@@ -4,6 +4,7 @@ import { FC } from "react";
import Avatar from "../avatar/avatar";
import { useRoom } from "../../app/sdk/client";
import Linkify from "linkify-react";
+import DOMPurify from "dompurify";
type MessageEventProps = {
/**
@@ -32,9 +33,52 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, roomID, hasPreviousEv
const renderCorrectMessage = (event: IRoomEvent) => {
if (isRoomMessageTextEvent(event)) {
if (event.content.format === "org.matrix.custom.html") {
- // TODO: Sanitize HTML
+ const sanitized = DOMPurify.sanitize(event.content.formatted_body!, {
+ ADD_TAGS: [
+ "font",
+ "del",
+ "h1",
+ "h2",
+ "h3",
+ "h4",
+ "h5",
+ "h6",
+ "blockquote",
+ "p",
+ "a",
+ "ul",
+ "ol",
+ "sup",
+ "sub",
+ "li",
+ "b",
+ "i",
+ "u",
+ "strong",
+ "em",
+ "strike",
+ "code",
+ "hr",
+ "br",
+ "div",
+ "table",
+ "thead",
+ "tbody",
+ "tr",
+ "th",
+ "td",
+ "caption",
+ "pre",
+ "span",
+ "img",
+ "details",
+ "summary"
+ ]
+ })
+ // TODO: sanitize the attributes allowed by matrix spec
+
return (
- <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out" : "flex flex-row p-2 pt-0 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
+ <div className={!hasPreviousEvent ? "flex flex-row gap-4 p-2 pb-1 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start" : "flex flex-row p-2 pt-0 hover:bg-gray-200 rounded-md duration-200 ease-in-out"}>
{!hasPreviousEvent && <Avatar
displayname={room?.getMemberName(event.sender) || ""}
avatarUrl={room?.getMemberAvatar(event.sender)}
@@ -44,13 +88,13 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, roomID, hasPreviousEv
<div className={!hasPreviousEvent ? "flex flex-col gap-1" : "ml-[3.7rem]"}>
{!hasPreviousEvent && <h2 className="text-sm font-medium text-red-500 whitespace-normal">{room?.getMemberName(event.sender)}</h2>}
{/* TODO: Fixme */}
- <p className="whitespace-normal" dangerouslySetInnerHTML={{ __html: event.content.formatted_body! }}></p>
+ <p className="whitespace-normal text-black text-base font-normal" dangerouslySetInnerHTML={{ __html: sanitized }}></p>
</div>
</div>
)
} else {
return (
- <div className="flex flex-row gap-4 p-2 hover:bg-gray-200 rounded-md duration-200 ease-in-out">
+ <div className="flex flex-row gap-4 p-2 hover:bg-gray-200 rounded-md duration-200 ease-in-out items-start">
<Avatar
displayname={room?.getMemberName(event.sender) || ""}
avatarUrl={room?.getMemberAvatar(event.sender)}
@@ -59,7 +103,7 @@ const MessageEvent: FC<MessageEventProps> = memo(({ event, roomID, hasPreviousEv
/>
<div className="flex flex-col gap-2">
<h2 className="text-sm font-medium text-red-500 whitespace-normal">{room?.getMemberName(event.sender)}</h2>
- <Linkify options={linkifyOptions} as='p' className="whitespace-normal">{event.content.body}</Linkify>
+ <Linkify options={linkifyOptions} as='p' className="whitespace-normal text-black text-base font-normal">{event.content.body}</Linkify>
</div>
</div>
)