mdx-formatter
GitHub repository

Type to search...

to open search from anywhere

Usage

CLI and API usage for mdx-formatter

CLI

# Check files (exit with error if formatting needed)
mdx-formatter --check "**/*.{md,mdx}"

# Format files in place
mdx-formatter --write "**/*.{md,mdx}"

# Preview what would be changed (default)
mdx-formatter "**/*.{md,mdx}"

# Preview every rule-level change on stderr without touching files
mdx-formatter --dry-run "**/*.{md,mdx}"

# Ignore specific patterns
mdx-formatter --write "**/*.md" --ignore "node_modules/**,dist/**"

# Apply additional .gitignore-style rules (repeatable)
mdx-formatter --write "**/*.md" --ignore-path .ci/mdx-ignore

# Disable automatic .gitignore discovery for this invocation
mdx-formatter --check "**/*.md" --no-gitignore

# Use a custom config file
mdx-formatter --write "**/*.md" --config ./my-config.json

The CLI loads .gitignore files automatically for glob discovery. Rules are anchored to the directory containing each .gitignore; nested files are evaluated after parent files, so deeper rules override shallower ones. Files above the current working directory are not consulted. Use repeatable --ignore-path options for caller-provided rules (later files override earlier ones); --no-gitignore disables only the automatic lookup.

An explicit path argument bypasses config exclude and automatic .gitignore rules, but --ignore and --ignore-path still apply. Quote glob operands: when the shell expands an unquoted *.md into real filenames, the CLI sees explicit paths and therefore cannot apply exclude or automatic .gitignore rules to them.

Ignore-file examples

If .ci/mdx-ignore contains generated/, apply it while discovering files:

mdx-formatter --check "**/*.{md,mdx}" --ignore-path .ci/mdx-ignore

To inspect files that the project's .gitignore would normally hide:

mdx-formatter --check "**/*.{md,mdx}" --no-gitignore

The --ignore-path rules still apply when --no-gitignore is present.

Preview changes with --dry-run

--dry-run writes a per-rule change report to stderr and leaves files byte-identical on disk. It always exits 0 regardless of whether there was anything to report, and it conflicts with --write / --check.

Each entry is printed as:

<path>:<start>-<end> [<rule>]
  - <before-line-1>
  - <before-line-2>
  + <after-line-1>
  + <after-line-2>

Before/after snippets are capped at 3 lines each and truncated with … beyond that. Line numbers are 1-based. The report format matches the standalone Rust CLI's output byte-for-byte so tooling can consume either.

Use this to preview what the five list-normalize rules (and any other rule) would change before committing to --write.

Programmatic dry-run

import { dryRunReport } from '@takazudo/mdx-formatter';

const entries = dryRunReport(content);
// [
//   { rule: 'tighten-list-continuations',
//     startLine: 0, endLine: 2,
//     before: ['- foo, or', '', '  bar'],
//     after:  ['- foo, or', '  bar'] },
//   …
// ]

startLine / endLine are 0-indexed.

API

import { format } from '@takazudo/mdx-formatter';

// Format a string
const formatted = await format('# Hello\nWorld');
console.log(formatted); // '# Hello\n\nWorld'

// Format with custom settings
const formatted2 = await format(content, {
  settings: {
    addEmptyLinesInBlockJsx: {
      blockComponents: ['Outro', 'InfoBox'],
    },
    indentJsxContent: {
      containerComponents: ['Outro', 'InfoBox'],
    },
    formatMultiLineJsx: {
      ignoreComponents: ['CodeBlock'],
    },
  },
});

Stdin

cat file.md | ./format-stdin.js > formatted.md

Integration with lint-staged

Add to your package.json:

{
  "lint-staged": {
    "*.{md,mdx}": ["mdx-formatter --write"]
  }
}

Revision History

CreatedUpdated