# MD087 - Disable comments should suppress something

Aliases: `unused-disable-comment`

This rule is off by default. Enable it explicitly:

```toml
[global]
extend-enable = ["MD087"]
```

## What this rule does

Reports an inline disable comment that removed no finding from the run:

```markdown
A short line. <!-- rumdl-disable-line MD013 -->
```

MD013 has nothing to say about this line, so the comment does nothing.

## Why this matters

A disable comment is written for one line at one moment. The line then gets
rewritten, the rule gets reconfigured, or a false positive gets fixed, and the
comment stays. Nothing points this out: a comment that suppresses nothing costs
no findings, so it survives every run and every review.

What it does cost is the coverage it silently keeps switched off. This one was
added for a long URL:

```markdown
<!-- rumdl-disable-next-line MD013 MD034 -->
See https://example.com/a-very-long-path-that-once-exceeded-the-line-limit
```

Shorten the line later and both rules stay disabled on it. MD034 will not report
the bare URL that appears on that line next year, and nobody will know why.

The same thing happens one scope up. A `<!-- rumdl-disable MD024 -->` left in
place after the duplicate headings it covered were renamed keeps MD024 off for
the rest of the file.

## Examples

### Incorrect

```markdown
A short line. <!-- rumdl-disable-line MD013 -->
```

```markdown
<!-- rumdl-disable-file MD012 -->

# Title

A document with no consecutive blank lines in it.
```

### Correct

```markdown
<!-- rumdl-disable-next-line MD013 -->
A line so long that it genuinely exceeds the configured limit, which is what the comment is for.
```

A comment naming several rules is reported only for the names that suppressed
nothing:

```markdown
Text with <b>html</b>. <!-- rumdl-disable-line MD033 MD013 -->
```

MD033 fires here and MD013 does not, so the message names MD013 alone.

## Configuration

This rule has no options.

## What this rule leaves alone

**A rule the run does not carry.** The verdict comes from what the run
suppressed, so a rule that is not part of the run produced nothing to suppress
and its comments cannot be judged by that silence. This covers a rule turned off
in the configuration, one excluded by `--disable` or a narrowed `--enable`, one
listed under `per-file-ignores`, and the rules that check a workspace rather than
a file (MD051 and MD057), whose findings are filtered after this rule has
reported. Run the rule to have its comments judged.

**A comment naming no rule.** `<!-- rumdl-disable -->` turns off every rule at
once, including the ones a given run does not carry, so no run can show that it
silenced nothing. Naming the rules a comment is for is what makes it reviewable:

```markdown
<!-- rumdl-disable-line MD013 -->
```

**A comment inside a code block.** Fenced and indented code shows a directive
rather than writing one, and it configures nothing:

````markdown
```markdown
<!-- rumdl-disable-line MD013 -->
```
````

An indented block that the document's flavor holds as structure is not code:
a comment in a MkDocs admonition or content-tab body configures the document
like any other, so it is judged like any other.

**`<!-- prettier-ignore -->`**, which belongs to another formatter.

**An unknown rule name.** `<!-- rumdl-disable-line MD999 -->` names nothing this
run carries, so MD087 stays quiet about it. Every run already reports it as an
inline config warning, with a suggestion for the name that was probably meant.

## Scope

Each kind of comment is judged over the lines it can act on:

| Directive | Judged against findings on |
| --- | --- |
| `rumdl-disable-line` | the comment's own line |
| `rumdl-disable-next-line` | the following line |
| `rumdl-disable-file` | the whole document |
| `rumdl-configure-file` with `"MDxxx": false` | the whole document |
| `rumdl-disable` | the lines below the comment, to the end of the document |

A block `rumdl-disable` is measured to the end of the document even when a
`rumdl-enable` closes it earlier. A scope wider than the truth can only leave a
dead comment unreported; a narrower one would report a live comment as dead, and
that is the direction worth avoiding.

A finding spanning several lines is silenced by the first line of its range the
rule is off on, so that is the line its comment is credited for. A second comment
further down the same range is reported, because it is the first one that does
the work and deleting the second changes nothing.

### Comments that cover each other

Two comments can reach the same finding, and then only one of them is doing the
work:

```markdown
<!-- rumdl-disable-file MD013 -->

A very long line that MD013 would otherwise report. <!-- rumdl-disable-line MD013 -->
```

MD013 is already off for the whole file, so the line comment suppresses nothing
of its own and is reported. Delete it and the run says exactly what it said
before.

Which comment is reported follows from which one is still needed. A directive
that turns a rule off for the whole file answers first, then a block
`rumdl-disable`, then a line comment. So the case above reverses when the block
is closed before the finding:

```markdown
<!-- rumdl-disable MD013 -->
<!-- rumdl-enable MD013 -->
A very long line that MD013 would otherwise report. <!-- rumdl-disable-line MD013 -->
```

Here the line comment is the only thing keeping the line quiet, and the block
`rumdl-disable` is the one reported.

## Automatic fixes

None. A disable comment is content the author wrote, sometimes with the line it
protects about to come back, so `rumdl fmt` does not remove it.

## Related rules

- [MD086 - Comments should be closed](md086.md), for the comments that never end
- [Inline configuration reference](inline-configuration.md), which documents
  every directive this rule judges
