How to give every markdown table a clean header and separator row
- Step 1Paste the documentation — Drop the doc containing tables that may lack a proper header/separator. The entire file is processed, so every table is normalized in one pass.
- Step 2Verify the first row is the intended header — The tool always uses the first pipe line of a table run as the header. If a header was lost, the first data row is promoted — reorder the source so the real header is first before running.
- Step 3Run normalization — Click run. A single fresh separator is written under each header, extra separators are dropped, and rows are matched to the header width. No settings to choose.
- Step 4Note that alignment is reset — Every regenerated separator is plain
---. If a table relied on:---:centring or---:right-alignment, re-add those markers to the output separator afterward. - Step 5Render to confirm GFM compliance — Preview the result or paste it into GitHub or VS Code to confirm each table now renders with its header on top instead of as plain text.
- Step 6Commit the normalized doc — Copy or download the result and replace the original. Tables now render reliably across parsers.
Header and separator normalization rules
What the tool does to the structural rows of each table. Verified against the repair function.
| Situation | Normalization applied |
|---|---|
| No separator under the header | Inserts a fresh | --- | --- | separator beneath the first row |
| One valid separator already present | The original is dropped and an identical plain---- one is regenerated |
| Two or more separator lines | All originals dropped; exactly one regenerated separator remains |
Separator with alignment (:---:) | Dropped and regenerated as plain --- — alignment not preserved |
| Header missing entirely | First surviving body row is promoted to header |
How parsers treat a separator-less table (why this matters)
A header row with no separator beneath it is the most common silent-failure case. Behaviour is parser-dependent — normalization removes the ambiguity.
| Parser | Table with no separator row | After normalization |
|---|---|---|
| GitHub (GFM) | Renders as plain pipe text | Renders as a table |
| VS Code preview | Renders as plain pipe text | Renders as a table |
| Most static-site generators | Plain text or inconsistent | Consistent table output |
| CommonMark-only (no table extension) | No table support either way | Still no table — use a GFM-aware renderer |
Tier limits for Markdown Table Repair
Markdown-family limits. The character limit is independent of 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
Before/after Markdown from docs that failed to render. Each block shows the non-compliant source on top and the normalized output below.
Header with no separator row
The classic GFM compliance failure. The tool inserts a separator directly under the header so the table renders everywhere.
Before: | Setting | Default | | theme | dark | | locale | en | After: | Setting | Default | | --- | --- | | theme | dark | | locale | en |
Doubled separator from a merge conflict
Two branches each added a separator. Normalization keeps exactly one.
Before: | Key | Value | | --- | --- | | --- | --- | | host | localhost | After: | Key | Value | | --- | --- | | host | localhost |
Separator drifted below a blank line
A blank line between the header and separator ends the table early. After normalization the header gets its own separator and the orphaned dashes are treated separately.
Before: | Name | Score | | --- | --- | | Ada | 9 | After: | Name | Score | | --- | --- | | --- | --- | | Ada | 9 | Fix: remove the blank line in the source so the rows form one table, then re-run.
Alignment markers reset to plain dashes
A table with centred columns is normalized to the most-compatible plain form. Re-add alignment if needed.
Before: | Col | Num | |:---:|---:| | a | 1 | After: | Col | Num | | --- | --- | | a | 1 |
Header lost — data row promoted
When the header line was deleted, the first data row becomes the header. This is the one case to watch for during cleanup.
Before (header 'Name | Role' was deleted): | Ada | Lead | | Bo | Dev | After (first row treated as header): | Ada | Lead | | --- | --- | | Bo | Dev | Fix: re-add the header line at the top of the source first.
Edge cases and what actually happens
Table with no separator row
FixedA header followed straight by body rows gets a fresh | --- | separator inserted beneath the first row, making it valid GFM that renders in strict parsers.
Two or more separator lines
DeduplicatedEvery separator-shaped line (only pipes, dashes, colons, spaces) after the header is dropped, and exactly one is regenerated. Doubled separators from merges or pastes are cleaned up automatically.
Alignment markers on the separator
Not preservedCentring (:---:) and right-alignment (---:) are intentionally reset to plain --- for maximum cross-parser compatibility. Re-add them to the output if a specific table needs alignment.
Header row missing
By designThe tool cannot invent a header — the first pipe line is always treated as the header. If yours was deleted, a data row is promoted. Restore the header line in the source first.
Blank line between header and separator
Splits the tableA blank line ends a table, so a separator that drifted below one is treated as the start of a new (separate) structure. Remove the blank line so the header and rows form one table before running.
Header-less data needs a placeholder
Manual stepGFM requires a header row. If your data genuinely has no header, add a placeholder header line (e.g. | Col 1 | Col 2 |) at the top of the source — the tool will then build a valid table around it.
Raw HTML `<table>` in the doc
Passed throughHTML table markup has no leading pipes, so it is left exactly as written. Normalization only acts on pipe tables. Convert HTML separately if you want pipe-table form.
Table inside a fenced code block
PreservedA table shown as a code example in triple backticks is treated as code and passed through unchanged — its missing separator is deliberately not 'fixed', because it is documentation, not a live table.
Document over your tier's char limit
RejectedFree allows 500,000 characters and 1 MB. Large documentation sets can exceed the character limit — split the file or upgrade the tier.
Frequently asked questions
Does every table really need a separator row?
Yes, for GFM. The separator (| --- |) directly under the header is what tells a GFM parser the first row is a header and the rest are data. Without it, GitHub, VS Code, and most generators render the table as plain pipe text. This tool guarantees one is present.
Can I have a header-less table?
Not in valid GFM — a header row is required. If your data has no natural header, add a placeholder header line at the top of the source (e.g. | Col 1 | Col 2 |); the tool then builds a compliant table around it.
Will it preserve my alignment markers?
No. The regenerated separator is always plain ---, which is the most widely-compatible form. Centring and right-alignment are dropped on purpose. Re-add :---: or ---: to the output separator if a specific table needs alignment.
What happens to duplicate separator rows?
They are removed. Any separator-shaped line after the header (made only of pipes, dashes, colons, and spaces) is dropped, and exactly one fresh separator is regenerated from the header. This cleans up the doubled separators that merges and pastes create.
What about raw HTML tables?
They pass through unchanged. The tool only acts on lines containing pipes, and <table> markup has none. If you want HTML turned into a pipe table, convert it first with HTML to Markdown.
How does it decide which row is the header?
It always uses the first pipe line of each table run. There is no content-based detection, so if your header was deleted the first data row is promoted to header. Keep the header line first in the source.
Does it also align the body rows?
Yes — header normalization and column repair happen in the same pass. After the separator is set, every body row is padded or trimmed to the header's column count.
Are there any options for this normalization?
No. The transform is fixed and has no settings — needsOptions is false. The separator is always plain --- and the first row is always the header.
Why did a blank line between my header and separator break things?
A blank (or any pipe-free) line ends a table. If your separator drifted below a blank line, the tool sees two separate structures. Remove the blank line so the header and rows are contiguous, then re-run.
Does it touch code blocks?
No. Fenced code blocks (triple backticks) are passed through unchanged, so a table shown as a syntax example keeps its original (possibly separator-less) form on purpose.
Can I normalize tables across a whole docs folder at once?
One file per run. Merge files with the Markdown merger, normalize here, then split with the splitter. For broader style checks, run the linter afterward.
After normalizing, can I publish to HTML or GitHub?
Yes. The output is GFM-compliant, so it renders correctly on GitHub directly, or convert it with Markdown to GitHub HTML for a standalone preview.
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.