Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion src/Parser/BlockParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -2269,7 +2269,13 @@ protected function tryParseList(Node $parent, array $lines, int $start): ?int
$this->parseBlocks($listItem, $itemLines, 0);
} else {
$paragraph = new Paragraph();
$this->inlineParser->parse($paragraph, implode("\n", $itemLines), $start);
// Plain-paragraph item: continuation lines strip ALL leading
// whitespace (djot soft-break rule), matching tryParseParagraph().
// itemLines keep indent relative to the item for the block-parse
// branch above; here that surplus indent would leak into the
// inline text (e.g. an over-indented continuation rendering as
// " c" instead of "c").
$this->inlineParser->parse($paragraph, implode("\n", array_map('ltrim', $itemLines)), $start);
$listItem->appendChild($paragraph);
}
} elseif ($itemLines !== ['']) {
Expand Down
40 changes: 40 additions & 0 deletions tests/TestCase/NestedListEdgeCasesTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
namespace Djot\Test\TestCase;

use Djot\DjotConverter;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;

/**
Expand Down Expand Up @@ -732,4 +733,43 @@ public function testSingleBlankLineAllowsBlockElement(): void
$this->assertNotFalse($headingPos);
$this->assertGreaterThan($lastUlPos, $headingPos);
}

// ============ Over-indented paragraph continuation in a list item ============

/**
* A tight list-item paragraph continuation line indented MORE than the item
* content indent must strip all leading whitespace (djot soft-break rule),
* not just the item indent. Matches canonical djot.js, which renders every
* variant below identically.
*
* @return array<string, array{0: string}>
*/
public static function overIndentedContinuationProvider(): array
{
return [
'flush continuation' => ["- a\n - b\nc\n"],
'one-space continuation' => ["- a\n - b\n c\n"],
'content-indent continuation' => ["- a\n - b\n c\n"],
'over-indented continuation' => ["- a\n - b\n c\n"],
];
}

#[DataProvider('overIndentedContinuationProvider')]
public function testOverIndentedParagraphContinuationStripsSurplusIndent(string $djot): void
{
$result = $this->converter->convert($djot);

// The "- b" line and "c" line are plain paragraph continuation text of
// item "a"; surplus indentation must not leak into the inline output.
$this->assertStringContainsString("a\n- b\nc", $result);
$this->assertStringNotContainsString(' c', $result);
}

public function testListItemOverIndentedContinuationWithoutNestedMarker(): void
{
$result = $this->converter->convert("- a\n c\n");

$this->assertStringContainsString("a\nc", $result);
$this->assertStringNotContainsString(' c', $result);
}
}
Loading