Skip to content

Commit 8e489e4

Browse files
authored
Fix nested blockquotes and code blocks in list items (#83) (#84)
The parser was not properly recognizing blockquotes (>) and code blocks (```) when they appeared directly inside list items without a preceding blank line. This fix: 1. Detects when list item content starts with a block element marker (blockquote, code fence, div, etc.) and parses it as blocks instead of treating it as inline paragraph text. 2. Calculates proper content indent based on list type: - Ordered lists use actual marker width (e.g., "1. " = 3 chars) - Bullet and task lists use base marker width (2 chars) This allows proper parsing of: - `- > quote` (blockquote starting a bullet list item) - `1. > quote` (blockquote in ordered list) - List items with code fences on the first line - Multi-line blockquotes with proper continuation
1 parent dd4460d commit 8e489e4

File tree

2 files changed

+662
-7
lines changed

2 files changed

+662
-7
lines changed

src/Parser/BlockParser.php

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,8 +1647,19 @@ protected function tryParseList(Node $parent, array $lines, int $start): ?int
16471647
$lastItemHadBlankAfter = false;
16481648
$hasNonMarkerContinuation = false;
16491649

1650-
// Calculate content indent (base + marker width, typically 2 for "- ")
1651-
$contentIndent = $baseIndent + 2;
1650+
// Calculate content indent based on list type and marker width
1651+
// For bullet lists (including task lists): use 2 (for "- ")
1652+
// For ordered lists: use actual marker width (varies with number length)
1653+
// Task list checkbox is considered part of content, not marker
1654+
if ($listType === ListBlock::TYPE_ORDERED) {
1655+
// Ordered list marker width = length of trimmed line - length of content
1656+
// Examples: "1. " = 3, "10. " = 4, "(1) " = 4, "(10) " = 5
1657+
$markerWidth = strlen($trimmedLine) - strlen($itemContent);
1658+
} else {
1659+
// Bullet and task lists use 2-char base marker ("- " or "* " or "+ ")
1660+
$markerWidth = 2;
1661+
}
1662+
$contentIndent = $baseIndent + $markerWidth;
16521663

16531664
while ($i < $count) {
16541665
$nextLine = $lines[$i];
@@ -1718,12 +1729,20 @@ protected function tryParseList(Node $parent, array $lines, int $start): ?int
17181729
}
17191730
}
17201731

1721-
// For tight lists with continuation lines, parse as plain text
1722-
// This prevents "-like" lines from being parsed as nested lists
1732+
// For tight lists with continuation lines, check if content starts with
1733+
// a block element. If so, parse as blocks; otherwise parse as plain text.
1734+
// This prevents "-like" lines from being parsed as nested lists while
1735+
// still allowing blockquotes, code blocks, etc. to be properly recognized.
17231736
if ($hasNonMarkerContinuation) {
1724-
$paragraph = new Paragraph();
1725-
$this->inlineParser->parse($paragraph, implode("\n", $itemLines), $start);
1726-
$listItem->appendChild($paragraph);
1737+
$firstLine = $itemLines[0];
1738+
if ($this->isBlockElementStart($firstLine)) {
1739+
// Content starts with a block element (blockquote, code fence, etc.)
1740+
$this->parseBlocks($listItem, $itemLines, 0);
1741+
} else {
1742+
$paragraph = new Paragraph();
1743+
$this->inlineParser->parse($paragraph, implode("\n", $itemLines), $start);
1744+
$listItem->appendChild($paragraph);
1745+
}
17271746
} else {
17281747
$this->parseBlocks($listItem, $itemLines, 0);
17291748
}

0 commit comments

Comments
 (0)