There's a reason John Gruber's initial spec for Markdown didn't approach the level of complexity the CommonMark people wanted: You end up with exceptionally wordy jive like what we find for list items.

From commonmark.org:

And let M be the marker 1., and N = 2. Then rule #1 says that the following is an ordered list item with start number 1, and the same contents as Ls:

[example removed -mfn]

The most important thing to notice is that the position of the text after the list marker determines how much indentation is needed in subsequent blocks in the list item. If the list marker takes up two spaces, and there are three spaces between the list marker and the next non-whitespace character, then blocks must be indented five spaces in order to fall under the list item.

Phew. That was fun, wasn't it?

I was in the CommonMark spec today for two reasons. First, I fairly recently (well, months ago) swapped my main Markdown engine to the .NET CommonMark renderer (don't worry; table support and other features are done outside of CommonMark). Second, I wanted to know why only two of the following were creating nested lists, though my old renderer would create nested lists from all three.

1. Testing ye olde bullet points
    2. Still testing
    3. Testing

1. Testing ye olde bullet points
    * Still testing
    * Testing

1. Testing ye olde bullet points
    1. Still Testing
    2. Testing

Curious? You've probably guessed, but here's the rendered HTML, first as HTML, then the HTML source.

  1. Testing ye olde bullet points 2. Still testing 3. Testing
  1. Testing ye olde bullet points
    • Still testing
    • Testing
  1. Testing ye olde bullet points
    1. Still Testing
    2. Testing
<ol>
<li>Testing ye olde bullet points
2. Still testing
3. Testing</li>
</ol>
<ol>
<li>Testing ye olde bullet points
<ul>
<li>Still testing</li>
<li>Testing</li>
</ul>
</li>
</ol>
<ol>
<li>Testing ye olde bullet points
<ol>
<li>Still Testing</li>
<li>Testing</li>
</ol>
</li>
</ol>

See what happened there? If your nested list starts with a 2., as in the first example, though that'd be a bulleted list without the nest...

2. See? It's still...
4. a list.
  1. See? It's still...
  2. a list.

... it's not when nested.

Note that CommonMark is paying attention to the starting number of your ordered list. See how the list, above, starts with 2., though the next bullet is a 3., even though I used 4. in the raw Markdown?

Why is the nesting ignored in the first example? The spec tells us:

From commonmark.org:

Since it is well established Markdown practice to allow lists to interrupt paragraphs inside list items, the principle of uniformity requires us to allow this outside list items as well. (reStructuredText takes a different approach, requiring blank lines before lists even inside other list items.)

In order to solve of unwanted lists in paragraphs with hard-wrapped numerals, we allow only lists starting with 1 to interrupt paragraphs. Thus,

The number of windows in my house is
14.  The number of doors is 6.
<p>The number of windows in my house is
14.  The number of doors is 6.</p>

We may still get an unintended result in cases like

The number of windows in my house is
1.  The number of doors is 6.
<p>The number of windows in my house is</p>
<ol>
<li>The number of doors is 6.</li>
</ol>

but this rule should prevent most spurious list captures. [emphasis mine -mfn]

Make sense? 1. is special. If your nest doesn't start with 1., CommonMark thinks you're in the same "paragraph", give or take. You're not going to get that nest.

Which means MarkUpDown needs to capture when someone has a bullet from a numbered list, hits return, gets the next number automatically inserted...

1. They enter this first bullet.
2. Hit return and get a two. Then hit tab...

... which leaves them with...

1. They enter this first bullet.
    2. Hit return and get a two. Then hit tab...

... which doesn't render as a nested list. What they likely want is...

1. They enter this first bullet.
    1. Hit return and get a two. Then hit tab...

I'd hoped to get in automatic renumbering of ordered lists anyhow, but we'll start with this simpler change first... if it looks nested, we're going to reset the number to 1.

I realize this is a pretty boring post if you're not a Markdown aficionado. I've got some more interesting drafts around here somewhars. I'll try to find time to post them, but this one bugged me enough to write up.

Labels: , ,