Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Markdown enumerated list with indices over 99 changes nested list formatting

Tags:

markdown

In multiple markdown to pdf converters I have used, when you have an enumerated list with indices going over 99 any nested lists on the items no longer format as I would expect.

As an example,

98. 98th element
    1. This is fine
99. 99th element
    - This looks okay
100. 100th element
    - This should not look like this
101. 101th element
    1. This is also broken

when converted to pdf becomes,

enter image description here

As a workaround I know that you don't have to put the correct numbers as the indices in an enumerated list, but it makes editing the markdown file easier if you do.

My questions is, is the above behaviour expected or is it a bug in the pdf converters I have been using?

like image 474
James Elderfield Avatar asked Mar 07 '23 16:03

James Elderfield


1 Answers

You probably need to add an extra space of indent to the nested items for any item over 99. See examples below.

The correct behavior and syntax depends in part on whether you are using an old-school Markdown implementation or a CommonMark implementation. For a comparison of how different implementations behave, see Babelmark.

Markdown

The Markdown syntax rules don't actually explain how to nest list items in other list items. However, they do demonstrate nesting paragraphs (also blockquotes and code blocks):

List items may consist of multiple paragraphs. Each subsequent paragraph in a list item must be indented by either 4 spaces or one tab:

1.  This is a list item with two paragraphs. Lorem ipsum dolor
    sit amet, consectetuer adipiscing elit. Aliquam hendrerit
    mi posuere lectus.

    Vestibulum enim wisi, viverra nec, fringilla in, laoreet
    vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
    sit amet velit.

2.  Suspendisse id sem consectetuer libero luctus adipiscing.

Of course, if you use a list item instead of a paragraph and indent it the in the same manner, you get a nested list item. As the reference implementation works that way, most old-school clones also work the same way.

Finally, note how in that example, all of the lines of all of the paragraphs in the list items line up on the left edge. Even the first line of the list item has an extra space between the list marker and the first word of the paragraph. For demonstration purposes, here is the same example with spaces replaced by dots:

1.··This is a list item with two paragraphs. Lorem ipsum dolor
····sit amet, consectetuer adipiscing elit. Aliquam hendrerit
····mi posuere lectus.

····Vestibulum enim wisi, viverra nec, fringilla in, laoreet
····vitae, risus. Donec sit amet nisl. Aliquam semper ipsum
····sit amet velit.

2.··Suspendisse id sem consectetuer libero luctus adipiscing.

That makes for nice cleanly formatted text. However, in old-school markdown that is not necessary. As the very next paragraph of the rules state:

It looks nice if you indent every line of the subsequent paragraphs, but here again, Markdown will allow you to be lazy...

Of course, when your list gets longer than 99 items, the nicely aligned "columns" no longer work with four spaces of indent:

100.·This is a list item with two paragraphs. Lorem ipsum dolor
····sit amet, consectetuer adipiscing elit. Aliquam hendrerit
····mi posuere lectus.

However, as any block-level item can be indented up to three spaces (without becoming a code block, you can add up to three more spaces of indent to the nested lines:

100.·This is a list item with two paragraphs. Lorem ipsum dolor
·····sit amet, consectetuer adipiscing elit. Aliquam hendrerit
·····mi posuere lectus.

Or even:

10000.·This is a list item with two paragraphs. Lorem ipsum dolor
·······sit amet, consectetuer adipiscing elit. Aliquam hendrerit
·······mi posuere lectus.

Of course, in Markdown, that's not necessary, but it does look nice. And once you get above 99999 it no longer works as you would have too much indent, resulting in the nested items being code blocks.

Commonmark

As I understand it, the creators of Commonmark wanted to enforce the nicely formatted columns without the limit of 99999 items, and so they diverged from the Markdown rules. Commonmark doesn't require four spaces of indent to nest an item, but according to its spec:

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.

...

It is tempting to think of this in terms of columns: the continuation blocks must be indented at least to the column of the first non-whitespace character after the list marker. However, that is not quite right. The spaces after the list marker determine how much relative indentation is needed. Which column this indentation reaches will depend on how the list item is embedded in other constructions...

In other words, the nice-to-have but not necessary formatting in Markdown to have nicely aligned columns is required in Commonmark. To demonstrate, consider the example provided in the question with an extra space of indent for the nested items of items 100 and 101 (with dots for spaces):

98.·98th element
····1.·This is fine
99.·99th element
····-·This looks okay
100.·100th element
·····-·This should not look like this
101.·101th element
·····1.·This is also broken

In items 100 and 101 notice how the first character of the item lines up in the same column with the fist character of the nested list marker. According to Babelmark, this works in both Markdown and Commonmark.

Of course, the two digit items and three digit items don't line up with eachother, but that's okay because each item is calculated independently. However, for the anal retentive, you can add some extra indent to the lower numbered items for complete alignment if you like:

1.···First item
·····1.·Foo
98.··98th element
·····1.·This is fine
99.··99th element
·····-·This looks okay
100.·100th element
·····-·This should not look like this
101.·101th element
·····1.·This is also broken

And as Babelmark demonstrates, that gets consistent results across Markdown and Commonmark implementations.

As mentioned earlier, the implementations diverge again when you get over 99999 items:

99999.·Foo

·······not a code block

100000.·Bar

········A code block in Markdown, but not in Commonmark.

And that, presumably is why Commonmark has the alternate behavior. Although, as Babelmark demonstrates, some of the newer non-commonmark implementations do follow Commonmark in this case. So, depending on which Markdown implementation you are using, YMMV.

like image 157
Waylan Avatar answered Apr 10 '23 09:04

Waylan