---
title: "Markdown heading not working after paragraph text"
slug: markdown-heading-after-paragraph
excerpt: "Quoted under What the markdown reader did with hb.md is pandoc's output for a hash line typed straight under a sentence."
quickAnswer: "Under What the markdown reader did with hb.md, the single paragraph pandoc wrote for a hash line with text right above it is quoted. The section A blank line above the heading quotes pandoc's output for hb-blank.md. Pandoc's results once the extension was dropped sit in Turning off blank_before_header. Commonmark output for both test files, with the spec lines it matches, is in What commonmark and the spec say. Reader output for a sentence wrapped onto a hash line appears in A wrapped sentence and a stray hash. Steps to locate and repair the line are listed in Find and fix the heading."
keyTakeaways:
  - "Pandoc's one-paragraph result for hb.md is quoted under What the markdown reader did with hb.md."
  - "An h1 carrying the id notes is shown in A blank line above the heading."
  - "Runs with the extension removed are quoted in Turning off blank_before_header."
  - "Spec line numbers and commonmark output are paired in What commonmark and the spec say."
  - "Grep and pandoc commands that test a file are set out in Find and fix the heading."
publishedDate: 2026-10-20
dateModified: 2026-10-20
author: Bobby Huang
cluster: B
role: post
status: published
faq:
  - q: Why did my heading stay inside the paragraph?
    a: "The single p element pandoc wrote for that file is quoted under What the markdown reader did with hb.md."
  - q: Is the blank line needed under commonmark?
    a: "Under What commonmark and the spec say, its output for hb.md and hb-blank.md is quoted."
  - q: What if there is no space after the hash?
    a: "The section Find and fix the heading links the cheat sheet for a hash lacking a space after it."
  - q: How do I repair the line?
    a: "Five steps using grep and pandoc are listed in Find and fix the heading."
related:
  - markdown-paragraphs-blank-lines
  - markdown-cheat-sheet
  - markdown-headings-anchor-links
---

When a markdown heading is not working after paragraph text, check the line sitting just above the hash. In pandoc's `markdown` reader, a `# Notes` line placed directly beneath a sentence stayed part of that sentence's paragraph in this test.

Each test here ran a single time on one Mac; the converter was pandoc 3.8.3. Quoted here are the elements pandoc wrote; nothing beyond that HTML got checked. For how blank lines split paragraphs in general, see the [post on paragraphs and blank lines](markdown-paragraphs-blank-lines.md).

## The test files

Running `cat hb.md` printed:

```markdown
Jane Doe wrote this line.
# Notes
More text.
```

The second file, `hb-blank.md`, adds one empty line between the first line and `# Notes`. Running `cat hb-blank.md` printed:

```markdown
Jane Doe wrote this line.

# Notes
More text.
```

Each file was converted under three reader settings: `markdown`, `markdown-blank_before_header` and `commonmark`.

## What the markdown reader did with hb.md

The command:

```sh
pandoc -f markdown -t html hb.md
```

Output:

```html
<p>Jane Doe wrote this line. # Notes More text.</p>
```

Pandoc wrote one `p` element and no `h1`. The hash sign, the space and the word Notes came through as paragraph text, and the line breaks around them turned into spaces. The third line, `More text.`, joined the same paragraph.

Asking `pandoc --list-extensions=markdown` for its list printed a `+blank_before_header` line here, so that extension was on for the run above.

A level 2 line acted the same way. In `hb-h2.md`, where `## Notes` sits under the sentence, `markdown` output read `<p>Jane Doe wrote this line. ## Notes More text.</p>`.

## A blank line above the heading

The same reader on the second file:

```sh
pandoc -f markdown -t html hb-blank.md
```

Output:

```html
<p>Jane Doe wrote this line.</p>
<h1 id="notes">Notes</h1>
<p>More text.</p>
```

The empty line split the file into three blocks. Pandoc wrote a paragraph, an `h1` with the id `notes`, and a second paragraph. No blank line sat between `# Notes` and `More text.`, yet pandoc still gave `More text.` a paragraph of its own. In this test, one blank line above `# Notes` was enough, and the line below could stay as it was.

## Turning off blank_before_header

A minus sign after the reader name removes an extension for that run. This one took `blank_before_header` out:

```sh
pandoc -f markdown-blank_before_header -t html hb.md
```

Output:

```html
<p>Jane Doe wrote this line.</p>
<h1 id="notes">Notes</h1>
<p>More text.</p>
```

Those three lines match what `hb-blank.md` gave in the section above, and the source file stayed untouched. Run on `hb-blank.md`, this setting printed those three lines again. On `hb-h2.md`, it wrote `<h2 id="notes">Notes</h2>` between two paragraphs.

## What commonmark and the spec say

Plain `commonmark` ran on `hb.md`:

```sh
pandoc -f commonmark -t html hb.md
```

Output:

```html
<p>Jane Doe wrote this line.</p>
<h1>Notes</h1>
<p>More text.</p>
```

Under `commonmark`, `hb-blank.md` gave those same three lines. Pandoc put no `id` on the `h1` in either run.

ATX headings, in the words of spec lines 1209-1210 (CommonMark 0.31.2), "need not be separated from surrounding content by blank lines, and they can interrupt paragraphs". Its example 78 (lines 1222-1230) puts `# baz` straight under `Foo bar` and lists `<h1>baz</h1>` in the output.

Searching that spec text for `blank_before_header` with a fixed-string, case-insensitive grep returned 0, and so did a search for `blank before`. For a control, `ATX heading` under that grep returned 6. So here, the need for a blank line came from pandoc's `markdown` reader.

## A wrapped sentence and a stray hash

The extension cuts both ways. The file `hb-wrap.md` holds a sentence split over two lines, and its second line happens to open with a hash and a space:

```markdown
Jane Doe ranked the plan
# 1 on the list.
```

Under `markdown`, pandoc kept the sentence whole: `<p>Jane Doe ranked the plan # 1 on the list.</p>`. Under `commonmark`, the second line turned into a heading:

```html
<p>Jane Doe ranked the plan</p>
<h1>1 on the list.</h1>
```

With `markdown-blank_before_header`, pandoc wrote a heading as well, `<h1 id="on-the-list.">1 on the list.</h1>`. The leading `1` was left out of that id.

So before you add a blank line, ask whether the hash line was meant to be a heading at all. If it belongs to a sentence, join it back onto the line above. A text line that opens with a hash and a space became an `h1` under two of the three settings here.

## Find and fix the heading

Work down this list when a heading line ends up stuck inside a paragraph.

1. Print every hash line together with its previous line. `grep -n -B1 '^#' hb.md` printed `1-Jane Doe wrote this line.` and then `2:# Notes`. Text right above a hash line is the case this post tests.
2. Run that search on the repaired file. For `hb-blank.md` it printed `2-` and then `3:# Notes`, so line 2 was empty.
3. Count headings in pandoc's output. Running `pandoc -f markdown -t html hb.md -o hb.html` and then `grep -c '<h1' hb.html` printed `0`. The same pair of commands on `hb-blank.md` printed `1`.
4. Put a blank line in the source directly before the heading. If you can't edit the file, add `-blank_before_header` to the reader name, as the section Turning off blank_before_header shows.
5. Let pandoc write the blank lines. `pandoc -f commonmark -t markdown hb.md` printed the file back with an empty line before and after `# Notes`. Under `-f markdown`, that command printed `Jane Doe wrote this line. \# Notes More text.`, where a backslash now sat before the hash.

A hash lacking a space after it, as in `#Notes`, is a separate cause this post leaves aside. For that slip, see the [syntax cheat sheet](markdown-cheat-sheet.md).

## Where Sashmark fits

Under its v1 plan, Sashmark could have you retouch a sentence while seeing the page rendered. Saving would then rely on the plan's own clean Round-Trip piece: any line left untouched would go back to disk with identical bytes. Another planned part, a Changes View, would show you each spot that moved since your earlier pass through the file, and git would not be needed.

It is in development and has not been released. The app itself has no AI features. See the [planned features](/features), the [help pages](/help) and the [roadmap](/roadmap) for where each part stands.

More at [sashmark.com](https://www.sashmark.com/).
