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
2 changes: 1 addition & 1 deletion docs/reference/enhancements.md
Original file line number Diff line number Diff line change
Expand Up @@ -1008,7 +1008,7 @@ The `^ caption text` syntax adds captions to images, tables, and block quotes:
- `^ ` marker at start of line triggers caption parsing
- Can interrupt paragraphs (no blank line required before caption)
- Blank line between element and caption is allowed for readability
- Multi-line captions supported (continues until blank line or new block)
- Multi-line captions supported (continues until blank line or new block; an adjacent `^ ` line is caption text with its caret preserved)
- Full roundtrip support in HtmlToDjot converter

**Multi-line caption example:**
Expand Down
2 changes: 1 addition & 1 deletion src/Parser/BlockParser.php
Original file line number Diff line number Diff line change
Expand Up @@ -3728,7 +3728,7 @@ protected function tryParseCaption(Node $parent, array $lines, int $start): ?int
break;
}
// Stop at block-level elements
if ($this->startsNewBlock($nextLine)) {
if ($this->startsNewBlock($nextLine) && !preg_match('/^\^ /', $nextLine)) {
break;
}
// Stop at new table
Expand Down
44 changes: 44 additions & 0 deletions tests/TestCase/DjotConverterTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,15 @@ public function testTableCaptionWithBlankLine(): void
$this->assertStringContainsString('<caption>Caption after blank line</caption>', $result);
}

public function testBlankSeparatedSecondCaptionReplacesTheFirst(): void
{
$djot = "| A | B |\n|---|---|\n| 1 | 2 |\n^ First\n\n^ Second";
$expected = "<table>\n<caption>Second</caption>\n<tr>\n<th>A</th>\n<th>B</th>\n</tr>\n"
. "<tr>\n<td>1</td>\n<td>2</td>\n</tr>\n</table>\n";

$this->assertSame($expected, $this->converter->convert($djot));
}

public function testTableCaptionMultiline(): void
{
$djot = "| A | B |\n|---|---|\n| 1 | 2 |\n^ This is a long caption\nthat continues on the next line";
Expand All @@ -390,6 +399,41 @@ public function testTableCaptionMultiline(): void
$this->assertStringContainsString("<caption>This is a long caption\nthat continues on the next line</caption>", $result);
}

public function testAdjacentCaptionMarkerIsLiteralTableCaptionText(): void
{
$djot = "| A | B |\n|---|---|\n| 1 | 2 |\n^ First\n^ Second";
$expected = "<table>\n<caption>First\n^ Second</caption>\n<tr>\n<th>A</th>\n<th>B</th>\n</tr>\n"
. "<tr>\n<td>1</td>\n<td>2</td>\n</tr>\n</table>\n";

$this->assertSame($expected, $this->converter->convert($djot));
}

public function testAdjacentCaptionMarkerIsLiteralImageCaptionText(): void
{
$djot = "![alt](image.png)\n^ First\n^ Second";
$expected = "<figure>\n<img alt=\"alt\" src=\"image.png\"><figcaption>First\n^ Second</figcaption>\n</figure>\n";

$this->assertSame($expected, $this->converter->convert($djot));
}

public function testAdjacentCaptionMarkerIsLiteralBlockquoteCaptionText(): void
{
$djot = "> q\n^ First\n^ Second";
$expected = "<figure>\n<blockquote>\n<p>q</p>\n</blockquote>\n<figcaption>First\n^ Second</figcaption>\n"
. "</figure>\n";

$this->assertSame($expected, $this->converter->convert($djot));
}

public function testTwoCaptionedTablesKeepTheirOwnCaptions(): void
{
$djot = "| A |\n|---|\n| 1 |\n^ First\n\n| B |\n|---|\n| 2 |\n^ Second";
$expected = "<table>\n<caption>First</caption>\n<tr>\n<th>A</th>\n</tr>\n<tr>\n<td>1</td>\n</tr>\n</table>\n"
. "<table>\n<caption>Second</caption>\n<tr>\n<th>B</th>\n</tr>\n<tr>\n<td>2</td>\n</tr>\n</table>\n";

$this->assertSame($expected, $this->converter->convert($djot));
}

public function testReferenceLink(): void
{
$djot = "[Example][ex]\n\n[ex]: https://example.com";
Expand Down
Loading