react版本markdown编辑器md-editor-rt,支持ssr

md-editor-rt是前段时间学习vue3时开发的一个vue3版本编辑器md-editor-v3的同系列项目,它是react版本的,因为vue3版本的也是使用tsx完成的,所以react版本的代码相差不大。

作者的 博客前端内容是使用 nextjs开发的,而内容管理又是使用 vue开发的,提取编辑文章和内容渲染的功能形成了这个项目。
1. 预览 1.1 功能预览
  1. 快捷插入内容工具栏、编辑器浏览器全屏、页面内全屏等;
  2. 内置的白色主题和暗黑主题,支持绑定切换;
  3. 支持快捷键插入内容;
  4. 支持使用 prettier 格式化内容(使用 CDN 方式引入,只支持格式化 md 内容,可在代码内设置关闭);
  5. 支持多语言,支持自行扩展语言;
  6. 支持复制粘贴上传图片,图片裁剪上传;
  7. 支持渲染模式(不显示编辑器,只显示 md 预览内容,无额外监听);
  8. 支持ssr,支持在nextjs中使用;
1.2 在线预览
文档与在线预览:传送门
1.3 图片预览
默认模式
react版本markdown编辑器md-editor-rt,支持ssr
文章图片

暗黑模式
react版本markdown编辑器md-editor-rt,支持ssr
文章图片

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 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 ; };

从写法来讲,没有区别,值得注意的是,服务端渲染时最好提供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([{ text: '预览', level: '2' }]);

在作者的博客开源blog-template-nextjs中,已经基于antd封装了导航菜单,使用相当简单:
import Topicfy from '@/Topicfy'; // 将`onGetCatalog`取得的标题列表直接赋值到`Topicfy`组件即可

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 ( ); };

3.2 工具栏自定义
默认的全部工具栏,并且每个功能都绑定了快捷键,如果需要选择性显示工具栏,提供了两个api:toolbarstoolbarsExclude,前者显示数组中的全部,后者屏蔽数组中的全部,后者的权重更大。下面是个参考:
案例不显示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 ( <> ); };

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 ( ); };

如果key = 'zh-CN',就可以实现中文覆盖,以此类推。
3.4 主题切换
【react版本markdown编辑器md-editor-rt,支持ssr】这一块相对比较简单了,内置了暗黑主题和默认主题,通过themeapi切换,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 ; };

结尾 更多的更新请关注:md-editor-rt

    推荐阅读