Markdown转HTML转换器

页面内自实现的两阶段 Markdown 解析器:先块级后行内,先转义尖括号和号再生成任何标签,代码块内部一律不解析,输出只作文本展示。

输入上限 20 万字符;生成结果只写进右侧文本框(value),绝不用 innerHTML 注入页面,所以原文里的原始标签只会被转义、不会被执行。HTML 下载不带 BOM(JSON / HTML 一律不带),对照表 CSV 相反必须带 BOM。

Markdown 语法支持对照(本页实现 = CommonMark 子集 + GFM 删除线;数值仅作演示)
Markdown 写法本页支持输出与说明
# 标题支持1~6 个 # 生成 h1~h6
标题下加 ===支持Setext 一级标题,生成 h1
标题下加 ---支持Setext 二级标题,生成 h2
**粗体** / __粗体__支持生成 strong
*斜体* / _斜体_支持生成 em
~~删除线~~支持(GFM)生成 del,CommonMark 原文没有
`行内代码`支持生成 code,内部不再解析
三反引号围栏代码块支持生成 pre+code,可带 language-xx 类
- 列表 / 1. 列表支持生成 ul / ol,2 空格缩进算嵌套
> 引用支持生成 blockquote,内部可再含段落
[文字](链接)支持生成 a,URL 与标题做属性转义
单独一行 ---支持生成 hr(3 个以上 - * _ 均可)

使用方法

  1. 打开 Markdown转HTML转换器时左侧已预置 29 行示例,右侧同步显示转换好的 HTML,无需任何配置;想换内容直接把左侧替换成你自己的 Markdown。
  2. 多行输入时按 Ctrl / Cmd + Enter 触发转换(Enter 留给换行)。输入上限 20 万字符,超长会给出提示而不是卡死页面。
  3. 看统计条:示例 29 行输入生成 57 个标签、输出 632 字符——标签数与输出长度可用于估算嵌入模板后的体积。
  4. 点「复制 HTML」把结果送到剪贴板,或点「下载 .html」拿到不带 BOM 的纯文本文件,可直接作为静态页面打开。
  5. 下方对照表列出本页支持的语法与明确不支持的语法,默认 12 行,「加载更多」展开其余行,「导出对照表 CSV」下载带 BOM 的表格。

这个Markdown转HTML转换器能解决什么问题

第一个场景是写文档、写 README、写博客草稿时想立刻看到对应的标签结构。编辑器里的「预览」往往是成品渲染,看不到源码;本页把 Markdown 原文和生成的标签并排放在一起,方便你确认某个写法会不会被识别、会不会漏掉闭合标签。

第二个场景是排查「为什么我的 Markdown 在某平台渲染不对」。同一段文字在不同解析器下结果可能不同:~~删除线~~ 属于 GFM 扩展,纯 CommonMark 不认;标题下加 --- 在有些方言里是二级标题、在另一些方言里被当成水平线。本页按一套明确的规则给出结果,并把规则写在对照表里。

第三个场景是理解转义与安全。很多人在模板里直接拼 Markdown 生成的 HTML,结果原文里的 <script> 被执行了;本页的做法是先转义再生成标签,原始 HTML 永远变成可见文本,且结果只进文本框,从机制上避免注入。

本页只做 Markdown → HTML 单向转换:反向走 HTML转Markdown转换器;只要纯文本走 Markdown转纯文本;要拼表格走 Markdown表格生成器。本页不做表格、脚注、数学公式的渲染,也不做语法高亮。

原理与规则说明

解析分两个阶段,块级优先于行内。第一阶段按行扫描,先识别块级结构——围栏代码块、ATX 与 Setext 标题、水平线、引用、列表、段落;第二阶段才对段落、标题、列表项、引用的文本内容做行内解析(粗体、斜体、删除线、行内代码、链接、图片)。这个顺序很重要:如果反过来先做行内,「*」和反引号会先被当成强调或代码,破坏后面判断引用符与列表符的能力。

转义必须先于任何标签生成。本页对每一段文本内容先做三次替换——& 变 &amp;、< 变 &lt;、> 变 &gt;——然后才拼 <strong> 这类自己的标签。顺序反了就会出事:若先生成 <strong> 再整体转义,你生成的标签也会被转义成可见文本;若先转义但漏了某处,原文里的 <script> 就会变成真标签。至于链接的 URL 与标题,因为要放进属性里,额外把双引号转成 &quot;,避免属性被提前闭合。

代码块与行内代码内部不再解析。行内解析的第一步就是把反引号包裹的内容整体抽出、替换成占位符,占位符在最后一步才还原;围栏代码块则在块级阶段整体跳过。所以代码块里的 ** 不会被当成粗体、< 也不会被当成标签,只会被转义成可见字符,保证贴代码进去不会走样。

列表嵌套按相对缩进递归。本页用「同一块内缩进更大的行属于上一项的子列表」这条规则递归处理:- a 下一行写两个空格再写 - b,就被识别为 a 的子列表;写四个空格也识别为子列表。这与 CommonMark 的直观行为一致(CommonMark 允许 1~3 个空格的松散缩进),但比严格实现宽松;不追求与某个库逐字节一致,只保证结果可预测。

本实现明确不支持的语法:表格(| a | b |)、脚注([^1])、数学公式($x$)、自动链接(<http://…>)、原始 HTML 内联(<div> 会被转义成文本)、引用式链接([x][id])与自定义容器语法。这些不是「忘了实现」,而是刻意收窄:每多支持一种方言,解析器的分支与出错可能就多一层,而转义规则一旦有缺口就是安全问题。需要表格请用表格生成器,其余语法请在上游把 Markdown 改写成本页支持的写法。

安全铁律:生成结果永远只写进输出文本框的 value,绝不使用 innerHTML 把它注入页面。也就是说,即使解析器有未知缺口、即使原文里塞了 <img onerror=…>,它也只会出现在文本框里当字符显示,不可能被浏览器执行。这是这一页能在「自实现解析」同时守住安全的根本原因。

完整示例(数值仅作演示)

Markdown转HTML转换器左侧预置的 29 行示例覆盖了最常出错的几类结构,逐段看它转出来的结果:

整份输出 29 行输入生成 57 个标签、632 字符,统计条上的数字与右侧框内容一致,可复制出去用浏览器打开复核。

输入范围与对照表

输入上限 20 万字符(解析在主线程同步执行,超长会阻塞页面);单次解析 29 行示例在毫秒级完成。下面这张表把本页支持与不支持的语法一次列清,默认 12 行,可加载更多:

Markdown 写法本页支持输出与说明
# 标题支持1~6 个 # 生成 h1~h6
标题下加 ===支持Setext 一级标题,生成 h1
标题下加 ---支持Setext 二级标题,生成 h2
**粗体**支持生成 strong(__ 亦可)
*斜体*支持生成 em(_ 亦可)
~~删除线~~支持(GFM)生成 del,CommonMark 原文没有
`行内代码`支持生成 code,内部不再解析
三反引号围栏支持生成 pre+code,可带 language 类
- 列表 / 1. 列表支持生成 ul / ol,2 空格算嵌套
> 引用支持生成 blockquote
[文字](链接)支持生成 a,属性值做转义
单独一行 ---支持生成 hr

输入范围、边界与精度说明

输入规模边界:上限 20 万字符。本页解析器是同步的字符串处理,20 万字符在普通电脑上仍是毫秒级;真正需要限制的是「一次粘贴几十兆文件」这种把主线程拖住的操作,所以到阈值直接给出中文提示并停止,不做静默截断——截断会产出缺斤少两的 HTML,比报错危险。

未闭合围栏按到文末处理。若 ``` 只有开头没有结尾,本页把其后的所有行都当作代码块内容输出到 <pre><code> 里,而不是报错。这是 CommonMark 的容错行为:未闭合围栏在规范里就是「一直到文档结束」,照此处理能让用户一眼看出少写了结束围栏。

空输入与纯空白:都返回空字符串,不生成空 <p></p>。段落只在遇到非空行时才开始,连续空行被折叠,不会输出空标签——空标签在嵌入模板时是常见的排版噪音来源。

列表缩进的取舍:本页用「缩进量比较」判定层级,而不是严格按 CommonMark 的 1~3 空格容器规则。代价是对 4 空格这种「看似代码块实为嵌套」的写法,本页一律按嵌套列表处理;收益是实现简单、行为可预测。若你确实需要把 4 空格缩进当成代码块,请改用三反引号围栏。

强调符号的边界:本页按「** 优先于 *、__ 优先于 _」的顺序替换,并且要求强调标记紧邻非空白字符。像 a * b * c 这种两侧有空格的星号不会被当成斜体,会被原样保留——这是为了避免把算术里的乘号误判成强调。

与规范的差异要讲清:本页实现的是「CommonMark 的一个子集 + GFM 删除线」,不追求通过 CommonMark 全部约 650 条一致性用例。它覆盖日常写文档需要的语法,明确不支持的那几类都列在对照表里,宁可不支持也不做半吊子解析——半吊子解析会产出看似成功、实际语义错位的 HTML。

常见问题

为什么我的表格没有被渲染成表格?

本页明确不支持表格语法,| a | b | 会被当成普通段落整行输出。这是刻意的收窄:表格解析要处理对齐行、转义竖线、单元格内行内标记,分支多且容易与段落判定互相干扰。需要表格请用站内的 Markdown表格生成器 生成,再把结果贴进正文。

我原文里有 <div> 标签,为什么转出来是文字?

因为本页先转义再生成标签,原始 HTML 一律变成可见文本,不解析、不执行。这是安全设计而非缺陷:很多平台正是因为允许内联 HTML,才被 <script> 或 <img onerror> 注入。若你确实需要内联 HTML,请在上游手动处理,本页不做。

结果会不会被页面当成真的 HTML 执行?

不会。生成结果只写进输出文本框的 value,从不通过 innerHTML 注入页面,所以哪怕原文塞了恶意标签,也只会在框里当字符显示。你可以复制走,也可以下载成文件,但在这个页面上它始终是纯文本。

为什么粗体在代码块里没生效?

因为代码块与行内代码内部一律不解析。这是规范行为:代码是「原样呈现」的区域,里面的星号、反引号、尖括号都应该保留原貌。示例里的 var x = a < b && c > d; 就是靠这条规则,把 < 与 && 原样转义保留下来。

下载的 HTML 为什么没有 BOM?CSV 却有?

因为两个格式的生态约定相反:BOM(U+FEFF)会让 JSON.parse 直接报错、让 HTML 文件多出不可见字符,所以 HTML 与 JSON 一律不带;而 Excel 打开不带 BOM 的 CSV 会出现中文乱码,所以 CSV 必须带。本页按各自惯例处理,下载按钮旁的提示也写明了这一点。

列表嵌套要缩进几个空格?2 个还是 4 个?

本页两种都能识别,因为它按「缩进量比上一项大就是子列表」处理,而不是硬性要求某一个数值。CommonMark 官方允许 1~3 个空格的松散缩进,社区里 2 空格与 4 空格都常见。取一致即可,别在同一份文档里混用,混用会让层级看起来乱。

20 万字符以上怎么办?

本页会提示超出上限并停止转换,不会截断。原因是解析同步执行,兆级输入会明显卡住页面;而且截断产出的 HTML 是残缺的,用户很难发现。真要处理超大文档,请先在本地拆分成几段分别转换,或改用命令行工具。

它和在线 Markdown 编辑器、HTML转Markdown 是什么关系?

方向与用途不同:在线Markdown编辑器偏实时预览与写作,本页偏「看清标签结构」与安全转义;HTML转Markdown转换器 是本页的逆方向;只要去掉标签文本则用 去除HTML标签。按你要的结果挑一个即可。

相关工具