笔者平时写文章应用的都是 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();
};
复制代码
同样批改了光标地位并且让编辑器从新聚焦。