rumdl 0.2.59

A fast Markdown linter written in Rust (Ru(st) MarkDown Linter)
Documentation
# Md063 - Heading Capitalization

Aliases: `heading-capitalization`

## What This Rule Does

Enforces consistent capitalization styles for markdown headings. This rule supports title case, sentence case, and all caps styles.

**Note:** This rule is disabled by default. You must explicitly enable it in your configuration.

## Why This Matters

- **Consistency**: Ensures all headings follow the same capitalization style
- **Professional appearance**: Properly capitalized headings look more polished
- **Readability**: Consistent formatting helps readers navigate your document
- **Style guide compliance**: Many style guides require specific heading capitalization

## Examples

### Title Case (default)

#### Incorrect

```markdown
# the quick brown fox
## getting started with javascript
### self-documenting code practices
```

#### Correct

```markdown
# The Quick Brown Fox
## Getting Started with JavaScript
### Self-Documenting Code Practices
```

### Sentence Case

#### Incorrect

```markdown
# The Quick Brown Fox
## Getting Started With JavaScript
```

#### Correct

```markdown
# The quick brown fox
## Getting started with JavaScript
```

### All Caps

#### Incorrect

```markdown
# introduction
## Getting Started
```

#### Correct

```markdown
# INTRODUCTION
## GETTING STARTED
```

## Configuration

| Option                        | Type     | Default        | Description                                                        |
| ----------------------------- | -------- | -------------- | ------------------------------------------------------------------ |
| `style`                       | string   | `"title-case"` | Capitalization style: `title-case`, `sentence-case`, or `all-caps` |
| `lowercase-words`             | string[] | *(see below)*  | Words to keep lowercase in title case                              |
| `ignore-words`                | string[] | `[]`           | Words to preserve exactly (brand names)                            |
| `preserve-cased-words`        | boolean  | `true`         | Auto-preserve words with internal capitals                         |
| `sentence-case-restart-after` | string[] | `[]`           | Punctuation that starts a new sentence in sentence case            |
| `min-level`                   | integer  | `1`            | Minimum heading level to check (1-6)                               |
| `max-level`                   | integer  | `6`            | Maximum heading level to check (1-6)                               |

### Default Lowercase Words

```text
a, an, and, as, at, but, by, for, in, nor, of, on, or, so, the, to, up, yet
```

### Example Configurations

#### Enable With Title Case (default)

```toml
[MD063]
enabled = true
style = "title-case"
```

#### Sentence Case

```toml
[MD063]
style = "sentence-case"
```

#### Sentence Case That Restarts After a Colon

```toml
[MD063]
style = "sentence-case"
sentence-case-restart-after = [":"]
```

#### All Caps

```toml
[MD063]
style = "all-caps"
```

#### Preserve Brand Names

```toml
[MD063]
style = "title-case"
ignore-words = ["iPhone", "macOS", "GitHub", "JavaScript", "TypeScript"]
preserve-cased-words = true
```

#### Only Check H1 and H2 Headings

```toml
[MD063]
style = "title-case"
min-level = 1
max-level = 2
```

#### Custom Lowercase Words

```toml
[MD063]
style = "title-case"
lowercase-words = ["a", "an", "the", "and", "but", "or", "for", "nor", "on", "at", "to", "by", "from", "with", "without", "into", "onto", "upon", "vs", "via"]
```

## Special Handling

### Sentence Boundaries Inside a Heading

By default sentence case capitalizes only the heading's first word, so everything after a colon is lowercased:

```markdown
# Requirement 1: Struct to Logger Slice Conversion
```

Becomes:

```markdown
# Requirement 1: struct to logger slice conversion
```

Set `sentence-case-restart-after` to the punctuation that should start a new sentence:

```toml
[MD063]
style = "sentence-case"
sentence-case-restart-after = [":"]
```

Now the word after the colon is capitalized like the heading's first word:

```markdown
# Requirement 1: Struct to logger slice conversion
```

Each entry is matched against the **end of a word**, so the boundary is only recognized where whitespace follows it. That is what keeps `Well-Known Ports` intact when `-` is configured, and leaves `https://example.com/A/B` alone when `:` is:

```markdown
# Ports: Well-Known ports explained
```

A boundary with nothing after it (`# Setup:`) changes nothing, and words preserved by `ignore-words`, `preserve-cased-words` or an MD044 proper name keep winning over the restart, so `iPhone` after a colon stays `iPhone` rather than becoming `IPhone`.

Boundaries are recognized in the parts of a heading the rule capitalizes, which is plain text and link text:

```markdown
# Topic [see:]./guide.md More detail
```

Inline code, HTML and image alt text are preserved verbatim rather than capitalized, so a boundary inside one of them is not treated as a sentence break:

```markdown
# Topic `see:` more detail
```

The default is empty, which is the behavior described at the top of this section.

### Inline Code

Inline code spans are preserved as-is:

```markdown
# Using `const` in JavaScript
```

Becomes:

```markdown
# Using `const` in JavaScript
```

The backticked content is never modified.

### Links

Link text is capitalized, but URLs are preserved:

```markdown
# See the [getting started]./guide.md guide
```

Becomes:

```markdown
# See the [Getting Started]./guide.md Guide
```

### Custom Header IDs

Custom header IDs (Kramdown syntax) are preserved:

```markdown
# getting started {#intro}
```

Becomes:

```markdown
# Getting Started {#intro}
```

### Mixed-Case Words

When `preserve-cased-words` is enabled (default), words with internal capitals are preserved:

```markdown
# using GitHub actions
```

Becomes:

```markdown
# Using GitHub Actions
```

Note: "GitHub" is preserved because it has an internal capital letter.

### Hyphenated Words

Each part of a hyphenated word is capitalized in title case:

```markdown
# self-documenting code
```

Becomes:

```markdown
# Self-Documenting Code
```

## Automatic Fixes

This rule can automatically fix capitalization issues. Run:

```bash
rumdl check --fix yourfile.md
```

## Related Rules

- [MD025 - Single H1 heading]md025.md
- [MD026 - No trailing punctuation in heading]md026.md
- [MD044 - Proper names]md044.md

## Rationale

Consistent heading capitalization improves document readability and professionalism. This rule uses the `titlecase` crate which implements John Gruber's title case algorithm, ensuring proper handling
of edge cases like articles, prepositions, and hyphenated words.

The rule is disabled by default because capitalization preferences vary widely between style guides (AP, Chicago, APA) and personal preferences. Enable it only if your project requires consistent
heading capitalization.