md-editor-rt是前段时间学习vue3时开发的一个vue3版本编辑器md-editor-v3的同系列项目,它是react版本的,因为vue3版本的也是使用tsx
完成的,所以react版本的代码相差不大。
作者的博客前端内容是使用
nextjs
开发的,而内容管理又是使用vue
开发的,提取编辑文章和内容渲染的功能形成了这个项目。
1. 预览
1.1 功能预览
- 快捷插入内容工具栏、编辑器浏览器全屏、页面内全屏等;
- 内置的白色主题和暗黑主题,支持绑定切换;
- 支持快捷键插入内容;
- 支持使用 prettier 格式化内容(使用 CDN 方式引入,只支持格式化 md 内容,可在代码内设置关闭);
- 支持多语言,支持自行扩展语言;
- 支持复制粘贴上传图片,图片裁剪上传;
- 支持渲染模式(不显示编辑器,只显示 md 预览内容,无额外监听);
- 支持
ssr
,支持在nextjs
中使用;
1.2 在线预览
文档与在线预览:传送门
1.3 图片预览
默认模式
暗黑模式
2. 基本使用
react版本目前没有导出umd
版本。
2.1 常规单页应用
import React, { useState } from 'react';
import Editor from 'md-editor-rt';
import './index.less';
export default () => {
const [md, setMd] = useState('');
return <Editor theme="dark" modelValue={md} onChange={(v) => setMd(v)} />;
};
2.2 服务端渲染
服务端渲染的情况一般是提供markdown
文本渲染内容而非加载整个编辑器,下面的例子即是使用仅预览模式的情况。
import React, { useState } from 'react';
import Editor from 'md-editor-rt';
import './index.less';
export default () => {
const [md] = useState('# title');
// 仅预览模式只需提供md文本而不会改变文本
return <Editor editorId="article-content" theme="dark" modelValue={md} previewOnly />;
};
从写法来讲,没有区别,值得注意的是,服务端渲染时最好提供editorId
属性,由于默认情况下编辑器会随机生成editorId
,所以会造成服务端的html
内容和客户端渲染的html
内容不一致而提示错误(该问题在nextjs基础环境中可以重现)。
2.3 标题导航实现
react版本最初就提供了onGetCatalog
属性,在编辑器每一次render
后会调用该方法,将markdown内容中的标题作为列表传递回来,结构如下:
interface HeadList {
text: string;
level: 1 | 2 | 3 | 4 | 5 | 6;
}
// eg
const [heads, setHeads] = useState<HeadList>([{ text: '预览', level: '2' }]);
在作者的博客开源blog-template-nextjs中,已经基于antd封装了导航菜单,使用相当简单:
import Topicfy from '@/Topicfy';
// 将`onGetCatalog`取得的标题列表直接赋值到`Topicfy`组件即可
<Topicfy heads={heads} />
3. 编辑器的功能演示
3.1 扩展库链接
编辑器扩展内容大多使用了cdn
,考虑了无外网情况,支持了内网链接扩展,演示(假设外部库都在根目录下):
import React, { useState } from 'react';
import MdEditor from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';
export default () => {
const [text] = useState('');
return (
<MdEditor
modelValue={text}
highlightJs="/highlight.min.js"
highlightCss="/atom-one-dark.min.css"
prettierCDN="/standalone.js"
prettierMDCDN="/parser-markdown.js"
cropperJs="/cropper.min.js"
cropperCss="/cropper.min.css"
iconfontJs="/iconfont.js"
/>
);
};
3.2 工具栏自定义
默认的全部工具栏,并且每个功能都绑定了快捷键,如果需要选择性显示工具栏,提供了两个api:toolbars
和toolbarsExclude
,前者显示数组中的全部,后者屏蔽数组中的全部,后者的权重更大。下面是个参考:
案例不显示github
按钮
import React, { useState } from 'react';
import MdEditor from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';
export default () => {
const [data] = useState({
text: '',
toobars: [
'bold',
'underline',
'italic',
'strikeThrough',
'sub',
'sup',
'quote',
'unorderedList',
'orderedList',
'codeRow',
'code',
'link',
'image',
'table',
'revoke',
'next',
'save',
'pageFullscreen',
'fullscreen',
'preview',
'htmlPreview'
],
toolbarsExclude: ['github']
});
return (
<>
<MdEditor modelValue={data.text} toolbars={data.toobars} />
<MdEditor modelValue={data.text} toolbarsExclude={data.toolbarsExclude} />
</>
);
};
3.3 扩展语言
编辑器默认内置了中文和英文,并且两者都可以通过扩展api覆盖,该功能主要用来设置内容提示,比如弹窗中的标题等。
扩展一门语言,我们取名为zh-NB
import React, { useState } from 'react';
import MdEditor, { StaticTextDefaultValue } from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';
const languageUserDefined: { 'zh-NB': StaticTextDefaultValue } = {
'zh-NB': {
toolbarTips: {
bold: '加粗',
underline: '下划线',
italic: '斜体',
strikeThrough: '删除线',
title: '标题',
sub: '下标',
sup: '上标',
quote: '引用',
unorderedList: '无序列表',
orderedList: '有序列表',
codeRow: '行内代码',
code: '块级代码',
link: '链接',
image: '图片',
table: '表格',
revoke: '后退',
next: '前进',
save: '保存',
prettier: '美化',
pageFullscreen: '浏览器全屏',
fullscreen: '屏幕全屏',
preview: '预览',
htmlPreview: 'html代码预览',
github: '源码地址'
},
titleItem: {
h1: '一级标题',
h2: '二级标题',
h3: '三级标题',
h4: '四级标题',
h5: '五级标题',
h6: '六级标题'
},
linkModalTips: {
title: '添加',
descLable: '链接描述:',
descLablePlaceHolder: '请输入描述...',
urlLable: '链接地址:',
UrlLablePlaceHolder: '请输入链接...',
buttonOK: '确定',
buttonUpload: '上传'
},
clipModalTips: {
title: '裁剪图片上传',
buttonUpload: '上传'
},
copyCode: {
text: '复制代码',
tips: '已复制'
}
}
};
export default () => {
const [data] = useState({
text: '',
language: 'zh-NB',
languageUserDefined
});
return (
<MdEditor
modelValue={data.text}
language={data.language}
languageUserDefined={data.languageUserDefined}
/>
);
};
如果key = 'zh-CN',就可以实现中文覆盖,以此类推。
3.4 主题切换
这一块相对比较简单了,内置了暗黑主题和默认主题,通过theme
api切换,demo如下:
import React, { useState } from 'react';
import MdEditor from 'md-editor-rt';
import 'md-editor-rt/lib/style.css';
export default () => {
const [data] = useState({
text: '',
theme: 'dark'
});
return <MdEditor modelValue={data.text} theme={data.theme} />;
};
结尾
更多的更新请关注:md-editor-rt