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.03k stars 149 forks source link

How to have hashtags render as links? #628

Closed bardic closed 3 months ago

bardic commented 3 months ago

Hey all,

Trying to make a something like #tag render as a URL. Here's what I have so far

const REG = /\B(\#[a-zA-Z]+\b)(?!;)/gi;

<MDEditor 
    style={{width: "100%", height: "100%"}} 
    minHeight={500} 
    value={value} 
    onChange={(event) => {
        setValue(event || '');
    }} 
    previewOptions={{
        rehypePlugins: [
            [
            rehypeRewrite,
            {
                rewrite: (node : any, index: any, parent: any) => {
                if (node.type === "element" && node.tagName === "p") {
                    let text = getCodeString(node.children);
                    if (REG.test(text)) {
                        node.children = [
                        {
                            type: 'link',
                            url: 'https://example.com',
                            children: [{type: 'text', value: text} ]
                        }];
                    }
                }}
            },
        ]],
    }}
/>

The regex properly matches the text but instead of the node being replaced with a link, it just doesn't render anything.

Any guidance on what I may be doing wrong would be much appreciated

bardic commented 3 months ago

Codesandbox of the problem:

https://codesandbox.io/p/sandbox/uiwjs-react-md-editor-issues-366-forked-3qx3l7?file=%2Findex.js

jaywcjlove commented 3 months ago

@bardic

rewrite: (node: any, index: any, parent: any) => {
  if (node.type === "element") {
    let text = getCodeString(node.children);
    if (REG.test(text)) {
      node.tagName = "a";
      node.properties = {
        href: "https://example.com",
      };
    }
  }
},
bardic commented 2 months ago

For completeness sake, here's what I've settled with after some tweaking

rehypeRewrite,
{
  rewrite: (node: any, index: any, parent: any) => {
    if (node.type === "element" && node.tagName != "a") {
      let text = getCodeString(node.children);
      let m;
      let parts: any[] = [];
      if (REG.test(text)) {
        m = text.split(" ") 

        for (let element of m) {
          if (REG.test(element)) {
            parts.push(
              {
                type: "element",
                tagName: "a",
                properties: {
                  href: "https://google.ca",
                },
                children: [{ type: "text", value: " " + element + " " }],
              })
          } else {
            parts.push(
              {
                type: 'element',
                tagName: 'span',
                properties: {},
                children: [
                  { type: 'text', value: element }
                ]
              })
          }
        }
      }
      console.log(parts)
      if (parts.length > 0) {
        node.children = parts;
      }
    }
  },
}