Sashmark / Blog

How to indent a paragraph in Markdown: four tests

Bobby Huang ·

The section Plain leading spaces quotes pandoc's output for lines opening with two and four spaces under markdown and commonmark. Under Backslash before a space, output for four escaped spaces sits beside the all_symbols_escapable extension list and an od byte dump. Byte dumps for the entity line are in Four entity references. A pointer for spaces on lines of verse or an address is in Spaces on separate lines. Commands that find and test a leading indent are listed in Indent a line and check the result.

Key takeaways

  • Under Plain leading spaces, the two-space and four-space lines appear as both readers converted them.
  • Reader output for escaped spaces, beside an extension list, appears in Backslash before a space.
  • Hex bytes pandoc wrote for the entity line are quoted in Four entity references.
  • Readers wanting leading spaces on several lines get a link to line blocks in Spaces on separate lines.
  • Grep, pandoc and od commands run against one file are in Indent a line and check the result.

If you want to know how to indent a paragraph in Markdown, start with what the converter keeps. Pandoc dropped two plain leading spaces in this test and turned four into code. Typed as entities, four spaces became four U+00A0 characters under both readers; typed as escapes, they did so under one reader.

Each run took place one time on one Mac, and pandoc was at release 3.8.3. Spec line numbers point into CommonMark version 0.31.2. Only the HTML elements and bytes pandoc produced are quoted, and nothing beyond them was checked. The four lines tested are typed into one small file.

The test file

Running cat ind.md printed:

  Two spaces open this line.

    Four spaces open this line.

\ \ \ \ Four escaped spaces open this line.

    Four entities open this line.

Blank lines keep the four lines apart, so pandoc treats each one as its own block. The file was converted twice, once with -f markdown and once with -f commonmark.

Plain leading spaces

The two commands:

pandoc -f markdown -t html ind.md
pandoc -f commonmark -t html ind.md

Both readers wrote the same first two lines:

<p>Two spaces open this line.</p>
<pre><code>Four spaces open this line.</code></pre>

The p element lost the two spaces that opened the first line. Spec line 3319 reads "Leading spaces or tabs are skipped". Its example 222 (lines 3321-3327) feeds in a line with two leading spaces and lists <p>aaa with no spaces in front.

Four spaces changed the result. Pandoc wrote a pre element holding a code element, and the code text starts at the word Four. For this test, the one fact needed from the guide to splitting paragraphs is that a first line opening with four spaces turns into code.

So plain spaces gave two results in this test. Two spaces were dropped, and four gave the pre and code elements in the block above. Neither result put a space ahead of the paragraph text.

Backslash before a space

The third line puts a backslash before each of four spaces. The two readers part ways on this line.

Under commonmark, pandoc wrote the backslashes back out as text:

<p>\ \ \ \ Four escaped spaces open this line.</p>

A backslash escape works, per spec line 481, on "Any ASCII punctuation character" alone. Lines 489-490 add that "Backslashes before other characters are treated as literal backslashes". The list of those characters on lines 332-337 leaves out the space, and example 13 (lines 492-496) includes a backslash and a space that stay as typed.

The markdown reader dropped the backslashes from that line. In their place, ahead of Four, pandoc wrote four characters that are not plain spaces. The od byte dump of that output holds this run:

           2f  70  72  65  3e  0a  3c  70  3e  c2  a0  c2  a0  c2  a0  c2
           a0  46  6f  75  72  20  65  73  63  61  70  65  64  20  73  70

After 3c 70 3e, the bytes for <p>, the pair c2 a0 appears four times before 46 6f 75 72, the letters of Four. In UTF-8, the code point U+00A0 takes those two bytes.

The extension behind this is all_symbols_escapable. This extension check printed +all_symbols_escapable, so it was on:

pandoc --list-extensions=markdown | grep all_symbols_escapable

The same grep with -c on the commonmark list printed 0. To confirm, a run with the extension turned off:

pandoc -f markdown-all_symbols_escapable -t html ind.md

That run wrote the third line as <p>\ \ \ \ Four escaped spaces open this line.</p>, which matches the commonmark result above.

Four entity references

The last line types the entity four times before the text: &nbsp;&nbsp;&nbsp;&nbsp;Four. Both readers handled it the same way.

Here are the last bytes od printed for the markdown output:

           69  6e  65  2e  3c  2f  70  3e  0a  3c  70  3e  c2  a0  c2  a0
           c2  a0  c2  a0  46  6f  75  72  20  65  6e  74  69  74  69  65

An extra test piped the commonmark output through od -An -tx1, and its last bytes were identical, c2 a0 four times after 3c 70 3e. In both runs pandoc wrote four U+00A0 characters where the source held four entity references.

Spec lines 606-608 say valid entity references "can be used in place of the corresponding Unicode character", and the entity used here is in the sample list on line 631. Counting output lines that hold c2 a0 gave numbers that fit: 2 for markdown (the escape line and the entity line) and 1 for commonmark (the entity line alone).

The character U+00A0 has side effects of its own. One placed after a heading's hash is tested in the post on invisible characters.

Spaces on separate lines

The tests above treat one paragraph with a single opening indent. Verse, an address or a short poem where each line keeps its own leading spaces is a separate case. For that case, see pandoc's line_blocks extension in the line blocks post.

Indent a line and check the result

Use these steps on a file where a paragraph needs space in front of it.

  1. List lines that open with a space. On the test file, grep -n '^ ' ind.md printed 1: Two spaces open this line. and 3: Four spaces open this line. Any match is a line whose leading spaces pandoc may drop or turn into code.
  2. Count lines opening with at least four spaces. grep -c '^ ' ind.md printed 1. Pandoc turned that line into the pre element quoted under Plain leading spaces.
  3. Pick a form for the indent. The escape form gave U+00A0 under markdown alone; the entity form gave U+00A0 under both readers here. Use grep -c '&nbsp;' ind.md to count lines holding the entity; it printed 1.
  4. Run pandoc with your chosen reader, using the first command in the block after this list. Under commonmark, it printed four output lines: a p, a pre, then two more p elements.
  5. Count output lines holding bytes outside printable ASCII with the second command. Run as shown, it printed 2; after swapping in the other reader name, it printed 1.
  6. Read the bytes with the third command. It lists each c2 a0 pair in hex, so you can count the U+00A0 characters on a line.
pandoc -f commonmark -t html ind.md
pandoc -f markdown -t html ind.md | LC_ALL=C grep -c '[^ -~]'
pandoc -f commonmark -t html ind.md | od -An -tx1

Where Sashmark fits

Within the v1 that Sashmark has planned, a reader could amend text inside its rendered view. Each save would hand off to a clean Round-Trip named in that plan, writing back each line nobody edited exactly as it stood. On that list too: a Changes View able to flag every change made after your last read, all without git.

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

More at sashmark.com.

Questions

Why did my two leading spaces vanish?
A two-space line, as pandoc converted it, is quoted under Plain leading spaces.
Does a backslash before a space keep the space?
Output from markdown, commonmark and markdown-all_symbols_escapable appears in the section Backslash before a space.
Which character did pandoc write for the entity?
The section Four entity references names the code point and quotes the od bytes.
How do I test a file of my own?
Steps using grep, pandoc and od are listed in Indent a line and check the result.

What Sashmark plans for v1: Features · Roadmap

View as Markdown