Components/Stream Markdown

Stream Markdown

A Markdown renderer built for streaming output.

VerifiedSince 0.3.9

Usage

Basic

While streaming, an unclosed tail fence defers rendering instead of flashing in half-written.

Loading demo...

Best Practices

  • Keep sanitize on: model output is untrusted, and this is where it becomes DOM.
  • Set streaming to false when generation ends, or the caret stays at the tail.
  • In custom renderers, show a loading state while closed is false instead of parsing a partial block.
  • Key renderers by the lowercase first word of the fence (```chart → chart).
  • On non-English surfaces, pass the code and diagram wording along with the image and table copy: the built-in blocks show it, and it defaults to English.
  • Use TxMarkdownView for static Markdown; it needs none of the block and caret machinery.

API Reference

Props

NameTypeDefaultDescription
contentstring—The Markdown source. Required.
streamingbooleanfalseOutput is still arriving; drives the caret, the reveal, and deferred tail-fence rendering.
reveal'aurora' | 'hue' | 'blur' | 'languid' | 'none''aurora'How new text enters, with TxStreamText's presets; languid keeps its slow blur but not its rise.
caretbooleantrueShows the Tuff caret at the write head while streaming; switched off, it goes at once.
sanitizebooleantrueSanitizes HTML through DOMPurify.
theme'light' | 'dark' | 'auto''auto'Color theme; auto follows the environment.
renderersRecord<string, StreamMarkdownBlockRenderer>—Block renderers by fence language; each receives StreamMarkdownBlockContext as props.
blockRemoteImagesbooleantrueShows remote images (http(s)://, //) as a placeholder until the reader loads them.
blockedImageTextstring'Remote image blocked'Title of the blocked-image placeholder.
loadImageOnceTextstring'Load this image'Text of the button that loads only this image.
allowSessionImagesTextstring'Allow for this conversation'Text of the button that allows every remote image for the conversation.
copyTableTextstring'Copy CSV'Text of a table's copy-as-CSV button.
copiedTableTextstring'Copied'Button text shown briefly after a successful copy.
codePreviewTextstring'Preview'Text of a code block's button that shows HTML, SVG, or XML rendered.
codeSourceTextstring'Code'Text of the same button while the preview shows, which returns to the source.
codeFrameLabelFormatter(lang: string) => string(lang) => `${lang} preview`Builds the preview frame's accessible name from the fence language.
copyCodeTextstring'Copy'Text of a code block's copy button.
copiedCodeTextstring'Copied'Copy button text shown briefly after a successful copy.
diagramZoomLabelstring'Zoom diagram'Accessible name of a rendered diagram, which opens the preview.
diagramPreviewLabelstring'Diagram preview'Accessible name of the fullscreen diagram preview.
diagramCloseLabelstring'Close preview'Accessible name of the preview's close button.
diagramErrorTextstring'Diagram failed to render — showing source.'Shown above the source when a diagram fails to render.

TxCodeBlock Props

The built-in renderer for every language without one of its own, also exported for showing code outside a document. It receives StreamMarkdownBlockContext as props; inside TxStreamMarkdown, its copy comes from the code* props and copyCodeText / copiedCodeText.

NameTypeDefaultDescription
previewablebooleantrueOffers a rendered view of a settled HTML, SVG, or XML fence.
previewLabelstring'Preview'Text of the button that shows the rendered view.
codeLabelstring'Code'Text of the same button while the preview shows.
frameLabelFormatter(lang: string) => string(lang) => `${lang} preview`Builds the preview frame's accessible name from the fence language.
copyLabelstring'Copy'Text of the copy button.
copiedLabelstring'Copied'Copy button text shown briefly after a successful copy.

TxMermaidBlock Props

The built-in mermaid renderer, which also receives StreamMarkdownBlockContext as props; inside TxStreamMarkdown, its copy comes from the diagram* props and copyCodeText / copiedCodeText.

NameTypeDefaultDescription
zoomLabelstring'Zoom diagram'Accessible name of the rendered diagram, which opens the preview.
previewLabelstring'Diagram preview'Accessible name of the fullscreen preview.
closeLabelstring'Close preview'Accessible name of the preview's close button.
errorTextstring'Diagram failed to render — showing source.'Shown above the source when the diagram fails to render.
copyLabelstring'Copy'Text of the copy button on the source shown after a failed render.
copiedLabelstring'Copied'Copy button text shown briefly after a successful copy.

Overview

  • The document renders block by block, so appended text never reflows the whole page.
  • While streaming, the still-growing tail fence defers its final rendering until it closes; renderers get closed: false only for that fence.
  • Unregistered languages use the built-ins: TxMermaidBlock for mermaid, TxCodeBlock for the rest.
  • The caret is TxStreamText's: right after the last character of a paragraph, heading, or quote, otherwise on its own line below. Under reduced motion nothing enters and the caret rests.
  • DOMPurify loads dynamically; with sanitize on, nothing renders until it loads, or at all if loading fails. Sanitizing is no substitute for a server-side trust boundary.
  • Image consent is module-level and shared by every instance; call the exported resetRemoteImagePolicy() when the conversation changes.
  • Each instance owns its own Marked (gfm, breaks); the GitHub Markdown sheet is scoped under :where(.tx-md), leaving the host's .markdown-body alone.