笔者平时写文章应用的都是Markdown,然而公布的时候就会遇到一些平台不反对Markdown的状况,重排是不可能重排的,所以都会应用一些Markdown转富文本的工具,比方markdown-nice,用的多了就会好奇是怎么实现的,于是就有了本篇文章。
markdown-nice是一个基于React构建的我的项目,先来看一下它的整体页面:

一个顶部工具栏,两头三个并列的区域,别离是编辑区域、预览区域、自定义主题区域,自定义主题区域默认是暗藏的。
大体上就是一个Markdown编辑器,减少了一些对各个平台的适配而已。
编辑器
编辑器应用的是CodeMirror,具体来说是一个二次封装的组件React-CodeMirror:
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选项设置一些快捷键,此外还在工具栏中减少了一些快捷按钮:

这些快捷键或者命令按钮操作文本内容的逻辑根本是统一的,先获取以后选区的内容:
const selected = editor.getSelection()
复制代码
而后进行加工批改:
**${selected}**
复制代码
最初替换选区的内容:
editor.replaceSelection(**${selected}**)
复制代码
此外也能够批改光标的地位来晋升体验,比方加粗操作后光标地位会在文字前面,而不是*前面就是因为markdown-nice在替换完选区内容后还批改了光标的地位:

export const bold = (editor, selection) => {
editor.replaceSelection(**${selection}**);
const cursor = editor.getCursor();
cursor.ch -= 2;// 光标地位向前两个字符
editor.setCursor(cursor);
};
复制代码
表格
Markdown的表格语法手写起来是比拟麻烦的,markdown-nice对于表格只提供了帮你插入表格语法符号的性能,你能够输出要插入的表格行列数:

确认当前会主动插入符号:

实现其实就是一个字符串的拼接逻辑:
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");

};
复制代码
表格字符生成当前替换以后选区内容即可:
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();

};
复制代码
同样批改了光标地位并且让编辑器从新聚焦。