Skip to main content
Urbicon UI
source

StreamingMarkdownexperimental

Streaming-safe markdown renderer for LLM output. Parses a growing string incrementally, caches settled blocks, and enforces a strict URL policy by default — rendering to a real component tree, never to an HTML string.

Streaming answer

The renderer parses markdown as it arrives — settled blocks are cached and never re-render, so a long answer stays cheap to append to.

  • Zero {@html}, safe by construction

  • Strict URL policy on by default

ts
for await (const chunk of stream) render(chunk);
Size
Loading...
Loading syntax highlighting...

01 Examples

Static markdown — tables and task lists

A settled answer renders GFM tables and task lists the same whether the text arrived all at once or streamed chunk by chunk. Set headingLevelStart so message headings stay out of the page outline.

Release checklist

StepOwnerStatus
FreezePlatformDone
Sign-offQAPending

Remaining work:

  • Bump the version

  • Regenerate the docs

  • Publish the tag

Loading...
Loading syntax highlighting...

Citations from sources

Ids in the sources prop activate the matching [n] markers in the text; each becomes a CitationChip whose popover shows the title, snippet, and a policy-checked link. Markers without a matching id stay plain text.

Transformers replaced recurrence with self-attention

, and later work mapped how quality scales with model and dataset size
. A bare marker like [3] with no matching source stays plain text.

Loading...
Loading syntax highlighting...

Hostile input, neutralized

Untrusted model output is safe by construction: the renderer never emits an HTML string. The strict-by-default URL policy turns scheme-smuggled links into inert text, blocks external images to an alt-text chip, and leaves raw HTML as literal text — no configuration required.

A normal link renders as a real link.

A scheme-smuggled link becomes inert text with a dotted underline — the URL never reaches the DOM.

External images are blocked and shown as an alt-text chip: remote tracker

Raw HTML stays literal text, never parsed: <img src=x onerror="alert(1)">

Loading...
Loading syntax highlighting...

Custom node renderer

A renderers snippet fully replaces the built-in renderer for one node type — the dependency-free hook point for syntax highlighting, lightboxes, or router-aware links. Here a custom code-block presentation.

Fenced code flows through your own renderer:

ts custom renderer
export const answer = 42;
Loading...
Loading syntax highlighting...

02 Customization

Every element maps to a named slot (paragraph, heading1heading6, inlineCode, codeBlock, table, …). Restyle any of them via slotClasses, or register a reusable look as a preset on BlocksProvider. Reach for renderers only when you need to replace a whole node type (highlighting, custom links); use slotClasses for pure styling.

The urlPolicy is strict by default. Widen it deliberately and narrowly — allow a specific image CDN via allowedImagePrefixes, never a broad prefix. Keep the policy object referentially stable; a new reference re-parses the whole content.

03 Accessibility

Heading hierarchy

Markdown # maps to the DOM level set by headingLevelStart (deeper levels shift along, clamped at h6). In a chat surface set it to 3 so a message's own headings slot beneath the page <h1> instead of competing with it. Visual sizing keeps following the author's level independently.

Streaming cursor

The pulsing cursor shown while streaming is true is decorative and carries aria-hidden="true", so screen readers announce only the text. Its pulse is gated on motion-safe:, so it holds still under prefers-reduced-motion.

Scrollable tables

Wide tables scroll inside a focusable region (tabindex="0") labelled by tableRegionLabel, so keyboard users can reach and scroll the overflow (WCAG 2.1.1). Horizontal scroll stays inside the block — never the page.

Blocked links and images

A policy-blocked link renders as inert text with a dotted underline as the "this was a link" cue; a blocked image becomes an alt-text chip. The blocked state is visible, not silent — the reader can tell something was withheld.

04 API Reference

16 props
16 props 1 required

No matching properties

No matching properties

05 Installation

Import

Loading...
Loading syntax highlighting...