Markdown实时预览

在左侧输入Markdown,右侧立即显示渲染效果,还可以切换查看并复制生成的HTML源码。转换完全在浏览器中进行,输入的内容不会上传。

字符数: 0行数: 0标题: 0链接: 0被拦截的网址: 0

什么是Markdown

Markdown是一种用简单符号表示格式的轻量标记写法,由John Gruber在2004年设计,Aaron Swartz也参与了语法的讨论。它的设计目标是:即使不转换,原文本身也容易阅读。行首的#是标题,用两个星号包住的文字是粗体,行首的连字符是列表项。由于只是纯文本,任何编辑器都能写,版本管理工具能清楚地比较差异,贴进聊天窗口也不会乱。因此它被广泛用于README、开发文档、博客、笔记应用和维基。

本页用一段专门编写的小型转换程序把Markdown转成HTML。结果区可以在渲染预览和HTML源码之间切换,并显示字符数、行数、标题数、链接数,以及被判定为不安全而拦截的网址数量。

本工具支持的语法

下表中的每一项都已用本页的转换程序验证过。把"输入示例"一列直接粘贴进编辑框,就能看到结果。

语法输入示例HTML备注
标题# 标题1 ~ ###### 标题6h1-h6#后面必须有空格;下划线式(=== / ---)也支持
粗体・斜体**粗体** *斜体*strong, em也支持 __粗体__ 和 _斜体_(单词中间的下划线会被忽略)
删除线~~删除~~delGFM扩展
列表- 项目 / 1. 项目ul, ol缩进两个以上空格即为嵌套;有序列表保留起始编号
任务列表- [x] 已完成 / - [ ] 未完成input[type=checkbox]GFM扩展;预览中的复选框不可点击
表格| 列1 | 列2 | + |:--|--:|tableGFM扩展;用冒号指定对齐方式
引用> 引用文字blockquote内部可嵌套列表和标题
代码`code` / ```语言 ... ```code, pre也支持 ~~~ 围栏;内容原样显示,不做转换
链接・图片[文字](网址) / ![说明](网址)a, img只保留 http、https、mailto、tel 和相对路径;可读取引号内的标题
自动链接https://example.com / <https://...>a仅限 http 和 https
分隔线・换行--- / 行尾两个空格hr, br紧贴在段落下一行的 --- 会被当作标题下划线

反斜杠转义也受支持,写\*会原样显示星号。嵌套最多八层,更深的部分不再转换,而是作为转义后的文字显示。只有表头行和分隔行的列数相同,才会被识别为表格。

不支持的有:引用式链接([文字][1])、脚注、定义列表、数学公式、Mermaid图表、缩进式代码块(请改用围栏)以及原始HTML块。这些都是各家渲染器本来就不一致的地方,凭猜测转换只会让预览和最终发布平台对不上。

CommonMark、GFM与最初的Markdown

最初的Markdown说明有许多含糊之处,同一段输入在不同实现里会得到不同结果。CommonMark就是为消除这种歧义而制定的规范,撰写本文时的最新版本是2024年1月28日发布的0.31.2。GFM(GitHub Flavored Markdown)在CommonMark基础上增加了这些扩展:

本工具实现了表格、任务列表、删除线和自动链接。标签过滤则无需实现,因为它根本不会让原始HTML通过(见下文安全部分)。

同样的Markdown为什么显示不同

按真实输出核对的两个例子

例1:带对齐的表格 输入包含两列表头、分隔行中的:--(左对齐)与--:(右对齐),以及两行数据。转换后表格外面有一层可滚动的容器,每个表头和数据单元格都带有text-align样式。

| 姓名 | 分数 |
|:--|--:|
| 小王 | 90 |
| 小李 | 85 |
<div class="md-table-wrap"><table>
<thead><tr><th style="text-align:left">姓名</th><th style="text-align:right">分数</th></tr></thead>
<tbody>
<tr><td style="text-align:left">小王</td><td style="text-align:right">90</td></tr>
<tr><td style="text-align:left">小李</td><td style="text-align:right">85</td></tr>
</tbody></table></div>

例2:嵌套列表 把"苹果"和"梨"缩进两个空格,它们就成为"水果"条目里的子列表。结果是两个顶层项目和两个嵌套项目。

- 水果
  - 苹果
  - 梨
- 蔬菜
<ul>
<li>水果
<ul>
<li>苹果</li>
<li>梨</li>
</ul></li>
<li>蔬菜</li>
</ul>

安全:为什么不能轻信转换后的HTML

Markdown允许在原文里夹杂HTML,所以把用户输入的Markdown直接变成页面HTML,很容易造成跨站脚本(XSS)漏洞。常见的攻击有三种:

本工具在代码中对这三种情况都做了处理。它先把&、<、>和引号转成实体,所以输入中的原始HTML只会显示为文字,不会变成元素。链接和图片的地址只接受 http、https、mailto、tel,以及相对路径和锚点,其余一律替换为#,用来伪装协议的控制字符在判断前会被去掉。外部链接带有rel="noopener noreferrer nofollow"并在新标签页打开。预览区直接填入生成的HTML,所以这些步骤就是唯一的防线,没有使用另外的净化库。在"安全测试示例"中,javascript:链接和data:图片都被替换为#,"被拦截的网址"显示为2,而script标签和图片标签则以文字形式显示。

作为只给自己看的预览工具,这样已经够用,但它不是生产代码的范本。手写的转换程序可能被意想不到的组合绕过。如果你的网站要显示他人撰写的Markdown,请同时使用持续维护的Markdown库和专门的HTML净化库,并尽量配置内容安全策略(CSP)作为第二道防线。

常见错误

局限与不适合使用的场合

这是一个覆盖核心语法和部分GFM扩展的简易转换器,并不能通过CommonMark的全部测试。较复杂的结构,比如嵌套列表里的代码块,结果可能与GitHub或你使用的静态站点生成器不同。使用外部地址的图片时,预览会让浏览器访问该服务器,对方可能因此看到你的IP地址。发布前请务必在实际的发布平台(GitHub、博客系统或笔记应用)上再预览一次。另外,密码和个人信息不要输入任何在线工具,即使本工具不会上传输入内容,这也是一个好习惯。

如何利用转换结果

  1. 一边在左侧写,一边检查标题层级有没有跳级(例如h1后面直接是h3)。
  2. 切到"HTML源码"标签查看转换结果,需要时点"复制HTML"。注意粘贴到的网站会按自己的规则净化HTML。
  3. 要放进README或维基的文档,请在目标平台的渲染器里确认表格、任务列表和换行是否一致。
  4. 检查字数用字数统计,比较两个版本用文本对比工具,统一英文大小写用大小写转换。
  5. 如果文档里要放JSON示例,可以先用JSON格式化工具整理好。

常见问题

可以复制转换后的HTML吗?

可以。在"HTML源码"标签里查看,点"复制HTML"即可。粘贴到其他网站时,该网站自己的净化规则决定哪些标签和属性会保留。

表格怎么写?

第一行写表头,格式为| 列1 | 列2 |,第二行写分隔行,如|--|--|,之后是数据行。分隔行里:--为左对齐,:-:居中,--:右对齐。每一行的列数都要和表头相同。

Markdown里可以直接写HTML标签吗?

在本工具中不行。出于安全考虑,HTML标签不会被渲染,而是作为文字显示。GitHub等平台会保留允许的标签并过滤其余部分,但各平台的范围不同,请在实际发布的平台上确认。

换行后内容还是连成一行怎么办?

在CommonMark中,单个换行不会产生新的一行。请在行尾加两个空格,或者用空行分段。也可以勾选编辑框上方的"把换行直接转为 <br>",看看对换行敏感的系统会怎样显示。

输入的内容会发送到服务器吗?

不会。转换由浏览器中的脚本完成,输入内容不会上传。唯一的例外是外部图片:如果Markdown里引用了外部图片地址,预览会为了加载图片而访问该地址。

该用Markdown还是HTML?

以文字为主的文档(README、博客、笔记)用Markdown更省事;需要精确排版、颜色或表单时用HTML更合适。许多平台允许在Markdown中夹杂少量HTML,但前提是其渲染器允许。