diff --git a/phpcs.xml b/phpcs.xml index 3cf4581..759198c 100644 --- a/phpcs.xml +++ b/phpcs.xml @@ -8,7 +8,10 @@ */vendor/* - + + + + diff --git a/src/Parser/BlockParser.php b/src/Parser/BlockParser.php index 3483f53..7c8af24 100644 --- a/src/Parser/BlockParser.php +++ b/src/Parser/BlockParser.php @@ -1500,6 +1500,14 @@ protected function tryParseList(Node $parent, array $lines, int $start): ?int if ($itemInfo !== null && $itemInfo['type'] === $listInfo['type'] && $itemInfo['marker'] === $listInfo['marker'] && $sameStyle) { break; } + // After a blank line, content dropping back to base indent + // starts a new block outside the list - let parent handle it. + if ($sawBlankLine) { + $lastItemHadBlankAfter = true; + $brokeForParentContent = true; + + break; + } // Content at base indent that's not a matching list marker // Check if it's a block element - if so, end list content collection // Use isBlockElementStart() which detects blocks regardless of mode diff --git a/tests/TestCase/Extension/HeadingReferenceExtensionTest.php b/tests/TestCase/Extension/HeadingReferenceExtensionTest.php index 15cfcc6..ef5ec00 100644 --- a/tests/TestCase/Extension/HeadingReferenceExtensionTest.php +++ b/tests/TestCase/Extension/HeadingReferenceExtensionTest.php @@ -251,7 +251,7 @@ public function testHeadingWithNoTextIsIgnored(): void public function testUserAuthoredLinkWithMatchingPlaceholderIsNotRewritten(): void { - $extension = new class ('heading-ref') extends HeadingReferenceExtension { + $extension = new class('heading-ref') extends HeadingReferenceExtension { protected function generatePlaceholderPrefix(): string { return 'collision-placeholder-'; diff --git a/tests/TestCase/NestedBlocksInListsTest.php b/tests/TestCase/NestedBlocksInListsTest.php index a54fe4a..b635fdc 100644 --- a/tests/TestCase/NestedBlocksInListsTest.php +++ b/tests/TestCase/NestedBlocksInListsTest.php @@ -633,4 +633,39 @@ public function testIssue83CodeBlockCase(): void // Should NOT be inline code $this->assertStringNotContainsString('

', $result); } + + /** + * After a nested block inside a list item and a blank line, an + * unindented paragraph must terminate the list rather than being + * absorbed as a sub-item of the previous list item. + * + * @see https://github.com/php-collective/djot-php/issues/176 + */ + public function testIssue176UnindentedParagraphAfterNestedCodeBlockEndsList(): void + { + $djot = <<<'DJOT' +1. Item 1 +2. Item 2 + + ``` + Example + ``` + +New list: + +* New item 1 +* New item 2 +DJOT; + + $result = $this->converter->convert($djot); + + $this->assertStringContainsString('', $result); + // The "New list:" paragraph must appear after the ordered list closes. + $olClose = strpos($result, ''); + $paragraph = strpos($result, '

New list:

'); + $this->assertNotFalse($paragraph); + $this->assertGreaterThan($olClose, $paragraph); + // And the following bullet list must be a sibling, not nested in
  • . + $this->assertMatchesRegularExpression('#\s*

    New list:

    \s*
      #', $result); + } }