fix(app): sanitize markdown -> html
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
import { useMarked } from "../context/marked"
|
||||
import DOMPurify from "dompurify"
|
||||
import { checksum } from "@opencode-ai/util/encode"
|
||||
import { ComponentProps, createResource, splitProps } from "solid-js"
|
||||
import { isServer } from "solid-js/web"
|
||||
|
||||
type Entry = {
|
||||
hash: string
|
||||
@@ -10,6 +12,31 @@ type Entry = {
|
||||
const max = 200
|
||||
const cache = new Map<string, Entry>()
|
||||
|
||||
if (typeof window !== "undefined" && DOMPurify.isSupported) {
|
||||
DOMPurify.addHook("afterSanitizeAttributes", (node: Element) => {
|
||||
if (!(node instanceof HTMLAnchorElement)) return
|
||||
if (node.target !== "_blank") return
|
||||
|
||||
const rel = node.getAttribute("rel") ?? ""
|
||||
const set = new Set(rel.split(/\s+/).filter(Boolean))
|
||||
set.add("noopener")
|
||||
set.add("noreferrer")
|
||||
node.setAttribute("rel", Array.from(set).join(" "))
|
||||
})
|
||||
}
|
||||
|
||||
const config = {
|
||||
USE_PROFILES: { html: true, mathMl: true },
|
||||
SANITIZE_NAMED_PROPS: true,
|
||||
FORBID_TAGS: ["style"],
|
||||
FORBID_CONTENTS: ["style", "script"],
|
||||
}
|
||||
|
||||
function sanitize(html: string) {
|
||||
if (!DOMPurify.isSupported) return ""
|
||||
return DOMPurify.sanitize(html, config)
|
||||
}
|
||||
|
||||
function touch(key: string, value: Entry) {
|
||||
cache.delete(key)
|
||||
cache.set(key, value)
|
||||
@@ -34,6 +61,8 @@ export function Markdown(
|
||||
const [html] = createResource(
|
||||
() => local.text,
|
||||
async (markdown) => {
|
||||
if (isServer) return ""
|
||||
|
||||
const hash = checksum(markdown)
|
||||
const key = local.cacheKey ?? hash
|
||||
|
||||
@@ -46,8 +75,9 @@ export function Markdown(
|
||||
}
|
||||
|
||||
const next = await marked.parse(markdown)
|
||||
if (key && hash) touch(key, { hash, html: next })
|
||||
return next
|
||||
const safe = sanitize(next)
|
||||
if (key && hash) touch(key, { hash, html: safe })
|
||||
return safe
|
||||
},
|
||||
{ initialValue: "" },
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user