阅读 226

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 图片预览

默认模式

image.png

暗黑模式

image.png

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: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 (
    <>
      <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 主题切换

这一块相对比较简单了,内置了暗黑主题默认主题,通过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 <MdEditor modelValue={data.text} theme={data.theme} />;
};
复制代码

结尾

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

文章分类
前端