diff --git a/src/components/ui/notification-details-card.tsx b/src/components/ui/notification-details-card.tsx index 54332f7..fb05bbf 100644 --- a/src/components/ui/notification-details-card.tsx +++ b/src/components/ui/notification-details-card.tsx @@ -1,6 +1,7 @@ "use client"; import { TNotificationDetailsResponse } from "@/lib/api/types/NotificationHistory"; import { capitalize, unixToDate } from "@/utils/shared"; +import { sanitizeHtmlWithStyles } from "@/lib/utils"; import { FC } from "react"; import IsVisible from "./IsVisible"; import Status from "./Status"; @@ -43,7 +44,12 @@ export const NotificationDetailsCard: FC = ({ data }) => {
-

{data.message}

+
diff --git a/src/lib/utils.ts b/src/lib/utils.ts index bd0c391..1a0bb60 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -1,6 +1,81 @@ -import { clsx, type ClassValue } from "clsx" -import { twMerge } from "tailwind-merge" +import { clsx, type ClassValue } from "clsx"; +import { twMerge } from "tailwind-merge"; export function cn(...inputs: ClassValue[]) { - return twMerge(clsx(inputs)) + return twMerge(clsx(inputs)); +} + +export function sanitizeHtmlWithStyles(htmlString: string): string { + if (!htmlString) return ""; + + if (typeof window !== "undefined") { + const tempDiv = document.createElement("div"); + tempDiv.innerHTML = htmlString; + + const dangerousTags = [ + "script", + "iframe", + "object", + "embed", + "form", + "input", + "button", + ]; + const dangerousAttributes = [ + "onclick", + "onload", + "onerror", + "onmouseover", + "onfocus", + "onblur", + ]; + + dangerousTags.forEach((tag) => { + const elements = tempDiv.getElementsByTagName(tag); + for (let i = elements.length - 1; i >= 0; i--) { + elements[i].remove(); + } + }); + + const allElements = tempDiv.getElementsByTagName("*"); + for (let i = 0; i < allElements.length; i++) { + const element = allElements[i]; + dangerousAttributes.forEach((attr) => { + if (element.hasAttribute(attr)) { + element.removeAttribute(attr); + } + }); + + Array.from(element.attributes).forEach((attr) => { + if (attr.name.toLowerCase().startsWith("on")) { + element.removeAttribute(attr.name); + } + }); + } + + return tempDiv.innerHTML; + } + + return htmlString + .replace(/]*>[\s\S]*?<\/script>/gi, "") + .replace(/]*>[\s\S]*?<\/iframe>/gi, "") + .replace(/]*>[\s\S]*?<\/object>/gi, "") + .replace(/]*>/gi, "") + .replace(/on\w+="[^"]*"/gi, "") + .replace(/on\w+='[^']*'/gi, ""); +} + +export function stripHtmlTags(htmlString: string): string { + if (!htmlString) return ""; + + if (typeof window !== "undefined") { + const tempDiv = document.createElement("div"); + tempDiv.innerHTML = htmlString; + return tempDiv.textContent || tempDiv.innerText || ""; + } + + return htmlString + .replace(/<[^>]*>/g, "") + .replace(/ /g, " ") + .trim(); }