reactjsmarkdownsubscriptreact-markdown

Render subscript in using react-markdown


I am unable to render subscript the markdown notation (~this is subscript~but not this) using react-markdown.

There are three ways I could easily find to render a do this: remark-supersub, remark-sub-super and something like this:

components={{ 
    em: ({ node, ...props }) => { 
            if ( props.children[0] && typeof props.children[0] === 'string' && props.children[0].startsWith('^')) { 
                    return <sup>{props.children[0].substring(1)}</sup> 
                } 
            if ( props.children[0] && typeof props.children[0] === 'string' && props.children[0].startsWith('~')) { 
                    return <sub>{props.children[0].substring(1)}</sub> 
                } 
            return <i {...props} /> 
            },
}}

... none of them works for me (they either do nothing or throw an error while rendering). Any other ideas? Thanks in advance.


Solution

  • One of the packages you mentioned, remark-supersub works pretty well without much configuration.

    You should pass this plugin as a remarkPlugins prop in the Markdown component:

    import Markdown from "react-markdown";
    import supersub from "remark-supersub";
    import remarkGfm from "remark-gfm";
    import remarkMath from "remark-math";
    
    const markdown = `
    # Markdown
    
    21^st^ Century
    
    H~2~O
    
    ~this is subscript~but not this
    
    Something in ~~strikethrough~~
    `;
    
    export default function App() {
      return (
        <Markdown
          remarkPlugins={[
            [remarkGfm, { singleTilde: false }],
            remarkMath,
            supersub,
          ]}
        >
          {markdown}
        </Markdown>
      );
    }
    

    This will render your markdown like this:

    Output image.

    Edit React Markdown - Super/Sub


    Update: As seen in your comment, the issue lies with remark-gfm because this plugin will interpret by default ~text~ as strikethrough. The solution would be to pass { singleTilde: false } to remarkGfm, that way you can keep a single ~text~ as subtext instead and ~~text~~ as strikethrough.