An mdformat plugin that provides unified control over Markdown spacing:
- EditorConfig support: Configure list indentation via
.editorconfigfiles - Tight list formatting: Automatically removes unnecessary blank lines between list items
- Frontmatter spacing: Normalizes spacing after YAML frontmatter (works with mdformat-frontmatter)
- Consecutive blank line normalization: Limits runs of 3+ empty lines to a maximum of 2
- Trailing whitespace removal: Strips trailing whitespace outside code blocks
- Escaped link repair: Fixes malformed multi-line links from web-clipped content
- Smart dash conversion: Converts
--to en-dash (–) and---to em-dash (—), preserving code blocks, inline code, HTML comments, and HTML tags - Wikilink preservation: Handles Obsidian-style
[[links]],[[links|aliases]],[[page#heading]],[[page#^blockid]], and![[embeds]] - Soft break joining: Joins soft breaks (plain newlines within paragraphs) into single lines, normalizing to single-line paragraphs
pip install mdformat-space-controlOr with pipx for command-line usage:
pipx install mdformat
pipx inject mdformat mdformat-space-controlAfter installation, mdformat will automatically use this plugin:
mdformat your-file.mdCreate an .editorconfig file in your project:
# .editorconfig
root = true
[*.md]
indent_style = space
indent_size = 4Nested lists will use the configured indentation:
Before:
- Item 1
- Nested item
- Item 2After (with 4-space indent):
- Item 1
- Nested item
- Item 2Lists with single-paragraph items are automatically formatted as tight lists:
Before:
- Item 1
- Item 2
- Item 3After:
- Item 1
- Item 2
- Item 3Multi-paragraph items preserve loose formatting:
- First item with multiple paragraphs
Second paragraph of first item
- Second itemWhen used with mdformat-frontmatter, this plugin removes blank lines between the frontmatter closing delimiter and the first content block:
Before:
---
title: My Document
---
# IntroductionAfter:
---
title: My Document
---
# IntroductionInstall both plugins for this feature:
pip install mdformat-space-control mdformat-frontmatter| Property | Status | Notes |
|---|---|---|
indent_style |
Supported | space or tab for list indentation |
indent_size |
Supported | Number of spaces per indent level |
tab_width |
Supported | Used when indent_size = tab |
When using the Python API, you can set the file context for EditorConfig lookup:
import mdformat
from mdformat_space_control import set_current_file
set_current_file("/path/to/your/file.md")
try:
result = mdformat.text(markdown_text, extensions={"space_control"})
finally:
set_current_file(None)Markdown dash sequences are automatically converted to their Unicode equivalents:
--→ en-dash (–, U+2013)---→ em-dash (—, U+2014)
Before:
The result---unexpected as it was---changed everything.
Pages 10--20 of the report.After:
The result—unexpected as it was—changed everything.
Pages 10–20 of the report.Dashes are preserved inside fenced code blocks, inline code spans, HTML comments, and HTML tags. Thematic breaks (---) and frontmatter delimiters are not affected. Sequences of 4+ dashes are left unchanged.
Obsidian-style wikilinks are preserved during formatting:
Link to [[another note]] or [[note|with alias]].
Embed an image: ![[photo.jpg]]
Link to heading: [[note#section]]
Block reference: [[note#^blockid]]Wikilinks inside markdown link text are correctly handled without duplication:
[![[image.jpg]]](http://example.com)Soft breaks (plain newlines within paragraphs) are joined into single lines with spaces. This normalizes editor-inserted line wraps to single-line paragraphs, matching CommonMark rendering behavior where soft breaks produce spaces in HTML output. The joining applies to paragraphs, list items, and blockquotes.
Before:
This is a paragraph with
a soft line break in the source.After:
This is a paragraph with a soft line break in the source.Explicit hard breaks (\ + newline) are preserved unchanged.
This plugin is tested to work alongside:
- mdformat-frontmatter - YAML frontmatter parsing
- mdformat-simple-breaks - Normalizes thematic breaks to
--- - mdformat-gfm - GFM table parsing (prevents hard breaks from being inserted into pipe table rows)
For formatting files in an Obsidian vault, the recommended install is:
pip install mdformat-space-control mdformat-frontmatter mdformat-gfmNote: Wikilink support is built-in; mdformat-wikilink is not needed.
# Install dependencies
uv sync
# Run tests
uv run python -m pytest
# Run with coverage
uv run python -m pytest --cov=mdformat_space_controlMIT - see LICENSE file for details.