How to match every markdown table row to the header column count
- Step 1Paste the misaligned table — Drop the Markdown containing tables whose body rows don't match the header. Whole documents are fine — every table is processed in one pass.
- Step 2Make sure the header has the right number of columns — The tool counts columns from the header and forces all body rows to match it. If the header itself is wrong, fix the header first — otherwise correct rows will be padded or trimmed to the wrong width.
- Step 3Run the repair — Click run. Short rows gain empty cells; over-long rows lose their trailing cells; the separator is regenerated. There are no alignment or padding options to choose.
- Step 4Spot-check trimmed rows — If a body row had real data in an extra column the header doesn't define, that data was dropped during trimming. Scan rows that previously had more cells than the header before committing.
- Step 5Render to confirm columns line up — Preview the result or paste it into a GFM viewer. Every body row should now sit under the correct header, with blanks where data was genuinely missing.
- Step 6Copy or download the result — Copy the aligned Markdown or download it as a file, then replace the original in your docs repo.
Header vs. body — how each mismatch is resolved
Header defines the canonical column count. Body rows are coerced to it. Verified against the repair function.
| Mismatch type | What the tool does | Risk to your data |
|---|---|---|
| Body row has fewer cells than header | Appends empty cells until the count matches | None — only blanks are added |
| Body row has more cells than header | Drops the surplus trailing cells | Data in the dropped cells is lost |
| Body row count equals header | Left unchanged | None |
| Header itself has the wrong column count | Used as-is — all rows coerced to it | All rows aligned to the wrong width |
Worked column-count examples (header = 4 columns)
Each input row is forced to four cells.
| Input body row | Cells in | Output row |
|---|---|---|
| GET | /users | 200 | | 3 | | GET | /users | 200 | | |
| POST | /users | 201 | created | dup | | 5 | | POST | /users | 201 | created | |
| DELETE | /users/1 | 204 | no content | | 4 | | DELETE | /users/1 | 204 | no content | |
| PATCH | | 1 | | PATCH | | | | |
Tier limits for Markdown Table Repair
Markdown-family limits. The character limit is independent of byte size — large reference tables can hit charLimit first.
| 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
Before/after rows from real reference and config tables. Each block shows the misaligned source on top and the tool's exact aligned output below.
API table with one short row
A new Auth column was added to the header but one endpoint row was never updated. The short row gets an empty trailing cell so it aligns.
Before: | Method | Path | Auth | | --- | --- | --- | | GET | /health | | POST | /login | none | After: | Method | Path | Auth | | --- | --- | --- | | GET | /health | | | POST | /login | none |
Row with an accidental extra pipe
A trailing | left an empty 4th cell where the header has 3 columns. The overflow cell is trimmed away.
Before: | Key | Default | Notes | | --- | --- | --- | | retries | 3 | per request | | timeout | 30 | seconds || After: | Key | Default | Notes | | --- | --- | --- | | retries | 3 | per request | | timeout | 30 | seconds |
Mixed short and long rows in one table
Different rows drifted in different directions. All are coerced to the header's column count in a single pass.
Before: | Flag | Type | Required | | --- | --- | --- | | --verbose | bool | | --out | string | yes | extra | | --tag | string | no | After: | Flag | Type | Required | | --- | --- | --- | | --verbose | bool | | | --out | string | yes | | --tag | string | no |
Missing separator and misaligned rows together
The table lost its separator AND has ragged rows. Both problems are fixed in the same run.
Before: | Env | URL | | dev | http://localhost | | prod | https://app.example.com | live | After: | Env | URL | | --- | --- | | dev | http://localhost | | prod | https://app.example.com |
Data lost when an extra column held real content
A cautionary case — the trimmed cell was not empty. The tool drops the surplus, so widen the header first if every column matters.
Before (header has 2 columns): | Name | Email | | --- | --- | | Ada | ada@x.com | Owner | After (the 'Owner' cell is dropped): | Name | Email | | --- | --- | | Ada | ada@x.com |
Edge cases and what actually happens
Body row shorter than the header
PaddedMissing cells are appended as empty strings until the row matches the header column count. The cells render as blank — valid GFM. No existing content is changed.
Body row longer than the header
TrimmedSurplus trailing cells are dropped. If those cells contained real data, it is lost. Add the missing column to the header before running when every column carries meaning.
The header itself is the wrong width
PropagatedThe tool never second-guesses the header — it is the source of truth for the column count. A header missing a column will cause every correct body row to be trimmed to the header's narrower width. Fix the header first.
Alignment markers on the separator
Not preservedThe regenerated separator is plain --- for every column, so :---: and ---: alignment is dropped. Re-add it to the output after the columns are aligned if you need it.
A prose line with a pipe right above the table
Misread as headerIf a sentence containing | sits directly above your table with no blank line between them, that sentence becomes the header and your real header becomes a body row. Separate prose from tables with a blank line.
Pipe inside a cell (escaped or code-span)
Splits the cellCells are split on every |. An escaped \| or a pipe inside an inline code span counts as a delimiter, so the cell splits into two — and the surplus may then be trimmed. Only fenced-block pipes are safe.
Empty cell you wrote intentionally
PreservedAn intentionally blank cell stays blank — it counts toward the column total and is never removed. The tool only appends blanks to reach the header width or trims overflow at the end of a row.
Table inside a fenced code block
PreservedTables shown as code examples in triple-backtick fences are passed through unchanged — they are never aligned, padded, or trimmed.
Document over your tier's char limit
RejectedFree allows 500,000 characters and 1 MB. A reference doc with many wide tables can exceed the character limit even under 1 MB — split it or upgrade the tier.
Frequently asked questions
How does the tool know how many columns the table should have?
From the header — specifically the first pipe line of each table run. Its cell count becomes the canonical width, and every body row is padded or trimmed to match it. If the header is wrong, the alignment will be wrong too, so verify the header first.
What happens to a row with too few cells?
Empty cells are appended until the row matches the header's column count. The added cells render as blank table cells, which is valid GFM. Your existing cell content is untouched.
What happens to a row with too many cells?
The surplus trailing cells are dropped so the row matches the header width. If those cells held real data, it is lost — widen the header before running if you need to keep every column.
Can it auto-detect which row is the header?
It always uses the first pipe line of a table run as the header. There is no content-based detection, so if your header line was deleted, the first surviving row will be treated as the header.
Will a pipe inside a cell break the column count?
Yes. The splitter treats every | as a delimiter — including escaped \| and pipes inside inline code spans — so such a cell splits into multiple cells and can be miscounted or trimmed. Keep literal pipes out of cells, or wrap the whole line in a code fence.
Are there padding or alignment options?
No. The transform is fixed and the tool has no settings. Cells are joined with single spaces around single pipes, and the separator is always plain ---. For visual column padding or alignment, edit the output by hand.
Does it preserve empty cells I added on purpose?
Yes. An intentionally blank cell is counted as a cell and kept. The tool only adds blanks to reach the header width and only removes cells that overflow past the header width.
Does it touch code blocks?
No. Fenced code blocks (triple backticks) are passed through unchanged. Only pipe lines outside fences are aligned. Inline code spans are not protected.
Can I align tables across several files at once?
Not directly — the tool takes one input per run. Combine files with the Markdown merger first, align here, then split back out with the splitter if you need separate files again.
My table came from CSV or HTML — should I use this tool?
Only if it is already in pipe-table form. To build a table from spreadsheet data use CSV to Markdown table; from an HTML table use HTML to Markdown. Then run this repair if the result has ragged rows.
Is the output deterministic?
Yes. With no options and a fixed rule set, the same input always produces the same aligned output — which makes the tool safe to run as a repeatable step in a docs pipeline.
What if I also need broken lists fixed?
This tool only handles pipe-table columns. For bullet and numbered lists use the list fixer, and for an all-round tidy run the prettifier.
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.