| Name | Modified | Size | Downloads / Week |
|---|---|---|---|
| Parent folder | |||
| README.md | 2026-09-30 | 9.0 kB | |
| streamdown@2.7.0 source code.tar.gz | 2026-09-30 | 1.2 MB | |
| streamdown@2.7.0 source code.zip | 2026-09-30 | 1.4 MB | |
| Totals: 3 Items | 2.5 MB | 0 | |
This release is mostly about streaming speed, plus a few new props and a lot of fixes.
:zap: Performance • Code blocks now highlight only the new lines as they stream, instead of the whole block on every update • Blocks that are already parsed get reused while a document streams, and only block tokens are lexed • Code and table auto-scroll runs once per frame instead of on every chunk • Showing and hiding the caret no longer restyles the whole document, which used to cost tens of ms per toggle on long streams • The code highlight cache now has a size limit (LRU), so memory stays bounded in long sessions • Mermaid diagrams render one at a time while their fence streams, so a growing diagram no longer holds up the stream
:sparkles: New
• fallbackComponent: a fallback renderer for tags in allowedTags or HTML tags that have no entry in components
• disableAutolinkProtocols: turn off GFM autolinking for specific protocols (e.g. ["mailto"])
• portal: set the container used by Mermaid and table fullscreen and the link safety modal
• defaultComponents is now exported, so you can build overrides on top of the built-in renderers
• onCopy / onError now work on the default code and Mermaid copy buttons
• Incomplete images show a loading skeleton while they stream instead of disappearing
:bug: Fixes
• Mermaid diagrams auto-fit their container and text is readable again
• A < inside math (e.g. $$ \sum_{j<k} $$) no longer cuts off the rest of the message
• Code block buttons can be clicked inside nested scroll containers
• Tables copied or downloaded as Markdown keep literal HTML tags and entities
• Loose list items no longer get extra spacing from a wrapping <p>
• CJK: bare URLs after fullwidth punctuation are linkified again
:jigsaw: remend 1.4.0
• New single-pass scanner that follows CommonMark for code fences and spans: handles ~~~, fences in quotes and lists, CRLF, and multi-backtick spans
• Fixes slow (quadratic) healing on input full of delimiters
• Identifiers like snake__case no longer create false emphasis
• Healing is now idempotent
:warning: Heads up
• @streamdown/code@2.0.0 moves to Shiki v4 and now needs Node 20 or newer
• marked is now on v18
Below, you can find the detailed changes.
Minor Changes
- 6b14de4: Add a
disableAutolinkProtocolsprop to<Streamdown>for disabling GFM autolinking of specific URL protocols (e.g.mailto).
tsx
<Streamdown disableAutolinkProtocols={["mailto"]}>
{"Contact us at hello@example.com"}
</Streamdown>
Bare emails and bare URLs whose protocol matches the list (case-insensitive, "mailto" and "mailto:" are equivalent) are unwrapped back to plain text. Explicit markdown links ([text](url)) are left as links, including when the label reconstructs the URL (e.g. [foo@x.com](mailto:foo@x.com)). When the prop is omitted, autolinking behavior is completely unchanged.
Closes [#607].
- b1965bb: feat: add
fallbackComponentprop for missing map entries /allowedTags
Adds a new fallbackComponent prop to <Streamdown>. When provided, it is
used as a fallback renderer for any HTML tag or allowed custom tag that does
not have an explicit entry in the components map:
```tsx <streamdown allowedtags="{{" mention: ["user_id"] }} fallbackcomponent="{({" node, children, ...props })> createElement(node!.tagName, props, children) }
{markdown}```
fallbackComponent applies to custom tags declared via allowedTags (with no
explicit component entry) and to standard HTML tags absent from the built-in
component set (e.g. <span>, <em>, <div>, <br>). Built-in and explicit
components entries always win — this is not a full unstyled mode.
Refs [#543]
Patch Changes
- b651249: Give animated word spans a style object instead of a CSS string, so rendering skips parsing a style declaration for every word on every update.
createAnimatePluginstill writes CSS strings. - b651249: Check whether a stream only appended text by comparing a slice of the new input with the previous one instead of calling
startsWith, which compared the whole document character by character on every update. - b651249: Hide the caret after a table or an unfinished code fence by marking the last element instead of changing the container's class and style. Each toggle used to restyle the whole document, which cost tens of milliseconds per flip on long streams.
- c971f42: Wire
onCopyandonErrorthrough default code and Mermaid copy controls viacontrols.code.copyandcontrols.mermaid.copy. - 4ec5639: Bound the code highlight cache. Results of streaming code blocks are no longer cached (each is superseded by the next update), and finished code blocks are kept in a least-recently-used cache bounded by their size (tokens, lines and characters) and by a limit of 5,000 results. Lookups compare the full code, so blocks that differ only in the middle no longer share tokens. A code block also ignores highlight results for code it has already moved past.
- 16e7e65: Export
defaultComponentsso customcomponentsoverrides can compose Streamdown's built-in renderers (styles,data-streamdown, link safety, code/mermaid/table behavior) instead of reimplementing them. - 163c63b: fix(code-block): use absolute positioning for action buttons to fix click events in nested scroll containers
Switches the code block action button wrapper from position: sticky to
position: absolute (with position: relative on the container) so that
hit-testing works correctly in layouts with multiple nested overflow: auto
scroll containers. Previously, the sticky + pointer-events-none/auto
pattern caused browsers to mis-route click events to the code block wrapper
rather than the buttons when the component was embedded in 2+ nested scroll
containers.
- e0ce123: Incomplete images during streaming now render a loading placeholder instead of being removed entirely. Incomplete images (e.g.
 are replaced withby remend, and the streamdownImageComponentrenders an animated skeleton for this special URL. This mirrors the existing behavior for incomplete links (streamdown:incomplete-link). Thestreamdownprotocol is allowlisted forimg[src]in the default sanitize schema so the sentinel survives rehype-sanitize + rehype-harden. - e7a23ef: Render Mermaid diagrams one at a time while their code fence streams, pausing after each render for as long as it took, so a growing diagram no longer holds up the stream. Once the fence closes or the stream stops, the final diagram renders without a pause.
- b651249: Pin streaming code blocks and tables to the bottom once per frame instead of on every update, avoiding a forced layout per streamed chunk.
- 5504e50: Preserve literal HTML tags and character entities when copying or downloading tables as Markdown.
- 5b26c28: Speed up block parsing by lexing only block tokens and reusing already parsed blocks while a document streams.
- 18dcb20: Add a top-level
portalprop for configuring the container used by Mermaid fullscreen, table fullscreen, and the built-in link safety modal. - fdf4e33: Fix Mermaid diagrams so text is readable and diagrams auto-fit container.
- Normalize SVG to remove responsive shrinking
- Extract intrinsic size from viewBox
- Add width-and-height auto-fit in PanZoom
- Preserve user zoom/pan after initial fit
- Add tests for SVG utilities and auto-fit behavior
- 53812cf: fix: unwrap a single paragraph child inside list items
Loose list items from the markdown pipeline are often wrapped in a <p>. MemoLi now detects that sole paragraph child (including the memoized paragraph component) and renders its contents directly, so list items stay visually tight. Also updates the list animation retrigger test to match the unwrapped markup.
Fixes [#475]
- a155a9e: Update
markedfrom^17.0.1to^18.0.11.
marked v18 no longer folds a block token's trailing blank line(s) into its own raw; that whitespace now surfaces as a separate space token immediately following the block (e.g. after html, heading, and table tokens). This changed the token stream shape that parseMarkdownIntoBlocks consumes, causing a dangling space token after a closed custom-tag HTML block to be emitted as its own standalone block. parseMarkdownIntoBlocks now folds a space token into the preceding block instead of pushing it as a new one, restoring v17-identical block boundaries and counts. The lossless token.raw concatenation invariant is preserved.
- Updated dependencies [cf0ac1c]
- Updated dependencies [e0ce123]
- Updated dependencies [fdd1351]
- remend@1.4.0