Skip to content

Releases: quantizor/markdown-to-jsx

v9.4.2

17 Dec 05:52

Choose a tag to compare

Patch Changes

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

v9.4.1

17 Dec 05:19

Choose a tag to compare

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

16 Dec 15:31

Choose a tag to compare

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

12 Dec 05:26
69d08b0

Choose a tag to compare

Patch Changes

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

v9.3.4

11 Dec 03:57
b197466

Choose a tag to compare

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

09 Dec 03:34
7038496

Choose a tag to compare

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

06 Dec 01:39
2945c3a

Choose a tag to compare

Patch Changes

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

v9.3.1

06 Dec 01:09
5f7a028

Choose a tag to compare

Patch Changes

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

v9.3.0

30 Nov 07:18
7f210c7

Choose a tag to compare

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

28 Nov 07:37

Choose a tag to compare

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.