# What changed in markdown-to-jsx

> 78 changes in markdown-to-jsx 9 from its official release notes, upgrade guides and advisories: 8 breaking, 1 security, 9 new APIs and options. Each one cited. Sources checked 2026-10-21. HTML: https://unstale.sh/npm/markdown-to-jsx/

To see which of these apply to a repository, run `npx @unstale/cli init` in it.

## markdown-to-jsx 9

### Breaking changes

- Dangerous tags are escaped by default across React, HTML, Solid, Vue, and React Native outputs; their bodies and closing tags remain visible as inert text. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Heading ids are generated from plain text rather than raw Markdown, so links, formatting markers, and image alt text no longer affect anchors. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Destinations that conceal dangerous schemes with HTML entities are rejected; compilers omit unsafe href or src values, and direct AST rendering re-checks link targets. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Dangerous url(javascript:…) and similar payloads are stripped from HTML and Markdown string outputs. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Dangerous event-handler and URL attributes, srcdoc, and obfuscated unsafe schemes are stripped before output; safe attributes and data:image URLs remain supported. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- A reference definition split across blockquote lines is no longer matched by a link using the raw, unnormalized label. (9.8.2) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.2)
- Each React Native styles key is narrowed to the style type accepted by its component, catching mismatched styles at compile time. (9.8.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.0)
- HTML block content on its own line without surrounding blank lines is preserved as literal text; content surrounded by blank lines continues to parse markdown. (9.7.14) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.14)

### Security

- Markdown with long runs of brackets or footnote markers now parses in linear time, avoiding severe slowdowns when rendering untrusted input on a server. (9.10.2) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.2)

### New APIs and options

- React Native elements can be replaced with custom components via overrides. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Adds a style key for the checkmark glyph of a GFM task item. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Adds styles.footnote to style React Native footnote references, which now render as superscript. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Adds a style key for the checked-box accent of a GFM task item. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Adds a style key for table cell grid lines. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Adds a style key for the bold table header run. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Adds a style key for table row grid lines. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- styles.text sets a base font and color for all text at once. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Adds an option to skip frontmatter detection entirely. (9.7.14) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.14)

### Performance

- With the option enabled, incomplete-syntax suppression scans only the block that can hold the live edge, reducing repeated work on deeply nested content. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Compiling a large document runs roughly 5–7% quicker, especially for list- and heading-heavy content. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Documents with many bold or italic spans now parse much faster, avoiding sharp slowdowns on very large or adversarial inputs. (9.8.2) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.2)
- The component no longer re-parses unchanged content when a parent re-renders with unchanged props. (9.8.2) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.2)
- Parsing is around 40% faster on large documents, with the biggest gains on link-heavy and code-heavy content. (9.8.2) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.2)
- Markdown with many malformed link starts parses quickly instead of slowing to a crawl on large inputs. (9.8.1) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.1)
- HTML compiler performance improved by about 57%, bringing it to parity with the React compiler. (9.7.3) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.3)
- JSX output bypasses React.createElement by constructing React element objects directly for about 2x faster output; a custom createElement option still falls back to createElement. (9.7.1) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/v9.7.1)

### Behavior and default changes

- The option now works in the React Native renderer, suppressing partial structures during streaming. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- React Native output now has readable defaults for headings, code, block spacing, blockquotes, tables, and GFM task items; styles remain customizable. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- The component accepts `string[]` children to support the common JSX case where children arrive as a coalesced array. (9.8.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.0)
- Task list items now use row and center-aligned defaults so checkboxes and labels sit on the same line; set `styles.listItem` to opt out. (9.8.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.0)

### Fixes and other changes

- HTML tag overrides are applied regardless of the casing of the source tag. (9.10.3) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.3)
- Shortcut reference links labeled `__proto__` or `constructor` no longer throw and resolve like any other reference label. (9.10.3) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.3)
- Link destinations preserve punctuation such as underscores while markdown is streamed, preventing generated links from being changed or broken. (9.10.3) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.3)
- Browser bundles no longer crash when reading environment checks because the library no longer imports Node's process module. (9.10.1) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.1)
- PascalCase custom JSX components and hyphenated custom elements retain Markdown children across a blank line, which no longer leaks following content as a sibling. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Headings with identical text receive unique HTML ids; custom slugify still sets the base string, with uniqueness applied afterward. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Rejected image destinations use null in the parsed AST, allowing TypeScript consumers to treat ImageNode.target as string | null. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- TypeScript consumers can treat LinkNode.target as string | null, matching rejected link destinations on the parsed AST. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Processing instructions, CDATA sections, declarations, and orphan closing tags are re-emitted exactly as written instead of being reconstructed as generic self-closing elements. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Incomplete HTML is deferred consistently across compilers, including Solid and Vue, while ordinary less-than text continues rendering. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Backslashes before pipes in table cells are escaped when compiling to Markdown, preventing the pipe from splitting the row when reparsed. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- Single-line script, style, pre, and textarea blocks preserve their text content when tagfilter is off, including under forceInline. (9.10.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.10.0)
- The last paragraph inside a blockquote no longer leaves extra space below it. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Compiled Markdown better round-trips to the same document, preserving literal characters, table and list structure, code delimiters, titles, raw HTML attributes, and empty inline elements. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Tables remain hidden until enough syntax has streamed to render them, then stay visible as rows arrive, across every renderer. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Footnote references render as superscript instead of bold, and notes in the list appear on one line next to their numbers. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Fixes React key warnings when raw HTML mixes with other content or a custom component follows a heading. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Prevents crashes when text, block elements, or images are mixed; image links remain tappable. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Vue renderRule types now allow a custom rule and its next callback to return arrays of nodes. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- URLs containing emoji and other non-BMP Unicode characters render without crashing. (9.9.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.9.0)
- Text on its own line after a nested HTML element now renders when no blank line separates them, consistently across React, React Native, Solid, and Vue outputs. (9.8.2) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.2)
- Fast-skip no longer truncates bare email local-parts containing inline-special characters. (9.8.1) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.1)
- React Native overrides now fire for parsed markdown elements, including inline emphasis, fenced code, headings, lists, and GFM task checkboxes. (9.8.0) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.8.0)
- Lists, blockquotes, fenced code, and headings inside table cells now render as nested content without breaking surrounding rows or dropping closing tags. (9.7.16) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.16)
- Fixes the Vue adapter warning about a non-function default slot when component overrides are used. (9.7.14) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.14)
- The HTML compiler now preserves closing tags for empty non-void elements. (9.7.14) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.14)
- Frontmatter detection no longer consumes content when a thematic break starts the document; detection now validates YAML key-value syntax. (9.7.14) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.14)
- Markdown lists inside HTML table cells now render as proper nested lists instead of breaking the table structure. (9.7.14) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.14)
- Adds key props to thead and tbody in table rendering to resolve a React key warning. (9.7.14) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.14)
- Void HTML elements no longer drop subsequent content when they are not followed by a newline. (9.7.14) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.14)
- Fixes streaming mode incorrectly stripping self-closing custom component tags and leaking incomplete trailing tags as escaped text in inline content. (9.7.13) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.13)
- Fixes missing TypeScript declaration files in the published package so consumers can use its types. (9.7.12) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.12)
- Tables with only a header row and no data rows no longer render an empty tbody. (9.7.11) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.11)
- Fixes the development warning “Attempted to render without development properties” in React 19 RSC. (9.7.11) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.15), [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.11)
- Trailing asterisks are trimmed from bare URLs wrapped in bold Markdown so generated link hrefs are correct. (9.7.10) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.10)
- Emphasis delimiters closing before hard line breaks are now resolved correctly. (9.7.10) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.10)
- Raw React elements now unconditionally include `_store` so React dev-mode validation works across bundler environments. (9.7.10) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.10)
- Fixed broken exports in bundled output caused by a Bun bundler bug with cross-entry re-exports. (9.7.8) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.8)
- Nested HTML blocks with the same tag name now correctly match depth-paired closing tags. (9.7.7) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.7)
- Ambiguous Setext headings are suppressed during streaming to avoid premature heading rendering. (9.7.7) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.7)
- Raw React elements now include the `_owner` field expected by React’s reconciler, preventing dev-mode errors in React 19. (9.7.6) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.6)
- Void elements preceded by a blank line are returned as content-less blocks, and compilers prevent children from being passed to them, avoiding React error #137. (9.7.6) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.6)
- Raw elements created by the fast path now include `_store: {}` in non-production builds, fixing a React dev-mode error when setting `validated`. (9.7.5) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.5)
- Fixes incorrect matching of bare email autolinks when DNS labels exceed 63 characters. (9.7.4) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.4)
- HTML entities in link titles now decode correctly; for example, `&ndash;` becomes `–`. (9.7.4) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.4)
- Content in `<pre>`, `<script>`, `<style>`, and `<textarea>` is rendered verbatim instead of being parsed as markdown. (9.7.4) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.4)
- GFM alert blockquote syntax is now accepted case-insensitively, matching GitHub's behavior. (9.7.2) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/markdown-to-jsx%409.7.2)
- Exposes entities as a public subpath export so bundlers resolve the browser condition and use the optimized DOM-based decoder instead of the full entity table. (9.7.1) — [release notes](https://github.com/quantizor/markdown-to-jsx/releases/tag/v9.7.1)
