react-markdown
是一款 github
上开源的适用于 react
的 markdown
组件,可以基本实现 markdown
的功能,且可以根据自己实际应用定制的 remark
组件。
安装
安装 markdown
预览插件 react-markdown
npm install react-markdown
或者:
yarn add react-markdown
安装 markdown
编辑器插件 for-editor
yarn add for-editor
或者:
npm install for-editor
安装代码高亮插件包 react-syntax-highlighter
npm install react-syntax-highlighter
或者:
yarn add react-syntax-highlighter
安装 remark-math
npm install remark-math
或者:
yarn add remark-math
安装 rehype-katex
npm install rehype-katex
或者:
yarn add rehype-katex
安装 rehype-raw
npm install rehype-raw
或者:
yarn add rehype-raw
组件依赖
组件涉及的依赖及版本 package.json
:
{
"dependencies": {
"antd": "^4.16.10",
"less": "^4.1.1",
"less-loader": "4.0.1",
"react": "^17.0.2",
"react-dom": "^17.0.2",
"react-router-dom": "^5.2.0",
"for-editor": "^0.3.5", // Markdown编辑
"react-markdown": "^8.0.7", // Markdown预览
"rehype-katex": "^6.0.2", // 数学公式katex语法
"rehype-raw": "^6.1.1", // 支持HTML语法解析
"remark-math": "^5.1.1", // 支持数学公式
"react-scripts": "4.0.3",
"typescript": "^5.0.4",
}
}
for-editor
:markdown
编辑器react-markdown
:markdown
内容预览及展示rehype-raw
:解析HTML
文本富文本内容remark-math、rehype-katex
:数学公式支持及语法解析使用(数学公式的样式展示需要katex.min.css
文件支持)
基本使用
编辑器 for-editor
属性
名称 | 类型 | 默认值 | 描述 |
---|---|---|---|
value | String | - | 输入框内容 |
placeholder | String | 开始编辑… | 占位文本 |
lineNum | Boolean | true | 是否显示行号 |
style | Object | - | 编辑器样式 |
height | String | 600px | 编辑器高度 |
preview | Boolean | false | 预览模式 |
expand | Boolean | false | 全屏模式 |
subfield | Boolean | false | 双栏模式(预览模式激活下有效) |
language | String | zh-CN | 语言(支持 zh-CN:中文简体, en:英文) |
toolbar | Object | 如下 | 自定义工具栏 |
/*
默认工具栏按钮全部开启, 传入自定义对象
例如: {
h1: true, // h1
code: true, // 代码块
preview: true, // 预览
}
此时, 仅仅显示此三个功能键
注:传入空对象则不显示工具栏
*/
toolbar: {
h1: true, // h1
h2: true, // h2
h3: true, // h3
h4: true, // h4
img: true, // 图片
link: true, // 链接
code: true, // 代码块
preview: true, // 预览
expand: true, // 全屏
/* v0.0.9 */
undo: true, // 撤销
redo: true, // 重做
save: true, // 保存
/* v0.2.3 */
subfield: true, // 单双栏模式
}
事件
名称 | 参数 | 类型 | 默认值 | 描述 |
---|---|---|---|---|
onChange | String: value | function(e) | - | 内容改变时回调 |
onSave | String: value | function(e) | - | 保存时回调 |
addImg | File: file | function(e) | - | 添加图片时回调 |
快捷键
名称 | 描述 |
---|---|
tab | 两个空格缩进 |
ctrl+s | 保存 |
ctrl+z | 上一步 |
ctrl+y | 下一步 |
在 views/md-editor/
文件夹下面新建 MdEditor.js
文件:
import React, { useState } from "react"
import MdEditor from 'for-editor'
const DemoEditor = () => {
/** 默认工具栏按钮全部开启, 传入自定义对象
例如: {
h1: true, // h1
code: true, // 代码块
preview: true, // 预览
}
此时, 工具栏只显示此三个功能键(注:传入空对象则不显示工具栏)
*/
// 工具栏菜单
const toolbar = {
h1: true, // h1
h2: true, // h2
h3: true, // h3
h4: true, // h4
img: true, // 图片
link: true, // 链接
code: true, // 代码块
preview: true, // 预览
expand: true, // 全屏
/* v0.0.9 */
undo: true, // 撤销
redo: true, // 重做
save: true, // 保存
/* v0.2.3 */
subfield: true, // 单双栏模式
};
// 保存Markdown文本内容
const [mdContent, setMdContent] = useState('')
// 上传图片
function uploadImg (file) {
console.log('file', file);
};
// 输入内容改变
function handleEditorChange (value) {
console.log('handleChange', value);
setMdContent(value)
}
// 保存输入内容
function handleEditorSave (value) {
console.log('handleEditorSave', value);
}
return (
<MdEditor placeholder="请输入Markdown文本" height={600} lineNum={false}
toolbar={toolbar} value={mdContent} onChange={handleEditorChange} onSave={handleEditorSave} addImg={uploadImg} />
)
}
export default DemoEditor
在 App.js
中引入 md-editor.js
文件:
import './assets/css/App.css';
import MdCtxEditor from './views/md-editor/MdEditor';
function App () {
return (
<div className="App">
<MdCtxEditor />
</div>
);
}
export default App;
页面效果:
预览 react-markdown
在 views/md-editor/
文件夹下面新建 MdPreview.js
文件:
import React, { useEffect, useState } from "react"
import ReactMarkdown from 'react-markdown'
const DemoPage = () => {
const [docmentContent, setDocmentContent] = useState('')
const content = '# This is title 1\n\n## This is title 2\n\n### This is title 3\n\nAnd this is a paragraph\n\n**A paragraph with strong importance**\n\n*A block quote with ~strikethrough~*'
useEffect(() => {
setDocmentContent(content)
}, [])
return (
<div className="markdown-body" style={{ padding: '30px', borderRadius: '10px' }}>
<ReactMarkdown children={docmentContent} />
</div>
)
}
export default DemoPage
在 App.js
中引入 MdPreview.js
文件:
import './assets/css/App.css';
import MdCtxPreview from './views/md-editor/MdPreview';
function App () {
return (
<div className="App">
<MdCtxPreview />
</div>
);
}
export default App;
页面效果:
代码块高亮
修改 MdPreview.js
文件:
import React, { useEffect, useState } from "react"
import ReactMarkdown from 'react-markdown'
import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'
// 设置高亮样式
import { xonokai } from 'react-syntax-highlighter/dist/esm/styles/prism'
const Code = {
code ({ node, inline, className, children, ...props }) {
const match = /language-(\w+)/.exec(className || '')
return !inline && match ? (
<SyntaxHighlighter
children={String(children).replace(/\n$/, '')}
style={xonokai}
language={match[1]}
PreTag="div"
{...props}
/>
) : (
<code className={className} {...props}>
{children}
</code>
)
}
}
const DemoPage = () => {
const [docmentContent, setDocmentContent] = useState('')
const content = `This is some JavaScript code:
~~~js
console.log('Hello world!')
~~~
`
useEffect(() => {
setDocmentContent(content)
}, [])
return (
<div className="markdown-body" style={{ padding: '30px', borderRadius: '10px' }}>
<ReactMarkdown
children={docmentContent}
components={Code}
/>
</div>
)
}
export default DemoPage
页面效果:
支持 HTML
修改 MdPreview.js
文件:
import React, { useEffect, useState } from "react"
import ReactMarkdown from 'react-markdown'
import rehypeRaw from 'rehype-raw';
const DemoPage = () => {
const [docmentContent, setDocmentContent] = useState('')
const content = `<div class="note">Some *emphasis* and <strong>strong</strong>!</div>`
useEffect(() => {
setDocmentContent(content)
}, [])
return (
<div className="markdown-body" style={{ padding: '30px', borderRadius: '10px' }}>
<ReactMarkdown children={docmentContent}
rehypePlugins={[rehypeRaw]} />
</div>
)
}
export default DemoPage
页面效果:
rehype-katex
和 remark-math
展示数学公式
使用 rehype-katex
和 remark-math
可以轻松的翻译输入的数学公式。
注意:需要使用 katex.css
来展示相应的效果,否则会出现公式乱掉的 BUG
。
在 index.html
中引入公式解析样式文件:
<!-- 解析Markdown数学公式样式 -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.13.13/dist/katex.min.css" integrity="sha384-RZU/ijkSsFbcmivfdRBQDtwuwVqK7GMOw6IMvKyeWL2K5UAlyp6WonmB8m7Jd0Hn" crossorigin="anonymous">
修改 MdPreview.js
文件:
import React, { useEffect, useState } from "react"
import ReactMarkdown from 'react-markdown'
import remarkMath from 'remark-math'
import rehypeKatex from 'rehype-katex'
const DemoPage = () => {
const [docmentContent, setDocmentContent] = useState('')
const ctx = `$$
I = \int_0^{2\pi} \sin(x)\,dx
$$`
useEffect(() => {
setDocmentContent(ctx)
}, [])
return (
<div className="markdown-body" style={{ padding: '30px', borderRadius: '10px' }}>
<ReactMarkdown
children={docmentContent}
remarkPlugins={[remarkMath]}
rehypePlugins={[rehypeKatex]}
/>
</div>
)
}
export default DemoPage
页面效果:
相关链接
react-markdown github 源码
for-editor github
markdown-navbar github