Skip to content

jdmonaco/mdformat-space-control

Repository files navigation

mdformat-space-control

Build Status PyPI version

An mdformat plugin that provides unified control over Markdown spacing:

  • EditorConfig support: Configure list indentation via .editorconfig files
  • 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

Installation

pip install mdformat-space-control

Or with pipx for command-line usage:

pipx install mdformat
pipx inject mdformat mdformat-space-control

Usage

After installation, mdformat will automatically use this plugin:

mdformat your-file.md

EditorConfig Support

Create an .editorconfig file in your project:

# .editorconfig
root = true

[*.md]
indent_style = space
indent_size = 4

Nested lists will use the configured indentation:

Before:

- Item 1
  - Nested item
- Item 2

After (with 4-space indent):

- Item 1
    - Nested item
- Item 2

Tight List Formatting

Lists with single-paragraph items are automatically formatted as tight lists:

Before:

- Item 1

- Item 2

- Item 3

After:

- Item 1
- Item 2
- Item 3

Multi-paragraph items preserve loose formatting:

- First item with multiple paragraphs

  Second paragraph of first item

- Second item

Frontmatter Spacing

When used with mdformat-frontmatter, this plugin removes blank lines between the frontmatter closing delimiter and the first content block:

Before:

---
title: My Document
---


# Introduction

After:

---
title: My Document
---
# Introduction

Install both plugins for this feature:

pip install mdformat-space-control mdformat-frontmatter

EditorConfig Properties

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

Python API

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)

Smart Dash Conversion

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.

Wikilink Preservation

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 Break Joining

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.

Compatible Plugins

This plugin is tested to work alongside:

For formatting files in an Obsidian vault, the recommended install is:

pip install mdformat-space-control mdformat-frontmatter mdformat-gfm

Note: Wikilink support is built-in; mdformat-wikilink is not needed.

Development

# Install dependencies
uv sync

# Run tests
uv run python -m pytest

# Run with coverage
uv run python -m pytest --cov=mdformat_space_control

License

MIT - see LICENSE file for details.

About

An mdformat plugin that tightens list, separates them with empty lines, and applies EditorConfig indentation settings.

Topics

Resources

License

Stars

Watchers

Forks

Contributors

Languages