Files
portfolio/lib/richtext.ts
2026-01-12 14:36:10 +00:00

72 lines
1.7 KiB
TypeScript

import sanitizeHtml from "sanitize-html";
import type { JSONContent } from "@tiptap/react";
import { generateHTML } from "@tiptap/html";
import StarterKit from "@tiptap/starter-kit";
import Underline from "@tiptap/extension-underline";
import Link from "@tiptap/extension-link";
import { TextStyle } from "@tiptap/extension-text-style";
import Color from "@tiptap/extension-color";
import Highlight from "@tiptap/extension-highlight";
import { FontFamily } from "@/lib/tiptap/fontFamily";
export function richTextToSafeHtml(doc: JSONContent): string {
const raw = generateHTML(doc, [
StarterKit,
Underline,
Link.configure({
openOnClick: false,
autolink: false,
HTMLAttributes: { rel: "noopener noreferrer", target: "_blank" },
}),
TextStyle,
FontFamily,
Color,
Highlight,
]);
return sanitizeHtml(raw, {
allowedTags: [
"p",
"br",
"h1",
"h2",
"h3",
"blockquote",
"strong",
"em",
"u",
"a",
"ul",
"ol",
"li",
"code",
"pre",
"span"
],
allowedAttributes: {
a: ["href", "rel", "target"],
span: ["style"],
code: ["class"],
pre: ["class"],
p: ["class"],
h1: ["class"],
h2: ["class"],
h3: ["class"],
blockquote: ["class"],
ul: ["class"],
ol: ["class"],
li: ["class"]
},
allowedSchemes: ["http", "https", "mailto"],
allowProtocolRelative: false,
allowedStyles: {
span: {
color: [/^#[0-9a-fA-F]{3,8}$/],
"background-color": [/^#[0-9a-fA-F]{3,8}$/],
"font-family": [/^(Inter|ui-sans-serif|ui-serif|ui-monospace)$/],
},
},
});
}