// HTML gate for every v-html sink (post body, category content, author bio). // The three patterns are the verbatim regex sources of the Journal plugin's // FormatHTML / CheckHTML gate (classes/format_html.go), with the i flag for // Go's (?i). Imported content bypasses the Go gate, so the layer checks again. export const UNSAFE_TAG = /<(?:script|iframe|object|embed)\b/i export const EVENT_HANDLER = /\son[a-z]+\s*=/i export const DANGEROUS_URL = /(?:javascript|vbscript|data):/i /** True when `html` matches none of the three Journal patterns. */ export function isSafeJournalHtml(html: string | null | undefined): boolean { if (!html) return true return !(UNSAFE_TAG.test(html) || EVENT_HANDLER.test(html) || DANGEROUS_URL.test(html)) } /** * Gate result for a v-html sink: `html` is the input when safe and "" when * not, so the unsafe value never reaches the DOM. Null input is safe and "". */ export function gateJournalHtml(html: string | null | undefined): { safe: boolean; html: string } { if (!html) return { safe: true, html: '' } return isSafeJournalHtml(html) ? { safe: true, html } : { safe: false, html: '' } }