design

Markdown to HTML: Chọn Converter Nào Cho Công Việc Nào (Kèm Cheatsheet)

Cùng một file Markdown tạo HTML khác nhau tuỳ theo công cụ. Converter nào cho browser, pandoc, Python, JS, VS Code — kèm cheatsheet.

Published 2026-09-03 · 8 min read

Affiliate disclosure

Some links below are affiliate links. I may earn a commission from qualifying purchases at no extra cost to you. Recommendations come from published specifications and independent reviews, not hands-on testing.

Markdown to HTML conversion on a developer's laptop screen — original hero illustration
AI illustration

Dán một file Markdown vào hai converter khác nhau và bạn có thể nhận được hai document khác nhau. Không phải formatting khác, mà là structure khác. Một bảng trở thành <table> thực sự trong một tool nhưng xuất hiện dưới dạng paragraph chứa đầy ký tự pipe trong công cụ khác, và không có công cụ nào bị lỗi cả.

Đó là phần hầu hết các hướng dẫn "markdown to html converter" bỏ qua, và đó là phần quyết định công cụ nào bạn thực sự nên dùng.

TL;DR — Với một lần dán một lần, dùng browser converter như Markdown to HTML tool của chúng tôi. Cho công việc batch và pipeline docs, dùng pandoc. Để convert bên trong app của bạn, dùng markdown-it (JavaScript) hoặc package markdown (Python). Nếu Markdown đến từ user, sanitize HTML sau đó với DOMPurify bất kể converter nào tạo ra nó.

Tại sao cùng một Markdown tạo HTML khác nhau?

Không có một Markdown duy nhất. Bản phát hành ban đầu năm 2004 bởi John Gruber và Aaron Swartz là một Perl script và mô tả prose, không phải specification, và các triển khai lệch nhau trong một thập kỷ.

CommonMark tồn tại để kết thúc sự lệch đó. Đó là một precise spec, hiện tại phiên bản 0.31.2 và phát hành tháng Một 2024, bắt đầu năm 2014 bởi John MacFarlane với kỹ sư từ GitHub, Reddit, Stack Overflow và Discourse. GitHub Flavored Markdown là một strict superset của CommonMark thêm bảng, strikethrough, task list và autolink.

Khoảng cách giữa hai cái đó là nơi hầu hết bất ngờ sống. Lấy input này:

| Fruit | Qty |
|---|---|
| Apple | 3 |
| Pear  | 5 |

Converted với pandoc -f commonmark -t html, các pipe là text literal:

<p>| Fruit | Qty | |---|---| | Apple | 3 | | Pear | 5 |</p>

Converted với pandoc -f gfm -t html, bạn nhận được bảng mà bạn mong đợi:

<table><thead><tr><th>Fruit</th><th>Qty</th></tr></thead>
<tbody><tr><td>Apple</td><td>3</td></tr><tr><td>Pear</td><td>5</td></tr></tbody></table>

Cùng file, cùng program, một flag cách nhau. Sự chia tách tương tự tái tạo trong codebase không liên quan: new MarkdownIt('commonmark') render ~~strike~~ dưới dạng text literal, trong khi new MarkdownIt() render <s>strike</s>. Vì vậy đây không phải là pandoc quirk. Đây là ranh giới CommonMark/GFM chính nó.

Hệ quả thực tế: khi output trông sai, câu hỏi đầu tiên không phải "tool này có bug không" mà "flavor nào mà tool này đang parse".

Làm sao bạn biết được converter nào dùng flavor nào?

Hầu hết converter trực tuyến không bao giờ nêu rõ parser nào ở phía sau, vì vậy test nó chứ không tin nó. Dán probe bốn dòng này vào bất kỳ tool nào và đọc output:

| a | b |
|---|---|
| 1 | 2 |

~~strike~~ and a task: - [x] done

Nếu bảng render dưới dạng bảng và strike xuất hiện strikethrough, bạn đang trên GFM-capable parser. Nếu cái nào cũng trả về dưới dạng punctuation literal, tool đang chạy gần hơn plain CommonMark, và bất kỳ document nào bạn convert với nó đều sẽ mất các construct đó trong im lặng. Im lặng là từ chính xác: không có lỗi, output chỉ im lặng mất structure.

Có một gia đình thứ ba đáng biết, vì nó giải thích output không khớp với cả hai kết quả. PHP Markdown Extra, được maintain bởi Michel Fortin kể từ 2003, thêm footnote, definition list, abbreviation và attribute ID như {#id}. Nó ở đằng sau nhiều ecosystem PHP và CMS cũ, vì vậy một file render một cách trong tool WordPress-era và một cách khác trên GitHub thường là vượt qua ranh giới đó chứ không phải hit a bug.

Converter nào nên dùng cho công việc nào?

MethodSetup costBest forBad fit for
Browser toolZeroOne-off paste, no install, works on a phoneAutomation; confidential text you haven't checked
pandoc CLIMedium (~279MB)Batch conversion, docs pipelines, many output formatsA single quick paste; embedding in a web request
Python (markdown)Low (pip)Django/Flask backends, static site generatorsClient-side rendering
JS (markdown-it, marked)Low (npm)Web apps, live preview, Node backendsOne-off internal scripts
VS Code extensionLow, one-timeDevs already writing docs in the editorNon-technical users, automation

Khi nào pandoc là tool đúng?

Pandoc là tool đúng một khi bạn đang convert nhiều hơn một vài file, hoặc convert sang nhiều format từ một source. Phiên bản 3.11 là current.

brew install pandoc                       # macOS
winget install --exact --id JohnMacFarlane.Pandoc   # Windows

Trên Debian và Ubuntu, apt install pandoc hoạt động nhưng ship lạc hậu. Ubuntu 26.04 carry 3.7.0.2 và một số Debian branch thậm chí còn cũ hơn. Nếu bạn cần current behaviour, lấy .deb từ releases page thay vào đó.

pandoc input.md -o output.html      # HTML fragment
pandoc -s input.md -o output.html   # standalone document with <html> and <head>

Flag -f là flavor selector mà section trên thực sự là về: -f commonmark, -f gfm, -f markdown_strict, hoặc extended dialect của pandoc by default.

Một caveat đáng biết trước khi bạn diff output so với tool khác: pandoc không phát ra plain <pre><code> cho fenced code block. Nó bao bọc chúng trong <div class="sourceCode"> với syntax-highlighting span. Đó là deliberate choice, không phải bug, nhưng nghĩa là HTML của pandoc không byte-comparable với library dưới đây.

Skip pandoc nếu bạn đang convert một paragraph dán. Một 279MB install để convert changelog một lần là trade sai, và pandoc là native binary — shell out tới nó bên trong web request path để xử lý user input là operational và security smell.

Làm sao bạn convert Markdown bên trong app của bạn?

Python. Package markdown là câu trả lời phổ biến. Bản phát hành hiện tại là 3.10.3, nhưng lưu ý nó yêu cầu Python 3.10 hoặc mới hơn — trên Python 3.9, pip install Markdown im lặng resolve thành 3.9 thay vì fail.

import markdown
html = markdown.markdown(text)                                        # bare
html = markdown.markdown(text, extensions=['tables', 'fenced_code'])  # tables + code blocks

Dòng thứ hai quan trọng hơn nó trông. Không có fenced_code, một triple-backtick block không trở thành <pre><code> ở tất cả — nó sập thành một inline <code> run duy nhất bên trong paragraph. Nếu bạn từng tự hỏi tại sao code sample của bạn xuất hiện bị hỏng, đây thường là tại sao. markdown-it-py (4.2.0) là alternative khi bạn muốn strict CommonMark compliance hoặc plugin architecture.

JavaScript. Hai library chiếm ưu thế, và sự khác biệt giữa chúng là security posture, không phải feature list.

npm install markdown-it   # or: npm install marked
import MarkdownIt from 'markdown-it';
const html = new MarkdownIt().render('# markdown-it rulezz!');

marked (18.0.11) là nhanh và permissive: raw HTML pass through untouched by default. markdown-it (15.0.1) là CommonMark-compliant và escape raw HTML by default, và html: false là literal default trong own preset source của nó. Cho web app render Markdown bạn không viết, đó là default bạn muốn.

Có an toàn không để convert Markdown bạn không viết?

Markdown cho phép inline HTML by design, vì vậy converter không phải là sanitizer và hầu hết không claim thế. Cho cả hai library string Hello <script>alert(1)</script> với tùy chọn mặc định và chúng không đồng ý: marked phát ra script tag intact, markdown-it escape nó thành harmless text.

marked từng ship sanitizesanitizer option. Cả hai đều deprecated trong v0.7.0 và removed trong v8.0.0; tài liệu của library giờ point tới DOMPurify (3.4.14) thay vào đó:

import DOMPurify from 'dompurify';
const clean = DOMPurify.sanitize(marked.parse(input));

Ba điều theo sau. Sanitize bất cứ khi nào Markdown là user-submitted — comments, wikis, issue trackers, bất kỳ cái nào bạn không author. Làm nó bất kể library, vì markdown-it's safe default là một html: true cách từ bị unsafe và Python's markdown package không sanitize either. Và lưu ý DOMPurify là DOM-based: trong browser nó hoạt động natively, nhưng server-side trong Node nó cần jsdom.

Nếu bạn chỉ cần display Markdown dưới dạng visible text chứ không render nó, escaping angle bracket với HTML entity encoder sidestep câu hỏi hoàn toàn.

Markdown to HTML cheatsheet

MarkdownHTMLSpec
# H1###### H6<h1><h6>CommonMark
**bold**<strong>CommonMark
*italic*<em>CommonMark
`code`<code>CommonMark
[text](url)<a href="url">CommonMark
![alt](url)<img src="url" alt="alt">CommonMark
- item<ul><li>CommonMark
1. item<ol><li>CommonMark
> quote<blockquote><p>CommonMark
fenced block<pre><code class="language-…">CommonMark
---<hr>CommonMark
~~text~~<del> (MDN)GFM only
| a | b |<table><thead>…<tbody>GFM only
- [x] done<li><input type="checkbox" checked disabled>GFM only

Ba hàng GFM-only là những thứ break khi bạn di chuyển file từ GitHub sang stricter parser.

Làm sao bạn export sang HTML từ VS Code hoặc browser?

Built-in preview của VS Code (Cmd+Shift+V, hoặc Ctrl+Shift+V) render Markdown nhưng không export nó. Tài liệu không mô tả bất kỳ built-in save-as-HTML command nào. Thêm Markdown All in One (yzhang.markdown-all-in-one) và lệnh "Print current document to HTML" của nó, hoặc Markdown PDF (yzane.markdown-pdf), export HTML despite tên của nó.

Browser converter là route nhanh nhất cho single paste và cái duy nhất hoạt động trên phone. Trade-off là hầu hết không disclose parser nào chúng dùng, vì vậy bạn không thể assume flavor, và bạn nên biết text có rời khỏi device của bạn không. Điều đó checkable trong khoảng mười giây: mở devtools, watch Network tab, chạy conversion, và tìm outgoing POST mang text của bạn. Genuinely client-side tool không make request nào cả. Làm check đó trước khi dán bất kỳ cái gì proprietary.

Verdict

Chọn theo công việc, không phải theo popularity. One-off paste muốn browser converter; docs pipeline muốn pandoc; application render Markdown muốn markdown-it plus DOMPurify. Rule duy nhất span tất cả chúng là Markdown là một gia đình dialect chứ không phải format, vì vậy name flavor của bạn trước khi debug output — và nếu bạn cũng work across config format, cùng lesson áp dụng cho lựa chọn giữa JSON, YAML và TOML và cho biết khi nào browser tool beat CLI.

Cái bạn không nên làm là viết converter yourself. Unbalanced asterisk, escaped literal, emphasis bên trong link text và doubled-backtick code span đều parse chính xác dưới real library và đều break chain regex replacement. Grammar của Markdown là context-sensitive; một npm install buy bạn một thập kỷ edge case đã được handle.

Đọc tiếp

Phần mềm chỉnh sửa ảnh được hiển thị trên màn hình laptop.

design

Nén Hình Ảnh Mà Không Giảm Chất Lượng: Hiểu Rõ Sự Đánh Đổi Thực Tế

Nén hình mà không mất chất lượng chỉ tồn tại ở định dạng không mất dữ liệu. Bạn cần 'không mất chất lượng về mặt hình ảnh' — đây là sự khác biệt thực sự.

11 min read


“Nói suông thì rẻ. Cho tôi xem code.”
― Linus Torvalds

design

Bảng Tham Khảo Cú Pháp Cron (2026): Đọc và Tạo Mọi Biểu Thức Crontab

Giải thích cú pháp cron: thứ tự 5 trường, mô hình đọc trong 10 giây, 16 biểu thức đã kiểm chứng, cái bẫy OR của ngày trong tuần, các lỗi DST và so sánh cron với systemd timers.

10 min read

công cụ kiểm regex và tạo pattern cho developer — hình minh họa hero gốc

design

Regex Tester & Pattern Builder: Hướng Dẫn Thực Hành Viết Regex Xịn Xò, Chạy Chuẩn

Cách viết regex thực sự hiệu quả: từ anchor, quantifier, cái bẫy khác biệt giữa các engine, đến lỗi ReDoS có thể làm sập server của bạn. Hãy luôn test khi viết.

9 min read

Laptop mở code và cây cảnh nhỏ trong quán cà phê

design

JSON vs YAML vs TOML: Khi Nào Nên Chọn Định Dạng Nào (Cẩm Nang Quyết Định cho Developer)

So sánh JSON vs YAML vs TOML: Chọn JSON cho API và data, YAML cho config Kubernetes/CI (cẩn thận 'Norway problem'), TOML cho config tường minh như Cargo.toml. Cẩm nang quyết định rõ ràng.

9 min read

khả năng chi trả vay xe hơi và quy tắc 20/4/10 — hình minh họa gốc

finance

Máy Tính Khả Năng Thanh Toán Vay Xe vs Quy Tắc 20/4/10: Cái Nào Đang Nói Dối Bạn?

Máy tính thanh toán nói khoản vay xe trung bình $44,156 có khả năng chi trả. Quy tắc 20/4/10 nói bạn cần $146,000. Đây là con số thực.

8 min read

CSS Gradient Generator Workflow: Create, Check, and Copy

CSS Gradient Generator Workflow: Create, Check, and Copy

Build a CSS gradient you can copy and paste, then validate its syntax and add a practical fallback without installing another tool.

5 min read