Skip to content

MD064 - No Multiple Consecutive Spaces

Aliases: no-multiple-consecutive-spaces

Rule Details

This rule is triggered when multiple consecutive spaces (2 or more) are found in markdown content. Multiple spaces between words serve no purpose in markdown and typically indicate formatting issues or copy-paste artifacts.

Rationale

Multiple consecutive spaces in markdown:

  1. Render as single space: Most markdown renderers collapse multiple spaces into a single space, so extra spaces have no visual effect
  2. Indicate potential issues: Often result from copy-paste errors or accidental keystrokes
  3. Reduce readability: Make the source markdown harder to read

Examples

Incorrect

This is   a sentence with extra spaces.

- List   item with extra spaces

> Quote   with extra spaces

Correct

This is a sentence with single spaces.

- List item with single spaces

> Quote with single spaces

Exceptions

This rule does NOT flag spaces in the following contexts:

1. Inline Code Spans

Spaces inside inline code are intentional and preserved:

Use `code   with   spaces` for formatting.

2. Fenced/Indented Code Blocks

Code block content is not processed:

```
code   with   intentional   spaces
```

3. Leading Indentation

Leading whitespace for structure is preserved:

    Indented paragraph (4 spaces)

4. Trailing Spaces

All trailing spaces are handled by MD009 and are not flagged by this rule:

Line with trailing spaces
Another line with trailing spaces

Use MD009 to control trailing space behavior.

5. Front Matter

YAML/TOML/JSON front matter is not processed:

---
title:   Document Title
author:   John Doe
---

6. HTML Comments

Content inside HTML comments is not processed:

<!-- comment   with   spaces -->

7. HTML Blocks

Content inside HTML block elements is not processed.

8. Table Rows

Table rows with alignment padding are not flagged:

| Header 1 | Header 2 |
| -------- | -------- |
| Cell 1   | Cell 2   |

GFM-style tables without leading/trailing pipes are also skipped:

Header 1  | Header 2  | Header 3
--------- | --------- | ---------
Cell 1    | Cell 2    | Cell 3

The spaces used for visual alignment in tables are intentional.

9. List Marker Spacing

Spaces after list markers are handled by MD030, not MD064:

*   Item with extra space after marker
1.  Numbered item with extra space

10. Blockquote Marker Spacing

Spaces after blockquote markers are handled by MD027:

>  Quote with extra space after marker
>>  Nested blockquote

Spaces after the colon in reference link definitions:

[ref]:  https://example.com
[link]:   https://example.com "Title"

12. Footnote Markers

Spaces after footnote markers:

[^1]:  Footnote text
[^note]:   Extended footnote

13. Definition List Markers

Spaces after definition list markers (PHP Markdown Extra / Pandoc):

Term
:   Definition text

14. Task List Checkboxes

Spaces after task list checkboxes:

- [ ]  Unchecked task
- [x]  Checked task

Under the obsidian flavor, extended checkboxes such as [/], [-] and [>] are recognized as well (see the Obsidian flavor).

15. Tab-Width Runs

A run of 4, 8, 12 or any other multiple of 4 spaces is treated as a replaced tab and is not flagged, so this rule does not undo MD010's tab-to-spaces conversion at MD010's default width. With spaces-per-tab set to 2 or 3, a tab inside a line becomes a run this rule flags:

Column one    column two        column three

Runs of 2 and 3 spaces, and runs such as 5 or 6 that are not a multiple of 4, are still flagged. Use MD010 to control tabs and their replacement width.

16. Column-Aligned Lists

When a list has at least two items and every item contains a run of two or more spaces, the spacing is read as deliberate column alignment (the "Useful commands" section that cdk init generates is the classic case) and the item lines of that list are skipped. A single item has nothing to align with, so it is checked like any other line. Continuation lines under an item are still checked. Collapsing the runs item by item would break the alignment while leaving the document lint-clean, so the rule keeps the layout instead:

- `npm run build`   compile typescript to js
- `npm run watch`   watch for changes and compile
- `npm run test`    perform the jest unit tests

Each list is judged on its own items, so a nested list is aligned or not independently of the list that contains it.

Fix

The automatic fix collapses multiple consecutive spaces to a single space.

Before:

This is   a sentence   with extra   spaces.

After:

This is a sentence with extra spaces.

When allow-sentence-double-space is enabled, the fix preserves exactly 2 spaces after sentence boundaries while collapsing other multiple spaces to 1.

Configuration

Option Type Default Description
allow-sentence-double-space boolean false Allow exactly 2 spaces after sentence-ending punctuation

allow-sentence-double-space

The allow-sentence-double-space option enables the traditional typographical convention of using two spaces after sentence-ending punctuation (., !, ?) while still flagging multiple spaces elsewhere:

[MD064]
allow-sentence-double-space = true

With this configuration:

End of sentence.  Start of next sentence.       <- OK (2 spaces after period)
Multiple  spaces  in middle of sentence.        <- Flagged (not after sentence)
What a question!  Here's the answer.            <- OK (2 spaces after !)
Really?  Yes, really.                           <- OK (2 spaces after ?)

Recognized Sentence Boundaries

The rule recognizes sentences ending with:

  • Period (.) followed by spaces (not part of ellipsis or abbreviation)
  • Exclamation mark (!)
  • Question mark (?)

Closing punctuation after the sentence-ending punctuation is handled correctly:

"End quote."  Next sentence.                    <- OK (period inside quotes)
She said "Hello!"  He replied.                  <- OK (! inside quotes)
(See appendix.)  More content.                  <- OK (period inside parens)
The book [2024].  Next reference.               <- OK (period inside brackets)

Ellipsis Handling

Ellipsis (...) is treated as a sentence boundary, allowing double space after:

And so it goes...  The story continues.         <- OK (after ellipsis)

Disabling the Rule

To disable this rule entirely:

[global]
disable = ["MD064"]
  • MD009 - Trailing spaces (handles trailing whitespace)
  • MD010 - Hard tabs (handles tab characters)
  • MD012 - Multiple consecutive blank lines
  • MD027 - Multiple spaces after blockquote symbol
  • MD030 - Spaces after list markers