feat(SanitizedDiv): add a new component to sanitize and render HTML content safely

🔨 refactor(chatMessage): replace the usage of DOMPurify with SanitizedHTMLWrapper component in chatMessage component
🔨 refactor(formModal): replace the usage of DOMPurify with SanitizedHTMLWrapper component in formModal component
🔨 refactor(genericModal): replace the usage of DOMPurify with SanitizedHTMLWrapper component in genericModal component
This commit is contained in:
Gabriel Luiz Freitas Almeida 2023-07-08 15:11:59 -03:00
commit 9a3e0d2891
4 changed files with 38 additions and 20 deletions

View file

@ -0,0 +1,21 @@
import DOMPurify from "dompurify";
const SanitizedHTMLWrapper = ({
className,
content,
onClick,
suppressWarning = false,
}) => {
const sanitizedHTML = DOMPurify.sanitize(content);
return (
<div
className={className}
dangerouslySetInnerHTML={{ __html: sanitizedHTML }}
suppressContentEditableWarning={suppressWarning}
onClick={onClick}
/>
);
};
export default SanitizedHTMLWrapper;

View file

@ -1,5 +1,4 @@
import Convert from "ansi-to-html";
import DOMPurify from "dompurify";
import { MessageCircle, User2 } from "lucide-react";
import { useEffect, useRef, useState } from "react";
import ReactMarkdown from "react-markdown";
@ -8,6 +7,7 @@ import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import AiIcon from "../../../assets/Gooey Ring-5s-271px.svg";
import AiIconStill from "../../../assets/froze-flow.png";
import SanitizedHTMLWrapper from "../../../components/SanitizedDiv";
import { ChatMessageType } from "../../../types/chat";
import { classNames } from "../../../utils";
import { CodeBlock } from "../../formModal/chatMessage/codeBlock";
@ -68,13 +68,12 @@ export default function ChatMessage({
</div>
)}
{chat.thought && chat.thought !== "" && !hidden && (
<div
onClick={() => setHidden((prev) => !prev)}
<SanitizedHTMLWrapper
className=" chat-message-modal-thought"
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
}}
></div>
content={convert.toHtml(chat.thought)}
suppressWarning={false}
onClick={() => setHidden((prev) => !prev)}
/>
)}
{chat.thought && chat.thought !== "" && !hidden && <br></br>}
<div className="chat-message-modal-markdown">

View file

@ -1,5 +1,4 @@
import Convert from "ansi-to-html";
import DOMPurify from "dompurify";
import { ChevronDown } from "lucide-react";
import { useState } from "react";
import ReactMarkdown from "react-markdown";
@ -8,6 +7,7 @@ import remarkGfm from "remark-gfm";
import remarkMath from "remark-math";
import MaleTechnology from "../../../assets/male-technologist.png";
import Robot from "../../../assets/robot.png";
import SanitizedHTMLWrapper from "../../../components/SanitizedDiv";
import { THOUGHTS_ICON } from "../../../constants";
import { ChatMessageType } from "../../../types/chat";
import { classNames } from "../../../utils";
@ -57,13 +57,11 @@ export default function ChatMessage({
</div>
)}
{chat.thought && chat.thought !== "" && !hidden && (
<div
<SanitizedHTMLWrapper
className=" form-modal-chat-thought"
content={convert.toHtml(chat.thought)}
onClick={() => setHidden((prev) => !prev)}
className=" form-modal-chat-thought "
dangerouslySetInnerHTML={{
__html: DOMPurify.sanitize(convert.toHtml(chat.thought)),
}}
></div>
/>
)}
{chat.thought && chat.thought !== "" && !hidden && <br></br>}
<div className="w-full">

View file

@ -1,6 +1,6 @@
import DOMPurify from "dompurify";
import { FileText, Variable } from "lucide-react";
import { useContext, useEffect, useRef, useState } from "react";
import SanitizedHTMLWrapper from "../../components/SanitizedDiv";
import ShadTooltip from "../../components/ShadTooltipComponent";
import { Badge } from "../../components/ui/badge";
import { Button } from "../../components/ui/button";
@ -15,7 +15,7 @@ import {
} from "../../components/ui/dialog";
import { Textarea } from "../../components/ui/textarea";
import {
HIGHLIGH_CSS,
HIGHLIGHT_CSS,
PROMPT_DIALOG_SUBTITLE,
TEXT_DIALOG_SUBTITLE,
} from "../../constants";
@ -120,13 +120,13 @@ export default function GenericModal({
const TextAreaContentView = () => {
return (
<div
className={HIGHLIGH_CSS}
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(coloredContent) }}
suppressContentEditableWarning={true}
<SanitizedHTMLWrapper
className={HIGHLIGHT_CSS}
content={coloredContent}
onClick={() => {
setIsEdit(true);
}}
suppressWarning={true}
/>
);
};