Skip to content

MD086 - Comments should be closed

Aliases: no-unclosed-comments

What this rule does

Reports a comment opener that nothing closes: <!-- with no --> after it, and in the Obsidian flavor %% with no second %%.

Why this matters

An unclosed comment does not fail loudly. It produces a document that still looks complete in the source while the rendered page is wrong, and which way it is wrong depends on where the opener sits.

At the start of a line, <!-- opens an HTML block that runs to the end of the document. Every heading, list and paragraph below it disappears from the render:

# Release notes

<!-- TODO: rewrite this section

## Breaking changes

The `--force-exclude` flag is gone.

Here the breaking-changes section is published nowhere. The file is 40 lines long and the page shows one heading.

In the middle of a paragraph the failure inverts. CommonMark has no comment to open there, so it renders the marker as literal text and the note the author meant to hide gets published:

The migration is straightforward. <!-- ask legal before publishing this

Neither case is caught by the rest of the linter: no other rule reports a missing closer, and rumdl fmt will not add one. Without this rule both documents above lint clean.

Examples

Incorrect

<!-- a note that is never closed

# Heading
Some prose <!-- an aside that runs off the end

Correct

<!-- a note that is closed -->

# Heading
<!--
A comment may span
as many lines as it needs.
-->

Obsidian comments

Under flavor = "obsidian" the same check applies to %%, whose closer is another %%. Obsidian hides everything from an unclosed %% to the end of the note, so the consequence matches the block form above.

%% a note that is never closed

## Section

Other flavors treat %% as ordinary text and are not checked for it.

The two syntaxes hide each other's delimiters. A <!-- between a pair of %% is text Obsidian hides, not an opener, so it is not reported:

%% reminder: <!-- is how HTML comments start %%

This holds both ways round. Obsidian hides everything from an unclosed %% to the end of the note, so a <!-- below one is inside it. An unclosed <!-- at the start of a line opens an HTML block, so a %% inside that block is comment text too. Neither is reported as a second unclosed comment.

An unclosed <!-- in the middle of a paragraph is different: CommonMark renders it as literal text, so it opens nothing and a %% after it is reported on its own. The same applies once the block ends, which inside a blockquote or a list item happens before the end of the document.

Configuration

This rule has no options.

What this rule leaves alone

<!--> and <!---> are complete comments, not unclosed ones. A comment ends at the first -->, and the opener's own dashes may supply that closer's leading dashes, so these render as an empty comment and everything after them is normal content.

<!--> This text is published, because the comment above it is closed.

Openers inside code are shown, not used, so a <!-- in a fenced code block or a code span is ignored:

```html
<!-- an example of HTML comment syntax
```

Front matter is data rather than markdown. A <!-- in a YAML or TOML value is part of the value and is not reported:

---
description: "the <!-- marker opens a comment"
---

Automatic fixes

None. Where the missing closer belongs is a guess, and both guesses are destructive: appending --> at the end of the document would comment out everything the author meant to publish, and inserting it after the first line would assume the comment was a one-liner. The fix is a judgment about intent, so it stays with the author.