Markdown增强(echarts等插件)

前言

在markdown 语法中我们可以实现标题、表格、图片等功能的实现,但同样有一些定制化的表现形式难以在markdown中实现,最近就遇到一个需求要在markdown渲染器中展示图表,搜阅了很多文档并没有找到现成的实现方法,最终在react-mardown官方文档中受到启发并实现了这个需求。

react-markdown

react-markdown 是React生态中的一个三方库,主要功能是渲染markdown语法的文本为markdown的预览模式。 使用方法也比较简单:

tsx 复制代码
import React, { FC } from 'react';
import Markdown from 'react-markdown';
import styled from 'styled-components';
interface MDPropsType {}
/** */
export const MD: FC<MDPropsType> = (props) => {
	const markdown = `
# 前言
在markdown 语法中我们可以实现标题、表格、图片等功能的实现,但同样有一些定制化的表现形式难以在markdown中实现,最近就遇到一个需求要在markdown渲染器中展示图表,搜阅了很多文档并没有找到现成的实现方法,最终在[react-mardown官方文档](https://github.com/remarkjs/react-markdown)中受到启发并实现了这个需求。

## react-markdown
react-markdown 是React生态中的一个三方库,主要功能是渲染markdown语法的文本为markdown的预览模式。
使用方法也比较简单:
\`\`\`js
console.log("Hello, Word!")
\`\`\`
	`;
	return (
		<MDContain>
			<Markdown children={markdown}></Markdown>
		</MDContain>
	);
};
//style_components
const MDContain = styled.div`
	width: 100%;
	height: 100%;
`;

这里的显示结果是没有样式的,可以去引用三方的样式或者说是自己去写样式

在此处我采用的是引用github markdown的样式

这里可以看到代码块是没有样式和高亮的
react-mardown官方文档中有提到解决方案

当然,其他插件也可以使用:

按照官方文档的指引去完善代码

  1. npm i remark-gfm react-syntax-highlighter --save-dev
  2. 完善代码
tsx 复制代码
import React, { FC } from 'react';
import Markdown from 'react-markdown';
import styled from 'styled-components';
import remarkGfm from 'remark-gfm';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
interface MDPropsType {}
/** */
export const MD: FC<MDPropsType> = (props) => {
  const markdown = `
# 前言
在markdown 语法中我们可以实现标题、表格、图片等功能的实现,但同样有一些定制化的表现形式难以在markdown中实现,最近就遇到一个需求要在markdown渲染器中展示图表,搜阅了很多文档并没有找到现成的实现方法,最终在[react-mardown官方文档](https://github.com/remarkjs/react-markdown)中受到启发并实现了这个需求。

## react-markdown
react-markdown 是React生态中的一个三方库,主要功能是渲染markdown语法的文本为markdown的预览模式。
使用方法也比较简单:
\`\`\`js
console.log("Hello, Word!")
\`\`\`
	`;
  return (
    <MDContain>
      <Markdown
        children={markdown}
        remarkPlugins={[remarkGfm]}
        components={{
          code(props) {
          const { children, className, node, ...rest } = props;
          const match = /language-(\w+)/.exec(className || '');
          return match ? (
            <SyntaxHighlighter
               {...rest}
               PreTag='div'
               children={String(children).replace(/\n$/, '')}
               language={match[1]}
               style={atomDark}
             />
             ) : (
             <code {...rest} className={className}>
               {children}
             </code>
             );
           }
         }}></Markdown>
       </MDContain>
     );
};
//style_components
const MDContain = styled.div`
	width: 100%;
	height: 100%;
`;

结果是这个样子的

观察代码高亮的插件实现不难发现其中的原理

在components对象的的code方法上可以通过className去捕获对应的语,这里我们用```echarts来定义语言

而children就是代码块里面的内容,这里我们用json来保存图标数据

return 会返回如何渲染

那么我们可以写一个Echarts组件接收 option 内容去渲染图表

tsx 复制代码
import React, { FC, useEffect, useRef } from 'react';
import Markdown from 'react-markdown';
import styled from 'styled-components';
import remarkGfm from 'remark-gfm';
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter';
import { atomDark } from 'react-syntax-highlighter/dist/esm/styles/prism';
import * as echarts from 'echarts';
interface MDPropsType {}
/** */
export const MD: FC<MDPropsType> = (props) => {
  const markdown = `
# 前言
在markdown 语法中我们可以实现标题、表格、图片等功能的实现,但同样有一些定制化的表现形式难以在markdown中实现,最近就遇到一个需求要在markdown渲染器中展示图表,搜阅了很多文档并没有找到现成的实现方法,最终在[react-mardown官方文档](https://github.com/remarkjs/react-markdown)中受到启发并实现了这个需求。

## react-markdown
react-markdown 是React生态中的一个三方库,主要功能是渲染markdown语法的文本为markdown的预览模式。
使用方法也比较简单:
\`\`\`js
console.log("Hello, Word!")
\`\`\`
\`\`\`echarts
{"xAxis":{"type":"category","data":["Mon","Tue","Wed","Thu","Fri","Sat","Sun"]},"yAxis":{"type":"value"},"series":[{"data":[120,200,150,80,70,110,130],"type":"bar"}]}
\`\`\`
  `;
  return (
    <MDContain>
      <Markdown
        children={markdown}
        remarkPlugins={[remarkGfm]}
        components={{
          code(props) {
            const { children, className, node, ...rest } = props;
            const match = /language-(\w+)/.exec(className || '');
            if (!match) {
              return (
                <code {...rest} className={className}>
                  {children}
                </code>
              );
            }
            if (match[1] === 'echarts') {
              return <ChartsRende option={JSON.parse(children)}></ChartsRende>;
            }
            return (
              <SyntaxHighlighter
                {...rest}
                PreTag='div'
                children={String(children).replace(/\n$/, '')}
                language={match[1]}
                style={atomDark}
              />
            );
          }
        }}></Markdown>
    </MDContain>
  );
};
//style_components
const MDContain = styled.div`
  width: 100%;
  height: 100%;
`;
const ChartsRende: React.FC<{ option: echarts.EChartsOption }> = ({ option }) => {
  const chartRef = useRef<echarts.ECharts>();
  const domRef = useRef<HTMLElement>();
  useEffect(() => {
    chartRef.current = echarts.init(domRef.current);
    chartRef.current.setOption(option);
  }, [option]);

  return <div ref={domRef} style={{ height: 300 }} className='chart_contain'></div>;
};

这样就得出了在markdown中显示的Echarts

相关推荐
腾讯TNTWeb前端团队3 小时前
helux v5 发布了,像pinia一样优雅地管理你的react状态吧
前端·javascript·react.js
范文杰6 小时前
AI 时代如何更高效开发前端组件?21st.dev 给了一种答案
前端·ai编程
拉不动的猪7 小时前
刷刷题50(常见的js数据通信与渲染问题)
前端·javascript·面试
拉不动的猪7 小时前
JS多线程Webworks中的几种实战场景演示
前端·javascript·面试
FreeCultureBoy7 小时前
macOS 命令行 原生挂载 webdav 方法
前端
uhakadotcom8 小时前
Astro 框架:快速构建内容驱动型网站的利器
前端·javascript·面试
uhakadotcom8 小时前
了解Nest.js和Next.js:如何选择合适的框架
前端·javascript·面试
uhakadotcom8 小时前
React与Next.js:基础知识及应用场景
前端·面试·github
uhakadotcom8 小时前
Remix 框架:性能与易用性的完美结合
前端·javascript·面试
uhakadotcom8 小时前
Node.js 包管理器:npm vs pnpm
前端·javascript·面试