MD024 - Avoid duplicate heading text¶
Aliases: no-duplicate-heading
What this rule does¶
Checks that headings don't have identical text, preventing confusion and navigation issues.
Why this matters¶
- Better navigation: Unique headings make it easier to find specific sections
- Clear table of contents: Automated TOCs need unique headings to create proper links
- Improved accessibility: Screen readers rely on unique headings for navigation
- Avoid confusion: Readers won't wonder which "Introduction" section they're in
Examples¶
✅ Correct¶
# Project Setup
## Installing Dependencies
Details about npm install...
## Configuring the Environment
Details about environment setup...
## Running Tests
How to run the test suite...
❌ Incorrect¶
# Project Setup
## Setup
Details about npm install...
## Setup
Details about environment setup...
## Setup
How to run the test suite...
🔧 Fixed¶
# Project Setup
## Installing Dependencies
Details about npm install...
## Environment Configuration
Details about environment setup...
## Test Setup
How to run the test suite...
Configuration¶
[MD024]
allow-different-nesting = false # Allow duplicates at different levels (default: false)
siblings-only = true # Only check siblings at same level (default: true)
allow-different-link-anchors = true # Treat headings with different {#custom-id} as distinct (default: true)
Note: rumdl defaults siblings-only to true (unlike markdownlint's false ) to reduce false positives in CHANGELOGs and structured documentation. To match markdownlint's stricter behavior, set
siblings-only = false .
allow-different-link-anchors¶
When true (the default), two headings with the same visible text are considered distinct if they carry different {#id} suffixes — a syntax supported by Hugo, Pandoc, Kramdown, and other processors. For example:
These produce different rendered anchors and are not flagged. This matches the effective behavior of markdownlint, which compares raw heading text (which retains the {#id} suffix).
Set to false to ignore {#id} suffixes during deduplication (the previous behavior).
Headings inside blockquotes¶
Headings inside blockquotes (including nested quotes, a quote inside a list item
and a list item inside a quote) are checked like any other heading. They share the
duplicate set with unquoted headings, because every heading gets an anchor, and
they follow allow-different-nesting and siblings-only exactly as a heading
inside a list item does: a quoted heading takes its place in the section path.
Automatic fixes¶
This rule cannot be automatically fixed because changing heading text requires understanding the content's meaning. You'll need to manually update duplicate headings to be more descriptive.