Releases: quantizor/markdown-to-jsx
v9.4.2
v9.4.1
Patch Changes
- 7ee8a22: Ensure
renderRulealways executes before any other rendering code across all renderers. TherenderRulefunction now has full control over node rendering, including normally-skipped nodes likeref,footnote, andfrontmatter. Additionally,renderChildrenin the markdown renderer now invokesrenderRulefor recursively rendered child nodes, ensuring consistent behavior when customizing rendering logic. - 7ee8a22: HTML blocks are now always fully parsed into the AST
childrenproperty, even when marked asverbatim. Theverbatimflag now acts as a rendering hint rather than a parsing control. Default renderers still userawTextfor verbatim blocks (maintaining CommonMark compliance), butrenderRuleimplementations can now access the fully parsed AST inchildrenfor all HTML blocks. ThenoInnerParseproperty has been replaced withverbatimfor clarity. - 7ee8a22: Add
HTMLNode.rawTextfield for consistency withrawAttrs. TherawTextfield contains the raw text content for verbatim HTML blocks, whilechildrencontains the parsed AST. Thetextproperty is now deprecated and will be removed in a future major version. Both fields are set to the same value for backward compatibility.
v9.4.0
Minor Changes
-
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 JSX
Benefits:
- Avoid prop-drilling - Set options once at the top level:
<MarkdownProvider options={commonOptions}> <App> <Markdown>...</Markdown> <Markdown>...</Markdown> </App> </MarkdownProvider>
- Performance optimization - Content is only parsed when it actually changes, not on every render
- Fully backwards compatible - Existing usage works unchanged, providers are optional
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.evalUnserializableExpressionsto eval function expressions and other unserializable JSX props from trusted markdown sources.⚠️ SECURITY WARNING: STRONGLY DISCOURAGED FOR USER INPUTSThis 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
renderRuleto 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:
- Arrays and objects are parsed via
JSON.parse():data={[1, 2, 3]}→attrs.data = [1, 2, 3] - Booleans are parsed:
enabled={true}→attrs.enabled = true - Functions are kept as strings for security:
onClick={() => ...}→attrs.onClick = "() => ..." - Complex expressions are kept as strings:
value={someVar}→attrs.value = "someVar"
The original raw attribute string is preserved in the
rawAttrsfield.Benefits:
- Type-safe access to structured data without manual parsing
- Backwards compatible - check types before using
- Secure by default - functions remain as strings
Example:
// 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
renderRulefor case-by-case handling, or see the newoptions.evalUnserializableExpressionsfeature for opt-in eval (not recommended for user inputs). - Arrays and objects are parsed via
Patch Changes
-
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:
<Figure> <div>content</div> </Figure>
Parsed as 3 siblings:
<Figure>,<div>,</Figure>After:
Parsed as parent-child:
<Figure>contains<div>as a childThis 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.
v9.3.5
v9.3.4
v9.3.3
v9.3.2
v9.3.1
v9.3.0
Minor Changes
- a482de6: Add SolidJS integration with full JSX output support. Includes compiler, parser, astToJSX, and Markdown component with reactive support via signals/accessors.
- f9a8fca: Add Vue.js 3+ integration. Includes
compiler,parser,astToJSX, andMarkdowncomponent. Vue uses standard HTML attributes (class, not className) with minimal attribute mapping (only 'for' -> 'htmlFor').
Patch Changes
- 2bb3f2b: Fix AST and options mutation bugs that could cause unexpected side effects when using memoization or reusing objects across multiple compiler calls.
v9.2.0
Minor Changes
-
88d4b1f: Add comprehensive React Native support with new
/nativeexport. Includes:- React Native Component Mapping: Enhanced HTML tag to React Native component mapping with semantic support for
img→Image, block elements (div,section,article,blockquote,ul,ol,li,table, etc.) →View, and inline elements →Text - Link Handling: Native link support with
onLinkPressandonLinkLongPresscallbacks, defaulting toLinking.openURL - Styling System: Complete
NativeStyleKeytype system with styles for all markdown elements and HTML semantic tags - Component Overrides: Full support for overriding default components with custom React Native components and props
- Accessibility: Built-in accessibility support with
accessibilityLabelfor images and proper link handling - Type Safety: Comprehensive TypeScript definitions with
NativeOptionsandNativeStyleKeytypes - Performance: Optimized rendering with proper React Native best practices and component lifecycle
React Native is an optional peer dependency, making this a zero-dependency addition for existing users.
- React Native Component Mapping: Enhanced HTML tag to React Native component mapping with semantic support for