当前位置:网站首页>一款开源的Markdown转富文本编辑器的实现原理剖析
一款开源的Markdown转富文本编辑器的实现原理剖析
2022-07-03 09:01:00 【科技那些事儿】
笔者平时写文章使用的都是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();
};
复制代码同样修改了光标位置并且让编辑器重新聚焦。
边栏推荐
- LeetCode每日一题(1162. As Far from Land as Possible)
- Win10 quick screenshot
- [kotlin learning] classes, objects and interfaces - classes with non default construction methods or attributes, data classes and class delegates, object keywords
- Hudi学习笔记(三) 核心概念剖析
- Django operates Excel files through openpyxl to import data into the database in batches.
- 2022-2-13 learning xiangniuke project - version control
- 2022-1-6 Niuke net brush sword finger offer
- [kotlin learning] control flow of higher-order functions -- lambda return statements and anonymous functions
- Liteide is easy to use
- Digital management medium + low code, jnpf opens a new engine for enterprise digital transformation
猜你喜欢

Just graduate student reading thesis
![[set theory] order relation (chain | anti chain | chain and anti chain example | chain and anti chain theorem | chain and anti chain inference | good order relation)](/img/fd/c0f885cdd17f1d13fdbc71b2aea641.jpg)
[set theory] order relation (chain | anti chain | chain and anti chain example | chain and anti chain theorem | chain and anti chain inference | good order relation)

Move anaconda, pycharm and jupyter notebook to mobile hard disk

Hudi 集成 Spark 数据分析示例(含代码流程与测试结果)

LeetCode每日一题(1162. As Far from Land as Possible)

Run flash demo on ECS

Trial of the combination of RDS and crawler

The "booster" of traditional office mode, Building OA office system, was so simple!

Install third-party libraries such as Jieba under Anaconda pytorch

Principles of computer composition - cache, connection mapping, learning experience
随机推荐
Vscode编辑器右键没有Open In Default Browser选项
Liteide is easy to use
Tag paste operator (#)
【Kotlin学习】运算符重载及其他约定——重载算术运算符、比较运算符、集合与区间的约定
Common formulas of probability theory
[point cloud processing paper crazy reading classic version 8] - o-cnn: octree based revolutionary neural networks for 3D shape analysis
Severity code description the project file line prohibits the display of status error c2440 "initialization": unable to convert from "const char [31]" to "char *"
Using Hudi in idea
Spark 概述
ERROR: certificate common name “*.” doesn’t match requested ho
图像修复方法研究综述----论文笔记
Alibaba cloud notes for the first time
Crawler career from scratch (IV): climb the bullet curtain of station B through API
Explanation of the answers to the three questions
Go language - IO project
Instant messaging IM is the countercurrent of the progress of the times? See what jnpf says
LeetCode每日一题(2232. Minimize Result by Adding Parentheses to Expression)
Install database -linux-5.7
Win10 quick screenshot
Modify idea code