Skip to content

Conversation

@renovate
Copy link
Contributor

@renovate renovate bot commented Dec 2, 2025

This PR contains the following updates:

Package Change Age Confidence
markdown-to-jsx (source) ^7.7.6 -> ^9.5.0 age confidence

Release Notes

quantizor/markdown-to-jsx (markdown-to-jsx)

v9.5.0

Compare Source

Minor Changes
  • 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:

    • In RSC environments: Uses direct compilation without hooks for optimal server performance
    • In client environments: Uses hooks and memoization for optimal client performance
    • MarkdownProvider and MarkdownContext gracefully become no-ops in RSC environments
    • Maintains identical output and API in both contexts
    • Zero breaking changes for existing users

    This enables better bundle splitting and SSR performance by allowing markdown rendering to happen on the server when possible.

Patch Changes
  • 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.

v9.4.2

Compare Source

Patch Changes
  • 775b4bf: Expose parser and RuleType from the markdown entry point as documented.

v9.4.1

Compare Source

Patch Changes
  • 7ee8a22: Ensure 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.
  • 7ee8a22: HTML blocks are now always fully parsed into the AST 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.
  • 7ee8a22: Add 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.

v9.4.0

Compare Source

Minor Changes
  • c1be885: Added context providers and memoization to all major renderers for better developer experience and performance.

    React:

    • MarkdownContext - React context for default options
    • MarkdownProvider - Provider component to avoid prop-drilling
    • useMemo - 3-stage memoization (options, content, JSX)

    React Native:

    • MarkdownContext - React context for default options
    • MarkdownProvider - Provider component to avoid prop-drilling
    • useMemo - 3-stage memoization (options, content, JSX)

    Vue:

    • MarkdownOptionsKey - InjectionKey for provide/inject pattern
    • MarkdownProvider - Provider component using Vue's provide
    • computed - Reactive memoization for options, content, and JSX

    Benefits:

    1. Avoid prop-drilling - Set options once at the top level:
    <MarkdownProvider options={commonOptions}>
      <App>
        <Markdown>...</Markdown>
        <Markdown>...</Markdown>
      </App>
    </MarkdownProvider>
    1. Performance optimization - Content is only parsed when it actually changes, not on every render
    2. 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.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:

    • 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 rawAttrs field.

    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 renderRule for case-by-case handling, or see the new options.evalUnserializableExpressions feature for opt-in eval (not recommended for user inputs).

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 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.

v9.3.5

Compare Source

Patch Changes
  • 08dfe8a: Fix regression: Tables within list items are now properly parsed.

v9.3.4

Compare Source

Patch Changes
  • c5b6259: Fixed URIError when parsing HTML attributes containing the % character (e.g., width="100%"). The parser now gracefully handles invalid URI encodings in attribute values instead of throwing an error.

v9.3.3

Compare Source

Patch Changes
  • 7ac3408: Restore angle-bracket autolinks when raw HTML parsing is disabled so <https://...> still renders as links
  • 7ac3408: Improve autolink parsing: stricter angle controls, domain underscore validation, and added coverage for mailto labels and raw-HTML-disabled cases.

v9.3.2

Compare Source

Patch Changes
  • a84c300: Ensure Solid renderer uses Solid's hyperscript runtime so JSX returns real elements instead of [object Object] placeholders

v9.3.1

Compare Source

Patch Changes
  • c1b0ea2: Fix unintended node-specific code from entering browser bundles by changing build target from 'node' to 'browser'

v9.3.0

Compare Source

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, and Markdown component. 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

Compare Source

Minor Changes
  • 88d4b1f: Add comprehensive React Native support with new /native export. Includes:

    • React Native Component Mapping: Enhanced HTML tag to React Native component mapping with semantic support for imgImage, block elements (div, section, article, blockquote, ul, ol, li, table, etc.) → View, and inline elements → Text
    • Link Handling: Native link support with onLinkPress and onLinkLongPress callbacks, defaulting to Linking.openURL
    • Styling System: Complete NativeStyleKey type 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 accessibilityLabel for images and proper link handling
    • Type Safety: Comprehensive TypeScript definitions with NativeOptions and NativeStyleKey types
    • 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.

v9.1.2

Compare Source

Patch Changes
  • 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.

v9.1.1

Compare Source

Patch Changes
  • 733f10e: Fix lazy continuation lines for list items when continuation text appears at base indentation without a blank line. Previously, continuation text was incorrectly appended inline to the list item. Now both the existing inline content and the continuation text are properly wrapped in separate paragraphs.

v9.1.0

Compare Source

Minor Changes
  • 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
Patch Changes
  • f945132: Fix lazy continuation lines for list items when continuation text appears at base indentation without a blank line before it. Previously, such lines were incorrectly parsed as separate paragraphs instead of being appended to the list item content.
  • 36ef089: yWork around a bundling bug with exporting TypeScript namespaces directly. Bonus: MarkdownToJSX is now declared ambiently so you may not need to import it.

v9.0.0

Compare Source

Major Changes
  • 1ce83eb: Complete GFM+CommonMark specification compliance

    • Full CommonMark compliance: All 652 official test cases now pass
    • Verified GFM extensions: Tables, task lists, strikethrough, autolinks with spec compliance
    • Tag filtering: Default filtering of dangerous HTML tags (<script>, <iframe>, etc.) in both HTML string output and React JSX output
    • URL sanitization: Protection against javascript:, vbscript:, and malicious data: URLs

    Default filtering of dangerous HTML tags:

    • <script>, <iframe>, <object>, <embed>
    • <title>, <textarea>, <style>, <xmp>
    • <plaintext>, <noembed>, <noframes>

v8.0.0

Compare Source

Major Changes
  • 450d2bb: Added ast option to compiler to expose the parsed AST directly. When ast: true, the compiler returns the AST structure (ASTNode[]) instead of rendered JSX.

    Breaking Changes:

    • The internal type ParserResult has been renamed to ASTNode for clarity. If you were accessing this type directly (e.g., via module augmentation or type manipulation), you'll need to update references from MarkdownToJSX.ParserResult to MarkdownToJSX.ASTNode.

    First time the AST is accessible to users! This enables:

    • AST manipulation and transformation before rendering
    • Custom rendering logic without parsing
    • Caching parsed AST for performance
    • Linting or validation of markdown structure

    Usage:

    import { compiler } from 'markdown-to-jsx'
    import type { MarkdownToJSX } from 'markdown-to-jsx'
    
    // Get the AST structure
    const ast: MarkdownToJSX.ASTNode[] = compiler('# Hello world', {
      ast: true,
    })
    
    // Inspect/modify AST
    console.log(ast) // Array of parsed nodes
    
    // Render AST to JSX using createRenderer (not implemented yet)

    The AST format is MarkdownToJSX.ASTNode[]. When footnotes are present, the returned value will be an object with ast and footnotes properties instead of just the AST array.

  • 3fa0c22: Refactored inline formatting parsing to eliminate ReDoS vulnerabilities and improve performance. The previous regex-based approach was susceptible to exponential backtracking on certain inputs and had several edge case bugs with nested formatting, escaped characters, and formatting inside links. The new implementation uses a custom iterative scanner that runs in O(n) time and is immune to ReDoS attacks.

    This also consolidates multiple formatting rule types into a single unified rule with boolean flags, reducing code duplication and bundle size. Performance has improved measurably on simple markdown strings:

    Breaking Changes:

    The following RuleType enum values have been removed and consolidated into a single RuleType.textFormatted:

    • RuleType.textBolded
    • RuleType.textEmphasized
    • RuleType.textMarked
    • RuleType.textStrikethroughed

    If you're using these rule types directly (e.g., for custom AST processing or overrides), you'll need to update your code to check for RuleType.textFormatted instead and inspect the node's boolean flags (bold, italic, marked, strikethrough) to determine which formatting is applied.

Minor Changes
  • a421067: fix: overhaul HTML block parsing to eliminate exponential backtracking

    Replaced the complex nested regex HTML_BLOCK_ELEMENT_R with an efficient iterative depth-counting algorithm that maintains O(n) complexity. The new implementation uses stateful regex matching with lastIndex to avoid exponential backtracking on nested HTML elements while preserving all existing functionality.

    Performance improvements:

    • Eliminates O(2^n) worst-case exponential backtracking
    • Linear O(n) time complexity regardless of nesting depth
Patch Changes
  • e6b1e14: Fix renderer crash on extremely deeply nested markdown content

    Previously, rendering markdown with extremely deeply nested content (e.g., thousands of nested bold markers like ****************...text...****************) would cause a stack overflow crash. The renderer now gracefully handles such edge cases by falling back to plain text rendering instead of crashing.

    Technical details:

    • Added render depth tracking to prevent stack overflow
    • Graceful fallback at 2500 levels of nesting (way beyond normal usage)
    • Try/catch safety net as additional protection for unexpected errors
    • Zero performance impact during normal operation
    • Prevents crashes while maintaining O(n) parsing complexity

    This fix ensures stability even with adversarial or malformed inputs while having no impact on normal markdown documents.

  • fe95c02: Remove unnecessary wrapper when footnotes are present.

v7.7.17

Compare Source

Patch Changes
  • acc11ad: Fix null children crashing app in production

    When null is passed as children to the <Markdown> component, it would previously crash the app in production. This fix handles this case by converting it to empty string.

Usage Example

Before this fix, the following code would crash in production:

<Markdown>{null}</Markdown>

After this fix, this case is handled gracefully and renders nothing.

v7.7.16

Compare Source

Patch Changes
  • 7e487bd: Fix the issue where YAML frontmatter in code blocks doesn't render properly.

    This is done by lowering the parsing priority of Setext headings to match ATX headings; both are now prioritized lower than code blocks.

v7.7.15

Compare Source

Patch Changes
  • 8e4c270: Mark react as an optional peer dependency as when passing createElement, you don't need React

v7.7.14

Compare Source

Patch Changes
  • 73d4398: Cut down on unnecessary matching operations by improving qualifiers. Also improved the matching speed of paragraphs, which led to a roughly 2x boost in throughput for larger input strings.

v7.7.13

Compare Source

Patch Changes
  • da003e4: Fix exponential backtracking issue for unpaired inline delimiter sequences.

v7.7.12

Compare Source

Patch Changes
  • 4351ef5: Adjust text parsing to not split on double spaces unless followed by a newline.
  • 4351ef5: Special case detection of :shortcode: so the text processor doesn't break it into chunks, enables shortcode replacement via renderRule.

v7.7.11

Compare Source

Patch Changes
  • 4a692dc: Fixes the issue where link text containing multiple nested brackets is not parsed correctly.

    Before: [title[bracket1][bracket2]](url) fails to parse as a link
    After: [title[bracket1][bracket2]](url) correctly parses as a link

v7.7.10

Compare Source

Patch Changes
  • bf9dd3d: Unescape content intended for JSX attributes.

v7.7.9

Compare Source

Patch Changes
  • 95dda3e: Avoid creating unnecessary paragraphs inside of HTML.
  • 95dda3e: Fix HTML parser to avoid processing the inside of <pre> blocks.

v7.7.8

Compare Source

Patch Changes
  • db378c7: Implement early short-circuit for rules to avoid expensive throwaway work.
  • db378c7: Simpler fix that preserves existing performance.
  • db378c7: Various low-hanging minor performance enhancements by doing less work.
  • db378c7: Improve compression by inlining static RuleType entries when used in the codebase.

v7.7.7

Compare Source

Patch Changes
  • 89c87e5: Handle spaces in text as a stop token to improve processing, also adapt paragraph detection to exclude non-atx compliant headings if that option is enabled.

    Fixes #​680


Configuration

📅 Schedule: Branch creation - Between 12:00 AM and 03:59 AM ( * 0-3 * * * ) (UTC), Automerge - At any time (no schedule defined).

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about this update again.


  • If you want to rebase/retry this PR, check this box

This PR was generated by Mend Renovate. View the repository job log.

@renovate renovate bot added the renovatebot label Dec 2, 2025
@renovate renovate bot force-pushed the renovate/markdown-to-jsx-9.x branch 3 times, most recently from d5c8af4 to 284d4a5 Compare December 9, 2025 04:00
@renovate renovate bot force-pushed the renovate/markdown-to-jsx-9.x branch 4 times, most recently from da64168 to 148a112 Compare December 17, 2025 06:02
@renovate renovate bot force-pushed the renovate/markdown-to-jsx-9.x branch from 148a112 to ab67280 Compare December 21, 2025 04:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant