Markdownlint Configuration
Master markdownlint configuration including rule management, configuration files, inline comment directives, style inheritance, and schema validation for consistent Markdown linting.
Overview
Markdownlint is a Node.js style checker and linter for Markdown/CommonMark files. It helps enforce consistent formatting and style across Markdown documentation by providing a comprehensive set of rules that can be customized through configuration files or inline comments.
Installation and Setup
Basic Installation
Install markdownlint in your project:
npm install --save-dev markdownlint markdownlint-cli
or
pnpm add -D markdownlint markdownlint-cli
or
yarn add -D markdownlint markdownlint-cli
Verify Installation
npx markdownlint --version
Configuration File Structure
Basic .markdownlint.json
Create a .markdownlint.json file in your project root:
{ "default": true, "MD003": { "style": "atx_closed" }, "MD007": { "indent": 4 }, "no-hard-tabs": false, "whitespace": false }
This configuration:
-
Enables all default rules via "default": true
-
Configures MD003 (heading style) to use ATX closed format
-
Sets MD007 (unordered list indentation) to 4 spaces
-
Disables the no-hard-tabs rule
-
Disables all whitespace rules
Rule Naming Conventions
Rules can be referenced by their ID (MD###) or friendly name:
{ "MD001": false, "heading-increment": false, "MD003": { "style": "atx" }, "heading-style": { "style": "atx" }, "no-inline-html": { "allowed_elements": ["strong", "em", "br"] } }
Both ID and friendly name work identically.
Configuration Options
Enable/Disable All Rules
{ "default": true }
When "default": false , only explicitly enabled rules are active:
{ "default": false, "MD001": true, "MD003": { "style": "atx" }, "line-length": true }
Rule-Specific Parameters
Heading Style (MD003)
{ "heading-style": { "style": "atx" } }
Options: "atx" , "atx_closed" , "setext" , "setext_with_atx" , "setext_with_atx_closed"
Unordered List Style (MD004)
{ "ul-style": { "style": "asterisk" } }
Options: "asterisk" , "dash" , "plus" , "consistent" , "sublist"
List Indentation (MD007)
{ "ul-indent": { "indent": 4, "start_indented": true } }
Line Length (MD013)
{ "line-length": { "line_length": 100, "heading_line_length": 120, "code_block_line_length": 120, "code_blocks": true, "tables": false, "headings": true, "strict": false, "stern": false } }
No Trailing Spaces (MD009)
{ "no-trailing-spaces": { "br_spaces": 2, "list_item_empty_lines": false, "strict": false } }
No Inline HTML (MD033)
{ "no-inline-html": { "allowed_elements": [ "strong", "em", "br", "sub", "sup", "kbd", "details", "summary" ] } }
Horizontal Rule Style (MD035)
{ "hr-style": { "style": "---" } }
Options: "---" , "***" , "___" , or custom like "- - -"
First Line Heading (MD041)
{ "first-line-heading": { "level": 1, "front_matter_title": "" } }
Required Headings
{ "required-headings": { "headings": [ "# Title", "## Description", "## Examples", "## Resources" ] } }
Proper Names (MD044)
{ "proper-names": { "names": [ "JavaScript", "TypeScript", "GitHub", "markdownlint", "npm" ], "code_blocks": false } }
Inline Configuration Comments
Disable Rules for Entire File
<!-- markdownlint-disable-file -->
This file has no linting applied
Any markdown content here will not be checked.
Disable Specific Rules for File
<!-- markdownlint-disable-file MD013 MD033 -->
Long lines and HTML are allowed in this file
This line can be as long as you want without triggering MD013.
<div>Inline HTML is also allowed</div>
Disable Rules Temporarily
<!-- markdownlint-disable MD033 -->
<div class="custom-block"> HTML content here </div>
<!-- markdownlint-enable MD033 -->
Regular markdown content with rules enforced.
Disable for Single Line
This line follows all rules.
Long line that exceeds limit <!-- markdownlint-disable-line MD013 -->
This line follows all rules again.
Disable for Next Line
<!-- markdownlint-disable-next-line MD013 --> This is a very long line that would normally trigger the line-length rule but won't because of the comment above.
This line follows normal rules.
Capture and Restore Configuration
<!-- markdownlint-capture --> <!-- markdownlint-disable -->
Any violations allowed here.
<!-- markdownlint-restore -->
Back to original configuration.
Configure Rules Inline
<!-- markdownlint-configure-file { "line-length": { "line_length": 120 }, "no-inline-html": { "allowed_elements": ["strong", "em"] } } -->
Document Title
Rest of document follows inline configuration.
Configuration File Formats
JSON Configuration
.markdownlint.json :
{ "$schema": "https://raw.githubusercontent.com/DavidAnson/markdownlint/main/schema/markdownlint-config-schema.json", "default": true, "MD003": { "style": "atx" }, "MD007": { "indent": 2 }, "MD013": { "line_length": 100, "code_blocks": false }, "MD033": { "allowed_elements": ["br", "strong", "em"] } }
YAML Configuration
.markdownlint.yaml :
default: true MD003: style: atx MD007: indent: 2 MD013: line_length: 100 code_blocks: false MD033: allowed_elements: - br - strong - em
JavaScript Configuration
.markdownlint.js :
module.exports = { default: true, MD003: { style: "atx" }, MD007: { indent: 2 }, MD013: { line_length: 100, code_blocks: false }, MD033: { allowed_elements: ["br", "strong", "em"] } };
Configuration Inheritance
Extending Base Configurations
Create a base configuration:
base.json :
{ "default": true, "line-length": { "line_length": 100 } }
Extend it in your project:
custom.json :
{ "extends": "base.json", "no-inline-html": false, "line-length": { "line_length": 120 } }
Using Predefined Styles
Markdownlint includes predefined style configurations:
{ "extends": "markdownlint/style/relaxed" }
Available styles:
-
markdownlint/style/relaxed
-
Less strict rules
-
markdownlint/style/prettier
-
Compatible with Prettier
Schema Validation
Enable IDE Support
Include the $schema property for autocomplete and validation:
{ "$schema": "https://raw.githubusercontent.com/DavidAnson/markdownlint/main/schema/markdownlint-config-schema.json", "default": true }
This enables:
-
Autocomplete for rule names
-
Validation of configuration values
-
Inline documentation in supported editors
Project-Specific Configurations
Per-Directory Configuration
Place .markdownlint.json in specific directories:
project/ ├── .markdownlint.json # Root config ├── docs/ │ ├── .markdownlint.json # Docs-specific config │ └── guides/ │ └── .markdownlint.json # Guides-specific config
Monorepo Configuration
Root .markdownlint.json :
{ "default": true, "line-length": { "line_length": 100 } }
Package-specific packages/api/docs/.markdownlint.json :
{ "extends": "../../../.markdownlint.json", "no-inline-html": { "allowed_elements": ["code", "pre", "div"] } }
Common Configuration Patterns
Strict Documentation Standards
{ "default": true, "heading-style": { "style": "atx" }, "ul-style": { "style": "dash" }, "ol-prefix": { "style": "ordered" }, "line-length": { "line_length": 80, "strict": true }, "no-trailing-spaces": { "strict": true }, "no-inline-html": false, "first-line-heading": { "level": 1 }, "required-headings": { "headings": [ "# Title", "## Description", "## Usage", "## API" ] } }
Relaxed Blog/Article Style
{ "default": true, "line-length": false, "no-inline-html": { "allowed_elements": [ "img", "a", "strong", "em", "br", "div", "span" ] }, "no-duplicate-heading": { "siblings_only": true }, "first-line-heading": false, "single-title": false }
Technical Documentation
{ "default": true, "line-length": { "line_length": 120, "code_blocks": false, "tables": false }, "no-inline-html": { "allowed_elements": [ "details", "summary", "kbd", "sub", "sup", "br" ] }, "code-block-style": { "style": "fenced" }, "code-fence-style": { "style": "backtick" }, "emphasis-style": { "style": "asterisk" }, "strong-style": { "style": "asterisk" } }
README Template
{ "default": true, "line-length": { "line_length": 100, "tables": false, "code_blocks": false }, "no-inline-html": { "allowed_elements": [ "img", "br", "details", "summary", "sup" ] }, "required-headings": { "headings": [ "# *", "## Installation", "## Usage", "## License" ] }, "first-line-heading": { "level": 1 } }
When to Use This Skill
-
Setting up markdownlint in new projects
-
Configuring linting rules for documentation
-
Creating custom rule configurations for teams
-
Troubleshooting configuration issues
-
Establishing Markdown style guides
-
Migrating from other Markdown linters
-
Enforcing consistent documentation standards
-
Configuring monorepo Markdown linting
Best Practices
-
Use Schema Validation - Always include $schema for IDE support
-
Start with Defaults - Begin with "default": true and disable selectively
-
Document Exceptions - Comment why specific rules are disabled
-
Consistent Naming - Use either rule IDs or friendly names, not both
-
Version Control Config - Commit .markdownlint.json to repository
-
Team Agreement - Discuss rule changes with team before applying
-
Progressive Adoption - Gradually enable stricter rules over time
-
Test Changes - Run linter after configuration changes
-
Use Inheritance - Leverage extends for shared configurations
-
Inline Sparingly - Prefer file-level config over inline comments
-
Monitor Rule Updates - Review new rules in markdownlint updates
-
Environment-Specific - Use different configs for different doc types
-
Automation Integration - Include linting in pre-commit hooks
-
Regular Review - Periodically review and update configurations
-
Clear Comments - Add comments explaining complex configurations
Common Pitfalls
-
Conflicting Rules - Enabling contradictory rules (e.g., different heading styles)
-
Over-Configuration - Specifying too many inline disable comments
-
Missing Schema - Not including $schema for validation
-
Incorrect Paths - Using wrong paths in extends property
-
Rule Name Typos - Misspelling rule names (fails silently)
-
JSON Syntax Errors - Invalid JSON breaks configuration parsing
-
Overly Strict - Enabling strict rules without team buy-in
-
Ignoring Warnings - Dismissing legitimate style issues
-
No Base Config - Not establishing project-wide defaults
-
Hardcoded Values - Not using variables for repeated values
-
Stale Configurations - Not updating after markdownlint upgrades
-
Missing Allowed Elements - Blocking necessary HTML elements
-
Inconsistent Inheritance - Different base configs across projects
-
No Testing - Not testing configuration before committing
-
Unclear Disable Reasons - Using disable without explanation
Resources
-
markdownlint GitHub Repository
-
markdownlint Rules Documentation
-
Configuration Schema
-
markdownlint-cli Documentation
-
Custom Rules Guide