NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
npm · #4173 most downloaded on npm
A very fast and versatile markdown toolchain. AST, React, React Native, SolidJS, Vue, Markdown, and HTML output available with full customization.
Last release 19 days ago
15 Sep 2026
Ships fairly regularly
a new release about every 3 weeks
Nearly every release is documented
notes for 60 of the last 60 stable releases
1 version withdrawn
withdrawn after publishing
11 years old
193 releases · first in 2015
9ce68bf : Link destinations now preserve punctuation such as underscores while markdown is streamed, preventing generated links from being changed or
9ce68bf: Link destinations now preserve punctuation such as underscores while markdown is streamed, preventing generated links from being changed or broken.
Thanks Jacob Wisniewski and Jacob Wisniewski!
1c8f5a3: Apply HTML tag overrides regardless of source casing (#248)
Thanks Yuzhong Zhang and Yuzhong Zhang!
4d6add6: Shortcut reference links whose label is __proto__ or constructor no longer throw. Those labels now resolve like any other reference label.
Fixes #900.
2401d28 , b8ef1d5 : Markdown with long runs of brackets or footnote markers now parses in linear time instead of slowing to a crawl. Inputs such as th
One column per quarter.
2401d28, b8ef1d5: Markdown with long runs of brackets or footnote markers now parses in linear time instead of slowing to a crawl. Inputs such as thousands of repeated [ or [^ could previously take seconds to minutes, which mattered most when rendering untrusted input on a server.
Found by Team Atlanta, collected and verified by OSTIF, reported with a fix by smaury of Shielder.
74be92f : Stop importing Node's process module in library source so production builds can replace environment checks correctly. Browser bundles no lon
process module in library source so production builds can replace environment checks correctly. Browser bundles no longer crash when reading those checks.02bae9f : Heading ids are generated from each heading's plain text content instead of its raw markdown source. Link destinations, formatting markers,
## [text](https://e.com) becomes id="text" rather than id="texthttpsecom"). Anchors on headings that contained links, images, or autolinks may change; plain-text headings are unaffected. Duplicate-id suffixes (foo, foo-1) still apply.null on the parsed AST the same way rejected links already do, so TypeScript consumers can treat ImageNode.target and LinkNode.target as string | null. Compilers still omit src for rejected images and the markdown compiler still re-emits them as ![alt]().introduction, introduction-1, introduction-2), matching the usual Markdown hosting behavior. A custom slugify still controls the base string; uniqueness is applied afterward, so you no longer need a stateful slugify closure that breaks under React Strict Mode.02bae9f: Link and image destinations that hide a dangerous scheme behind HTML entities (for example [x](javascript:alert(1))) are now rejected the same way as a literal javascript: URL. Compilers drop the href for rejected links and omit the src for rejected images. The markdown compiler re-emits a rejected image as ![alt]() rather than . Direct AST rendering also re-checks link targets before they become hrefs.
02bae9f: Single-line <script>, <style>, <pre>, and <textarea> blocks keep their text content when tagfilter is off, including under forceInline. Previously the React output could emit an empty tag and drop the body.
4d08fd8: Custom JSX components written in PascalCase, and hyphenated custom elements, keep their markdown children when a blank line appears between the opening and closing tags. Content after the blank no longer leaks out as a sibling of the component.
e9a253d: Ship an llms.txt cheatsheet with the package and at markdown-to-jsx.quantizor.dev/llms.txt, so coding assistants can pick up the entry points, options, recipes, and AST shapes in a single short read instead of the full README.
The cheatsheet leads with the questions people actually ask: why a single newline is not a line break, how to wire up a syntax highlighter or KaTeX, opening links in a new tab, restricting which tags render, and the traps around indented template literals and case-sensitive override keys.
Two documentation corrections come along with it. The HTML entry point example named an export that does not exist; the helper there is astToHTML. And the class added to a fenced code block is language-<lang>, with the older lang-<lang> alongside it on the JSX renderers, rather than lang-<lang> alone as previously written.
02bae9f: The markdown compiler now re-emits processing instructions (<?xml ?>), CDATA sections, declarations (<!DOCTYPE html>), and orphan closing tags exactly as written. Previously these were reconstructed as a generic self-closing element, which mangled a processing instruction like <?xml version="1.0"?> down to <? /> and dropped CDATA and declaration content entirely.
02bae9f: optimizeForStreaming now defers incomplete HTML the same way in every compiler, including Solid and Vue. Tag-like prefixes that have not finished arriving (Hello <Citation, <!--…) stay hidden until they complete, while ordinary less-than text (5 < 3) keeps rendering.
02bae9f: Dangerous url(javascript:…) (and similar) payloads in raw HTML style attributes are now stripped from the HTML and Markdown string outputs, matching the React-family compilers.
02bae9f: Table cells that contain a backslash before a pipe are escaped correctly when compiling back to Markdown, so the pipe no longer splits the row on re-parse.
02bae9f: Dangerous HTML tags (<script>, <iframe>, <style>, and similar) are escaped by default across the React, HTML, Solid, Vue, and React Native outputs. Matching GFM, only each tag's leading < is neutralized; the body and closing tag stay visible as inert text instead of being dropped. Solid, Vue, and React Native previously rendered these tags live unless tagfilter: true was passed explicitly, and escaped output in every renderer stopped at the opener. Direct calls to astToJSX follow the same default.
373595c : React Native output now ships with a clean, minimal default look so markdown renders with a readable hierarchy out of the box: a heading siz
styles over the defaults per property, styles.text sets a base font and color for all text at once, and any element can be replaced with your own component via overrides.styles keys: checkmark and gfmTaskChecked (the checkmark glyph and the checked-box accent of a GFM task item), tableHeaderText (the bold header run), and tableCellDivider and tableRowDivider (the table grid lines). These join the existing bullet, number, and per-element keys, and each merges over the default so you can restyle just what you want. Blockquotes also render tighter: the last paragraph inside no longer leaves extra space below it.optimizeForStreaming option now works in the React Native renderer. Previously it was ignored on native, so incomplete markdown flashed raw syntax between tokens; it now suppresses partial structures the same way the web renderers do, which makes streaming LLM responses read smoothly.<video></video> no longer splits the surrounding paragraph.styles.footnote option. In the footnotes list, each note now reads on one line next to its number instead of below it.<div> holding paragraphs with text between them, or a custom component following a heading. These elements now receive unique keys.<Text> component", and an image inside a paragraph, heading, link, or emphasis threw "Unexpected view type nested under text node" on Android. Now a container follows its content: it stays a text element when everything inside is inline, and becomes a view (grouping text runs while laying images and blocks out alongside) when it holds a block. Image links remain tappable.optimizeForStreaming is on, the incomplete-syntax suppression now runs only on the block that can hold the document's live edge instead of re-scanning every closed block above it, so re-parsing on each streamed token does less work on outline-heavy documents.optimizeForStreaming, a table renders smoothly instead of flashing raw syntax. A partial table (a header row before its divider row, or the opening | of a new table) stays hidden until enough has streamed in to render, and once the table appears it no longer disappears and reappears as each new row arrives. This holds consistently across every renderer.onclick, onerror, onload, and any other on* attribute) and URL attributes carrying a javascript:, vbscript:, or non-image data: scheme (in href, src, action, formaction, poster, cite, and similar) are removed, srcdoc is dropped, and schemes hidden behind HTML entities such as java	script: are caught too. Safe attributes keep their original formatting, data:image URLs still work, and event handlers passed as expressions to your own components (<MyButton onClick={fn} />), along with bare boolean props on them (<MyButton onClick />), are preserved. Previously the HTML and Markdown string outputs emitted these attributes verbatim, and Solid and Vue injected them without protection.renderRule types now reflect that a single rule can render more than one sibling node. The next() callback and a custom renderRule may return an array of nodes, matching what the renderer already produced at runtime, so TypeScript no longer flags valid pass-through overrides.47408cd : Parsing is significantly faster, around 40% on large documents, with the biggest gains on link-heavy and code-heavy content. Also fixed an e
<Markdown> component no longer re-parses its content when a parent re-renders with unchanged props. Previously the rest-props object was reallocated on every render, which invalidated the internal compile cache and forced a full re-parse each time.</summary> inside <details>) now renders instead of being dropped or misplaced when no blank line separates them. This now behaves consistently across the React, React Native, Solid, and Vue outputs.24661c0 : fix: stop fast-skip from truncating bare email local-parts containing inline-special chars
51a68b1 : React Native: overrides now work the same as on web. Pass an override for code , pre , strong , em , del , blockquote , hr , h1 – h6 , ul ,
overrides now work the same as on web. Pass an override for code, pre, strong, em, del, blockquote, hr, h1–h6, ul, ol, li, or input and it fires for parsed markdown — no more silent no-ops on inline emphasis, fenced code, headings, lists, or GFM task checkboxes. The styles prop is also tightened: each key is narrowed to the style type its component actually accepts (TextStyle, ViewStyle, or ImageStyle), so passing an ImageStyle to paragraph is now a compile-time error. Task list items now render with sensible row + center-aligned defaults so the checkbox and label sit on the same line out of the box; pass your own styles.listItem to opt out (e.g. for multi-line task labels). The Markdown component additionally accepts string[] children to absorb the common JSX case where children arrive as a coalesced array.fb5efc2 : Fix HTML output for markdown inside <table> cells ( #862 ). Lists, blockquotes, fenced code, and headings inside a cell now render as nested
7ff0713 : Fix React 19 RSC dev warning "Attempted to render without development properties"
3df970f: Fix frontmatter detection silently consuming content when a thematic break (---) starts the document. The colon-anywhere heuristic is replace
3df970f: Fix frontmatter detection silently consuming content when a thematic break (---) starts the document. The colon-anywhere heuristic is replaced with proper YAML key-value validation, and a new disableFrontmatter option is added to skip detection entirely.
c7e0d07: Fix <hr> and other void HTML elements silently dropping all subsequent content when not followed by a newline (#856)
c7e0d07: Fix HTML blocks with markdown content inside tables (#862) and restore CommonMark-correct behavior for HTML block content without blank lines (#860)
<div>\n*text*\n</div>) is now preserved as literal text per CommonMark Example 189<div>\n\n*text*\n\n</div>) continues to parse markdown as before (CommonMark Example 188)0dfde05: Fix HTML compiler dropping the closing tag for empty non-void elements (e.g. <p></p> rendered as <p>, <div></div> rendered as <div>)
b0a7c68: fix: add key props to thead/tbody in table rendering to resolve React key warning (#858)
c7e0d07: Fix Vue adapter "Non-function value encountered for default slot" warning when using component overrides (#855)
bcf178a: Fix streaming mode incorrectly stripping self-closing custom component tags (e.g. ) and leaking incomplete trailing tags as escaped text in i
bcf178a: Fix streaming mode incorrectly stripping self-closing custom component tags (e.g. <CustomButton />) and leaking incomplete trailing tags as escaped text in inline content.
修复流式模式错误地移除自闭合自定义组件标签(如 <CustomButton />),以及内联内容中不完整的尾部标签作为转义文本泄漏的问题。
स्ट्रीमिंग मोड में सेल्फ-क्लोज़िंग कस्टम कंपोनेंट टैग (जैसे <CustomButton />) को गलत तरीके से हटाने और इनलाइन कंटेंट में अपूर्ण ट्रेलिंग टैग को एस्केप्ड टेक्स्ट के रूप में लीक होने की समस्या को ठीक करें।
1c430ae: Fix missing TypeScript declaration files in published package. Add standalone post-build verification that fails the build when type declarat
1c430ae: Fix missing TypeScript declaration files in published package. Add standalone post-build verification that fails the build when type declarations are not generated, independent of the bundler's plugin system.
发布包中缺少 TypeScript 声明文件的修复。添加独立的构建后验证,当类型声明未生成时构建失败,不依赖于打包器的插件系统。
प्रकाशित पैकेज में गायब TypeScript डिक्लेरेशन फ़ाइलों को ठीक करें। स्वतंत्र बिल्ड-बाद सत्यापन जोड़ें जो टाइप डिक्लेरेशन जनरेट न होने पर बिल्ड विफल करे, बंडलर के प्लगइन सिस्टम से स्वतंत्र।
5eecb05: Skip rendering empty tbody when a table has only a header row and no data rows.
5eecb05: Skip rendering empty tbody when a table has only a header row and no data rows.
仅有表头行而无数据行的表格不再渲染空的 tbody。
केवल हेडर पंक्ति और कोई डेटा पंक्ति न होने पर खाली tbody रेंडर नहीं किया जाता।
130cc33: Suppress React 19 RSC development warning about missing internal properties on manually-created elements.
修复 React 19 RSC 开发模式下手动创建的元素缺少内部属性时产生的警告。
React 19 RSC के विकास मोड में मैन्युअल रूप से बनाए गए तत्वों पर आंतरिक गुणों की अनुपस्थिति संबंधी चेतावनी को ठीक किया।
3daa41e: fix: strip trailing asterisks from bare URL href (fixes #839)
3daa41e: fix: strip trailing asterisks from bare URL href (fixes #839)
When a bare URL was wrapped in bold markdown (**url**), the generated link's href incorrectly included the closing asterisks (e.g. href="https://example.com/foo**"). The parser now trims trailing * from bare URLs so the href is correct. No consumer changes required.
当裸 URL 包裹在粗体 markdown(**url**)中时,生成的链接 href 错误地包含了闭合星号(例如 href="https://example.com/foo**")。解析器现在会从裸 URL 中去除尾部的 *,使 href 正确。无需更改消费者代码。
जब एक बेयर URL बोल्ड markdown (**url**) में लपेटा गया था, तो जनरेट किए गए लिंक का href गलत तरीके से क्लोज़िंग एस्टेरिस्क शामिल करता था (जैसे href="https://example.com/foo**")। पार्सर अब बेयर URL से अनुगामी * को हटा देता है ताकि href सही हो। कोई उपभोक्ता परिवर्तन आवश्यक नहीं है।
f520531: resolve emphasis delimiters closing before hard line breaks (two trailing spaces or backslash before newline)
解决在硬换行符(换行前有两个尾随空格或反斜杠)之前关闭强调分隔符的问题
हार्ड लाइन ब्रेक (न्यूलाइन से पहले दो ट्रेलिंग स्पेस या बैकस्लैश) से पहले एम्फ़ैसिस डिलीमिटर बंद होने की समस्या हल की
f520531: include _store on raw React elements unconditionally so React dev-mode validation works in all bundler environments
无条件地在原始 React 元素上包含 _store,使 React 开发模式验证在所有打包器环境中正常工作
सभी बंडलर वातावरण में React डेव-मोड सत्यापन काम करने के लिए रॉ React एलिमेंट्स पर बिना शर्त _store शामिल करें
2d21e43: Fail the build when type declarations are not generated, preventing releases without TypeScript types.
2d21e43: Fail the build when type declarations are not generated, preventing releases without TypeScript types.
当类型声明未生成时构建失败,防止发布缺少 TypeScript 类型的版本。
टाइप डिक्लेरेशन जनरेट न होने पर बिल्ड विफल करें, TypeScript टाइप्स के बिना रिलीज़ को रोकें।
58502fc: Resolve broken exports in bundled output caused by Bun bundler bug with cross-entry re-exports
58502fc: Resolve broken exports in bundled output caused by Bun bundler bug with cross-entry re-exports
解决由 Bun 打包器跨入口点重导出 bug 导致的打包输出中导出失效问题
Bun बंडलर के क्रॉस-एंट्री री-एक्सपोर्ट बग से होने वाली बंडल आउटपुट में टूटी हुई exports को ठीक किया
e0100f0: fix: nested HTML blocks with same tag name now correctly match depth-paired closing tags
e0100f0: fix: nested HTML blocks with same tag name now correctly match depth-paired closing tags
修复:嵌套的同名 HTML 块现在能正确匹配深度配对的关闭标签
修正:समान टैग नाम वाले नेस्टेड HTML ब्लॉक अब सही ढंग से गहराई-युग्मित समापन टैग से मिलान करते हैं
bf5d906: fix: suppress ambiguous setext headings during streaming to avoid premature heading rendering
修复:在流式传输过程中抑制歧义的 Setext 标题,避免过早渲染标题
修正:स्ट्रीमिंग के दौरान अस्पष्ट Setext शीर्षकों को दबाएं ताकि समय से पहले शीर्षक प्रदर्शन न हो
Nothing published for this version
565e3ea: fix: add missing _owner field on raw React elements for dev-mode compatibility
565e3ea: fix: add missing _owner field on raw React elements for dev-mode compatibility
Fixes "Cannot set properties of undefined (setting 'validated')" errors in React 19 dev mode by adding the _owner field that React's reconciler expects on all elements.
修复:在原始 React 元素上添加缺失的 _owner 字段,解决 React 19 开发模式下的兼容性问题。
सुधार: React 19 डेवलपमेंट मोड में "Cannot set properties of undefined" त्रुटि को ठीक करने के लिए raw React तत्वों पर गायब _owner फ़ील्ड जोड़ा गया।
565e3ea: fix: prevent void elements from receiving children when preceded by a blank line
Void HTML elements (e.g. <br>, <hr>, <img>) preceded by a blank line no longer cause React error #137. The parser now returns void elements as content-less blocks, and all compilers guard against passing children to void elements.
修复:当空行后跟空元素(如 <br>、<hr>、<img>)时,不再触发 React 错误 #137。解析器现在将空元素作为无内容块返回,所有编译器均防止向空元素传递子元素。
सुधार: जब खाली पंक्ति के बाद void तत्व (जैसे <br>, <hr>, <img>) आते हैं, तो अब React त्रुटि #137 नहीं होती। पार्सर अब void तत्वों को बिना सामग्री वाले ब्लॉक के रूप में लौटाता है, और सभी कंपाइलर void तत्वों को चाइल्ड तत्व देने से रोकते हैं।
cc1a8a7: Fix "Cannot set properties of undefined (setting 'validated')" error introduced in 9.7.1. React's dev-mode reconciler sets element._store.val
cc1a8a7: Fix "Cannot set properties of undefined (setting 'validated')" error introduced in 9.7.1. React's dev-mode reconciler sets element._store.validated to track element creation source; raw elements created by the fast path now include _store: {} in non-production builds.
修复 9.7.1 引入的 "Cannot set properties of undefined (setting 'validated')" 错误。React 开发模式协调器设置 element._store.validated 来追踪元素创建来源;快速路径创建的原始元素现在在非生产构建中包含 _store: {}。
9.7.1 में पेश हुई "Cannot set properties of undefined (setting 'validated')" त्रुटि ठीक की गई। React के dev-mode reconciler द्वारा element._store.validated सेट करने के लिए, फास्ट पाथ से बनाए गए raw elements अब non-production builds में _store: {} शामिल करते हैं।
Nothing published for this version
Fix HTML entity decoding in link titles (e.g. – now correctly decodes to –)
01b68df:
– now correctly decodes to –)<pre>, <script>, <style>, and <textarea> content being incorrectly parsed as markdown instead of rendered verbatim– 现在正确解码为 –)<pre>、<script>、<style> 和 <textarea> 内容被错误解析为 Markdown 而非原始文本渲染的问题– अब सही ढंग से – में बदलता है)<pre>, <script>, <style>, और <textarea> सामग्री को Markdown के बजाय यथावत् रेंडर करें``` +---------------------------------+---------------------+----------------------+-----------------------+
+---------------------------------+---------------------+----------------------+-----------------------+
| │ 1kB markdown string │ 27kB markdown string │ 211kB markdown string |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [parse] │ 1,454,794 ops/sec │ 4,315 ops/sec │ 516 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (9.7.2) [parse] │ 1,435,758 ops/sec │ 4,443 ops/sec │ 521 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| rehype [parse] │ 12,156 ops/sec │ 68.73 ops/sec │ 8.37 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| simple-markdown [parse] │ 176,142 ops/sec │ 20.57 ops/sec │ 0.41 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-it [parse] │ 692,586 ops/sec │ 2,767 ops/sec │ 361 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| marked [parse] │ 172,360 ops/sec │ 19.66 ops/sec │ 0.55 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [jsx] │ 1,170,133 ops/sec │ 3,463 ops/sec │ 391 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (9.7.2) [jsx] │ 1,144,191 ops/sec │ 3,466 ops/sec │ 379 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| rehype [jsx] │ 12,903 ops/sec │ 71.49 ops/sec │ 5.89 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| simple-markdown [jsx] │ 161,944 ops/sec │ 20.01 ops/sec │ 0.39 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| react-markdown [jsx] │ 21,365 ops/sec │ 99.87 ops/sec │ 11.15 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| Bun.markdown [jsx] │ 776,381 ops/sec │ 4,218 ops/sec │ 471 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [html] │ 901,435 ops/sec │ 2,891 ops/sec │ 317 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (9.7.2) [html] │ 654,830 ops/sec │ 2,148 ops/sec │ 267 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| Bun.markdown [html] │ 2,323,720 ops/sec │ 5,849 ops/sec │ 591 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-it [html] │ 530,612 ops/sec │ 1,922 ops/sec │ 253 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
2dca780: Improve HTML compiler performance by ~57%, bringing it to parity with the React compiler.
HTML 编译器性能提升约 57%,与 React 编译器持平。
HTML कंपाइलर के प्रदर्शन में ~57% सुधार, React कंपाइलर के बराबर।
30db3f3: Accept case-insensitive GFM alert blockquote syntax (e.g., [!Tip], [!tip]) matching GitHub's behavior.
30db3f3: Accept case-insensitive GFM alert blockquote syntax (e.g., [!Tip], [!tip]) matching GitHub's behavior.
接受不区分大小写的 GFM 警告引用块语法(例如 [!Tip]、[!tip]),与 GitHub 的行为保持一致。
GFM अलर्ट ब्लॉककोट सिंटैक्स में केस-इनसेंसिटिव मिलान स्वीकार करें (जैसे [!Tip], [!tip]), GitHub के व्यवहार के अनुरूप।
da2eb8c: Moved benchmarking and documentation website dev dependencies out of the library package for cleaner dependency management.
将基准测试和文档网站开发依赖项移出库包以实现更清晰的依赖管理。
बेंचमार्किंग और डॉक्यूमेंटेशन वेबसाइट डेव डिपेंडेंसी को साफ डिपेंडेंसी मैनेजमेंट के लिए लाइब्रेरी पैकेज से बाहर ले जाया गया।
Nothing published for this version
``` +---------------------------------+---------------------+----------------------+-----------------------+
+---------------------------------+---------------------+----------------------+-----------------------+
| │ 1kB markdown string │ 27kB markdown string │ 211kB markdown string |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [parse] │ 1,438,379 ops/sec │ 4,140 ops/sec │ 498 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (9.7.0) [parse] │ 1,407,537 ops/sec │ 4,122 ops/sec │ 490 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| rehype [parse] │ 11,794 ops/sec │ 63.95 ops/sec │ 7.52 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| simple-markdown [parse] │ 162,259 ops/sec │ 20.32 ops/sec │ 0.37 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-it [parse] │ 621,721 ops/sec │ 2,592 ops/sec │ 341 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| marked [parse] │ 161,682 ops/sec │ 17.57 ops/sec │ 0.51 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [jsx] │ 1,058,663 ops/sec │ 3,130 ops/sec │ 353 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (9.7.0) [jsx] │ 299,933 ops/sec │ 1,363 ops/sec │ 164 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| rehype [jsx] │ 11,292 ops/sec │ 62.72 ops/sec │ 5.44 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| simple-markdown [jsx] │ 160,005 ops/sec │ 19.71 ops/sec │ 0.38 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| react-markdown [jsx] │ 20,325 ops/sec │ 104 ops/sec │ 10.94 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| Bun.markdown [jsx] │ 730,073 ops/sec │ 4,066 ops/sec │ 461 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [html] │ 587,989 ops/sec │ 2,083 ops/sec │ 269 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| Bun.markdown [html] │ 2,235,232 ops/sec │ 5,772 ops/sec │ 574 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-it [html] │ 497,458 ops/sec │ 1,920 ops/sec │ 237 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
9830b70: Fix entity resolution in CodeSandbox and other bundlers by exposing entities as a public subpath export. Bundlers now resolve markdown-to-jsx/entities using the browser condition, ensuring the optimized DOM-based decoder (~300B) is used in browsers instead of the full entity table (~29KB).
通过将实体作为公共子路径导出来修复 CodeSandbox 和其他打包工具中的实体解析。打包工具现在使用 browser 条件解析 markdown-to-jsx/entities,确保浏览器使用优化的基于 DOM 的解码器(约 300B)而不是完整的实体表(约 29KB)。
CodeSandbox और अन्य बंडलर में एंटिटी रिज़ॉल्यूशन को ठीक करने के लिए एंटिटी को सार्वजनिक सबपाथ एक्सपोर्ट के रूप में एक्सपोज़ किया गया। बंडलर अब browser कंडीशन का उपयोग करके markdown-to-jsx/entities को रिज़ॉल्व करते हैं, यह सुनिश्चित करते हुए कि ब्राउज़र में पूर्ण एंटिटी टेबल (~29KB) के बजाय ऑप्टिमाइज़्ड DOM-आधारित डिकोडर (~300B) का उपयोग किया जाता है।
e537dca: Bypass React.createElement for ~2x faster JSX output by constructing raw React element objects directly. The $$typeof symbol is auto-detected from the installed React version for forward compatibility. Falls back to createElement when a custom createElement option is provided.
绕过 React.createElement,通过直接构造原始 React 元素对象实现约 2 倍的 JSX 输出速度提升。$$typeof 符号从已安装的 React 版本自动检测以确保前向兼容性。当提供自定义 createElement 选项时回退到 createElement。
React.createElement को बायपास करके कच्चे React एलिमेंट ऑब्जेक्ट सीधे बनाकर ~2x तेज़ JSX आउटपुट। $$typeof सिंबल आगे की संगतता के लिए स्थापित React संस्करण से स्वतः पहचाना जाता है। कस्टम createElement विकल्प प्रदान करने पर createElement पर वापस आता है।
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
``` +---------------------------------+---------------------+----------------------+-----------------------+
+---------------------------------+---------------------+----------------------+-----------------------+
| │ 1kB markdown string │ 27kB markdown string │ 211kB markdown string |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [parse] │ 1,437,462 ops/sec │ 4,271 ops/sec │ 502 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (9.6.1) [parse] │ 1,125,012 ops/sec │ 2,268 ops/sec │ 327 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| rehype [parse] │ 11,296 ops/sec │ 69.31 ops/sec │ 7.94 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| simple-markdown [parse] │ 170,206 ops/sec │ 19.13 ops/sec │ 0.38 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-it [parse] │ 695,880 ops/sec │ 2,762 ops/sec │ 365 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| marked [parse] │ 168,032 ops/sec │ 19.27 ops/sec │ 0.53 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [jsx] │ 328,461 ops/sec │ 1,495 ops/sec │ 181 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (9.6.1) [jsx] │ 302,556 ops/sec │ 1,066 ops/sec │ 160 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| Bun.markdown [jsx] │ 784,130 ops/sec │ 4,499 ops/sec │ 502 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| rehype [jsx] │ 12,912 ops/sec │ 69.58 ops/sec │ 6.22 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| simple-markdown [jsx] │ 163,363 ops/sec │ 19.57 ops/sec │ 0.39 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| react-markdown [jsx] │ 23,151 ops/sec │ 121 ops/sec │ 12.07 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
ab93d7b: Replaced the rule-based markdown parser with a compact table-driven parser. Parsing is 27-82% faster depending on input size and bundle size is reduced by ~25% (gzip). Improved CommonMark compliance for HTML block handling and streaming mode reliability. No API changes.
用紧凑的表驱动解析器替换了基于规则的 markdown 解析器。根据输入大小,解析速度提升 27-82%,包体积减少约 25%(gzip)。改进了 HTML 块处理和流式模式可靠性的 CommonMark 合规性。无 API 更改。
नियम-आधारित markdown पार्सर को कॉम्पैक्ट टेबल-ड्रिवन पार्सर से बदला गया। इनपुट आकार के अनुसार पार्सिंग 27-82% तेज़ है और बंडल आकार ~25% (gzip) कम हुआ। HTML ब्लॉक हैंडलिंग और स्ट्रीमिंग मोड विश्वसनीयता के लिए CommonMark अनुपालन में सुधार। कोई API परिवर्तन नहीं।
ab93d7b: Fixed attribute casing preservation across all output adapters. The parser no longer modifies attribute names; each adapter handles its own mappings. React/Native convert to JSX props (class->className, XML namespaces via colon-to-camelCase heuristic). Solid uses class per framework guidance. Vue passes HTML attributes directly.
修复了所有输出适配器中的属性大小写保留。解析器不再修改属性名称;每个适配器处理自己的映射。React/Native 转换为 JSX 属性(class->className,XML 命名空间通过冒号转驼峰启发式)。Solid 按框架指南使用 class。Vue 直接传递 HTML 属性。
सभी आउटपुट एडेप्टर में एट्रिब्यूट केसिंग संरक्षण ठीक किया गया। पार्सर अब एट्रिब्यूट नामों को संशोधित नहीं करता; प्रत्येक एडेप्टर अपनी मैपिंग संभालता है। React/Native JSX props में बदलता है (class->className, XML नेमस्पेस कोलन-टू-कैमलकेस से)। Solid फ्रेमवर्क दिशानिर्देश के अनुसार class उपयोग करता है। Vue सीधे HTML एट्रिब्यूट पास करता है।
ab93d7b: Improved optimizeForStreaming handling of incomplete inline syntax. Bold/italic/strikethrough markers, links, images, and nested badge constructs ([](url)) now stream cleanly without flashing raw markdown syntax. Incomplete images are fully suppressed instead of showing alt text.
改进了 optimizeForStreaming 对不完整内联语法的处理。粗体/斜体/删除线标记、链接、图片和嵌套徽章构造([](url))现在可以流畅地流式传输,不会闪烁原始 markdown 语法。不完整的图片会被完全抑制,而不是显示替代文本。
optimizeForStreaming में अपूर्ण इनलाइन सिंटैक्स की हैंडलिंग में सुधार। बोल्ड/इटैलिक/स्ट्राइकथ्रू मार्कर, लिंक, इमेज, और नेस्टेड बैज कंस्ट्रक्ट ([](url)) अब raw markdown सिंटैक्स की झलक के बिना सुचारू रूप से स्ट्रीम होते हैं। अपूर्ण इमेज alt टेक्स्ट दिखाने के बजाय पूरी तरह से दबा दी जाती हैं।
9bf4bad: Fix: Jest test suites failing with "Unexpected token 'export'" when using the library with jsdom environment. The browser condition in the pa
9bf4bad: Fix: Jest test suites failing with "Unexpected token 'export'" when using the library with jsdom environment. The browser condition in the package.json imports field now correctly provides both ESM (import) and CJS (require) sub-conditions, ensuring Jest resolves to the CommonJS version of the browser entities module.
修复:当在 jsdom 环境中使用该库时,Jest 测试套件会因"Unexpected token 'export'"而失败。package.json imports 字段中的 browser 条件现在正确提供 ESM(import)和 CJS(require)子条件,确保 Jest 解析到浏览器实体模块的 CommonJS 版本。
फिक्स: jsdom वातावरण में लाइब्रेरी का उपयोग करते समय Jest टेस्ट सुइट "Unexpected token 'export'" त्रुटि के साथ विफल हो रहे थे। package.json imports फ़ील्ड में browser कंडीशन अब सही ढंग से ESM (import) और CJS (require) सब-कंडीशन प्रदान करती है, जिससे Jest ब्राउज़र एंटिटी मॉड्यूल के CommonJS संस्करण को सही ढंग से रिज़ॉल्व करता है।
2432f0b: Fix: preserve camelCase attribute casing for all HTML/JSX tags, not just PascalCase components. This restores expected behavior where attributes like userId and firstName are no longer lowercased to userid and firstname.
修复:为所有 HTML/JSX 标签保留 camelCase 属性大小写,而不仅仅是 PascalCase 组件。这恢复了预期行为,使得 userId 和 firstName 等属性不再被转换为小写的 userid 和 firstname。
फिक्स: सभी HTML/JSX टैग के लिए camelCase एट्रिब्यूट केसिंग को संरक्षित करें, न कि केवल PascalCase कंपोनेंट के लिए। यह अपेक्षित व्यवहार को बहाल करता है जहां userId और firstName जैसे एट्रिब्यूट अब लोअरकेस userid और firstname में परिवर्तित नहीं होते हैं।
a97e2bf: Add optimizeForStreaming option to suppress incomplete syntax during streaming. When enabled, incomplete inline code, links, emphasis, and ot
optimizeForStreaming option to suppress incomplete syntax during streaming. When enabled, incomplete inline code, links, emphasis, and other markdown syntax is hidden cleanly as characters arrive, preventing visual artifacts and flickering. Particularly useful for AI-powered streaming applications.4252da4: Fixed inconsistent spacing between list item nodes when continuation lines have indentation equal to the nested list marker. Previously, text
13bdaf7: Fixed HTML tags with attributes spanning multiple lines being incorrectly parsed.
13bdaf7: Fixed HTML tags with attributes spanning multiple lines being incorrectly parsed.
Previously, HTML tags with attributes on separate lines (like <dl-custom\n data-variant='horizontalTable'\n>) would have their attributes incorrectly parsed, sometimes causing duplicate tags or missing attribute values. This fix ensures that newlines between HTML attributes are properly recognized as whitespace separators.
修复了属性跨多行的 HTML 标签解析不正确的问题。
之前,属性位于单独行上的 HTML 标签(如 <dl-custom\n data-variant='horizontalTable'\n>)的属性解析不正确,有时会导致重复的标签或缺失属性值。此修复确保 HTML 属性之间的换行符被正确识别为空白分隔符。
कई पंक्तियों में फैले एट्रिब्यूट वाले HTML टैग्स के गलत पार्सिंग को ठीक किया।
पहले, अलग-अलग पंक्तियों पर एट्रिब्यूट वाले HTML टैग्स (जैसे <dl-custom\n data-variant='horizontalTable'\n>) के एट्रिब्यूट गलत तरीके से पार्स होते थे, जिससे कभी-कभी डुप्लिकेट टैग्स या गायब एट्रिब्यूट वैल्यू होते थे। यह फिक्स सुनिश्चित करता है कि HTML एट्रिब्यूट के बीच न्यूलाइन को व्हाइटस्पेस सेपरेटर के रूप में सही ढंग से पहचाना जाता है।
13bdaf7: The text field in HTML AST nodes now contains cleaned inner content without opening/closing tags. Use rawText for full raw HTML. This affects custom renderRule implementations that rely on the text field.
HTML AST 节点中的 text 字段现在包含不带开/闭标签的清理后内容。使用 rawText 获取完整原始 HTML。这会影响依赖 text 字段的自定义 renderRule 实现。
HTML AST नोड्स में text फ़ील्ड अब ओपनिंग/क्लोज़िंग टैग्स के बिना साफ़ इनर कंटेंट रखता है। पूर्ण raw HTML के लिए rawText का उपयोग करें। यह उन कस्टम renderRule कार्यान्वयनों को प्रभावित करता है जो text फ़ील्ड पर निर्भर हैं।
76b7f12: Fix multi-line HTML tag attribute parsing
76b7f12: Fix multi-line HTML tag attribute parsing (#781)
HTML tags with attributes spanning multiple lines were not having their attributes correctly parsed into the AST. This caused custom elements with multi-line data-* attributes to have empty attrs objects, and the React compiler would then duplicate the opening tag when rendering.
This fix ensures:
children array instead of re-parsing rawText when attributes are already parsed修复多行 HTML 标签属性解析问题(#781)
具有跨多行属性的 HTML 标签没有正确将其属性解析到 AST 中。这导致具有多行 data-* 属性的自定义元素具有空的 attrs 对象,然后 React 编译器在渲染时会重复开始标签。
此修复确保:
children 数组而不是重新解析 rawTextबहु-पंक्ति HTML टैग विशेषता पार्सिंग ठीक करें (#781)
कई पंक्तियों में फैले विशेषताओं वाले HTML टैग अपनी विशेषताओं को AST में सही ढंग से पार्स नहीं कर रहे थे। इससे बहु-पंक्ति data-* विशेषताओं वाले कस्टम तत्वों में खाली attrs ऑब्जेक्ट थे, और फिर React कंपाइलर रेंडरिंग करते समय आरंभिक टैग को दोहरा देता था।
यह सुधार सुनिश्चित करता है:
rawText को दोबारा पार्स करने के बजाय पार्स किए गए children सरणी का उपयोग करता है7f724a6: Fix HTML block parsing for sibling elements like / without blank lines between them.
7f724a6: Fix HTML block parsing for sibling elements like <dt>/<dd> without blank lines between them.
Type 6 HTML blocks (such as <dl>, <dt>, <dd>, <table>, <tr>, <td>) were incorrectly parsed when sibling elements appeared without blank lines between them—the first element would consume all subsequent siblings as its content instead of treating them as separate elements.
This fix adds nesting-aware closing tag detection that properly handles:
<div><div></div></div>)<dt></dt><dd></dd>)修复了没有空行分隔的兄弟 HTML 元素(如 <dt>/<dd>)的块解析问题。
类型 6 HTML 块(如 <dl>、<dt>、<dd>、<table>、<tr>、<td>)在兄弟元素之间没有空行时解析错误——第一个元素会将所有后续兄弟元素作为其内容,而不是将它们视为单独的元素。
此修复添加了具有嵌套感知的关闭标签检测,正确处理:
<div><div></div></div>)<dt></dt><dd></dd>)रिक्त पंक्तियों के बिना भाई HTML तत्वों (जैसे <dt>/<dd>) के लिए HTML ब्लॉक पार्सिंग को ठीक किया।
टाइप 6 HTML ब्लॉक (जैसे <dl>, <dt>, <dd>, <table>, <tr>, <td>) गलत तरीके से पार्स हो रहे थे जब भाई तत्व बिना रिक्त पंक्तियों के दिखाई देते थे—पहला तत्व सभी अनुवर्ती भाई तत्वों को अपनी सामग्री के रूप में शामिल कर लेता था, उन्हें अलग तत्वों के रूप में मानने के बजाय।
यह सुधार नेस्टिंग-जागरूक क्लोजिंग टैग पहचान जोड़ता है जो सही ढंग से संभालता है:
<div><div></div></div>)<dt></dt><dd></dd>)58010ce: Fix duplicate opening tags for HTML elements with multi-line attributes (#781)
HTML tags with attributes spanning multiple lines (like custom elements with data-* attributes on separate lines) no longer produce duplicate opening tags in the output. This restores the expected behavior for custom HTML elements used with component overrides.
修复多行属性的 HTML 元素产生重复开始标签的问题(#781)
具有跨多行属性的 HTML 标签(例如在不同行上具有 data-* 属性的自定义元素)不再在输出中产生重复的开始标签。这恢复了与组件覆盖一起使用的自定义 HTML 元素的预期行为。
बहु-पंक्ति विशेषताओं वाले HTML तत्वों के लिए दोहरे आरंभिक टैग ठीक करें (#781)
कई पंक्तियों में फैली विशेषताओं वाले HTML टैग (जैसे अलग-अलग पंक्तियों पर data-* विशेषताओं वाले कस्टम तत्व) अब आउटपुट में दोहरे आरंभिक टैग उत्पन्न नहीं करते। यह कंपोनेंट ओवरराइड के साथ उपयोग किए जाने वाले कस्टम HTML तत्वों के अपेक्षित व्यवहार को पुनर्स्थापित करता है।
3e25913: Fix fenced code blocks consuming nested code block openings as content.
When a fenced code block with a language (e.g., ```markdown) encountered another code block opening with a language (e.g., ```python) inside it, the inner opening was incorrectly treated as content instead of being recognized as a new block. Now, fence lines with a language immediately following (no space between fence and language) are recognized as new block openings that implicitly close the previous block.
This matches behavior of other markdown renderers like GitHub and VSCode. Lines like ``` aaa (with space before info string) remain treated as content per CommonMark spec.
修复了围栏代码块将嵌套代码块开头作为内容消费的问题。
当带有语言的围栏代码块(例如 ```markdown)内部遇到另一个带语言的代码块开头(例如 ```python)时,内部开头被错误地视为内容,而不是被识别为新块。现在,语言紧随其后(围栏和语言之间没有空格)的围栏行被识别为隐式关闭前一个块的新块开头。
这与 GitHub 和 VSCode 等其他 markdown 渲染器的行为一致。按照 CommonMark 规范,像 ``` aaa(信息字符串前有空格)这样的行仍被视为内容。
फेंस्ड कोड ब्लॉक्स द्वारा नेस्टेड कोड ब्लॉक ओपनिंग को सामग्री के रूप में उपभोग करने की समस्या को ठीक किया।
जब भाषा वाला फेंस्ड कोड ब्लॉक (जैसे ```markdown) के अंदर भाषा वाला दूसरा कोड ब्लॉक ओपनिंग (जैसे ```python) आता था, तो आंतरिक ओपनिंग को नए ब्लॉक के रूप में पहचानने के बजाय गलती से सामग्री के रूप में माना जाता था। अब, भाषा तुरंत बाद आने वाली (फेंस और भाषा के बीच कोई स्पेस नहीं) फेंस लाइनें नए ब्लॉक ओपनिंग के रूप में पहचानी जाती हैं जो पिछले ब्लॉक को निहित रूप से बंद करती हैं।
यह GitHub और VSCode जैसे अन्य markdown रेंडरर के व्यवहार से मेल खाता है। CommonMark स्पेक के अनुसार ``` aaa (इन्फो स्ट्रिंग से पहले स्पेस) जैसी लाइनें अभी भी सामग्री के रूप में मानी जाती हैं।
8528325: Add CommonMark-compliant text normalization for null bytes and BOM
8528325: Add CommonMark-compliant text normalization for null bytes and BOM
Per CommonMark security specification, null bytes (U+0000) are now replaced with the replacement character (U+FFFD) instead of passing through unchanged. Additionally, the Byte Order Mark (U+FEFF) is now stripped when it appears at the start of a document, as specified in the CommonMark spec.
These changes improve spec compliance and security. Most documents are unaffected due to fast-path optimization that skips processing when no special characters are present.
282affe: Fix lists and other markdown structures not rendering correctly when input has CRLF line endings.
fa21868: Add Chinese (Mandarin) JSDoc documentation to all public APIs. All exported functions, types, interfaces, and components now include bilingua
fa21868: Add Chinese (Mandarin) JSDoc documentation to all public APIs. All exported functions, types, interfaces, and components now include bilingual documentation using the @lang zh tag for Simplified Chinese translations, improving developer experience for Chinese-speaking users.
fa21868: Add Hindi (हिन्दी) language support for internationalization. Includes full translations of documentation (README, markdown spec, GFM spec, interactive demo template), UI strings, and JSDoc translations for all public APIs using the @lang hi tag. Hindi is now the third supported language after English and Mandarin Chinese, following global speaker rankings (Ethnologue 2025).
897c4c2: Automatic browser bundle optimization via conditional exports. Browser builds now automatically use DOM-based entity decoding (textarea.innerHTML) instead of shipping the full ~11KB entity lookup table, reducing gzipped bundle size by ~11KB.
This optimization is automatic for bundlers that support the imports field with browser condition (Webpack 5+, Vite, esbuild, Rollup, Parcel). No configuration required.
Server-side/Node.js builds retain the full O(1) entity lookup table for maximum performance.
This feature uses the imports field in package.json. All modern bundlers support this field (Webpack 5+, Vite, esbuild, Rollup, Parcel).
Zero breaking changes for existing users
7605d88: Add React Server Components (RSC) support with automatic environment detection.
The Markdown component now seamlessly works in both RSC and client-side React environments without requiring 'use client' directives. The component automatically detects hook availability and adapts its behavior accordingly:
MarkdownProvider and MarkdownContext gracefully become no-ops in RSC environmentsThis enables better bundle splitting and SSR performance by allowing markdown rendering to happen on the server when possible.
d2075d2: Fix hard line breaks (two trailing spaces) inside list items not being converted to <br/>.
In v9, hard line breaks inside list items were being lost because the first line content and continuation lines were being parsed separately, causing the trailing spaces before the newline to be stripped before the hard break could be detected.
The fix ensures that for tight list items (without blank lines), simple text continuation lines are collected and concatenated with the first line content before parsing. This preserves the trailing spaces + newline sequence that triggers hard break detection.
This fix also handles hard line breaks inside blockquotes that are nested within list items, ensuring the blockquote continuation lines are properly collected together.
Fixes #766.
Nothing published for this version
775b4bf: Expose parser and RuleType from the markdown entry point as documented.
parser and RuleType from the markdown entry point as documented.…the parsed AST. The text property is now deprecated and will be removed in a future major version. Both fields are set to the same value for backward…
renderRule always executes before any other rendering code across all renderers. The renderRule function now has full control over node rendering, including normally-skipped nodes like ref, footnote, and frontmatter. Additionally, renderChildren in the markdown renderer now invokes renderRule for recursively rendered child nodes, ensuring consistent behavior when customizing rendering logic.children property, even when marked as verbatim. The verbatim flag now acts as a rendering hint rather than a parsing control. Default renderers still use rawText for verbatim blocks (maintaining CommonMark compliance), but renderRule implementations can now access the fully parsed AST in children for all HTML blocks. The noInnerParse property has been replaced with verbatim for clarity.HTMLNode.rawText field for consistency with rawAttrs. The rawText field contains the raw text content for verbatim HTML blocks, while children contains the parsed AST. The text property is now deprecated and will be removed in a future major version. Both fields are set to the same value for backward compatibility.c1be885: Added context providers and memoization to all major renderers for better developer experience and performance.
c1be885: Added context providers and memoization to all major renderers for better developer experience and performance.
React:
MarkdownContext - React context for default optionsMarkdownProvider - Provider component to avoid prop-drillinguseMemo - 3-stage memoization (options, content, JSX)React Native:
MarkdownContext - React context for default optionsMarkdownProvider - Provider component to avoid prop-drillinguseMemo - 3-stage memoization (options, content, JSX)Vue:
MarkdownOptionsKey - InjectionKey for provide/inject patternMarkdownProvider - Provider component using Vue's providecomputed - Reactive memoization for options, content, and JSXBenefits:
<MarkdownProvider options={commonOptions}>
<App>
<Markdown>...</Markdown>
<Markdown>...</Markdown>
</App>
</MarkdownProvider>
Example:
import { MarkdownProvider } from 'markdown-to-jsx/react'
function App() {
return (
<MarkdownProvider options={{ wrapper: 'article', tagfilter: true }}>
<Markdown># Page 1</Markdown>
<Markdown># Page 2</Markdown>
{/* Both inherit options from provider */}
</MarkdownProvider>
)
}
ef8a002: Added opt-in options.evalUnserializableExpressions to eval function expressions and other unserializable JSX props from trusted markdown sources.
⚠️ SECURITY WARNING: STRONGLY DISCOURAGED FOR USER INPUTS
This option uses eval() and should ONLY be used with completely trusted markdown sources (e.g., your own documentation). Never enable this for user-submitted content.
Usage:
// For trusted sources only
const markdown = `
<Button onPress={() => alert('clicked!')} />
<ApiEndpoint url={process.env.API_URL} />
`
parser(markdown, { evalUnserializableExpressions: true })
// Components receive:
// - onPress: actual function () => alert('clicked!')
// - url: the value of process.env.API_URL from your environment
// Without this option, these would be strings "() => alert('clicked!')" and "process.env.API_URL"
Safer alternative: Use renderRule to handle stringified expressions on a case-by-case basis with your own validation and allowlists.
See the README for detailed security considerations and safe alternatives.
ef8a002: JSX prop values are now intelligently parsed instead of always being strings:
JSON.parse(): data={[1, 2, 3]} → attrs.data = [1, 2, 3]enabled={true} → attrs.enabled = trueonClick={() => ...} → attrs.onClick = "() => ..."value={someVar} → attrs.value = "someVar"The original raw attribute string is preserved in the rawAttrs field.
Benefits:
Example:
<!-- prettier-ignore -->
// In markdown:
<ApiTable
rows={[
['Name', 'Value'],
['foo', 'bar'],
]}
/>
// In your component:
const ApiTable = ({ rows }) => {
// rows is already an array, no JSON.parse needed!
return <table>...</table>
}
// For backwards compatibility:
const rows =
typeof props.rows === 'string' ? JSON.parse(props.rows) : props.rows
Security: Functions remain as strings by default. Use renderRule for case-by-case handling, or see the new options.evalUnserializableExpressions feature for opt-in eval (not recommended for user inputs).
ef8a002: JSX components with double-newlines (blank lines) between opening and closing tags now properly nest children instead of creating sibling nodes. This fixes incorrect AST structure for JSX/MDX content.
Before:
<!-- prettier-ignore -->
<Figure>
<div>content</div>
</Figure>
Parsed as 3 siblings: <Figure>, <div>, </Figure>
After:
Parsed as parent-child: <Figure> contains <div> as a child
This was a bug where the parser incorrectly treated JSX components as siblings when double-newlines were present between the tags. The fix ensures proper parent-child relationships match expected JSX/MDX semantics.
08dfe8a: Fix regression: Tables within list items are now properly parsed.
c5b6259: Fixed URIError when parsing HTML attributes containing the % character (e.g., width="100%"). The parser now gracefully handles invalid URI en
width="100%"). The parser now gracefully handles invalid URI encodings in attribute values instead of throwing an error.7ac3408: Restore angle-bracket autolinks when raw HTML parsing is disabled so still renders as links
<https://...> still renders as linksa84c300: Ensure Solid renderer uses Solid's hyperscript runtime so JSX returns real elements instead of [object Object] placeholders
[object Object] placeholdersNothing published for this version
c1b0ea2: Fix unintended node-specific code from entering browser bundles by changing build target from 'node' to 'browser'
a482de6: Add SolidJS integration with full JSX output support. Includes compiler, parser, astToJSX, and Markdown component with reactive support via s
compiler, parser, astToJSX, and Markdown component. Vue uses standard HTML attributes (class, not className) with minimal attribute mapping (only 'for' -> 'htmlFor').88d4b1f: Add comprehensive React Native support with new /native export. Includes:
88d4b1f: Add comprehensive React Native support with new /native export. Includes:
img → Image, block elements (div, section, article, blockquote, ul, ol, li, table, etc.) → View, and inline elements → TextonLinkPress and onLinkLongPress callbacks, defaulting to Linking.openURLNativeStyleKey type system with styles for all markdown elements and HTML semantic tagsaccessibilityLabel for images and proper link handlingNativeOptions and NativeStyleKey typesReact Native is an optional peer dependency, making this a zero-dependency addition for existing users.
f93214a: Fix infinite recursion when using forceBlock: true with empty unclosed HTML tags
f93214a: Fix infinite recursion when using forceBlock: true with empty unclosed HTML tags
When React.createElement(Markdown, {options: {forceBlock: true}}, '<var>') was called with an empty unclosed tag, it would cause infinite recursion. The parser would set the text field to the opening tag itself (e.g., <var>), which would then be parsed again in the rendering phase, causing recursion.
This fix adds detection in createVerbatimHTMLBlock to detect when forceBlock is used and the text contains just the opening tag (empty unclosed tag), rendering it as an empty element to prevent recursion.
733f10e: Fix lazy continuation lines for list items when continuation text appears at base indentation without a blank line. Previously, continuation
0ba757d: Add preserveFrontmatter option to control whether YAML frontmatter is rendered in the output. When set to true, frontmatter is rendered as a
0ba757d: Add preserveFrontmatter option to control whether YAML frontmatter is rendered in the output. When set to true, frontmatter is rendered as a <pre> element in HTML/JSX output. For markdown-to-markdown compilation, frontmatter is preserved by default but can be excluded with preserveFrontmatter: false.
| Compiler Type | Default Behavior | When preserveFrontmatter: true |
When preserveFrontmatter: false |
|---|---|---|---|
| React/HTML | ❌ Don't render frontmatter | ✅ Render as <pre> element |
❌ Don't render frontmatter |
| Markdown-to-Markdown | ✅ Preserve frontmatter | ✅ Preserve frontmatter | ❌ Exclude frontmatter |
React code in the main entry point markdown-to-jsx is deprecated and will be removed in a future major release. In v10, the main entry point will only…
+---------------------------------+---------------------+----------------------+-----------------------+
| │ 1kB markdown string │ 27kB markdown string │ 211kB markdown string |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [parse] │ 1,316,464 ops/sec │ 3,056 ops/sec │ 450 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (8.0.0) [parse] │ 76,664 ops/sec │ 546 ops/sec │ 42.91 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| rehype [parse] │ 13,125 ops/sec │ 70.77 ops/sec │ 8.38 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| simple-markdown [parse] │ 135,737 ops/sec │ 20.52 ops/sec │ 0.40 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-it [parse] │ 686,807 ops/sec │ 2,681 ops/sec │ 367 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| marked [parse] │ 161,358 ops/sec │ 19.95 ops/sec │ 0.51 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (next) [jsx] │ 333,760 ops/sec │ 1,210 ops/sec │ 180 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| markdown-to-jsx (8.0.0) [jsx] │ 61,447 ops/sec │ 429 ops/sec │ 39.22 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| rehype [jsx] │ 13,816 ops/sec │ 71.20 ops/sec │ 6.20 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| simple-markdown [jsx] │ 159,076 ops/sec │ 20.53 ops/sec │ 0.40 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
| react-markdown [jsx] │ 24,084 ops/sec │ 118 ops/sec │ 12.44 ops/sec |
+---------------------------------+---------------------+----------------------+-----------------------+
1ce83eb: Complete GFM+CommonMark specification compliance
<script>, <iframe>, etc.) in both HTML string output and React JSX outputjavascript:, vbscript:, and malicious data: URLsDefault filtering of dangerous HTML tags:
<script>, <iframe>, <object>, <embed><title>, <textarea>, <style>, <xmp><plaintext>, <noembed>, <noframes>No changes necessary in most cases, but if you need to render potentially dangerous HTML tags, you can disable tag filtering:
compiler(markdown, { tagfilter: false })
Previous Behavior (Non-Compliant): The library previously allowed inline formatting to span multiple lines:
_Hello
World._
This was parsed as a single <em> element containing the newline.
New Behavior (CommonMark Compliant): Per CommonMark specification, inline formatting cannot span newlines. The above example is now parsed as literal underscores:
_Hello
World._
Renders as: <p>_Hello World._</p>
Impact:
*Hello World* → <em>Hello World</em>*Hello\nWorld* → literal asterisks*emphasis*, **bold**, ~~strikethrough~~, ==mark==Migration Options: If you have markdown with multi-line inline formatting:
*Hello World*<em>Hello\nWorld</em>Examples:
# Works (single line)
_This is emphasized_
**This is bold**
# No longer works (multi-line)
_This is
emphasized_
**This is
bold**
# Renders as literal delimiters:
<p>_This is
emphasized_</p>
<p>**This is
bold**</p>
# Workaround: Use HTML tags
<em>This is
emphasized</em>
<strong>This is
bold</strong>
1ce83eb: Remove internal type definitions and rename MarkdownToJSX.RuleOutput to MarkdownToJSX.ASTRender
This change removes internal type definitions from the MarkdownToJSX namespace:
NestedParser typeParser typeRule typeRules typeRuleOutput to ASTRender for clarityBreaking changes:
If you are using the internal types directly:
MarkdownToJSX.NestedParser, MarkdownToJSX.Parser, MarkdownToJSX.Rule, or MarkdownToJSX.Rules will need to be updatedrenderRule option in MarkdownToJSX.Options now uses ASTRender instead of RuleOutput for the renderChildren parameter typeHTMLNode.children type changed from ReturnType<MarkdownToJSX.NestedParser> to ASTNode[] (semantically equivalent, but requires updates if using the old type)1ce83eb: Remove options.namedCodesToUnicode. The library now encodes the full HTML entity list by default per CommonMark specification requirements.
Migration:
If you were using options.namedCodesToUnicode to add custom entity mappings, you can remove the option entirely as all specified HTML entities are now supported automatically.
1ce83eb: Drop support for React versions less than 16
>= 0.14.0 to >= 16.0.0<span> elements for React < 16 compatibility1ce83eb: Upgrade to React 19 types
@types/react@^19.2.2 and @types/react-dom@^19.2.2React.JSX.* namespace instead of JSX.* for React 19 compatibility1ce83eb: Adopt CommonMark-compliant class naming for code blocks
Code blocks now use both the language- and lang- class name prefixes to match the CommonMark specification for compatibility.
```js
console.log('hello')
```
Generated:
<pre><code class="lang-js">console.log('hello');</code></pre>
```js
console.log('hello')
```
Generated:
<pre><code class="language-js lang-js">console.log('hello');</code></pre>
1ce83eb: Separate JSX renderer from compiler and add new entry points
New parser function: Low-level API that returns AST nodes. Exported from main entry point and all sub-entry points.
import { parser } from 'markdown-to-jsx'
const source = '# Hello world'
const ast = parser(source)
New /react entry point: React-specific entry point that exports compiler, Markdown component, parser, types, and utils.
import Markdown, { astToJSX, compiler, parser } from 'markdown-to-jsx/react'
const source = '# Hello world'
const oneStepJSX = compiler(source)
const twoStepJSX = astToJSX(parser(source))
function App() {
return <Markdown children={source} />
// or
// return <Markdown>{source}</Markdown>
}
New /html entry point: HTML string output entry point that exports html function, parser, types, and utils.
import { astToHTML, compiler, parser } from 'markdown-to-jsx/html'
const source = '# Hello world'
const oneStepHTML = compiler(source)
const twoStepHTML = astToHTML(parser(source))
New /markdown entry point: Useful for situations where editing of the markdown is desired without resorting to gnarly regex-based parsing.
import { astToMarkdown, compiler, parser } from 'markdown-to-jsx/markdown'
const source = '# Hello world'
const oneStepMarkdown = compiler(source)
const twoStepMarkdown = astToMarkdown(parser(source))
React code in the main entry point markdown-to-jsx is deprecated and will be removed in a future major release. In v10, the main entry point will only export the parser function, the types, and any exposed utility functions.
markdown-to-jsx/reactmarkdown-to-jsx/html entry pointparser() for direct acces to ASTNothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →