diff --git a/app/Services/Parsers/BelgaArticlePageParser.php b/app/Services/Parsers/BelgaArticlePageParser.php index 3c1fdc44..955bd51a 100644 --- a/app/Services/Parsers/BelgaArticlePageParser.php +++ b/app/Services/Parsers/BelgaArticlePageParser.php @@ -110,12 +110,12 @@ public static function extractThumbnail(string $html): ?string { // Try OpenGraph image first if (preg_match('/]+src="([^"]+)"/i', $html, $matches)) { - return $matches[1]; + return html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'); } return null; diff --git a/app/Services/Parsers/GuardianArticlePageParser.php b/app/Services/Parsers/GuardianArticlePageParser.php index 4d462115..09c7c4fa 100644 --- a/app/Services/Parsers/GuardianArticlePageParser.php +++ b/app/Services/Parsers/GuardianArticlePageParser.php @@ -68,12 +68,12 @@ public static function extractThumbnail(string $html): ?string { // Try OpenGraph image first if (preg_match('/]+src="([^"]+)"/i', $html, $matches)) { - return $matches[1]; + return html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'); } return null; diff --git a/app/Services/Parsers/VrtArticlePageParser.php b/app/Services/Parsers/VrtArticlePageParser.php index e312bb6f..095c7389 100644 --- a/app/Services/Parsers/VrtArticlePageParser.php +++ b/app/Services/Parsers/VrtArticlePageParser.php @@ -67,11 +67,11 @@ public static function extractFullArticle(string $html): ?string public static function extractThumbnail(string $html): ?string { if (preg_match('/]+src="([^"]+)"/i', $html, $matches)) { - return $matches[1]; + return html_entity_decode($matches[1], ENT_QUOTES, 'UTF-8'); } return null; diff --git a/tests/Unit/Services/Parsers/BelgaArticlePageParserTest.php b/tests/Unit/Services/Parsers/BelgaArticlePageParserTest.php index 83a78baf..4774419d 100644 --- a/tests/Unit/Services/Parsers/BelgaArticlePageParserTest.php +++ b/tests/Unit/Services/Parsers/BelgaArticlePageParserTest.php @@ -242,6 +242,36 @@ public function test_extract_thumbnail_prefers_og_image(): void $this->assertEquals('https://example.com/og-image.jpg', $thumbnail); } + public function test_extract_thumbnail_decodes_html_entities_in_og_image(): void + { + // Real Belga CDN URLs carry query params, so the & in the raw HTML + // must be decoded or the URL Lemmy receives is malformed. See #117. + $html = '
'; + + $thumbnail = BelgaArticlePageParser::extractThumbnail($html); + + $this->assertEquals('https://cdn.example.com/img:12345:full?v=6a6c828f&m=cdodnjha', $thumbnail); + $this->assertStringNotContainsString('&', (string) $thumbnail); + } + + public function test_extract_thumbnail_decodes_html_entities_in_img_tag(): void + { + $html = '
';
+
+ $thumbnail = BelgaArticlePageParser::extractThumbnail($html);
+
+ $this->assertEquals('https://cdn.example.com/pic.png?a=1&b=2', $thumbnail);
+ }
+
+ public function test_extract_data_returns_decoded_thumbnail(): void
+ {
+ $html = '';
+
+ $data = BelgaArticlePageParser::extractData($html);
+
+ $this->assertEquals('https://cdn.example.com/x.jpg?v=1&m=2', $data['thumbnail']);
+ }
+
public function test_extract_thumbnail_returns_null_when_not_found(): void
{
$html = '
';
+
+ $thumbnail = GuardianArticlePageParser::extractThumbnail($html);
+
+ $this->assertEquals('https://i.guim.co.uk/img/pic.png?a=1&b=2', $thumbnail);
+ }
}
diff --git a/tests/Unit/Services/Parsers/VrtArticlePageParserTest.php b/tests/Unit/Services/Parsers/VrtArticlePageParserTest.php
new file mode 100644
index 00000000..6f3c6a61
--- /dev/null
+++ b/tests/Unit/Services/Parsers/VrtArticlePageParserTest.php
@@ -0,0 +1,75 @@
+