mdtablefix
mdtablefix unb0rks and reflows Markdown tables so that each column has a
uniform width. When the --wrap option is used, it also wraps paragraphs and
list items to 80 columns.
Hyphenated words are treated as indivisible during wrapping, so
very-long-word will move to the next line intact rather than split at the
hyphen. The tool ignores fenced code blocks and respects escaped pipes (\|),
making it safe to use on Markdown with mixed content.
Installation
Install via Cargo:
On Linux x86_64-unknown-linux-gnu and aarch64-unknown-linux-gnu, install
the prebuilt release archive via cargo-binstall:
Or clone the repository and build from source:
Command-line usage
-
When one or more file paths are provided, the corrected tables are printed to stdout.
-
Use
--versionto print the current version and exit. -
Use
--wrapto reflow paragraphs and list items to 80 columns. Task list items (- [ ]/- [x]) are indented correctly. -
Use
--renumberto rewrite ordered lists with consistent sequential numbering. The renumbering logic correctly handles nested lists by tracking indentation (tabs are interpreted as four spaces) and restarts numbering after a list is interrupted by other content, such as a paragraph at a lower indentation level, a thematic break, or a heading. Blank lines between items are ignored, so numbering continues uninterrupted. -
Use
--breaksto standardize thematic breaks to a line of 70 underscores (configurable via theTHEMATIC_BREAK_LENconstant). -
Use
--ellipsisto replace groups of three dots (...) with the ellipsis character (…). Longer runs are processed left-to-right, so any leftover dots are preserved. -
Use
--fencesto normalize code block delimiters to three backticks before other processing. -
Use
--footnotesto convert bare numeric references and the final numbered list into GitHub-flavoured footnote links.A bare numeric reference is a trailing number after punctuation, like
An example.1. -
Use
--code-emphasisto fix emphasis markers that directly adjoin inline code without spaces, ensuring the code span remains intact. -
Use
--headingsto convert Setext headings that use underline markers into hash-prefixed headings. The underline must contain at least three matching=or-characters, so the converter can distinguish headings from thematic breaks and list markers. -
Use
--in-placeto modify files in-place. -
If no files are specified, input is read from stdin and output is written to stdout.
YAML frontmatter
Documents that begin with a YAML frontmatter block have that block preserved
exactly while the remainder of the document is formatted. A frontmatter block
starts with a line containing exactly --- and ends with a line containing
exactly --- or .... Only a block at the very beginning of the document is
recognized as frontmatter.
Before:
title: My Document
author: Jane Doe
After running mdtablefix:
title: My Document
author: Jane Doe
Concurrency
When multiple file paths are supplied, mdtablefix processes them in parallel
using the rayon crate. The CLI buffers each result,
so it can print them in the original order. This buffering uses extra memory.
It might outweigh the speed gains for small files.
Example: Table Reflowing
Before:
After running mdtablefix:
Example: List Renumbering
Before:
1. 4.
A brief intermission for pizza.
9. 1. 5.12.
After running mdtablefix --renumber:
1. 2.
A brief intermission for pizza.
1. 1. 2.2.
Library usage
The crate exposes helper functions for embedding the table-reflow logic in Rust projects:
use ;
use Path;
The footnotes option also rewrites bare numeric references:
use ;
let lines = vec!;
let opts = Options ;
let out = process_stream_opts;
assert_eq!;
It converts a trailing numbered list into footnote definitions:
use ;
let lines = vec!;
let opts = Options ;
let out = process_stream_opts;
assert_eq!;
-
process_stream_opts(lines: &[String], opts: Options) -> Vec<String>rewrites tables in memory. The options enable paragraph wrapping, ellipsis substitution, fence normalization, Setext-to-ATX heading conversion, and footnote conversion whenfootnotesis set totrue. The flags arefalseby default. -
rewrite(path: &Path) -> std::io::Result<()>modifies a Markdown file on disk in-place.
HTML table support
mdtablefix recognizes basic HTML <table> elements embedded in Markdown.
These are converted to Markdown in a preprocessing stage using
convert_html_tables, prior to reflow.
Only simple tables composed of <tr>, <th>, and <td> tags are supported.
Tag case and attributes are ignored. After conversion, they are reformatted
alongside regular Markdown tables.
See HTML table support for more details.
Module structure
For an overview of how the crate's internal modules relate to each other, see
Module relationships.
Testing
The test suite is structured using the rstest crate. See
Rust testing with rstest fixtures
for details.
License
This project is licensed under the ISC License. See the LICENSE file for full details.