UNPKG

@humanspeak/svelte-markdown

Version:

Markdown and HTML renderer for Svelte 5 — built for rendering streaming AI agent output from Claude Code, ChatGPT, and agentic workflows. XSS-safe defaults, streaming-aware sanitization, token caching, TypeScript types, and Svelte 5 runes.

63 lines (62 loc) 2.09 kB
const ALERT_TYPES = new Set(['note', 'tip', 'important', 'warning', 'caution']); /** * Creates a marked extension that tokenizes GitHub-style alert blockquotes * into custom `alert` tokens. * * The extension produces block-level tokens with * `{ type: 'alert', raw, text, alertType }` where `alertType` is one of * `note`, `tip`, `important`, `warning`, or `caution`, and `text` is the * alert body with leading `> ` stripped. * * Pair it with `AlertRenderer` (or your own component) to render the alerts. * * @example * ```svelte * <script lang="ts"> * import SvelteMarkdown from '@humanspeak/svelte-markdown' * import { markedAlert, AlertRenderer } from '@humanspeak/svelte-markdown/extensions' * * const renderers = { alert: AlertRenderer } * </script> * * <SvelteMarkdown * source={markdown} * extensions={[markedAlert()]} * {renderers} * /> * ``` * * @returns A `MarkedExtension` with a single block-level `alert` tokenizer */ export function markedAlert() { return { extensions: [ { name: 'alert', level: 'block', start(src) { return src.match(/>\s*\[!/)?.index; }, tokenizer(src) { const match = src.match(/^(?:>\s*\[!(\w+)\]\n)((?:[^\n]*(?:\n(?:>\s?)[^\n]*)*)?)(?:\n|$)/); if (match) { const alertType = match[1].toLowerCase(); if (!ALERT_TYPES.has(alertType)) return; const text = match[2] .split('\n') .map((line) => line.replace(/^>\s?/, '')) .join('\n') .trim(); return { type: 'alert', raw: match[0], text, alertType: alertType }; } } } ] }; }