mdformat plugin that inserts Semantic Line Breaks (sembr.org) as CommonMark soft breaks
Project description
mdformat-sembr
An mdformat parser-extension plugin that inserts Semantic Line Breaks (SemBr) as CommonMark soft breaks.
SemBr is a convention for adding line breaks in Markdown source at sentence and
clause boundaries. Because the breaks are CommonMark soft breaks (a bare \n
inside a paragraph), they render to a single space — the rendered HTML output is
unchanged, only the source becomes more diff-friendly.
The plugin is fully deterministic: no ML, no network, no LLM calls. The same input always produces the same output.
Why
Moving SemBr logic out of an LLM/agent loop into a token-free, reproducible formatter pass makes authored Markdown consistent and cheap to maintain.
Install
# uv (recommended) — --with is repeatable (or comma-separate the plugins)
uv tool install mdformat --with mdformat-sembr --with mdformat-frontmatter
# pipx — install the app, then inject the plugins into its environment
pipx install mdformat
pipx inject mdformat mdformat-sembr mdformat-frontmatter
# local development
pip install -e .
mdformat-frontmatter is optional: install it only if your Markdown uses
YAML/TOML frontmatter and you want mdformat to preserve/format it. It composes
with mdformat-sembr (frontmatter is a separate node type and is never broken).
Usage
mdformat --version # should list "mdformat_sembr"
echo "First sentence. Second sentence." | mdformat -
From Python:
import mdformat
mdformat.text("First sentence. Second sentence.\n", extensions={"sembr"})
# 'First sentence.\nSecond sentence.\n'
How it works
The plugin registers a postprocessor on the paragraph node type. At that point
inline formatting (emphasis, links, inline code) is already resolved into the string,
so it operates on the final rendered text and only protects a few inline constructs by
regex. Block-level elements (headings, code blocks, tables, frontmatter, HTML blocks)
are separate node types and are never touched.
CHANGES_AST = False: soft breaks are AST-safe by design, so mdformat's built-in
is_md_equal validator gates correctness. If validation ever fails, the break logic is
wrong — it is never worked around with --no-validate or hard breaks.
Configuration
Configure via [plugin.sembr] in .mdformat.toml, or via CLI flags. CLI values merge
over TOML.
| Option | Type | Default | Meaning |
|---|---|---|---|
min_chars |
int | 15 |
Minimum length of the segment before a break is allowed. |
abbreviations |
list[str] | see below | Tokens after which no sentence break is inserted. |
break_clauses |
bool | false |
Enable clause-level breaks (SemBr "SHOULD"). Off by default. |
clause_chars |
str | ",;:—" |
Clause punctuation set (only used when break_clauses true). |
CLI flags: --sembr-min-chars, --sembr-abbreviations, --sembr-break-clauses,
--sembr-clause-chars.
.mdformat.toml example:
[plugin.sembr]
min_chars = 20
break_clauses = true
License
MIT
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file mdformat_sembr-0.1.0.tar.gz.
File metadata
- Download URL: mdformat_sembr-0.1.0.tar.gz
- Upload date:
- Size: 16.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c8f0b00f8545744d23a94b7209491cf71f3d1914d6bf7c46768cad443d05e720
|
|
| MD5 |
fe93b16379870a667f9024ddca7f43d9
|
|
| BLAKE2b-256 |
eed13deac008e9ace9c6c884efccef0c282e9c9fe94efd3f15052282734bef67
|
Provenance
The following attestation bundles were made for mdformat_sembr-0.1.0.tar.gz:
Publisher:
publish.yml on bugrasan/mdformat-sembr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mdformat_sembr-0.1.0.tar.gz -
Subject digest:
c8f0b00f8545744d23a94b7209491cf71f3d1914d6bf7c46768cad443d05e720 - Sigstore transparency entry: 2043029868
- Sigstore integration time:
-
Permalink:
bugrasan/mdformat-sembr@7b8d7515409ce617e9d4f51eaa75e507ed643238 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bugrasan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7b8d7515409ce617e9d4f51eaa75e507ed643238 -
Trigger Event:
push
-
Statement type:
File details
Details for the file mdformat_sembr-0.1.0-py3-none-any.whl.
File metadata
- Download URL: mdformat_sembr-0.1.0-py3-none-any.whl
- Upload date:
- Size: 9.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
5689e5e0b1e55e5550b4bdc17cd3f5b9157a6ca35fc7d95fdbcd143b9eba70f7
|
|
| MD5 |
38c493b30e9b31ebe7575e93cb737980
|
|
| BLAKE2b-256 |
1b9fa758fc8c5d2b65a1dc09beb6842387f41ccecc86216f34dac425cad20991
|
Provenance
The following attestation bundles were made for mdformat_sembr-0.1.0-py3-none-any.whl:
Publisher:
publish.yml on bugrasan/mdformat-sembr
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
mdformat_sembr-0.1.0-py3-none-any.whl -
Subject digest:
5689e5e0b1e55e5550b4bdc17cd3f5b9157a6ca35fc7d95fdbcd143b9eba70f7 - Sigstore transparency entry: 2043029954
- Sigstore integration time:
-
Permalink:
bugrasan/mdformat-sembr@7b8d7515409ce617e9d4f51eaa75e507ed643238 -
Branch / Tag:
refs/tags/v0.1.0 - Owner: https://github.com/bugrasan
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@7b8d7515409ce617e9d4f51eaa75e507ed643238 -
Trigger Event:
push
-
Statement type: