Share your code. npm Orgs help your team discover, share, and reuse code. Create a free org »

    markdown-to-jsxpublic

    Markdown Component for React, Preact + Friends

    npm version build status codecov downloads


    markdown-to-jsx uses a fork of simple-markdown as its parsing engine and extends it in a number of ways to make your life easier. Notably, this package offers the following additional benefits:

    • Arbitrary HTML is supported and parsed into the appropriate JSX representation without dangerouslySetInnerHTML

    • Any HTML tags rendered by the compiler and/or <Markdown> component can be overridden to include additional props or even a different HTML representation entirely.

    • GFM task list support.

    • Fenced code blocks with highlight.js support.

    All this clocks in at around 5 kB gzipped, which is a fraction of the size of most other React markdown components.

    Requires React >= 0.14.

    Installation

    # if you use npm 
    npm i markdown-to-jsx
     
    # if you use yarn 
    yarn add markdown-to-jsx

    Usage

    markdown-to-jsx exports a React component by default for easy JSX composition:

    ES6-style usage*:

    import Markdown from 'markdown-to-jsx';
    import React from 'react';
    import {render} from 'react-dom';
     
    render((
        <Markdown>
            # Hello world!
        </Markdown>
    ), document.body);
     
    /*
        renders:
     
        <h1>Hello world!</h1>
     */

    * NOTE: JSX does not natively preserve newlines in multiline text. In general, writing markdown directly in JSX is discouraged and it's a better idea to keep your content in separate .md files and require them, perhaps using webpack's raw-loader.

    Parsing Options

    options.forceBlock

    By default, the compiler will try to make an intelligent guess about the content passed and wrap it in a <div>, <p>, or <span> as needed to satisfy the "inline"-ness of the markdown. For instance, this string would be considered "inline":

    Hello. _Beautiful_ day isn't it?

    But this string would be considered "block" due to the existence of a header tag, which is a block-level HTML element:

    # Whaddup?

    However, if you really want all input strings to be treated as "block" layout, simply pass options.forceBlock = true like this:

    <Markdown options={{ forceBlock: true }}>
        Hello there old chap!
    </Markdown>
     
    // or
     
    compiler('Hello there old chap!', { forceBlock: true });
     
    // renders
     
    <p>Hello there old chap!</p>

    options.forceInline

    The inverse is also available by passing options.forceInline = true:

    <Markdown options={{ forceInline: true }}>
        # You got it babe!
    </Markdown>
     
    // or
     
    compiler('# You got it babe!', { forceInline: true });
     
    // renders
     
    <span># You got it babe!</span>

    options.overrides - Override Any HTML Tag's Representation

    Pass the options.overrides prop to the compiler or <Markdown> component to seamlessly revise the rendered representation of any HTML tag. You can choose to change the component itself, add/change props, or both.

    import Markdown from 'markdown-to-jsx';
    import React from 'react';
    import {render} from 'react-dom';
     
    // surprise, it's a div instead!
    const MyParagraph = ({children, ...props}) => (<div {...props}>{children}</div>);
     
    render((
        <Markdown
            options={{
                overrides: {
                    h1: {
                        component: MyParagraph,
                        props: {
                            className: 'foo',
                        },
                    },
                },
            }}>
            # Hello world!
        </Markdown>
    ), document.body);
     
    /*
        renders:
     
        <div class="foo">
            Hello World
        </div>
     */

    If you only wish to provide a component override, a simplified syntax is available:

    {
        overrides: {
            h1: MyParagraph,
        },
    }

    Depending on the type of element, there are some props that must be preserved to ensure the markdown is converted as intended. They are:

    • a: title, href
    • img: title, alt, src
    • input[type="checkbox"]: checked, readonly (specifically, the one rendered by a GFM task list)
    • ol: start
    • td: style
    • th: style

    Any conflicts between passed props and the specific properties above will be resolved in favor of markdown-to-jsx's code.

    options.overrides - Rendering Arbitrary React Components

    One of the most interesting use cases enabled by the HTML syntax processing in markdown-to-jsx is the ability to use any kind of element, even ones that aren't real HTML tags like React component classes.

    By adding an override for the components you plan to use in markdown documents, it's possible to dynamically render almost anything. One possible scenario could be writing documentation:

    import Markdown from 'markdown-to-jsx';
    import React from 'react';
    import {render} from 'react-dom';
     
    import DatePicker from './date-picker';
     
    const md = `
    # DatePicker
     
    The DatePicker works by supplying a date to bias towards,
    as well as a default timezone.
     
    <DatePicker biasTowardDateTime="2017-12-05T07:39:36.091Z" timezone="UTC+5" />
    `;
     
    render((
        <Markdown
            children={md}
            options={{
                overrides: {
                    DatePicker: {
                        component: DatePicker,
                    },
                },
            }} />
    ), document.body);

    markdown-to-jsx also handles JSX interpolation syntax, but in a minimal way to not introduce a potential attack vector. Interpolations are sent to the component as their raw string, which the consumer can then eval() or process as desired to their security needs.

    In the following case, DatePicker could simply run parseInt() on the passed startTime for example:

    import Markdown from 'markdown-to-jsx';
    import React from 'react';
    import {render} from 'react-dom';
     
    import DatePicker from './date-picker';
     
    const md = `
    # DatePicker
     
    The DatePicker works by supplying a date to bias towards,
    as well as a default timezone.
     
    <DatePicker
      biasTowardDateTime="2017-12-05T07:39:36.091Z"
      timezone="UTC+5"
      startTime={1514579720511}
    />
    `;
     
    render((
        <Markdown
            children={md}
            options={{
                overrides: {
                    DatePicker: {
                        component: DatePicker,
                    },
                },
            }} />
    ), document.body);

    Another possibility is to use something like recompose's withProps() HOC to create various pregenerated scenarios and then reference them by name in the markdown:

    import Markdown from 'markdown-to-jsx';
    import React from 'react';
    import {render} from 'react-dom';
    import withProps from 'recompose/withProps';
     
    import DatePicker from './date-picker';
     
    const DecemberDatePicker = withProps({
        range: {
            start: new Date('2017-12-01'),
            end: new Date('2017-12-31'),
        },
        timezone: 'UTC+5',
    })(DatePicker);
     
    const md = `
    # DatePicker
     
    The DatePicker works by supplying a date to bias towards,
    as well as a default timezone.
     
    <DatePicker
      biasTowardDateTime="2017-12-05T07:39:36.091Z"
      timezone="UTC+5"
      startTime={1514579720511}
    />
     
    Here's an example of a DatePicker pre-set to only the month of December:
     
    <DecemberDatePicker />
    `;
     
    render((
        <Markdown
            children={md}
            options={{
                overrides: {
                    DatePicker,
                    DecemberDatePicker,
                },
            }} />
    ), document.body);

    options.createElement - Custom React.createElement behavior

    Sometimes, you might want to override the React.createElement default behavior to hook into the rendering process before the JSX gets rendered. This might be useful to add extra children or modify some props based on runtime conditions. The function mirrors the React.createElement function, so the params are type, [props], [...children]:

    import Markdown from 'markdown-to-jsx';
    import React from 'react';
    import {render} from 'react-dom';
     
    const md = `
    # Hello world
    `;
     
    render((
        <Markdown
            children={md}
            options={{
                createElement(type, props, children) {
                    return (
                        <div className='parent'>
                            {React.createElement(type, props, children)}
                        </div>
                    );
                }
            }} />
    ), document.body);

    Getting the smallest possible bundle size

    Many development conveniences are placed behind process.env.NODE_ENV !== "production" conditionals. When bundling your app, it's a good idea to replace these code snippets such that a minifier (like uglify) can sweep them away and leave a smaller overall bundle.

    Here are instructions for some of the popular bundlers:

    Usage with Preact

    Everything will work just fine! Simply Alias react to preact-compat like you probably already are doing.

    Using The Compiler Directly

    If desired, the compiler function is a "named" export on the markdown-to-jsx module:

    import {compiler} from 'markdown-to-jsx';
    import React from 'react';
    import {render} from 'react-dom';
     
    render(compiler('# Hello world!'), document.body);
     
    /*
        renders:
     
        <h1>Hello world!</h1>
     */

    It accepts the following arguments:

    compiler(markdown: string, options: object?)

    Changelog

    See Github Releases.

    MIT

    install

    npm i markdown-to-jsx

    Downloadsweekly downloads

    45,516

    version

    6.6.5

    license

    MIT

    repository

    githubgithub

    last publish

    collaborators

    • avatar