fix: bound render-summary strings, restore postdata globals, drain buffers

Review fix round 1 for lit/page-render-summary: extract shared Text::shorten()
(reused by NodeSummary), replace data: URIs with a short marker, prefer
data-src/data-lazy-src over placeholder src, dedup nested p/li/blockquote
text and ignore script/style/noscript content, restore every setup_postdata
global (not just $post), drain output buffers robustly around the_content,
and disclose that rendering can trigger oEmbed/network requests.

Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01At3V6SjwbMe6eMzVGW3Hs7
This commit is contained in:
2026-09-26 12:31:20 +02:00
co-authored by Claude Opus 5.5
parent 2e9acd686a
commit b3cd0eee62
7 changed files with 345 additions and 47 deletions
@@ -42,6 +42,81 @@ final class PageRenderSummaryAbilityTest extends TestCase
self::assertCount(2, RenderSummary::fromHtml(str_repeat('<p>x</p>', 5), 2)['texts']);
}
public function testTruncatesLongExtractedStrings(): void
{
$longHeading = str_repeat('Ü', 250);
$longText = str_repeat('a', 400);
$longLinkText = str_repeat('b', 200);
$longHref = 'https://k.test/' . str_repeat('c', 400);
$longAlt = str_repeat('d', 300);
$html = "<h2>{$longHeading}</h2><p>{$longText}</p>"
. "<a href=\"{$longHref}\">{$longLinkText}</a>"
. "<img src=\"https://k.test/x.jpg\" alt=\"{$longAlt}\">";
$summary = RenderSummary::fromHtml($html);
self::assertSame(200, mb_strlen($summary['headings'][0]['text']));
self::assertStringEndsWith('…', $summary['headings'][0]['text']);
self::assertSame(300, mb_strlen($summary['texts'][0]));
self::assertStringEndsWith('…', $summary['texts'][0]);
self::assertSame(150, mb_strlen($summary['links'][0]['text']));
self::assertStringEndsWith('…', $summary['links'][0]['text']);
self::assertSame(300, mb_strlen($summary['links'][0]['href']));
self::assertStringEndsWith('…', $summary['links'][0]['href']);
self::assertSame(200, mb_strlen($summary['images'][0]['alt']));
self::assertStringEndsWith('…', $summary['images'][0]['alt']);
}
public function testRepresentsDataUrisAsAShortMarkerInsteadOfTruncatingThem(): void
{
$dataUri = 'data:image/png;base64,' . base64_encode(str_repeat('x', 5000));
$html = '<img src="' . $dataUri . '"><a href="' . $dataUri . '">Anhang</a>';
$summary = RenderSummary::fromHtml($html);
$marker = 'data:image/png;… (' . strlen($dataUri) . ' Bytes)';
self::assertSame($marker, $summary['images'][0]['src']);
self::assertSame($marker, $summary['links'][0]['href']);
}
public function testPrefersDataSrcOrDataLazySrcOverAPlaceholderSrc(): void
{
$html = '<img src="data:image/gif;base64,R0lGODlhAQABAAAAACw=" data-src="https://k.test/real.jpg" alt="Team">'
. '<img src="placeholder.gif" data-lazy-src="https://k.test/lazy.jpg">';
$summary = RenderSummary::fromHtml($html);
self::assertSame('https://k.test/real.jpg', $summary['images'][0]['src']);
self::assertSame('https://k.test/lazy.jpg', $summary['images'][1]['src']);
}
public function testWarnsAboutMultipleH1Headings(): void
{
$summary = RenderSummary::fromHtml('<h1>Erste</h1><h1>Zweite</h1>');
self::assertContains('2 Überschriften der Ebene h1 im Inhalt.', $summary['warnings']);
}
public function testDoesNotDuplicateTextFromNestedParagraphsListItemsOrBlockquotes(): void
{
$html = '<ul><li>Punkt <p>eingebettet</p></li></ul>'
. '<blockquote>Zitat <blockquote>innen</blockquote></blockquote>';
$summary = RenderSummary::fromHtml($html);
self::assertSame(['Punkt eingebettet', 'Zitat innen'], $summary['texts']);
}
public function testIgnoresScriptStyleAndNoscriptText(): void
{
$html = '<p>Sichtbar<script>var x = 1;</script><style>.a{color:red}</style>'
. '<noscript>Fallback</noscript> Ende</p>';
$summary = RenderSummary::fromHtml($html);
self::assertSame(['Sichtbar Ende'], $summary['texts']);
}
public function testRendersTheEntryAndAddsNotes(): void
{
$post = new WP_Post(['ID' => 7, 'post_type' => 'page', 'post_password' => 'geheim']);
@@ -60,7 +135,7 @@ final class PageRenderSummaryAbilityTest extends TestCase
self::assertSame(7, $result['post_id']);
self::assertSame('https://k.test/start/', $result['url']);
self::assertCount(2, $result['headings']);
self::assertCount(2, $result['notes']);
self::assertCount(3, $result['notes']);
self::assertTrue($ability->isDirect());
self::assertTrue($ability->annotations()['readonly']);
}