Markdown 转 HTML 是现代 Web 开发中最重要的工作流之一。每天有数百万开发者、技术作者和内容创作者使用 Markdown 转换器将轻量级纯文本格式转换为结构化 HTML。无论你需要为博客文章转换 Markdown、在 GitHub 上渲染 README 文件,还是使用 Markdown 解析器构建文档站点,理解这个转换管道至关重要。如果你需要快速在线将 Markdown 转换为 HTML,我们的免费工具可以即时完成,并提供实时预览和语法高亮。
立即试用我们的免费在线 Markdown 转 HTML 转换工具。
TL;DR (太长不看)
Markdown 是一种轻量级纯文本格式化语言,可转换为 HTML。JavaScript 中推荐 markdown-it(可扩展、符合 CommonMark)或 marked(轻量快速)。Python 中使用 mistune(最快)或 markdown 库。命令行使用 pandoc。React 项目用 react-markdown 或 MDX。GFM(GitHub Flavored Markdown)添加了表格、任务列表和删除线。始终对用户输入的 Markdown 进行 XSS 清理。使用 @tailwindcss/typography 的 prose 类为输出添加样式。
核心要点
- Markdown 通过三阶段管道(词法分析、AST 构建、HTML 渲染)转换为 HTML
- CommonMark 是基础规范,GFM 添加了表格、任务列表、删除线等扩展
- 主流库对比:marked(快速轻量)、markdown-it(可扩展)、remark(AST 驱动)、Goldmark(Go 语言)
- 安全第一:始终对用户生成的 Markdown 使用 DOMPurify 等工具清理 XSS
- 高级扩展包括数学公式(KaTeX)、Mermaid 图表、Front Matter 和目录生成
什么是 Markdown?
Markdown 是由 John Gruber 于 2004 年创建的轻量级标记语言,Aaron Swartz 也做出了重要贡献。其目标是创建一种易于阅读和编写的纯文本格式化语法,可以转换为结构化的 XHTML 或 HTML。与使用冗长尖括号标签的 HTML 不同,Markdown 语法使用直观的标点字符(如星号、井号和方括号)来表示格式。
自创建以来,Markdown 已成为 Web 内容编写的事实标准。GitHub 用于 README 文件、Issue 和 Pull Request;Reddit 用于评论和帖子;Stack Overflow 用于问答。Hugo、Jekyll、Gatsby 和 Astro 等静态站点生成器都使用 Markdown 文件生成 HTML 页面。
Markdown 的吸引力在于其简洁性和可移植性。.md 文件只是纯文本,可以在任何文本编辑器、版本控制系统或操作系统中使用。没有供应商锁定、没有专有格式、没有二进制编码。当你需要发布内容时,Markdown 转 HTML 转换器将纯文本源转换为浏览器可以渲染的语义化 HTML。
Markdown 语法参考
理解 Markdown 语法是有效进行 Markdown 转 HTML 转换的第一步。以下是最常用格式化元素及其 HTML 等价物的全面参考:
标题:使用 # 到 ###### 表示 1 到 6 级标题。例如 # 标题 变为 <h1>,## 副标题 变为 <h2>。
粗体和斜体:单个星号或下划线表示斜体,双星号表示粗体,三星号表示粗斜体。Markdown 渲染器将其转换为 <em> 和 <strong> 标签。
链接和图片:使用 [文本](URL) 创建链接, 创建图片。这些在 HTML 中转换为 <a href> 和 <img src> 标签。
代码:行内代码使用反引号:`code` 变为 <code>。围栏代码块使用三个反引号,可选语言标识符用于语法高亮。
列表:无序列表使用 -、* 或 + 作为标记。有序列表使用数字加句点。嵌套列表通过缩进创建。
引用:在行首添加 > 创建引用块。可以嵌套,可以包含其他 Markdown 元素。
表格:使用管道符(|)和连字符(-)创建表格。冒号控制对齐方式。
水平线:三个或更多连字符(---)、星号(***)或下划线(___)创建 <hr> 元素。
任务列表:使用 - [ ] 表示未完成,- [x] 表示已完成项目。
Markdown 转 HTML 的工作原理
Markdown 解析器通过多阶段管道将纯文本 Markdown 转换为 HTML。典型的转换过程包含三个主要阶段:
阶段 1 - 词法分析(Tokenization):解析器逐字符读取原始 Markdown 字符串,将其分解为令牌流。每个令牌代表一个有意义的元素:标题标记、段落文本、代码围栏、列表标记、强调标记等。
阶段 2 - AST 构建(解析):令牌流被组织成抽象语法树(AST),这是一种表示文档结构的层次数据结构。AST 中的每个节点对应一个 Markdown 元素。
阶段 3 - HTML 渲染:深度优先遍历 AST,将每个节点转换为对应的 HTML 元素。标题节点变为 <h1>-<h6>,段落变为 <p>,强调变为 <em>。
CommonMark 规范提供了 Markdown 语法的严格、无歧义定义。在 CommonMark 之前,不同解析器对相同输入会产生不同输出。CommonMark 通过 600 多个示例解决了这些歧义。
代码示例:Markdown 转 HTML
JavaScript / Node.js(marked、markdown-it、showdown、remark)
JavaScript 拥有最丰富的 Markdown 转 HTML 生态系统。以下是最流行的库及其使用示例:
// ===== marked.js (fast, lightweight) =====
import { marked } from 'marked';
const markdown = '# Hello World\n\nThis is **bold** and *italic*.';
const html = marked(markdown);
// <h1>Hello World</h1>
// <p>This is <strong>bold</strong> and <em>italic</em>.</p>
// Configure marked options
marked.setOptions({
gfm: true, // GitHub Flavored Markdown
breaks: true, // Convert \n to <br>
pedantic: false, // Conform to CommonMark
sanitize: false, // Use DOMPurify instead
});
// ===== markdown-it (extensible, plugin-based) =====
import MarkdownIt from 'markdown-it';
import markdownItAnchor from 'markdown-it-anchor';
import markdownItToc from 'markdown-it-toc-done-right';
const md = new MarkdownIt({
html: true, // Allow HTML tags in source
linkify: true, // Auto-convert URLs to links
typographer: true, // Smart quotes, dashes
})
.use(markdownItAnchor) // Add anchors to headings
.use(markdownItToc); // Generate table of contents
const result = md.render('# Hello\n\n${toc}\n\n## Section 1\n\nContent here.');
// ===== showdown (browser + Node.js) =====
import showdown from 'showdown';
const converter = new showdown.Converter({
tables: true,
tasklists: true,
strikethrough: true,
ghCodeBlocks: true,
});
const htmlOutput = converter.makeHtml('## Hello\n\n- [x] Task done');
// ===== unified / remark ecosystem (AST-based) =====
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypePrism from 'rehype-prism-plus';
const file = await unified()
.use(remarkParse) // Parse Markdown to mdast
.use(remarkGfm) // Support GFM (tables, etc.)
.use(remarkRehype) // Transform mdast to hast
.use(rehypePrism) // Syntax highlighting
.use(rehypeStringify) // Serialize hast to HTML
.process('# Hello **World**');
console.log(String(file));
// <h1>Hello <strong>World</strong></h1>Python(markdown、mistune、markdown2)
Python 提供了多个优秀的 Markdown 转 HTML 库:
# ===== markdown library (standard, extensible) =====
import markdown
# Basic conversion
md_text = "# Hello World\n\nThis is **bold** text."
html = markdown.markdown(md_text)
# <h1>Hello World</h1>
# <p>This is <strong>bold</strong> text.</p>
# With extensions
html = markdown.markdown(md_text, extensions=[
'tables', # GFM-style tables
'fenced_code', # Fenced code blocks
'codehilite', # Syntax highlighting (requires Pygments)
'toc', # Table of contents
'footnotes', # Footnote support
'attr_list', # Attribute lists for styling
'md_in_html', # Markdown inside HTML blocks
])
# ===== mistune (fastest Python Markdown parser) =====
import mistune
# Basic usage
html = mistune.html(md_text)
# Custom renderer for advanced control
renderer = mistune.create_markdown(
escape=False,
plugins=['table', 'footnotes', 'strikethrough', 'task_lists']
)
html = renderer(md_text)
# ===== markdown2 (simple API, many extras) =====
import markdown2
html = markdown2.markdown(md_text, extras=[
"fenced-code-blocks",
"tables",
"strike",
"task_list",
"code-friendly",
"cuddled-lists",
"header-ids",
"metadata",
])
# Convert a file
with open("README.md", "r") as f:
html = markdown2.markdown(f.read(), extras=["fenced-code-blocks"])
# Python-Markdown extension: convert file to HTML file
import markdown
md = markdown.Markdown(extensions=['meta', 'toc'])
md.convertFile(input='doc.md', output='doc.html')Bash / CLI(pandoc、cmark、grip)
命令行工具让你可以直接从终端将 Markdown 转换为 HTML:
# ===== pandoc (universal document converter) =====
# Basic Markdown to HTML
pandoc README.md -o output.html
# With standalone HTML (includes <head>, <body>)
pandoc README.md -s -o output.html
# With table of contents and syntax highlighting
pandoc README.md -s --toc --highlight-style=tango -o output.html
# GFM input format
pandoc -f gfm -t html README.md -o output.html
# With custom CSS
pandoc README.md -s --css=style.css -o output.html
# Convert multiple files
pandoc ch1.md ch2.md ch3.md -s --toc -o book.html
# ===== cmark (reference CommonMark implementation) =====
# Basic conversion
cmark README.md > output.html
# With smart typography (quotes, dashes)
cmark --smart README.md > output.html
# GFM extensions (cmark-gfm)
cmark-gfm -e table -e strikethrough -e tasklist README.md
# ===== grip (GitHub-flavored preview) =====
# Preview README in browser (uses GitHub API)
grip README.md
# Export to HTML file
grip README.md --export output.html
# Preview on specific port
grip README.md 0.0.0.0:8080
# ===== Simple pipe conversion with Node.js =====
echo "# Hello **World**" | npx marked
# <h1>Hello <strong>World</strong></h1>
cat README.md | npx marked > output.htmlReact / Next.js(react-markdown、MDX、rehype)
在 React 和 Next.js 应用中,Markdown 转 HTML 转换在组件级别进行:
// ===== react-markdown (React component) =====
import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';
import rehypeHighlight from 'rehype-highlight';
function MarkdownPreview({ content }: { content: string }) {
return (
<ReactMarkdown
remarkPlugins={[remarkGfm]}
rehypePlugins={[rehypeHighlight]}
components={{
// Custom component overrides
h1: ({ children }) => (
<h1 className="text-3xl font-bold mb-4">{children}</h1>
),
a: ({ href, children }) => (
<a href={href} className="text-blue-600 hover:underline"
target="_blank" rel="noopener noreferrer">
{children}
</a>
),
code: ({ className, children, ...props }) => {
const isInline = !className;
return isInline
? <code className="bg-gray-100 px-1 rounded">{children}</code>
: <code className={className} {...props}>{children}</code>;
},
}}
>
{content}
</ReactMarkdown>
);
}
// ===== MDX (Markdown + JSX) in Next.js =====
// next.config.js
import createMDX from '@next/mdx';
const withMDX = createMDX({
extension: /\.mdx?$/,
options: {
remarkPlugins: [remarkGfm],
rehypePlugins: [rehypeHighlight],
},
});
export default withMDX({
pageExtensions: ['ts', 'tsx', 'md', 'mdx'],
});
// app/blog/[slug]/page.tsx
import { MDXRemote } from 'next-mdx-remote/rsc';
export default async function BlogPost({ params }) {
const source = await getMarkdownContent(params.slug);
return <MDXRemote source={source} />;
}
// ===== Syntax highlighting with Shiki =====
import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeShiki from '@shikijs/rehype';
import rehypeStringify from 'rehype-stringify';
const html = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeShiki, { theme: 'github-dark' })
.use(rehypeStringify)
.process(markdownContent);GitHub 风格 Markdown(GFM)
GitHub Flavored Markdown(GFM)是 GitHub 开发的 CommonMark 超集。它添加了软件开发工作流中必不可少的功能。
表格:GFM 表格使用管道符和连字符语法。支持用冒号控制列对齐。大多数 Markdown 解析器库将 GFM 表格转换为完整的 HTML <table> 结构。
任务列表:GFM 任务列表在 GitHub Issue 和 PR 中渲染为复选框,常用于跟踪功能、Bug 修复和项目里程碑的进度。
删除线:用双波浪号包裹文本(~~已删除~~)渲染为删除线文本,使用 <del> 标签。
自动链接:GFM 自动将 URL 和电子邮件地址转换为可点击的链接。
脚注和提醒:扩展 GFM 支持脚注([^1])和提醒块(> [!NOTE]、> [!WARNING] 等)。
<!-- GFM Examples and their HTML output -->
<!-- Table with alignment -->
| Feature | CommonMark | GFM |
|:--------------|:----------:|------:|
| Tables | No | Yes |
| Task Lists | No | Yes |
| Strikethrough | No | Yes |
| Autolinks | No | Yes |
<!-- Converts to: -->
<table>
<thead>
<tr>
<th style="text-align:left">Feature</th>
<th style="text-align:center">CommonMark</th>
<th style="text-align:right">GFM</th>
</tr>
</thead>
<tbody>...</tbody>
</table>
<!-- Task list -->
- [x] Write the documentation
- [x] Add code examples
- [ ] Publish the article
<!-- Strikethrough -->
~~This text is deleted~~
<!-- Autolink -->
Visit https://example.com for details.
<!-- Footnote -->
Here is a statement[^1] with a footnote.
[^1]: This is the footnote content.
<!-- Alert blocks (GitHub-specific) -->
> [!NOTE]
> This is a note callout.
> [!WARNING]
> This is a warning callout.高级 Markdown 功能
除了基本和 GFM 语法外,Markdown 转 HTML 生态系统通过扩展和插件支持许多高级功能:
自定义容器/指令:markdown-it-container 和 remark-directive 等库允许使用冒号围栏语法定义自定义块元素,用于创建样式化的提示框和文档内容块。
数学公式(KaTeX / MathJax):行内数学使用 $E = mc^2$,块级数学使用 $$...$$。remark-math 配合 rehype-katex 可将 LaTeX 数学表达式渲染为公式。
Mermaid 图表:Mermaid 使用类 Markdown 的文本语法生成流程图、序列图、甘特图等。通过在围栏代码块中嵌入 Mermaid 代码,可直接从文本生成 SVG 图表。
Front Matter:Markdown 文件顶部的 YAML 前置元数据(--- 分隔)存储标题、日期、作者、标签等。静态站点生成器解析这些元数据生成页面标题和 URL。
目录生成:许多 Markdown 解析器插件可以从标题结构自动生成目录(TOC),如 remark-toc 和 markdown-it-toc-done-right。
<!-- Custom container (markdown-it-container) -->
::: warning
This is a warning message. Be careful!
:::
<!-- Renders as: -->
<div class="warning">
<p>This is a warning message. Be careful!</p>
</div>
<!-- Math with KaTeX -->
Inline math: $E = mc^2$
Display math:
$$
\sum_{i=1}^{n} x_i = \frac{n(n+1)}{2}
$$
<!-- Mermaid diagram -->
```mermaid
graph TD
A[Markdown Source] --> B[Tokenizer]
B --> C[AST Builder]
C --> D[HTML Renderer]
D --> E[HTML Output]
```
<!-- Front matter (YAML) -->
---
title: "My Blog Post"
date: 2024-01-15
author: "John Doe"
tags: [markdown, html, tutorial]
---
# My Blog Post
Content starts here...
<!-- Table of contents (remark-toc) -->
## Table of Contents
<!-- Auto-generated from headings -->
- [Introduction](#introduction)
- [Getting Started](#getting-started)
- [Advanced Usage](#advanced-usage)Markdown 最佳实践
遵循最佳实践可确保你的 Markdown 文件一致、可访问,并在 Markdown 转 HTML 转换时产生干净的输出:
一致的标题层级:始终从单个 H1 开始,按顺序使用后续级别,不要跳级。这创建了有利于屏幕阅读器和 SEO 的文档大纲。
图片描述性替代文本:始终在  语法中提供有意义的替代文本。良好的替代文本提高可访问性(WCAG 合规)。
语义换行:考虑在句子或逻辑短语边界处换行,而不是固定列宽。这使版本控制系统中的差异更易读。
使用 markdownlint 进行检查:使用 markdownlint(CLI 工具、VS Code 扩展或 GitHub Action)在 Markdown 文件中强制执行一致的样式。
可访问性考虑:确保正确的标题结构、描述性链接文本、仅对表格数据使用表格,以及在代码块中包含语言标识符。
另请参阅我们的 HTML 转 Markdown 转换器进行反向转换,以及 字数统计工具检查内容长度。
常见问题
如何将 Markdown 转换为 HTML?
你可以使用多种工具和库将 Markdown 转换为 HTML。JavaScript 中流行的选择包括 marked.js、markdown-it、showdown 和 unified/remark 生态系统。Python 中可使用 markdown 库、mistune 或 markdown2。命令行转换可使用 pandoc 和 cmark。转换过程涉及将 Markdown 语法解析为令牌、构建抽象语法树(AST)并将 AST 渲染为 HTML 元素。
最好的 Markdown 转 HTML 库是什么?
最佳库取决于你的使用场景。JavaScript 中 markdown-it 最受欢迎,因其速度快、符合 CommonMark 规范且有丰富的插件生态。React 应用中 react-markdown 是标准选择。Python 中 mistune 是最快的解析器。如需通用命令行工具,pandoc 支持数十种格式之间的转换。
GFM 和 CommonMark 有什么区别?
CommonMark 是原始 Markdown 语法的严格、无歧义规范。GFM 是 CommonMark 的超集,添加了软件开发中常用的扩展:表格、任务列表、删除线、自动链接等。大多数现代 Markdown 解析器同时支持 CommonMark 和 GFM,通常通过配置标志启用 GFM 扩展。
能在 React 和 Next.js 中使用 Markdown 吗?
可以。最流行的方法是使用 react-markdown 包,它将 Markdown 渲染为 React 组件。MDX 允许在 Markdown 中嵌入 JSX 组件。Next.js 中可使用 @next/mdx 或在构建时用 remark 和 rehype 插件处理 Markdown。unified 生态系统提供与 React 服务端组件无缝集成的 AST 转换。
如何为 Markdown 代码块添加语法高亮?
语法高亮需要两个步骤:解析器保留代码围栏的语言标识符,然后高亮库处理代码。常用选项包括 Prism.js、Shiki 和 highlight.js。在服务端渲染中,推荐使用 Shiki,因为它生成内联样式,无需客户端 JavaScript。
Markdown 是否安全,能防止 XSS 攻击吗?
原始的 Markdown 转 HTML 可能存在 XSS 漏洞。大多数解析器默认允许原始 HTML。为防止 XSS,请使用 DOMPurify 等清理库,或配置解析器禁用原始 HTML。GFM 默认禁止某些危险的 HTML 标签。始终在浏览器渲染前对用户生成的 Markdown 进行清理。
如何为 Markdown 生成的 HTML 添加样式?
最佳方法是将渲染的 HTML 包裹在容器元素中,使用 CSS 为子元素添加样式。Tailwind CSS 的 @tailwindcss/typography 插件提供 prose 类。GitHub 提供开源的 github-markdown-css 样式表。React 应用中可使用 react-markdown 的自定义渲染器组件。
总结
Markdown 转 HTML 是每个 Web 开发者和技术作者的基础技能。从理解解析管道到为你的技术栈选择合适的库,掌握 Markdown 转 HTML 工作流使你能够构建文档站点、博客和内容丰富的应用。收藏本指南以备参考,并使用我们的免费在线工具进行即时转换。