Fix various list bugs (dart-lang/markdown#102) * Fix various list bugs * Update CommonMark status; not worrying about Tabs
diff --git a/pkgs/markdown/lib/src/block_parser.dart b/pkgs/markdown/lib/src/block_parser.dart index bc53d03..6635271 100644 --- a/pkgs/markdown/lib/src/block_parser.dart +++ b/pkgs/markdown/lib/src/block_parser.dart
@@ -37,11 +37,16 @@ /// A line starting with one of these markers: `-`, `*`, `+`. May have up to /// three leading spaces before the marker and any number of spaces or tabs /// after. -final _ulPattern = new RegExp(r'^[ ]{0,3}[*+-][ \t]+(.*)$'); +/// +/// Contains a dummy group at [2], so that the groups in [_ulPattern] and +/// [_olPattern] match up; in both, [2] is the length of the number that begins +/// the list marker. +final _ulPattern = new RegExp(r'^([ ]{0,3})()([*+-])(([ \t])([ \t]*)(.*))?$'); /// A line starting with a number like `123.`. May have up to three leading /// spaces before the marker and any number of spaces or tabs after. -final _olPattern = new RegExp(r'^[ ]{0,3}\d+\.[ \t]+(.*)$'); +final _olPattern = + new RegExp(r'^([ ]{0,3})(\d{1,9})([\.)])(([ \t])([ \t]*)(.*))?$'); /// Maintains the internal state needed to parse a series of lines into blocks /// of Markdown suitable for further inline parsing. @@ -569,17 +574,58 @@ return match != null; } + var listMarker = null; + var indent; + while (!parser.isDone) { if (tryMatch(_emptyPattern)) { + if (_emptyPattern.firstMatch(parser.next ?? '') != null) { + // Two blank lines ends a list. + break; + } // Add a blank line to the current list item. childLines.add(''); + } else if (indent != null && parser.current.startsWith(indent)) { + // Strip off indent and add to current item. + var line = parser.current.replaceFirst(indent, ''); + childLines.add(line); } else if (tryMatch(_ulPattern) || tryMatch(_olPattern)) { + var precedingWhitespace = match[1]; + var digits = match[2] ?? ''; + var marker = match[3]; + var isBlank = match[4] == null; + var firstWhitespace = match[5] ?? ''; + var restWhitespace = match[6] ?? ''; + var content = match[7] ?? ''; + if (listMarker != null && listMarker != marker) { + // Changing the bullet or ordered list delimiter starts a new list. + break; + } + listMarker = marker; + var markerAsSpaces = ' ' * (digits.length + marker.length); + if (isBlank) { + // See http://spec.commonmark.org/0.25/#list-items under "3. Item + // starting with a blank line." + // + // If the list item starts with a blank line, the final piece of the + // indentation is just a single space. + indent = precedingWhitespace + markerAsSpaces + ' '; + } else if (match[5].length >= 4) { + // See http://spec.commonmark.org/0.25/#list-items under "2. Item + // starting with indented code." + // + // If the list item starts with indented code, we need to _not_ count + // any indentation past the required whitespace character. + indent = precedingWhitespace + markerAsSpaces + firstWhitespace; + } else { + indent = precedingWhitespace + + markerAsSpaces + + firstWhitespace + + restWhitespace; + } // End the current list item and start a new one. endItem(); - childLines.add(match[1]); - } else if (tryMatch(_indentPattern)) { - // Strip off indent and add to current item. - childLines.add(match[1]); + childLines.add(restWhitespace + content); } else if (BlockSyntax.isAtBlockEnd(parser)) { // Done with the list. break; @@ -637,7 +683,8 @@ bool removeTrailingEmptyLines(List items) { var anyEmpty = false; for (var i = 0; i < items.length; i++) { - while (_emptyPattern.hasMatch(items[i].lines.last)) { + while (items[i].lines.isNotEmpty && + _emptyPattern.hasMatch(items[i].lines.last)) { if (i < items.length - 1) { anyEmpty = true; }
diff --git a/pkgs/markdown/test/original/ordered_lists.unit b/pkgs/markdown/test/original/ordered_lists.unit index 277dba9..7c52652 100644 --- a/pkgs/markdown/test/original/ordered_lists.unit +++ b/pkgs/markdown/test/original/ordered_lists.unit
@@ -1,13 +1,27 @@ ->>> start with numbers -1. one +>>> ordered list with multiple items +1. one +2. two +10. ten +<<< +<ol><li> one</li><li> two</li><li>ten</li></ol> +>>> ordered list with almost nested item +1. one 45. two 12345. three <<< -<ol><li>one</li><li>two</li><li>three</li></ol> ->>> allow unordered lines after first +<ol><li> one</li><li> two</li><li>three</li></ol> +>>> nested ordered lists +1. one +2. two + 3. three + 4. four +5. five +<<< +<ol><li>one</li><li>two<ol><li>three</li><li>four</li></ol></li><li>five</li></ol> +>>> new list markers start new lists 1. a * b <<< -<ol><li>a</li><li>b</li></ol> +<ol><li>a</li></ol><ul><li>b</li></ul>
diff --git a/pkgs/markdown/test/original/setext_headers.unit b/pkgs/markdown/test/original/setext_headers.unit index 65038f0..7e34d9d 100644 --- a/pkgs/markdown/test/original/setext_headers.unit +++ b/pkgs/markdown/test/original/setext_headers.unit
@@ -10,13 +10,13 @@ <<< <h2>text</h2> ->>> h1 on first line becomes text +>>> h1 bar on first line becomes text === <<< <p>===</p> ->>> h2 on first line becomes text +>>> h2 bar on first line becomes list - <<< -<p>-</p> +<ul><li></li></ul>
diff --git a/pkgs/markdown/test/original/unordered_lists.unit b/pkgs/markdown/test/original/unordered_lists.unit index 4729287..44ab70e 100644 --- a/pkgs/markdown/test/original/unordered_lists.unit +++ b/pkgs/markdown/test/original/unordered_lists.unit
@@ -4,21 +4,19 @@ + plus <<< -<ul><li>star</li><li>dash</li><li>plus</li></ul> ->>> allow numbered lines after first +<ul><li>star</li></ul><ul><li>dash</li></ul><ul><li>plus</li></ul> +>>> new markers begin new lists * a 1. b <<< -<ul><li>a</li><li>b</li></ul> +<ul><li>a</li></ul><ol><li>b</li></ol> >>> allow a tab after the marker -* a -+ b -- c -1. d +* a +1. b <<< -<ul><li>a</li><li>b</li><li>c</li><li>d</li></ul> +<ul><li>a</li></ul><ol><li>b</li></ol> >>> wrap items in paragraphs if blank lines separate * one @@ -29,10 +27,10 @@ <p>one</p></li><li> <p>two</p></li></ul> >>> force paragraph on item before and after blank lines -* one -* two +* one +* two -* three +* three <<< <ul><li> @@ -50,11 +48,11 @@ <p>quote</p></blockquote></li><li> <h1>header</h1></li></ul> >>> can contain multiple paragraphs -* one +* one - two + two -* three +* three <<< <ul><li> @@ -62,19 +60,19 @@ <p>two</p></li><li> <p>three</p></li></ul> >>> can span newlines -* one - two -* three +* one + two +* three <<< <ul><li>one two</li><li>three</li></ul> >>> can nest lists -* one - * nested one - * nested two +* one + * nested one + * nested two -* two +* two <<< <ul><li>
diff --git a/pkgs/markdown/tool/common_mark_stats.json b/pkgs/markdown/tool/common_mark_stats.json index c07aa12..7eea678 100644 --- a/pkgs/markdown/tool/common_mark_stats.json +++ b/pkgs/markdown/tool/common_mark_stats.json
@@ -120,7 +120,7 @@ "338": true, "339": true, "340": false, - "341": false, + "341": true, "342": false, "343": false, "344": true, @@ -491,35 +491,35 @@ "213": true, "214": true, "215": true, - "216": false, - "217": false, + "216": true, + "217": true, "218": true, "219": true, "220": true, "221": true, "222": false, "223": true, - "224": false, - "225": false, + "224": true, + "225": true, "226": false, - "227": false, + "227": true, "228": false, "229": false, "230": true, - "231": false, + "231": true, "232": false, "233": true, "234": false, "235": false, "236": true, "237": true, - "238": false, + "238": true, "239": false, "240": false, "241": false, "242": false, "243": false, - "244": false, + "244": true, "245": true, "246": true, "247": true, @@ -528,39 +528,39 @@ "250": true, "251": true, "252": true, - "253": false, + "253": true, "254": true, "255": false, "256": false, "257": true, "258": false, - "259": false + "259": true }, "Lists": { - "260": false, + "260": true, "261": false, "262": true, "263": false, - "264": false, + "264": true, "265": true, - "266": false, - "267": false, - "268": false, + "266": true, + "267": true, + "268": true, "269": false, "270": false, "271": true, - "272": false, - "273": false, - "274": true, + "272": true, + "273": true, + "274": false, "275": false, - "276": false, - "277": false, - "278": false, + "276": true, + "277": true, + "278": true, "279": true, - "280": false, - "281": false, + "280": true, + "281": true, "282": false, - "283": false + "283": true }, "Paragraphs": { "179": true, @@ -634,10 +634,10 @@ "1": true, "2": false, "3": true, - "4": true, - "5": true, + "4": false, + "5": false, "6": true, - "7": false, + "7": true, "8": true, "9": false },
diff --git a/pkgs/markdown/tool/common_mark_stats.txt b/pkgs/markdown/tool/common_mark_stats.txt index 0c10a61..37235da 100644 --- a/pkgs/markdown/tool/common_mark_stats.txt +++ b/pkgs/markdown/tool/common_mark_stats.txt
@@ -4,7 +4,7 @@ 1 of 1 – 100.0% Blank lines 22 of 25 – 88.0% Block quotes 13 of 15 – 86.7% Code spans - 81 of 129 – 62.8% Emphasis and strong emphasis + 82 of 129 – 63.6% Emphasis and strong emphasis 10 of 12 – 83.3% Entity and numeric character references 24 of 27 – 88.9% Fenced code blocks 15 of 15 – 100.0% Hard line breaks @@ -14,14 +14,14 @@ 1 of 1 – 100.0% Inlines 11 of 23 – 47.8% Link reference definitions 52 of 81 – 64.2% Links - 22 of 47 – 46.8% List items - 5 of 24 – 20.8% Lists + 32 of 47 – 68.1% List items + 17 of 24 – 70.8% Lists 8 of 8 – 100.0% Paragraphs 1 of 1 – 100.0% Precedence 15 of 21 – 71.4% Raw HTML 20 of 26 – 76.9% Setext headings 2 of 2 – 100.0% Soft line breaks - 6 of 9 – 66.7% Tabs + 5 of 9 – 55.6% Tabs 3 of 3 – 100.0% Textual content 17 of 19 – 89.5% Thematic breaks - 427 of 616 – 69.3% TOTAL + 449 of 616 – 72.9% TOTAL