Problem
Markdown tables in PR descriptions render as a blob of plain text with pipe characters instead of a formatted table. This is because mdast-util-from-markdown only supports CommonMark by default — GFM (GitHub Flavored Markdown) features like tables require additional extensions.
Example input:
| File | Change |
|------|--------|
| `cli/Cargo.toml` | Explicit tokio features |
| `cli/Cargo.lock` | Removed unused `parking_lot` dep |
Current rendering: a single paragraph containing the raw | File | Change | ... text, pipes and all.
Expected: a nicely formatted table with aligned columns and borders.
Root Cause
- No GFM parser extensions — the project only has
mdast-util-from-markdown (CommonMark). Tables, task lists, strikethrough, and autolinks all require micromark-extension-gfm + mdast-util-gfm to parse into proper AST nodes.
- No table renderer —
src/lib/markdown.tsx has no Match case for type === "table" / tableRow / tableCell, so even if parsed, tables would hit the FallbackBlock and render nothing.
Other GFM features affected
These are also commonly used in GitHub PR bodies and are similarly broken:
| Feature |
Syntax |
Current behavior |
| Task lists |
- [x] done |
Renders as [x] done text |
| Strikethrough |
~~deleted~~ |
Renders as ~~deleted~~ text |
| Autolinks |
https://example.com |
Plain text (no link) |
Proposed Fix
1. Add GFM parsing extensions
bun add micromark-extension-gfm mdast-util-gfm
Then in src/lib/markdown.tsx:
import { gfm } from "micromark-extension-gfm";
import { gfmFromMarkdown } from "mdast-util-gfm";
// in MarkdownBody:
const tree = () => fromMarkdown(props.source, {
extensions: [gfm()],
mdastExtensions: [gfmFromMarkdown()],
});
2. Add table renderer component
Render table → tableRow → tableCell AST nodes as a TUI table. Key considerations:
- Column width calculation — measure the text content of each column across all rows, then pad to the max width per column
- Box-drawing borders — use
─, │, ┌, ┬, ┐, etc. for clean TUI table borders
- Alignment — the
Table node has an align array ("left" | "center" | "right" | null) per column
- Header row — first
tableRow is the header; render bold or with a separator line beneath
- Inline content in cells — cells contain
PhrasingContent[], so reuse InlineNodes for rendering
3. (Bonus) Task lists, strikethrough
- Task lists: check
listItem.checked (boolean | null) and render [✓] / [ ] prefix
- Strikethrough: wrap in
~~ style (dim or strikethrough if terminal supports it)
Files to Modify
package.json — add micromark-extension-gfm + mdast-util-gfm
src/lib/markdown.tsx — wire up GFM extensions, add MdTable/MdTableRow/MdTableCell components, add task list + strikethrough support
Problem
Markdown tables in PR descriptions render as a blob of plain text with pipe characters instead of a formatted table. This is because
mdast-util-from-markdownonly supports CommonMark by default — GFM (GitHub Flavored Markdown) features like tables require additional extensions.Example input:
Current rendering: a single paragraph containing the raw
| File | Change | ...text, pipes and all.Expected: a nicely formatted table with aligned columns and borders.
Root Cause
mdast-util-from-markdown(CommonMark). Tables, task lists, strikethrough, and autolinks all requiremicromark-extension-gfm+mdast-util-gfmto parse into proper AST nodes.src/lib/markdown.tsxhas noMatchcase fortype === "table"/tableRow/tableCell, so even if parsed, tables would hit theFallbackBlockand render nothing.Other GFM features affected
These are also commonly used in GitHub PR bodies and are similarly broken:
- [x] done[x] donetext~~deleted~~~~deleted~~texthttps://example.comProposed Fix
1. Add GFM parsing extensions
Then in
src/lib/markdown.tsx:2. Add table renderer component
Render
table→tableRow→tableCellAST nodes as a TUI table. Key considerations:─,│,┌,┬,┐, etc. for clean TUI table bordersTablenode has analignarray ("left" | "center" | "right" | null) per columntableRowis the header; render bold or with a separator line beneathPhrasingContent[], so reuseInlineNodesfor rendering3. (Bonus) Task lists, strikethrough
listItem.checked(boolean | null) and render[✓]/[ ]prefix~~style (dim or strikethrough if terminal supports it)Files to Modify
package.json— addmicromark-extension-gfm+mdast-util-gfmsrc/lib/markdown.tsx— wire up GFM extensions, addMdTable/MdTableRow/MdTableCellcomponents, add task list + strikethrough support