Markdown 预览

边写边看 Markdown 的渲染效果。原始 HTML 以文本显示而不执行,文档全程不离开浏览器。

所有处理均在你的浏览器内完成,数据不会上传。

标题

这是一段带 粗体斜体行内代码 的文字。

  • 列表项一
  • 列表项二
  • 已完成的任务

引用的内容

列 A列 B
12
const x = 1;

链接

54字数
169字符数
1标题数
1 分钟阅读时长

大纲

  • 标题

写在 Markdown 里的原始 HTML 会以文本显示,不会被渲染。这是有意为之:一个会执行你粘贴的 HTML 的预览工具,就是一个现成的 XSS,而粘进来的 Markdown 往往来自你无法控制的地方。输出里的每一个标签都由解析器自己生成。

链接与图片的地址会经过协议白名单检查,javascript: 与 data: 这类地址会保持为纯文本,不会变成可点击的链接。

使用方法

  1. 在左侧输入或粘贴 Markdown,预览随输入实时更新。
  2. 窄屏下两栏会自动改为上下堆叠。
  3. 复制 HTML 取走片段;下载 HTML 保存一个带样式的完整文件。
  4. 勾选 查看生成的 HTML 可以检视确切的输出。

关于「安全地渲染 Markdown」

Markdown 的设计目标是既能当纯文本读,又能干净地转成 HTML。容易被忽略的一点是:最初的 规范允许在文档里内嵌原始 HTML——这是有意留下的后门,用来表达 Markdown 本身表达不了的 东西。而这个后门同时也是问题所在。

预览工具会把你从任何地方粘来的文本,作为 HTML 插进当前页面。如果原始 HTML 能够透传,那么 粘贴一份含有 <script><img onerror=...> 的文档,就会在你的浏览器里、以你所在站点的 身份执行那段代码。这不是假想:它正是 Markdown 渲染器被攻破的标准方式,在评论系统、wiki 和 笔记应用里都造成过真实的漏洞。

本工具采取的立场很简单:先把一切转义,再套用 Markdown 语法。你输入的每一个尖括号,在 任何解析开始之前就已变成可见文本,因此输出里的每一个标签都由解析器自己生成,你写下的任何 内容都无法变成标签。代价是不支持原始 HTML 透传——如果你恰好需要它,这确实是个限制——但对 一个预览工具来说,这个取舍是对的。

不过单靠转义并不够,而这正是许多本来相当谨慎的实现失手的地方。看 [点我](javascript:alert(1)): 这里根本没有标签可供转义拦截,语法是完全合法的 Markdown,朴素的渲染器会产出 <a href="javascript:alert(1)">,点一下就会执行。防线是对链接与图片地址施加协议白名单: 只有 httphttpsmailtotel、锚点和相对路径能通过,其余保持为纯文本。这里用白名单 而不是黑名单很关键——黑名单必须预判攻击者可能尝试的每一种变形:大小写混写、在协议名中间插 一个制表符、开头塞一个空字节;而白名单根本不认识这些东西。

常见问题

为什么我写的 HTML 显示成了文本,没有被渲染?

因为渲染它就是一个安全漏洞。Markdown 允许内嵌原始 HTML,而一个会执行你粘贴的任意 HTML 的预览工具,就是一个现成的跨站脚本漏洞——你粘进来的 Markdown 往往来自你无法控制的地方:一份 README、一条聊天记录、别人发来的文档。本解析器先把输入的每一个字符转义,之后才套用 Markdown 语法,因此输出里的每个标签都由它自己生成。如果你需要原始 HTML 透传,这个工具不适合你,而这是一个刻意的立场,不是缺失的功能。

为什么我的链接没有变成可点击的?

链接与图片的地址要经过协议白名单——http、https、mailto、tel、锚点和相对路径。其余一律保持为纯文本,包括 javascript: 和 data:。这挡住了经典的 [点我](javascript:...) 手法,而单靠转义是挡不住的:转义拦得住标签,拦不住藏在 href 里的脚本。

我的文档会被上传吗?

不会。解析在你的浏览器里完成,不传输任何内容。这一点比看上去更要紧——人们用 Markdown 写的往往是草稿、内部文档和尚未发布的文章。

支持哪些 Markdown 语法?

常用的那部分:标题、粗体、斜体、删除线、行内代码、围栏代码块、引用、有序与无序列表、任务列表、表格、水平线、链接、图片和自动链接。刻意不支持的有:原始 HTML、脚注、定义列表和引用式链接。完整的 CommonMark 有六百多条规范测试用例;这里覆盖的是人们实际会写的部分,并如实说明,而不是宣称一个并不具备的完整度。

可以把 HTML 导出吗?

可以——「复制 HTML」给你片段,「下载 HTML」给你一个带基础样式、可独立打开的完整文件。勾选「查看生成的 HTML」可以看到解析器的确切输出。

阅读时长是怎么算的?

西文每分钟 200 词、中日韩每分钟 300 字,混排文档相加。它统计的是 Markdown 源文本,语法符号不计入词数,但这仍然只是粗估——请把它当作「短读还是长读」的判断依据,而不是一个精确数字。