这是班刊约稿的一篇文章.
全文约6000字, 预计需要 60 分钟读完.
Markdown 标记语言指北
TOC
Abstract
Markdown\(^1\) 创造于 2004 年, 是网络上最常用的用于编写文档的语言之一. 这篇文章作为一篇指南, 简要介绍了 Markdown 标记语言的语法和原理, 以及利用它撰写文档的一些实践. 同时, 本文也涉及到一些数学公式排版的内容与 \(\TeX\) 排版引擎的原理.
什么是 Markdown?
9102年了, 你还在用 Microsoft Word 写文档吗? (大雾)
毫无疑问, MS Word 是这个星球上通用性最强, 功能最强大的文字处理软件. 秉承着所见即所得\(^2\) (What You See Is What You Get, WYSIWYG) 的精神, 它提供了一流的写作与排版体验.
但是, 用 MS Word 编写所有文档可能并不是一个好的选择. 比如说:
- 你想写一个小文档, 打开了笨重达 2GB 的 MS Word
- 你想写一个文档, 然后一边写一边 (凭感觉) 排版, 甚至打乱了你的节奏
- 在很多地方并不支持 doc 和 docx 格式, 或者支持较弱. 比如 Linux, Mac OS, 笔记应用, 以及绝大部分网站
- MS Word 是付费软件. 你要不就付出每年至少 \(99\) 刀的 Office 365 授权费用, 要不就忍受使用盗版. (事实上, 这并不是一个小问题)
那么, 你还有 Markdown.
根据所见即所想\(^3\) (What You See Is What You Mean, WYSIWYM) 的理念, 我在这里推荐一种让你无需考虑排版, 轻量级, 纯文本格式, 但能让你快速写出十分美观的文档的标记语言. 它就是 Markdown.
-------------------------废话预警-------------------------
什么是标记语言呢?
据 Wikipedia\(^4\) , 标记语言是一种将文本以及文本相关的其他信息结合起来的文字编码.
比如说, 下面这段 Markdown:
- 尼采说:
> Was mich nicht umbringt, macht mich **stärker**.
会被翻译成:
尼采说:
Was mich nicht umbringt, macht mich stärker.
翻译的过程由处理引擎帮你处理 (这被称为渲染), 你只需在文字处打上对应的标记 (比如上文的 -
, **...**
) 即可.
这无疑为文字排版带来了极大的方便.
-------------------------废话预警结束-------------------------
简单的说, Markdown 通过一系列控制字符, 使得写作本身和排版的细节分离, 并且轻量化, 易读写.
Markdown 可以用来干什么?
作为一种为写作而生的语言, 它在日常写作方面几乎可以代替 MS Word.
你可以用 Markdown:
- 写文章
- 写书
- 写 Blog
- 写笔记
- 甚至, 写 (数学, 物理, 或者计算机的) 论文
很多知名的网站也支持 Markdown 写作. 比如:
- 简书 (http://www.jianshu.com/)
- 马克飞象, 印象笔记的一款工具
- GitHub, 全球最大的
同性(程序员)交友网站 - Reddit, 知名的娱乐、社交及新闻网站
- Stack Exchange, 专业问答社区
- Gitbook, 写作网站
另外, 这篇文章就由 Markdown 写成, 并转换为 PDF 文档.
第一步?
为了编写 Markdown 文档, 你需要一个能够渲染 Markdown 的编辑器.
我在这里推荐 Typora\(^5\) , 一款跨平台的 Markdown 写作软件. 和臃肿的 MS Word 不同, 这个软件的安装包仅有 43MB 大小, 并且具备写作 Markdown 的绝大部分功能. 你可以在 Windows, Mac OS, 甚至各大 Linux 发行版上使用它.
(内容来自 善用佳软\(^6\) , CC0协议)
常用的 Markdown 处理工具还包括:
- VS Code + Markdown All in One, 支持实时预览, 同样非常好用
- 马克飞象, 用于印象笔记
- Mou, Mac 下十分漂亮的写作软件
- 有道云笔记, 支持 Android, IOS, 网页端
一些专业一点的内容
Markdown 文本是如何渲染的?
事实上, Markdown 实现的东西就是标记式语言 HTML 的一个子集. 也就是说, 所有 Markdown 的标记都可以在 HTML 中找到等价的描述. 利用 Javascript 或者 PHP, 很容易写出一个 Parser, 把 Markdown 翻译成 HTML. 更进一步, 通过修改相关的 CSS 样式表, 也很容易实现主题, 字体的修改. 相关的实现有 MarkedJS\(^7\) , 以及神仙语言 Haskell 实现的 Pandoc\(^8\) 等等.
Markdown 的简要语法
GFM?
Markdown 只是一种大致的规范, 它有很多种具体的标准和扩展. 好在这几种标准之间只是在细节处有所不同. 在这里, 我主要介绍现在应用相对广泛的 Github Flavored Markdown (GFM, Github 口味的 Markdown, 对, 就是那个全球最大的同性交友网站). GFM 在原先的 CommonMark 上做了一些扩展, 使得 Markdown 的表达能力更强, 写作变得更加便利.
下面的叙述难免会遇到空白符. 为了叙述清楚, 我会用 •
代替空格, 用 →
代替 Tab (就是键盘第三排左面的那个键), 用 ↓
表示空行 ~
段落
我们先了解一个核心的概念: 段落.
Markdown 使用一个空行来分段.
为了兼容其他的一些符号, 简单的回车会被当成空格符.
另外, 如果你想在一段中插入多行, 可以在上一行尾加入两个空格.
例如:
空饮狂歌空度日
↓
飞扬跋扈为谁雄
↓
那一双傲慢的靴子至今还落在••
高力士羞愤的手里
人却不见了
会被渲染成:
空饮狂歌空度日
飞扬跋扈为谁雄
那一双傲慢的靴子至今还落在
高力士羞愤的手里
人却不见了
还记得我说过的所见即所想 (WYSIWYM) 吗?
在 Markdown 中, 你并没有简便的方法去实现一些你原先常用的操作. 比如说: 在两段之间插入三个空行. Markdown 会自动处理换行和行间距, 但你在大多数情况下并不需要连续的两个换行. 类似的, 你也无法在两个单词之间插入好几个空格.
在春天
↓
↓
最后的••••••••一个春天
在春天
最后的 一个春天
这并不是说禁止你这么干. 你也可以通过嵌入 HTML (<br>
) 的方式来实现连续的两个换行. 但是, 这个设计的精髓在于: 你没有必要考虑你的文字的排版细节. Markdown 会做好排版的事情, 而你只需要专注于重要的东西: 你正在写的内容. (这句话其实是 LyX 文档中的, 但无疑也适用于 Markdown)
你可能会想要首行缩进.
实际上 Markdown 也没有这样的设计, 但是你仍然可以利用 HTML: 在行首加一个  
. (或许你也会觉得这是没有必要的)
  Hahaha
Hahaha
有时候你可能会想要一个比段落更强的分隔. Markdown 提供了分割线, 用来分割两段的内容. 它就形如三个连续的 -
, 或者 *
, 或者 _
. (是不是很形象:P)
其实前面的演示中已经用到分割线了...
---
***
___
标题
在 MS Word 或者其他编辑器中, 你加入一个标题的过程可能是: 输入标题, 选择文字, 用模板或者手动修改样式. 但在 Markdown 中, 你只需要在文字前加入 \(1\) ~ \(6\) 个 #
, 就能实现不同层级的标题.
# 一级
## 二级
### 三级
#### 四级QAQ
##### 五级
###### 六级
一级
二级
三级
四级QAQ
五级
六级
标题还有一种更古老的样式: 在文字下加 ---
. 不过它不常用并且不方便, 还不支持三级以上的标题, 在这里就不介绍了.
文字的修饰
Markdown 提供了多种文字的修饰.
- 斜体:
*WORD*
- 加粗:
**WORD**
- 斜体加粗:
***WORD***
- 删除线:
~~WORD~~
前面三种的 *
也可以用 _
代替.
*例如*••
**你有五秒钟的时间**••
***来看试卷上的例题***••
~~你将听到以下对话~~••
__Excuse me. Can you tell me how much the shirt is ?__
例如
你有五秒钟的时间
来看试卷上的例题你将听到以下对话
Excuse me. Can you tell me how much the shirt is ?
我们已经学习了很多符号了.
你有没有想过这样一个问题: 如果你想在文字中包含这些字符怎么办?
Markdown 提供了一种解决方案: 使用转义字符.
在特殊字符前加 \
, 表示对这个字符转义, 也就是保留这个字符不变. 特殊的, 可以用 \\
来转义 \
.
**这是粗体**••
\*\*但这并不是\*\*••
\\*\\* 看看这个,反斜杠变成了斜体 \\*\\*••
这是粗体
**但这并不是**
\\ 看看这个,反斜杠变成了斜体 \\
这是一个可以转义的字符的列表:
\ 反斜线
` 反引号
* 星号
_ 底线
{} 花括号 (braces)
[] 方括号 (brackets)
() 括弧
# 井字号
+ 加号
- 减号
. 英文句点
! 惊叹号
段落的修饰
有时候你会想引用一段话. 比如一句名言, 诗歌, 或者你自己的一句话.
在 Markdown 中, 你只需要在你想引用的段落前加 >
即可.
另外, 没有用分隔符分开的两段, 在引用中会显示在同一个区块中.
在引用中仍然可以使用很多 Markdown 的标记, 比如标题, (后面要讲的) 列表等等.
林则徐在《赴戍登程口占示家人》中写道:
> 力微任重久神疲,再竭衰庸定不支。苟利国家生死以,岂因祸福避趋之。••
谪居正是君恩厚,养拙刚于戍卒宜。戏与山妻谈故事,试吟断送老头皮。
↓
> 注释:••
> 1. 戍:驻守••
> 1. 口占:即兴作诗,不打草稿,随口吟诵出来••
> 1. 衰庸:意近“衰朽”,衰老而无能,自谦之词••
林则徐在《赴戍登程口占示家人》中写道:
力微任重久神疲,再竭衰庸定不支。苟利国家生死以,岂因祸福避趋之。
谪居正是君恩厚,养拙刚于戍卒宜。戏与山妻谈故事,试吟断送老头皮。
注释:
- 戍:驻守
- 口占:即兴作诗,不打草稿,随口吟诵出来
- 衰庸:意近“衰朽”,衰老而无能,自谦之词
列表
Markdown 支持有序列表和无序列表.
无序列表把每一行用 -•
, *•
, 或者 +•
开头, 不过不要在一个列表中混用多个符号:
-•hia
-•hiA
-•hIa
*•hIA; 这是另一个列表
- hia
- hiA
- hIa
- hIA; 这是另一个列表
类似的, 有序列表把每一行用 非负数.•
开头, 不过略显复杂:
- 非负数的长度不能超过 \(9\) 位, 可以有前导 \(0\), 不过没有效果
- 第一个数表示列表的第一的标号, 后面的标号依次递增; 也就是说, 后面的数并不会影响渲染之后的标号
- 其实全用
1.
就好, 这样就不用关心具体的标号是多少了
- 其实全用
1. 这是合法的
4432. 这个标号是 2
00001. 这也是合法的••
1234567890. 但这并不合法••
0000000001. 这也不
- 这是合法的
- 这个标号是 2
- 这也是合法的
- 但这并不合法
- 这也不
Markdown 还支持多级列表.
具体的, 只需在行前加空格, 让列表某一行的标号在列表上一行的文字部分之后, 就可以缩进到二级 (或者更多级) 列表.
Tab 在行首有相同的功效. 事实上, 行首的 Tab 就相当于四个空格.
对我而言, 我更喜欢直接在行首加 Tab, 这样会使无论是源代码还是渲染后的结果都清晰易懂.
表格之间还可以嵌套. 也就是说, 在有序列表的二级列表可以是无序列表, 或者反过来.
类似引用, 在列表里也可以使用 Markdown 的其他元素.
1.•一级
•••1.•二级
••••••1.•三级
12343.•一级
•••1.•但这是一级
••••••1.•二级
→ → 1.•使用 Tab 的二级
1. ##### Lorem!
- 一个无序列表
---
1.•上面的是演示, 下面的才是正常风格
→ 1.•二级
→ → 1.•三级
1.•一级
→ - 一个无序列表
- 一级
- 二级
- 三级
- 二级
- 一级
- 但这是一级
- 二级
- 使用Tab的二级
Lorem!
- 上面的是演示, 下面的才是正常风格
- 二级
- 三级
- 二级
- 一级
- 一个无序列表
插入
Markdown 还支持插入图片和超链接.
超链接
超链接有三种形式.
行内式
形如这样: [an example](http://example.com/ "Title")
an example
是想显示出的文字http://example.com/
是网站链接, 也可以是本机路径, 或者相对路径"Title"
是把鼠标放在这个连接上时显示的文本- 相信你也发现了这个东西似乎没什么用; 所以, 这部分是可选的 :D
- 对于印刷品, 这没有任何卵用
例如:
This is [an example](http://example.com/ "Title") inline link.••
Since the title is useless, this is [another example](http://example.com/) inline link.
This is an example inline link.
Since the title is useless, this is another example inline link.
引用式
有时候你会用到一个链接很多次, 那么你也可以把一个链接映射到某个标记, 然后直接调用这个标记.
语法是这样的:
Some text [some text][id] other text...
在前面或者后面:
[id]: http://example.com/ "Title"
或者
[id]: http://example.com/
后面几行的标记并不会渲染出来; 它们只起到映射链接的作用.
一个例子:
This is [an example][exp1] reference style link.••
And [another cute example][exp2] reference style link.
↓
[exp1]:http://example.com/•"Title"
[exp2]:http://example.com/
This is [an example][exp1] reference style link.
And [another cute example][exp2] reference style link.
请不要忘记给网站的链接加上 http://
或者 https://
等前缀! 如果没有这些前缀, 这些链接会被当成相对路径, 也就是你的 Markdown 所在文件夹下的路径. (虽然事实上你并没有这个路径)
自动链接
有时候你并不想给你用到的链接取一个 label, 这时自动链接就派上用场了.
自动链接非常简单: 用一对 <>
括上你的链接. 它会直接显示出链接, 不过会变成蓝蓝的样子~
<http://example.com/>
你还可以用自动链接插入 Email. 这时需要在邮箱前加上 mailto:
, 不过不加也可以, 因为 Markdown 会帮你在链接处自动加上.
<aaaaa@foo.com>••
<mailto:aaaaa@foo.com>
aaaaa@foo.com
mailto:aaaaa@foo.com
注意: 不要轻易在公共网站公开你的邮箱! 否则你的邮箱可能会被垃圾邮件 overwhelmed (淹没)!
图片
插入图片的语法和超链接十分相似, 只是多了一个 !
:
![label](picture path)
或者
![label][id]
[id]: path
不过还要注意几点:
- label 在 (至少, 大多数) 编辑器中并没有什么用, 所有可以留空
- path 可以是本地的相对或者绝对路径; 不过建议使用相对路径, 否则如果移动整个文件夹或者发送给别人的时候, 图片就会挂掉
![One Pic](https://i-blog.csdnimg.cn/blog_migrate/da1c11cd4526858bf1f17f9133f74f79.png)
(图片来自 Iconfont-阿里巴巴矢量图标库\(^9\) )
表格
表格是 GFM 对 Markdown 原规范的扩展. 但几乎所有的编辑器都支持这一语法.
表格由两部分组成: 表头和内容.
| Items | Price | Description |
| - | :--: | -: |
| T-Shirt | £9.15 | Suggested in the NCEE |
| Uniform in H3Z | about ¥100 | bad design |
| left aligned | centered | right aligned |
Items | Price | Description |
---|---|---|
T-Shirt | £9.15 | Suggested in the NCEE |
Uniform in H3Z | about ¥100 | bad design |
left aligned | centered | right aligned |
上面的分隔符是 |
, 也就是 Backspace 和 Enter 中间的键.
- 表头(也就是第一行)是必选的
- 第二行声明了表格. 每格中
-
至少一个, 不过也可以是连续的多个, 没有影响- 每格中两边的
:
代表对齐方式:-
或者-
左对齐;:-:
居中对齐;-:
右对齐.
- 每格中两边的
- 之后的每一行就是表格的具体内容.
美观起见, 你可以在每一格的文字两边加入若干空格, 但没有影响.
每一格的文字都可以为空 (包括表头), 只需有两边的 |
即可. 这时表格中的这一格也会为空.
进阶的应用
数学公式
数学公式... 是个大话题.
引入数学公式的语法非常简单:
这是一个行内公式: $x^2 + y^2 = 1$
这是一个整行公式:
$$ x^3 + y^3 + z^3 = 1$$
这是一个行内公式: \(x^2 + y^2 = 1\)
这是一个整行公式:
\[ x^3 + y^3 + z^3 = 1\]
大概说一下数学公式的语法吧...
Markdown 支持的数学公式是 TeX 的一个子集.
TeX 也是一种标记语言, 是一套成功的, 流行于学术界的排版语言, 对数学公式有很好的支持.
上下标, 组合
上标可以利用 ^x
符号表示, 比如 x^2
, 会被渲染成 \(x^2\) .
下标类似, 利用 _x
符号表示, 比如 x_2
| \(x_2\) .
有时我们可能会需要多个字母的上下标. 可以利用 {}
使字符成组:x^{x^{23}}
| \(x^{x^{23}}\)
命令
公式的命令用 \
开头, 表示一些特殊的组合或符号. 几乎所有无法用键盘打出的数学符号都可以利用命令显示出来.
\alpha
| \(\alpha\)\Sigma
| \(\Sigma\)
命令也可以有参数, 上下标. 例如:
这个是分数:\frac{x+1}{y}
| \(\frac{x+1}{y}\)
求和符号:
\sum_{i=1}^n {f(i)}
| \(\sum_{i=1}^n {f(i)}\)
TeX 的数学公式可以让你利用大量类似的命令进行公式排版.
公式一览表可以在 \(^{10}\) (在最后) 中找到.
感兴趣的同学还可以在 \(^{11}\) 学习关于 TeX 和 LaTeX 的更多内容.
代码
Markdown 还可以嵌入代码, 并提供代码高亮等功能 (编译是不可能了)
语法是这样的:
使用一对 ` ` 括住一句行内代码;
使用一对单独成行的 ``` ``` 括住一段成段代码.
另外, 第一个 ``` 后可以加入用到的语言, 让编辑器自动代码高亮.
这是一句行内代码: a = b ** 100
这是一段成段代码:
class foo{
double x,y;
};
class foo{
double x,y;
};
在代码块中的文字通常不会因为渲染发生变化 (除了 ``` ). 因此, 可以利用代码块显示文字的原貌.
你可能已经发现了: 我前面演示用到的源码, 就是用代码块呈现的.
嵌入HTML
前面在讲原理的地方已经提到过了: Markdown 渲染就是把它翻译成 HTML.
那么, 我们可不可以在 Markdown 中直接使用 HTML 呢? 答案是肯定的.
有能力的同学, 可以在写的 Markdown 文档中加入 HTML 代码, 来实现一些 Markdown 本身无法实现的功能. (不过, 必须用 HTML 的地方其实很少)
比如说, 在表格中实现换行:
| Header1 | Header2 |
|---------|----------------------------------|
| item 1 | 1. one<br />2. two<br />3. three |
Header1 | Header2 |
---|---|
item 1 | 1. one 2. two 3. three |
还有, 有心的同学可能已经发现, 这篇文章中的图片, 和讲插入图片时的例子, 样式不大一样.
我插入图片是利用 HTML 实现的:
<center>
<img style="border-radius: 0.3125em;
box-shadow: 0 2px 4px 0 rgba(34,36,38,.12),0 2px 10px 0 rgba(34,36,38,.08);"
src="https://i-blog.csdnimg.cn/blog_migrate/da1c11cd4526858bf1f17f9133f74f79.png">
<br>
<div style="display: inline-block; color: #999;padding: 2px;">一个演示</div>
</center>
这段 HTML 似乎并不被 Typora 支持; 但我现在用的 VS Code 是支持的.
扩展的 Markdown
Markdown 也有很多扩展, 提供了一些有趣的功能. (比如 GFM, 就是一种扩展)
例如, 你可以使用 reveal-md
, 用 Markdown 写 slide (幻灯片);
利用 multimarkdown
实现表格的一些其他操作, 比如合并单元格;
And so on.
你可以从这个网站找到大量的 Markdown 扩展:
:P
总结
Markdown 的语法大概就这么多.
作为补充材料, 你可以在 \(^{12}\) 找到 GFM 的详细文档.
Markdown 作为一种标记语言, 它解决的核心问题在于: 建立一种方便的工具, 把写作和排版细节分离.
它也的确实现了这个目标. 讲真, 使用 Markdown 写作的确是一种优雅的体验. (你甚至不需要使用鼠标)
现在就用 Markdown 写一篇文章吧! 相信你也会体验到这个有数百万人使用的语言的优美之处.
最后, 希望这篇文章能够帮到你.
后记
完稿于 6/21/2019 凌晨.
由于我并不在哈尔滨, 在知道班刊的投稿之后 ddl 只有两天了... 我真的没有想到这么快就完成了这篇稿子. 至少, 传教 (指 Markdown) 还是很开心的~
❤
关于
我是董易昕, 哈尔滨第三中学, 17 级 2 班的学生, (前) OI 选手.
我的 ID 是 Ubospica (它是如此的奇葩以至于 google 到的结果一定是关于我的). Spica 是室女座 \(\alpha\) 星, 也就是角宿一.
欢迎来我的博客转转! 我的博客 (目前) 位于 https://www.cnblogs.com/ubospica/, 这是一个技术博客. 这篇文章的源码也会放上去~
你也可以这么联系我, 或者请我喝杯咖啡:
- QQ: 2031252283
- FB/Twitter/G+(死了): Ubospica
- 邮箱: ubospica@gmail.com, 或者 xiao3dong3@126.com
Reference
- https://en.wikipedia.org/wiki/Markdown
- https://en.wikipedia.org/wiki/WYSIWYG
- https://en.wikipedia.org/wiki/WYSIWYM
- https://zh.wikipedia.org/wiki/置标语言
- Typora — a markdown editor, markdown reader. - https://typora.io/
- 善用佳软 - http://xbeta.info/
- markedjs/marked: A markdown parser and compiler. Built for speed. - https://github.com/markedjs/marked
- Pandoc - https://pandoc.org/
- Iconfont-阿里巴巴矢量图标库 - https://www.iconfont.cn/
- TeX Tutorial - https://www.tutorialspoint.com/tex_commands/index.htm
- LaTeX - A document preparation system - https://www.latex-project.org/
- GitHub Flavored Markdown Spec - https://github.github.com/gfm/