How to repair pipe delimiters in broken markdown tables
- Step 1Paste the table with pipe problems — Drop the Markdown whose tables have missing edge pipes, doubled pipes, or a broken separator. Whole documents are processed at once.
- Step 2Move literal pipes out of cells FIRST — Before running, find any cell that needs a literal
|(a regex, a path likea|b, an 'or' notation). Rewrite it (e.g.a or b) or wrap the entire line in a triple-backtick fence — the tool will split on those pipes otherwise. - Step 3Run the repair — Click run. Edge pipes are normalized, the separator is rebuilt, stray separators are dropped, and rows are matched to the header. No options to set.
- Step 4Inspect cells that contained pipes — Any cell that had an internal
|(escaped or code-span) will have split into extra columns and possibly been trimmed. Review those rows and restore the intended value by hand. - Step 5Render to verify clean output — Preview the result or paste it into a GFM viewer. Cells should sit under the right headers with tidy
| a | b |spacing. - Step 6Copy or download — Copy or download the repaired Markdown and replace the original in your source.
Pipe problems — fixed vs. not fixed
Structural pipe damage is repaired; pipes inside cells are not protected. Verified against the repair function.
| Pipe problem | Handled? | What happens |
|---|---|---|
Missing leading/trailing | on a row | Fixed | Row re-emitted as | cell | cell | with edge pipes |
Doubled/empty || from a paste | Fixed (as an empty cell) | Counts as a blank cell, then padded/trimmed to header width |
Ragged spacing (|a| b|) | Fixed | Re-emitted with single spaces: | a | b | |
| Mangled / duplicated separator pipes | Fixed | Original separator dropped, plain --- regenerated |
Escaped pipe \| inside a cell | NOT protected | Split as a delimiter; the backslash is discarded |
Pipe inside an inline code span ` a|b | NOT protected | Split as a delimiter; the code span breaks |
| Pipe inside a fenced (```) block | Protected | Whole fenced block passed through unchanged |
How to keep a literal pipe in your content
Because the tool does not honour escaping, you must move literal pipes out of harm's way before repairing.
| You want to show | Don't rely on | Do this instead before running |
|---|---|---|
A regex alternation cat|dog | cat\|dog (split anyway) | Rewrite as cat or dog, or fence the line |
A shell pipe ls | wc | Inline code ` ls | wc ` (split anyway) | Put the example in a fenced code block, not a table cell |
| An 'a or b' option list | a \| b | Write a / b or a, b |
A file path dir|name | Escaping | Rename or rewrite the value to avoid the pipe |
Tier limits for Markdown Table Repair
Markdown-family limits. The character limit is separate from byte size.
| Tier | Max file size | Max characters | Files per run |
|---|---|---|---|
| Free | 1 MB | 500,000 | 1 |
| Pro | 10 MB | 5,000,000 | 10 |
| Pro-media | 50 MB | 20,000,000 | 50 |
| Developer | 500 MB | Unlimited | Unlimited |
Cookbook
Real before/after rows showing what pipe repair does — including the cases where an in-cell pipe breaks a cell. Each block shows the source on top and the exact output below.
Rows missing their edge pipes
A paste dropped the leading and trailing pipes. The tool re-emits every row with clean edge pipes and a regenerated separator.
Before: Name | Status Alice | active Bob | invited After: | Name | Status | | --- | --- | | Alice | active | | Bob | invited |
Doubled pipes and ragged spacing cleaned
Copy-paste left || and uneven spacing. The empty cell is counted, the row is padded/trimmed to the header width, and spacing is normalized.
Before: |Key|Value| |---|---| |host||localhost| |port| 8080 | After: | Key | Value | | --- | --- | | host | | | port | 8080 | Note: 'host' had an empty middle cell, so 'localhost' became a 3rd cell and was trimmed — review and re-enter it.
An escaped pipe is NOT protected
A cell with \| is split anyway and the backslash is dropped — this is the key behavior that surprises people. Move the pipe out of the cell instead.
Before: | Pattern | Meaning | | --- | --- | | a\|b | a or b | After (split into 3 cells, surplus trimmed): | Pattern | Meaning | | --- | --- | | a | b | Fix: write the pattern as 'a or b' in the source, or put it in a fenced code block.
A code-span pipe breaks the cell too
Inline code spans are NOT protected. Only fenced (triple-backtick) blocks are. The shell pipe splits the cell.
Before: | Command | Effect | | --- | --- | | `ls | wc -l` | count files | After (split on the pipe): | Command | Effect | | --- | --- | | `ls | wc -l` | Fix: show the command in a fenced code block instead of a table cell.
Fenced pipes are safe
Pipes inside a triple-backtick block pass through untouched, so you can document pipe syntax without the tool mangling it.
Before & After (identical — fence is preserved): ``` | this | is | not | parsed | ls | grep foo | wc -l ```
Edge cases and what actually happens
Escaped pipe `\|` inside a cell
Not protectedThe splitter ignores escaping and splits on the |; the backslash is discarded during the cell trim. The cell becomes two cells and may be trimmed. Rewrite the value or fence the line — do not rely on \|.
Pipe inside an inline code span
Not protectedA code span like ` a | b ` is treated as normal prose, so the inner pipe splits the cell. Only fenced (triple-backtick) blocks are protected. Move pipe-containing commands into a fenced block.
Pipe inside a fenced code block
PreservedThe entire fenced block is passed through byte-for-byte, so any pipes inside it are safe. This is the one reliable way to show literal pipe content.
Missing leading/trailing pipes
FixedRows are re-emitted with proper edge pipes (| ... |), so a table pasted without its outer pipes is restored to standard form.
Doubled / empty `||`
Treated as empty cellAn empty cell created by || is counted as a cell. The row is then padded or trimmed to the header column count, which can shift later values — review rows that had doubled pipes.
Ragged spacing around pipes
NormalizedCells are trimmed and re-joined with single spaces around single pipes, so |a| b| becomes | a | b |. This is cosmetic and never changes cell content.
Separator pipes mangled
RegeneratedAny malformed or duplicated separator line is dropped and a clean plain---- separator is regenerated from the header. Alignment markers are not carried over.
A prose line containing a pipe
Misread as a tableAny non-empty line with a | is parsed as a table row. A sentence like choose option A | B becomes a one-row table. Fence such lines or remove the pipe to keep them as prose.
Document over your tier's char limit
RejectedFree allows 500,000 characters and 1 MB. Large migration files can exceed the character limit — split the file or upgrade the tier.
Frequently asked questions
How do I include a literal `|` inside a table cell?
You can't rely on this tool to keep it — it splits on every pipe and ignores \| escaping. The safe options are to rewrite the value so it has no pipe (e.g. a or b), or move the pipe-containing content into a triple-backtick fenced code block, which the tool passes through untouched.
Will the tool protect pipes inside inline code spans?
No. Inline code spans (single backticks) are treated as ordinary prose, so a pipe inside ` a | b ` splits the cell. Only fenced (triple-backtick) blocks are protected. Put pipe-containing commands in a fenced block, not a table cell.
Does an escaped `\|` survive?
No. The backslash-escape is not honoured — the pipe still acts as a delimiter and the backslash is discarded when the cell is trimmed. This is a deliberate limitation of the simple split-on-pipe parser, so don't depend on \|.
What pipe problems does it actually fix?
Structural ones: missing leading/trailing pipes, doubled ||, ragged spacing around pipes, and a mangled or duplicated separator row. It re-emits clean | cell | cell | rows and a single plain---- separator.
Is the output Pandoc-compatible?
The output is standard GFM-style pipe tables with single | --- | separators, which most Pandoc pipe-table readers accept. It is not Pandoc-specific and does not produce Pandoc grid or multiline tables — convert those with Pandoc itself if you need them.
What happens to a doubled `||` in a row?
It is read as an empty cell. The row's cell count then changes, so the tool pads or trims it to the header width — which can shift the cells after it. Review rows that contained || to confirm values landed in the right columns.
Does it normalize the spacing around pipes?
Yes. Each cell is trimmed and re-joined with a single space on each side of a single pipe, turning |a| b| into | a | b |. This is purely cosmetic and never alters cell content.
Are there options to control pipe handling?
No. The tool has no settings — the split-on-pipe rule, the single-space joining, and the plain---- separator are all fixed.
Why did a sentence with a pipe become a table?
Because any non-empty line containing | is treated as a table row. A line like pick A | B gets a header and separator. Wrap such lines in a fenced code block, or remove the pipe, so they stay as prose.
Does it touch fenced code blocks?
No. Triple-backtick fenced blocks are passed through unchanged, so any pipes inside them — including shell pipelines and table examples — are preserved exactly. That's the reliable place for literal pipe content.
I'm migrating content with lots of pipe-heavy values — what's the workflow?
Move pipe-bearing values into fenced blocks or rewrite them first, then run the repair on the structural tables. For tables coming from other formats, build them cleanly with CSV to Markdown table or HTML to Markdown to avoid pipe collisions entirely.
What else can clean up the surrounding Markdown?
For misaligned columns specifically this same tool handles it; for broken lists use the list fixer, and for whole-document tidy-up use the prettifier or check style with the linter.
Privacy first
All Markdown processing runs locally in your browser using JavaScript. No file is ever uploaded to JAD Apps servers — only metadata counters are saved for signed-in dashboard stats.