Rewrite ListSyntax.parse() to be simpler, and extract determineBlockItems()
diff --git a/pkgs/markdown/CHANGELOG.md b/pkgs/markdown/CHANGELOG.md index a9291e7..c996795 100644 --- a/pkgs/markdown/CHANGELOG.md +++ b/pkgs/markdown/CHANGELOG.md
@@ -6,13 +6,16 @@ default extension set, which is `ExtensionSet.commonMark`, which includes FencedCodeBlock. * Inline HTML syntax support; This is also considered an extension (#18). -* The text `[foo] (bar)` now parses as an inline link (#53). +* The text `[foo] (bar)` no longer renders as an inline link (#53). * The text `[foo]()` now renders as an inline link. * Header identifier support in the HeaderWithIdSyntax and SetextHeaderWithIdSyntax extensions. * Implement backslash-escaping so that Markdown syntax can be escaped, such as `[foo]\(bar) ==> <p>[foo](bar)</p>`. -* New public method for BlockParser: `peek(int linesAhead)`. +* New public method for BlockParser: `peek(int linesAhead)`, meant for use in + subclasses. +* New public members for ListSyntax: `blocksInList` and `determineBlockItems()`, + meant for use in subclasses. ## 0.8.0
diff --git a/pkgs/markdown/lib/src/block_parser.dart b/pkgs/markdown/lib/src/block_parser.dart index cfdb60a..6a1d720 100644 --- a/pkgs/markdown/lib/src/block_parser.dart +++ b/pkgs/markdown/lib/src/block_parser.dart
@@ -413,6 +413,16 @@ const ListSyntax(); + /// A list of patterns that can start a valid block within a list item. + static final blocksInList = [ + _blockquotePattern, + _headerPattern, + _hrPattern, + _indentPattern, + _ulPattern, + _olPattern + ]; + Node parse(BlockParser parser) { var items = <ListItem>[]; var childLines = <String>[]; @@ -455,7 +465,29 @@ } endItem(); + determineBlockItems(items); + var itemNodes = <Node>[]; + for (var item in items) { + if (item.forceBlock) { + // Block list item. + var children = parser.document.parseLines(item.lines); + itemNodes.add(new Element('li', children)); + } else { + // Raw list item. + var contents = parser.document.parseInline(item.lines[0]); + itemNodes.add(new Element('li', contents)); + } + } + + return new Element(listTag, itemNodes); + } + + /// Determines whether each item in [items] is a block item. + /// + /// Also removes any trailing empty lines and notes which items are separated + /// by empty lines. + void determineBlockItems(List items) { // Markdown, because it hates us, specifies two kinds of list items. If you // have a list like: // @@ -498,56 +530,26 @@ // trailing empty lines on the last item don't force it into being a block. for (var i = 0; i < items.length; i++) { for (var j = items[i].lines.length - 1; j > 0; j--) { - if (_emptyPattern.firstMatch(items[i].lines[j]) != null) { - // Found an empty line. This item and the one after it are blocks. - if (i < items.length - 1) { - items[i].forceBlock = true; - items[i + 1].forceBlock = true; - } - items[i].lines.removeLast(); - } else { - break; + if (!_emptyPattern.hasMatch(items[i].lines[j])) break; + + // Found an empty line. This item and the one after it are blocks. + if (i < items.length - 1) { + items[i].forceBlock = true; + items[i + 1].forceBlock = true; } + items[i].lines.removeLast(); } + + // Items with more than one line are block items. + items[i].forceBlock = items[i].forceBlock || items[i].lines.length > 1; + + if (items[i].forceBlock) continue; + + // Items (even one-lined items) that start with a block syntax are block + // items. + items[i].forceBlock = + blocksInList.any((p) => p.hasMatch(items[i].lines[0])); } - - // Convert the list items to Nodes. - var itemNodes = <Node>[]; - for (var item in items) { - var blockItem = item.forceBlock || (item.lines.length > 1); - - // See if it matches some block parser. - var blocksInList = [ - _blockquotePattern, - _headerPattern, - _hrPattern, - _indentPattern, - _ulPattern, - _olPattern - ]; - - if (!blockItem) { - for (var pattern in blocksInList) { - if (pattern.firstMatch(item.lines[0]) != null) { - blockItem = true; - break; - } - } - } - - // Parse the item as a block or inline. - if (blockItem) { - // Block list item. - var children = parser.document.parseLines(item.lines); - itemNodes.add(new Element('li', children)); - } else { - // Raw list item. - var contents = parser.document.parseInline(item.lines[0]); - itemNodes.add(new Element('li', contents)); - } - } - - return new Element(listTag, itemNodes); } }