Skip to content

Repository files navigation

md-format

Format Markdown files with Prettier for general formatting, then re-align tables using the yzhang.markdown-all-in-one table alignment algorithm — with correct CJK and Emoji character width handling (which Prettier's byte-based alignment gets wrong). Use --tables-only to skip Prettier and align tables alone.

It ships in two forms that share the same formatting core:

  • a CLI (md-fmt) that recursively formats files — documented below;
  • a VS Code extension that formats the active document via Format Document (Shift+Alt+F) — see extension/.

Installation

git clone <repo-url> md-format
cd md-format
npm install
npm link

After npm link, the md-fmt command is available globally.

Usage

md-fmt [options] <directory|file> [<directory|file> ...]

Options

Option Description Default
-h, --help Show help message
-d, --dry-run Print what would be changed without writing false
--check Exit non-zero if any file needs formatting (for CI) false
--tables-only Only align tables; skip Prettier formatting false
--delimiter-no-pad Enable delimiterRowNoPadding false
--normalize-indent Enable normalizeIndentation false
--tab-size <n> Tab size for indentation normalization 4
--hr-length <n> Length of standalone thematic breaks (<hr>, e.g. ---); min 3 3

Examples

# Format all .md files under ./docs
md-fmt ./docs

# Preview changes without writing
md-fmt --dry-run ./docs

# Format a single file
md-fmt ./README.md

Configuration

Prettier formatting respects a standard .prettierrc, resolved relative to each target file's location via Prettier's own config lookup (not relative to where md-fmt runs). On top of that, md-fmt always applies a built-in default of embeddedLanguageFormatting: "off", so fenced code blocks (JSON, JS, etc.) are left untouched — this preserves things like multi-line JSON arrays and single-quoted JS regardless of the target location. A target-local .prettierrc can override this default. The table alignment step is configured separately:

Place a mdformat.config.js in the project root to override the default character width ranges:

module.exports = {
  // Unicode ranges treated as double-width (CJK, arrows, symbols, etc.)
  doubleWidthUnicodeRanges: [
    '\u2014-\u2015', // Em Dash, horizontal bar
    '\u2024-\u2026', // One Dot Leader, Two Dot Leader, Horizontal Ellipsis
    '\u2030-\u2031', // Per Mille Sign, Per Ten Thousand Sign
    '\u203b',        // Reference Mark
    '\u2190-\u2193', // Arrows (←, ↑, →, ↓)
    '\u25a0-\u25ff', // Geometric Shapes
    '\u2600-\u26ff', // Miscellaneous Symbols
    '\u2713',        // Check Mark
    '\u2717',        // Ballot X
    '\u2e80-\u2eff', // CJK Radicals Supplement
    '\u2f00-\u2fdf', // Kangxi Radicals
    '\u3000-\u9fff', // CJK Unified Ideographs
    '\uac00-\ud7af', // Hangul Syllables
    '\uf900-\ufaff', // CJK Compatibility Ideographs
    '\ufe30-\ufe4f', // CJK Compatibility Forms
    '\ufe50-\ufe6f', // Small Form Variants
    '\uff01-\uff60', // Fullwidth ASCII variants
  ],
  // Characters matched by \p{Extended_Pictographic} but rendered as narrow (1-width) in your font — subtract them back to width 1
  narrowOverrideUnicodeRanges: [
    '\u2122', // ™ Trade Mark Sign
    '\u2139', // ℹ Information Source
  ],
};

If no config file is present, the defaults above are used.

Excluding Files

md-fmt recursively formats files ending in .md or .markdown.

Create a .mdformatignore file to control what is skipped. It uses full .gitignore syntax (anchoring, negation with !, comments, any-depth matching), matched relative to each target root. If the file is present it replaces the built-in defaults; if it is absent, these defaults are used:

node_modules
vendor
.git
dist
build
.cache

Symlink cycles are detected (a directory is walked at most once by real path), and dangling symlinks are skipped.

VS Code Extension

The extension/ folder is a VS Code formatter extension built on the same core, so it produces output identical to the CLI. Register it as your Markdown formatter and use Format Document (Shift+Alt+F / Shift+Opt+F) or Format Document With….

cd extension
npm install
npm run compile     # bundle src/extension.js → dist/extension.js (esbuild)

Press F5 from the repository root to launch an Extension Development Host, or run npm run package (in extension/) to build a .vsix. Settings mirror the CLI options (mdFormat.tablesOnly, mdFormat.delimiterRowNoPadding, mdFormat.normalizeIndentation, mdFormat.tabSize, mdFormat.hrLength) plus mdFormat.doubleWidthUnicodeRanges / mdFormat.narrowOverrideUnicodeRanges; the extension also reads a workspace-root mdformat.config.js for width configuration. See extension/README.md for details.

Requirements

  • Node.js 18+ (uses the built-in node --test runner for npm test)
  • npm

License

MIT

Contributors

About

A CLI tool to recursively format Markdown files

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages