前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >一款开源的Markdown转富文本编辑器的实现原理剖析

一款开源的Markdown转富文本编辑器的实现原理剖析

作者头像
闻说社
发布2022-06-10 16:57:08
6550
发布2022-06-10 16:57:08
举报

笔者平时写文章使用的都是Markdown,但是发布的时候就会遇到一些平台不支持Markdown的情况,重排是不可能重排的,所以都会使用一些Markdown转富文本的工具,比如markdown-nice,用的多了就会好奇是怎么实现的,于是就有了本篇文章。

markdown-nice是一个基于React构建的项目,先来看一下它的整体页面:

一个顶部工具栏,中间三个并列的区域,分别是编辑区域、预览区域、自定义主题区域,自定义主题区域默认是隐藏的。

大体上就是一个Markdown编辑器,增加了一些对各个平台的适配而已。

编辑器

编辑器使用的是CodeMirror,具体来说是一个二次封装的组件React-CodeMirror

代码语言:javascript
复制
import CodeMirror from "@uiw/react-codemirror";

class App extends Component {
    render() {
        return (
        	<CodeMirror
                  value={this.props.content.content}
                  options={{
                    theme: "md-mirror",// 主题
                    keyMap: "sublime",// 快捷键
                    mode: "markdown",// 模式,也就是语言类型
                    lineWrapping: true,// 开启超长换行
                    lineNumbers: false,// 不显示行号
                    extraKeys: {// 配置快捷键
                      ...bindHotkeys(this.props.content, this.props.dialog),
                      Tab: betterTab,
                      RightClick: rightClick,
                    },
                  }}
                  onChange={this.handleThrottleChange}
                  onScroll={this.handleScroll}
                  onFocus={this.handleFocus}
                  onBlur={this.handleBlur}
                  onDrop={this.handleDrop}
                  onPaste={this.handlePaste}
                  ref={this.getInstance}
                />
        )
    }
}
复制代码

快捷键、命令

markdown-nice通过extraKeys选项设置一些快捷键,此外还在工具栏中增加了一些快捷按钮:

这些快捷键或者命令按钮操作文本内容的逻辑基本是一致的,先获取当前选区的内容:

代码语言:javascript
复制
const selected = editor.getSelection()
复制代码

然后进行加工修改:

代码语言:javascript
复制
`**${selected}**`
复制代码

最后替换选区的内容:

代码语言:javascript
复制
editor.replaceSelection(`**${selected}**`)
复制代码

此外也可以修改光标的位置来提升体验,比如加粗操作后光标位置会在文字后面,而不是*后面就是因为markdown-nice在替换完选区内容后还修改了光标的位置:

代码语言:javascript
复制
export const bold = (editor, selection) => {
  editor.replaceSelection(`**${selection}**`);
  const cursor = editor.getCursor();
  cursor.ch -= 2;// 光标位置向前两个字符
  editor.setCursor(cursor);
};
复制代码

表格

Markdown的表格语法手写起来是比较麻烦的,markdown-nice对于表格只提供了帮你插入表格语法符号的功能,你可以输入要插入的表格行列数:

确认以后会自动插入符号:

实现其实就是一个字符串的拼接逻辑:

代码语言:javascript
复制
const text = this.buildFormFormat(this.state.rowNum, this.state.columnNum);

buildFormFormat = (rowNum, columnNum) => {
    let formFormat = "";
    // 最少会创建三行
    for (let i = 0; i < 3; i++) {
        formFormat += this.buildRow(i, columnNum);
    }
    // 超过三行
    for (let i = 3; i <= rowNum; i++) {
        formFormat += this.buildRow(i, columnNum);
    }
    return formFormat;
};

buildRow = (rowNum, columnNum) => {
    let appendText = "|";
    // 第一行为表头和内容的分隔
    if (rowNum === 1) {
        appendText += " --- |";
        for (let i = 0; i < columnNum - 1; i++) {
            appendText += " --- |";
        }
    } else {
        appendText += "     |";
        for (let i = 0; i < columnNum - 1; i++) {
            appendText += "     |";
        }
    }
    return appendText + (/windows|win32/i.test(navigator.userAgent) ? "\r\n" : "\n");
};
复制代码

表格字符生成以后替换当前选区内容即可:

代码语言:javascript
复制
handleOk = () => {
    const {markdownEditor} = this.props.content;
    const cursor = markdownEditor.getCursor();

    const text = this.buildFormFormat(this.state.rowNum, this.state.columnNum);
    markdownEditor.replaceSelection(text);

    cursor.ch += 2;
    markdownEditor.setCursor(cursor);
    markdownEditor.focus();
};
复制代码

同样修改了光标位置并且让编辑器重新聚焦。

本文系转载,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文系转载前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 编辑器
    • 快捷键、命令
      • 表格
      领券
      问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档