MD018 - No missing space after hash in heading¶
Aliases: no-missing-space-atx
What this rule does¶
Ensures there's a space between the # symbols and the heading text.
Why this matters¶
- Readability: Headings without spaces look cramped and are harder to read
- Compatibility: Some Markdown processors won't recognize headings without spaces
- Standards: Proper spacing follows Markdown best practices
Examples¶
✅ Correct¶
❌ Incorrect¶
🔧 Fixed¶
Configuration¶
| Option | Type | Default | Description |
|---|---|---|---|
magiclink |
boolean | false |
Enable MagicLink support for issue/PR references |
tags |
boolean | null |
Recognize #word as tags instead of malformed headings. Defaults to true for Obsidian flavor, false otherwise |
MagicLink support¶
When magiclink = true, this rule skips PyMdown MagicLink issue/PR references at the start of a line. This prevents false positives when using MagicLink's auto-linking syntax for patterns like #123.
Example¶
# PRs that are helpful for context
#10 discusses the philosophy behind the project, and #37 shows a good example.
#Summary
With magiclink = true:
#10and#37are not flagged (MagicLink issue references)#Summaryis flagged (non-numeric, likely a malformed heading)
Special cases¶
This rule correctly handles:
- Emoji hashtags like #️⃣ and #⃣ (not treated as headings)
- Content inside HTML blocks and comments (e.g., CSS selectors like
#id) - YAML frontmatter comments
- Indented patterns (not at column 1)
Tag syntax support¶
When tags = true, this rule skips #word patterns that look like tags (e.g., #todo, #project/active) instead of treating them as malformed headings.
Tags are recognized following Obsidian's tag rules: a tag must contain at least one non-numerical character, so #1984 is not a tag but #y1984 and #3d_printing are. Multi-hash patterns like ##tag are always treated as malformed headings.
A leading run of digits is allowed as long as a letter, an underscore, a hyphen, a forward slash or an emoji follows it. Digits followed by other punctuation stay flagged, because #37. and #42, are issue references rather than tags.
When tags is not explicitly set, it defaults to true for Obsidian flavor and false otherwise. This means Obsidian users get tag support automatically, while users of other flavors can opt in:
Example¶
# Real Heading
#todo this is a tag
#project/active nested tag
#3d_printing tag starting with a digit
##Introduction
With tags = true:
#todo,#project/activeand#3d_printingare not flagged (recognized as tags)##Introductionis flagged (multi-hash, clearly a malformed heading)#1984is flagged (all-numeric, so not a valid tag)
Automatic fixes¶
This rule automatically adds a space after the # symbols to properly format the heading.
Learn more¶
- CommonMark specification for headings - Technical details about heading syntax