uiwjs / react-md-editor

A simple markdown editor with preview, implemented with React.js and TypeScript.
https://uiwjs.github.io/react-md-editor
MIT License
2.17k stars 157 forks source link

Custom markdown tags #454

Open asimaranov opened 1 year ago

asimaranov commented 1 year ago

Hello there. Are there ways to add custom markdown tags? For example I want to make text between $ signs to be rendered with my style. So $text$ in markdown should become <mytag>text</mytag> in the result html

jaywcjlove commented 1 year ago

https://github.com/uiwjs/react-md-editor/blob/f04dde8a050a8636163a028c995ae0f68be8b23b/core/src/Editor.tsx#L75-L78

@asimaranov This is possible. You need previewOptions to write a rehype plugin or use rehype-rewrite

<MDEditor 
  previewOptions={{
    remarkPlugins: [],
    rehypePlugins: []
  }}
/>
asimaranov commented 1 year ago

Thanks, but I have problems with tags inside my new tag. I wrote the following retype plugin

const merge = (str: string) => {
  return str.replace(/\$([^$]*)\$/g, function(string, first){
    return "█".repeat(first.length);
  })
};

const rewrite = (node: any, index: any, parent: any) => {
  console.log(node)
  if (node.type === "text") {
    node.value = merge(node.value);
  }
};

It works as expected for simple text

image

But if there'are inner tags, it fails

image

How can I fix it?

jaywcjlove commented 1 year ago

@asimaranov like this? https://codesandbox.io/embed/markdown-editor-for-react-uiwjs-react-md-editor-issues-454-5wb792?fontsize=14&hidenavigation=1&theme=dark

image

import React from "react";
import ReactDOM from "react-dom";
import MDEditor from "@uiw/react-md-editor";
import rehypeRewrite, { getCodeString } from "rehype-rewrite";
// No import is required in the WebPack.
// import "@uiw/react-md-editor/dist/markdown-editor.css";

const mkdStr = `
Markdown Editor

Editor $good$ 

Editor $good \`google\` $
`;

const REG = /\$(.*?)\$/gi;

function App() {
  const [value, setValue] = React.useState(mkdStr);
  return (
    <div className="container">
      <h3>Auto</h3>
      <MDEditor
        height={200}
        previewOptions={{
          rehypePlugins: [
            [
              rehypeRewrite,
              {
                rewrite: (node, index, parent) => {
                  if (node.type === "element" && node.tagName === "p") {
                    let text = getCodeString(node.children);
                    if (REG.test(text)) {
                      text = text.replace(REG, (txt) => {
                        return "█".repeat(txt.length);
                      });
                      node.children = [
                        {
                          type: "text",
                          value: text
                        }
                      ];
                    }
                  }
                }
              }
            ]
          ]
        }}
        value={value}
        onChange={setValue}
      />
    </div>
  );
}
asimaranov commented 1 year ago

Wow, thanks, you're my hero

jstiburek commented 1 year ago

@jaywcjlove

Hello, I have kinda similar use case.

Is there way to catch a char in actual writing with rehypeRewrite ? I want to detect when user write @ and show him options to select users to tag. Then replace text behing @ with selected option.

Thank you