CommonMark và GFM: Markdown của bạn thành HTML ra sao

Xuống dòng, bảng, danh sách việc, link trần và HTML thô: cùng một đoạn Markdown qua CommonMark và GitHub Flavored Markdown, kèm HTML được tạo ra.

Trong bài này

Markdown ra đời năm 2004 dưới dạng một bản mô tả ngắn và một đoạn script Perl, không phải một đặc tả. Mỗi bản cài đặt tự lấp chỗ trống theo cách riêng, nên cùng một tệp có thể hiển thị khác nhau trên hai trang. Có hai nỗ lực đưa mọi thứ vào nề nếp: CommonMark, đặc tả chính xác cho cú pháp lõi kèm hàng trăm ví dụ, và GitHub Flavored Markdown (GFM), là CommonMark cộng thêm vài phần mở rộng. Phần lớn công cụ ngày nay theo một trong hai, và phần lớn điều bất ngờ đến từ chỗ khác nhau giữa chúng.

Bài này đưa các đoạn nhỏ qua công cụ chuyển Markdown sang HTML và cho thấy HTML tạo ra, rồi ghi chú chỗ CommonMark, GFM và công cụ khác nhau.

Xuống dòng: điều bất ngờ phổ biến nhất

Line one
line two

trở thành <p>Line one và line two</p>, một đoạn văn với dấu xuống dòng thường bên trong, mà trình duyệt hiển thị như một dấu cách. Một lần xuống dòng trong mã nguồn là xuống dòng mềm. Muốn ép ra <br />, hãy kết thúc dòng đầu bằng hai dấu cách hoặc một dấu gạch chéo ngược; cả hai đều cho <p>Line one<br />line two</p>. Một dòng trống mở đầu đoạn văn mới.

Hai dấu cách cuối dòng thì vô hình và nhiều trình soạn thảo tự xoá chúng, nên dạng gạch chéo ngược an toàn hơn. Một số trình hiển thị, kể cả ô bình luận của GitHub, coi mọi lần xuống dòng là ngắt dòng, nên văn bản trông đúng ở đó lại dồn thành một dòng ở nơi khác.

Nhấn mạnh và dấu gạch dưới

*em* và _em_ đều cho <em>, còn **strong** hoặc __strong__ cho <strong>. CommonMark siết lại quy tắc của dấu gạch dưới để snake_case_name vẫn là chữ thường: dấu gạch dưới nằm giữa một từ không mở phần nhấn mạnh. Dấu sao thì không được bảo vệ như vậy, nên 2*3*4 có thể biến số 3 thành chữ nghiêng. Hãy thoát thành 2\*3\*4 khi bạn muốn viết phép nhân.

GFM thêm những gì

Những thứ sau đến từ GFM, không thuộc CommonMark lõi. Công cụ của chúng tôi hỗ trợ chúng:

MarkdownHTML tạo ra
~~old~~ price<del>old</del> price
- [x] done<li><input type="checkbox" disabled checked /> done</li>
bảng kẻ bằng dấu gạch đứng với :--- và ---:<th style="text-align:left"> và style="text-align:right"

Bảng cần một dòng tiêu đề và một dòng phân cách bằng dấu gạch ngang; dấu hai chấm trong dòng phân cách quy định căn lề của từng cột. Các ô đánh dấu bị vô hiệu hoá vì một tài liệu đã hiển thị không có chỗ nào để lưu dấu tích.

GFM còn có phần mở rộng tự tạo link: Visit https://example.com today thành link trên GitHub. CommonMark lõi để nguyên dạng chữ, và công cụ của chúng tôi cũng vậy. Cả hai đều biến <https://example.com>, đặt trong ngoặc nhọn, thành <a href="https://example.com">. Nếu link phải chạy được ở mọi trình hiển thị, hãy dùng ngoặc nhọn hoặc viết [chữ](url).

Danh sách: chặt, lỏng và đánh số lại

- a
- b

- c

Chỉ cần một dòng trống ở bất kỳ đâu giữa các mục là cả danh sách thành lỏng, và mỗi mục được bọc trong <p>, tạo thêm khoảng cách dọc. Bỏ dòng trống đi thì các mục trở về <li>a</li> đơn giản. Đó là lý do đôi khi danh sách trông như giãn dòng gấp đôi mà không rõ vì sao.

Danh sách có số chỉ quan tâm tới số đầu tiên. 5. five rồi 6. six tạo ra <ol start="5">; các số phía sau bị bỏ qua, nên viết 1. ở mọi dòng là hợp lệ và giúp sắp xếp lại dễ dàng. Đổi ký tự gạch đầu dòng, * rồi +, sẽ mở một danh sách mới thay vì nối tiếp danh sách cũ.

HTML thô: nơi các phiên bản thực sự khác nhau

CommonMark cho HTML thô đi qua nguyên vẹn: <b>bold</b> trong mã nguồn thành chữ đậm. GFM cũng vậy nhưng lọc một danh sách ngắn các thẻ nguy hiểm như <script>, <style> và <iframe>, rồi GitHub còn chạy bộ lọc riêng của mình lên trên.

Công cụ của chúng tôi chọn cách chặt nhất: HTML thô được coi là văn bản. <b>bold</b> <script>alert(1)</script> cho ra &lt;b&gt;bold&lt;/b&gt; &lt;script&gt;…, hiển thị nguyên văn. Link cũng được lọc: chỉ giữ http, https, mailto, tel, link tương đối và #neo, nên [click](javascript:alert(1)) chỉ còn chữ "click" không có link. Kết quả chỉ có thể chứa các thẻ trong một danh sách cố định, nhờ vậy dán vào CMS hay mẫu e-mail là an toàn. Nếu cần HTML cụ thể trong kết quả, hãy chuyển đổi trước rồi sửa HTML sau; bài thực thể HTML và thoát ký tự giải thích vì sao dán văn bản người dùng chưa thoát vào trang web là nguy hiểm.

Khối mã

Khối mã có hàng rào được mở bằng một dòng ba dấu backtick kèm tên ngôn ngữ, ở đây là js, và đóng bằng ba dấu backtick. Với dòng const a = 1 < 2; bên trong, nó trở thành <pre><code class="language-js">const a = 1 &lt; 2;</code></pre>. Dấu < được thoát, còn lớp language-js là thứ các thư viện tô màu cú pháp như Prism hay highlight.js tìm kiếm. Công cụ không tự tô màu mã.

Những lỗi thường gặp

  1. Nghĩ rằng một lần xuống dòng là ngắt dòng. Dùng dòng trống cho đoạn mới, hoặc kết thúc dòng bằng dấu gạch chéo ngược.
  2. Một dòng trống trong danh sách khiến cả danh sách thành lỏng.
  3. Trông chờ link trần tự thành link. Đó là phần mở rộng của GFM; hãy dùng <…> hoặc [chữ](url) để link chạy ở mọi nơi.
  4. Dán HTML vào Markdown cho một trang có thoát ký tự. Một số hệ thống bình luận, và công cụ của chúng tôi, cố ý hiển thị nó như văn bản.
  5. Bảng thiếu dòng phân cách. Không có |---|---| dưới tiêu đề thì "bảng" chỉ là một đoạn văn đầy dấu gạch đứng.
  6. Link kiểu tham chiếu ([chữ][1] với [1]: url ở dưới). Chúng thuộc CommonMark lõi nhưng không phải bộ chuyển đổi nhỏ nào cũng hỗ trợ, kể cả công cụ của chúng tôi; hãy dùng link nội dòng nếu văn bản sẽ đi nhiều nơi.

Hãy viết bản nháp trong công cụ chuyển Markdown sang HTML, kiểm tra bản xem trước, rồi sao chép đoạn HTML hoặc cả một tài liệu hoàn chỉnh. Nếu kết quả sẽ được chèn vào một trang khác, công cụ mã hoá thực thể HTML giúp xử lý những ký tự cần thoát bằng tay.

Công cụ được nhắc trong bài

Về trang blog