引言
markdown 是一种创作者通过输入简洁的文字便能够实现 自动排版 的排版语法,目前国内包括知乎、简书、掘金、v2ex,国外包括 stack overflow、github, 等各大内容创作平台都已经支持了 markdown 语法,创作者也因为习惯了 markdown 语法,如果某个平台不支持 markdown 语法,那么必然会留下一个不好的印象,甚至可能被拉黑名单。
总而言之,拥有一个支持 markdown 语法的编辑器对于内容创作平台而言是尤为重要的。
那么,作为一个开发者来说,我们应该如何实现一个 markdown 编辑器呢?
主要做的事情有两部分:
1. 针对文本内容进行语法分析并自定义样式
2. 针对代码关键词需要高亮展示
一. 针对文本内容进行语法分析
1.1 markdown语法转html标签
就 markdown 语法而言,我们获取的输入值往往是:
# 这是标题
> 这是内容
#### 这是表格
表头1 | 表头2 | 表头3
------|-------|-------
内容1 | 内容2 | 内容3
这些输入值保存到数据库中到文本内容为:
# 这是标题↵> 这是内容↵#### 这是表格↵表头1 | 表头2 | 表头3↵------|-------|-------↵内容1 | 内容2 | 内容3
这里我们需要将对应markdown转变为浏览器可以识别的html标签:
- 将
# 文字处理为<h1>文字</h1>标签 - 将
> 文字处理为<blockquote><p>文字<p></blockquote>标签 - 将
xxx | xxx | xxx \n ---|---|---\n内容1 | 内容2 | 内容3处理为<table><thead><tbody><th><td>标签
这里推荐使用第三方库showdown,它是一个 Javascript 到 HTML的转换器,可以在客户端(在浏览器中)或服务器端(NodeJs )使用。
需要注意的是 showdown 无法识别特殊符号↵,在调用makeHtml()前,需要先将特殊符号↵处理为\n换行符。
text.replace(/↵/g,'\n')
具体代码如下:
import showdown from 'showdown'
const converter = new showdown.Converter()
converter.setFlavor('github')
converter.makeHtml('# 这是标题↵> 这是内容↵#### 这是表格↵表头1 | 表头2 | 表头3↵------|-------|-------↵内容1 | 内容2 | 内容3'.replace(/↵/g,'\n'))
最终得到 HTML 结构:
<h1 id="这是标题">这是标题</h1>
<blockquote>
<p>这是内容</p>
</blockquote>
<h4 id="这是表格">这是表格</h4>
<table>
<thead>
<tr>
<th id="表头1">表头1</th>
<th id="表头2">表头2</th>
<th id="表头3">表头3</th>
</tr>
</thead>
<tbody>
<tr>
<td>内容1</td>
<td>内容2</td>
<td>内容3</td>
</tr>
</tbody>
</table>
1.2 markdown语法自定义样式
使用标签选择器自定义样式
blockquote {
color: #7f8fa4;
font-size: inherit;
padding: 8px 24px;
margin: 16px 0;
border-left: 3px solid #eaeaea;
p {
margin: 0;
}
}
table {
thead {
background: #292c34;
color: #a9b0bd;
th {
border: 1px solid #292c34;
border-right-color: #a9b0bd;
padding: 10px 20px;
box-sizing: border-box;
&:nth-last-child(1) {
border-color: #292c34;
}
}
}
tbody {
td {
border: 1px solid #292c34;
padding: 10px 20px;
box-sizing: border-box;
}
}
}
实际效果:
二. 针对代码关键词需要高亮展示
2.1 提取代码块关键词
我们使用 markdown 语法展示代码时,往往会带上语言类型,如javascript:
转换效果如下:
<pre>
<code class="javascript language-javascript">
import showdown from 'showdown'
const converter = new showdown.Converter()
converter.setFlavor('github')
converter.makeHtml('# 这是标题
**这是加粗的文字**
*这是斜体*'.replace(/
/g,'\n'))</code>
</pre>
转换结果使用<pre>、<code>标签将整个代码块都给包裹在里面,并不能够区分代码块关键词(eg: 'import'、'class'),无法满足我们的需求。 这时便需要借助highlight.js来提取关键词,同时给对应关键词添加上className。
2.2 highlight.js
highlight.js是一个 javascript 编写的语法高亮器,可以同时运行在浏览器跟服务端,不依赖任何框架,且具备自动检测语言功能。
highlightAll()方法可以自动识别页面上的"代码块",并自动检测语言。
识别结果:
<pre><code
<span class="hljs-keyword">class</span>
="javascript language-javascript">
<span class="hljs-keyword">import</span>
showdown
<span class="hljs-keyword">from</span>
<span class="hljs-string">'showdown'</span>
const converter =
<span class="hljs-built_in">new</span>
showdown.Converter()
converter.setFlavor(
<span class="hljs-string">'github'</span>
)
converter.makeHtml(
<span class="hljs-string">'# 这是标题
**这是加粗的文字**
*这是斜体*'
</span>.replace(/
/g,
<span class="hljs-string">'\n'</span>))</code></pre>
该库支持的语言种类繁多,包括go 、python、java等,详情可查看:
github.com/highlightjs…
2.3 代码高亮
代码高亮我们可以通过css自定义样式,也可以尝试引入hightlighth.js提供的官方样式(vscode、atom、xcode、github等)。
@import '../node_modules/highlight.js/styles/atom-one-dark.css';