4

Problem

Using React-Markdown I can fully use my custom built components. But this is with specific pre-built keywords in the markdown. Like paragraph or images. That works PERFECTLY. But the problem is that these seem to all be pre-built words/conditions like paragraphs, headers, or images.

I can't find a way to add something new key word in my markdown like "CustomComponent" to be used. That's all I need at this point ><

This works just fine for me to make the markdown's image into a custom "footer" component I made elsewhere. I know it's ridiculous but it works. But I have no idea how to make this renderer accept/create a new keyword like "emoji" or "customComponent" or "somethingSilly".

let body = 
    `![Fullstack React](https://dzxbosgk90qga.cloudfront.net/fit-in/504x658/n/20190131015240478_fullstack-react-cover-medium%402x.png)`;

const renderers = {
    image: () => <Footer/>
};

<ReactMarkdown source={body} renderers={renderers} />;

Some past work I did:

Some documentation: https://reposhub.com/react/miscellaneous/rexxars-react-markdown.html https://github.com/rexxars/commonmark-react-renderer/blob/master/src/commonmark-react-renderer.js#L50

Examples: https://codesandbox.io/s/react-markdown-with-custom-renderers-961l3?from-embed=&file=/src/App.js

But nothing indicates how I can use "CustomComponent" to indicate to inject a custom component.

Use Case / Background

I'm trying to retrieve an article from my database that is formatted like so in markdown (basically a giant string). I'm using regular react with typescript and redux-- this is the only portion of my application that needs this.

"
# Title

## Here is a subtitle

Some text

<CustomComponentIMade/>

Even more text after.


<CustomComponentIMade/>

"

1 Answer 1

7

I know its most likely a little late for your purposes, but I've managed to solve this issue using a custom remark component.

Essentially you'll need to use the remark-directive plugin as well as a small custom remark plugin (I got this plugin straight from the remark-directive docs)

Then in react markdown you can specify the plugins, custom renderers and custom tags for eg.

import React from 'react'
import ReactMarkdown from 'react-markdown'
import {render} from 'react-dom'
import directive from 'remark-directive'
import { MyCustomComponent } from './MyCustomComponent'
import { visit } from "unist-util-visit" 
import { h } from "hastscript/html.js"

// react markdown components list
const components = {
  image: () => <Footer/>,
  myTag: MyCustomComponent
}

// remark plugin to add a custom tag to the AST
function htmlDirectives() {
  return transform

  function transform(tree) {
    visit(tree, ['textDirective', 'leafDirective', 'containerDirective'], ondirective)
  }

  function ondirective(node) {
    var data = node.data || (node.data = {})
    var hast = h(node.name, node.attributes)

    data.hName = hast.tagname
    data.hProperties = hast.properties
  }
}

render(
  <ReactMarkdown components={components} remarkPlugins={[directive, htmlDirectives]}>
    Some markdown with a :myTag[custom directive]{title="My custom tag"}
  </ReactMarkdown>,
  document.body
)

So in your markdown wherever you have something like :myTag[...]{...attributes} you should render the MyCustomComponent with attributes as props.

Sorry I haven't tested the code, but hopefully it communicates the gist of things, if you need a working example let me know and I'll do my best to set one up.

Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, this was very helpful! Two imports you missed: import { visit } from "unist-util-visit" import { h } from "hastscript/html.js"
Also hast.tagName is converted to lowercase. I ended up using node.name instead.
could you create an example code on codesandbox? I can't make it work
changing data.hName to equal node.name works

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.