Skip to content

Releases: quantizor/markdown-to-jsx

v8.0.0

26 Oct 06:15
d4108e7

Choose a tag to compare

+--------------------------+------------------------+-----------------------+
|                          │ simple markdown string │ large markdown string |
+--------------------------+------------------------+-----------------------+
| markdown-to-jsx (next)   │ 116,892 ops/sec        │ 757 ops/sec           |
+--------------------------+------------------------+-----------------------+
| markdown-to-jsx (7.7.16) │ 110,756 ops/sec        │ 739 ops/sec           |
+--------------------------+------------------------+-----------------------+

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

  • 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

24 Oct 03:49
f71b888

Choose a tag to compare

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

19 Oct 02:58
5bd6874

Choose a tag to compare

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

07 Oct 13:33
7bdf47f

Choose a tag to compare

Patch Changes

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

v7.7.14

06 Oct 07:15
1deba58

Choose a tag to compare

+--------------------------+------------------------+-----------------------+
|                          │ simple markdown string │ large markdown string |
+--------------------------+------------------------+-----------------------+
| markdown-to-jsx (next)   │ 107,013 ops/sec        │ 709 ops/sec           |
+--------------------------+------------------------+-----------------------+
| markdown-to-jsx (7.7.13) │ 102,934 ops/sec        │ 396 ops/sec           |
+--------------------------+------------------------+-----------------------+

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

06 Aug 03:54
3b5820f

Choose a tag to compare

Patch Changes

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

v7.7.12

18 Jul 05:37
6fe8aba

Choose a tag to compare

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

18 Jul 04:19
f91069d

Choose a tag to compare

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

28 Jun 06:56
764f342

Choose a tag to compare

Patch Changes

  • bf9dd3d: Unescape content intended for JSX attributes.

v7.7.9

28 Jun 06:26
222ef2b

Choose a tag to compare

+--------------------------+------------------------+-----------------------+
|                          │ simple markdown string │ large markdown string |
+--------------------------+------------------------+-----------------------+
| markdown-to-jsx (7.7.9)  │ 103,280 ops/sec        │ 403 ops/sec           |
+--------------------------+------------------------+-----------------------+
| markdown-to-jsx (7.7.8)  │ 101,922 ops/sec        │ 401 ops/sec           |
+--------------------------+------------------------+-----------------------+

Patch Changes

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