Paragraph wrapping

Version 0.5.0 Updated Jul 27, 2026

Pass --wrap to reflow prose paragraphs so that every output line fits within 80 display columns. Width is measured in terminal columns, not bytes, so the wrapper accounts correctly for CJK glyphs, emoji, and accented characters. The flag does not accept a width parameter.

Line fitting is delegated to the textwrap crate using a greedy first-fit algorithm: each word is placed on the current line if it fits, and a new line is started otherwise. This produces predictable, diff-friendly output.

Inline code spans (`…`), Markdown links ([text](url)), and inline GFM footnote references ([^label]) are treated as unbreakable units during normal line fitting. mdtablefix --wrap never introduces a line break within an inline code span; the span otherwise moves as a whole to the next line when it would exceed the target width. The exception for an already cross-line overlong span is described below.

Reference-style links such as [text][reference] are likewise unbreakable. The opening [ always stays with the link label, avoiding leading whitespace inside link text after continuation indentation is applied.

A colon-suffixed footnote reference in running prose, such as subcategories [^96]:, remains attached to the preceding word. The wrapper therefore cannot move [^96]: to column one, where Markdown would reinterpret the reference as a footnote definition.

Common English prose dates, such as 25th December 2025, 19 March 2018, and July 4, 2008, are also treated as unbreakable inline fragments. This applies to ordinal-day, numeric-day, and month-name-first forms with full or abbreviated month names. If a date is wider than the configured wrap width, the existing long-token fallback behaviour applies.

Parenthesized inline citations such as pattern([1](url)) are also treated as unbreakable units, keeping the citation link and its surrounding parentheses together during wrapping.

When an inline code span is split across two or more soft-wrapped source lines, --wrap first joins the continuation lines into a single span before applying the line-length limit. When the joined span fits, the remainder of the paragraph is greedily reflowed during the same pass, including later continuation lines in a list item. Running --wrap again therefore produces no further changes.

The wrapper never introduces a new line break inside an inline-code span. When joining the span would exceed the configured width and each authored line already fits, however, it may retain the authored boundaries inside that span. Markdown renders those retained soft breaks as spaces, while the physical lines remain within the limit. These rules apply in all prefixed contexts — bulleted lists, ordered lists, blockquotes, and footnote definitions — as well as in plain paragraphs.

An inline code span may itself contain backslash-escaped backticks — for example `pass \`--file\` to the tool`. --wrap keeps the whole span, including its escaped inner backticks, opaque to ordinary line fitting. It does not introduce a split inside the span, and the escaped backticks are preserved verbatim; an already conforming authored boundary may still be retained under the overlong-span rule above.

For list items, deferred inline code continuations use continuation indentation rather than repeating the original list marker. This prevents a wrapped checklist item from being reformatted as several independent checklist entries.

Ambiguous close-and-reopen patterns are preserved verbatim, so the formatter does not introduce Markdownlint MD038 spacing violations or change the intended code-span boundaries.

When --wrap is combined with --renumber, ordered list item boundaries are preserved even when a list item contains a long inline code span. The wrapper may leave the span on its existing continuation line, but it does not split a single list item into new numbered steps or strand code-span fragments as separate list items.

When a footnote reference immediately follows an inline code span or Markdown link without intervening whitespace—for example `code`.[^ref] or [text](url).[^ref]—the reference stays on the same line as the preceding punctuation during wrapping. The same rule applies when opening punctuation is coupled to the span, such as (`code`).[^ref].

Inline GFM footnote references that immediately follow sentence punctuation are also kept attached as unbreakable units. For example, Sentence.[^ref], Sentence,[^ref], Sentence?[^ref], and Sentence"[^ref] remain attached during wrapping, and previously split paragraph text such as Sentence. [^ref] or Sentence. followed by [^ref] is normalized back to Sentence.[^ref]. Footnote definition lines such as [^ref]: note text remain definitions and are not joined to preceding prose.

Opening brackets and other opening punctuation ((, [, and CJK openers such as and ) that immediately precede an inline code span or Markdown link stay coupled to that span during wrapping. This prevents a lone opener from being stranded at the end of a line before the code or link that follows it.

Inflectional affixes and possessives that appear immediately after a closing inline code fence — for example `VarGuard`s, `class`'s, `fetch`ed, or `run`ning — are kept on the same line as the code span during wrapping. The tokenizer treats the backtick fence together with its directly attached suffix as a single unbreakable unit, so no line break is ever inserted between the closing backtick and the following letters.

Hyphenated compounds where a word ends with a hyphen immediately before an inline code span — for example pre-`LLMPort`, LLM-`Port`, or (API-`Foo`) — are also kept on the same line during wrapping. The hyphen-prefix token is coupled to the following code span, so wrapping never strands the prefix at the end of a line or the code span at the start of the next. This mirrors the opening-punctuation coupling rule but applies to any token that ends with a hyphen and contains at least one alphabetic character, including Unicode alphabetic characters such as pré-`code` or 字-`code`. If the compound alone exceeds the target width, it may be broken. Trailing-hyphen compounds such as `code`-style continue to be absorbed by the tokenizer at the closing fence.

When a Markdown link or inline code span is followed by trailing punctuation, such as a full stop or comma, mdtablefix keeps that punctuation attached to the same wrapped unit. It does not leave the punctuation orphaned on a line by itself after wrapping.

Blockquote prefixes (>) are parsed before their inner content at every nesting depth, including compact (>>) and spaced (> >) forms. Fenced code blocks, inline code spans, task-list item markers (- [ ], - [x]), ordinary list markers, and footnote definition labels ([^n]:) therefore retain their usual meaning inside blockquotes. Wrapped prose repeats the complete blockquote prefix. For a list inside a blockquote, continuations repeat the blockquote portion and replace only the list marker with an alignment indent.

Fenced code blocks, HTML blocks, indented code blocks (four or more leading spaces or a leading tab), and table rows are passed through unchanged. Wrapping is applied only to prose paragraphs and prefixed lines.

Link reference definitions — lines of the form [label]: <URL> or [label]: URL (with an optional inline title) are left untouched by the reflow pass. The definition line is preserved verbatim; when a valid standalone title continuation line follows (a separate line containing only the title in quotes or parentheses), that line is also preserved verbatim. Collapsed definitions that place the label on one line and an indented destination on the next line are also preserved, including the destination indentation:

[users-guide]:
  docs/users-guide.md

The indented destination continuation is distinct from a standalone title continuation. It must look like a link destination, so indented Markdown blocks such as lists, blockquotes, and headings are still routed through normal block wrapping.

Two trailing spaces at the end of a line produce a hard line break in rendered Markdown. mdtablefix --wrap preserves those trailing spaces on the final wrapped line, so hard-break semantics are not lost after reformatting.

Lines that consist entirely of whitespace — spaces, tabs, or any mixture — are normalized to empty strings during wrapping. Such lines act as paragraph boundaries and are never passed through with their original whitespace content, so the output uses a single uniform separator between paragraphs regardless of the input's incidental indentation.

When computing the indentation width for continuation lines in prefixed contexts (blockquotes, lists, and footnote definitions), mdtablefix measures the prefix using Unicode display width (UnicodeWidthStr::width) rather than byte or character count. Continuation lines therefore stay correctly aligned when the prefix contains full-width characters such as ideographic spaces or CJK punctuation.