Five Markdown Renderers, One Table: Where They Actually Differ
A Markdown table that looks perfect on GitHub can lose a cell on Zenn, split a row in your Astro blog, or refuse to render on Qiita. Most of the rules are shared. The disagreements are narrow, repeatable, and easy to hit in a docs pipeline.
On 2026-10-02 I sent the same table cases through five renderers:
- GitHub Markdown API
- Gitee Markdown API
- Qiita:
qiita_marker 0.23.9.0 - Zenn:
zenn-markdown-html 0.5.4(markdown-it 14.3.2) - micromark 4, the parser behind remark, MDX and Astro
The full matrix and fixtures are in the guide linked at the end. These are the differences that change output.
1. A backslash before a pipe is read differently
For the cell text x\\|y:
GitHub, Gitee, Qiita, Zenn -> one cell: x|y micromark (remark, MDX) -> two cells: x\ and y GitHub and markdown-it treat any pipe after a backslash as escaped. micromark consumes \\ first as an escaped backslash, so the pipe that follows splits the cell.
If you need a literal backslash followed by a pipe, write three backslashes: \\\| shows \| in all five.
2. An unescaped pipe always splits, even inside code
Table rows are split at pipes before cell content is parsed. So `a|b` ends the cell after `a. Write `a\|b`; all five render the code a|b and remove the backslash.
The same applies to a regular expression: (png|jpg) inside a cell must be (png\|jpg).
3. Header and delimiter rows must have the same cell count
| a | b | over |---| is not a table on any of the five. It becomes a paragraph of pipes.
4. A table may interrupt a paragraph
All five start the table right after a text line:
Intro line. | a | b | |---|---| | 1 | 2 | Next paragraph. Next paragraph. becomes a fourth row. A blank line after the table is optional for parsing, but it prevents this.
5. A full-width pipe is not a pipe
U+FF5C | is a different character. A table written with | renders as text on all five. This is common when the table was typed with a Japanese or Chinese IME.
6. CJK bold at the start of a cell
**注意:**这里 is not bold on any of the five. CommonMark's delimiter rules require the closing ** to be right-flanking; a following CJK punctuation mark breaks that. Two fixes:
**注意:** 这里 **注意**:这里 The first keeps the colon inside the bold; the second moves it out. Both render.
7. <br> works, until a sanitizer strips it
GitHub, Gitee, Qiita and Zenn render <br> inside a cell. A site that escapes raw HTML shows the tag as text. Check the target renderer before relying on it.
What to do
- Write
\|for a pipe and\\\|for a literal backslash followed by a pipe. - Add a space after bold when a CJK punctuation mark follows, or move the punctuation outside the bold.
- Never use
|as a table separator. - Keep header and delimiter cell counts equal.
- Test in the renderer that will publish the page. "Works on GitHub" is not a spec.
The measurements, the renderer-by-input matrix, and the JSON fixtures are in the full guide. There is also a Markdown table generator that escapes pipes and can compare the output of these renderers cell by cell.