From 6f1367de09c05e48aefb5a8fb28cb663e88f3fa3 Mon Sep 17 00:00:00 2001
From: postie
Date: Sat, 7 Mar 2026 00:29:27 +0000
Subject: Use Dom\HTMLDocument to generate link previews
---
Digitigrade/LinkPreview.php | 42 +++++++++++++++++-------------------------
1 file changed, 17 insertions(+), 25 deletions(-)
(limited to 'Digitigrade/LinkPreview.php')
diff --git a/Digitigrade/LinkPreview.php b/Digitigrade/LinkPreview.php
index 4716cc8..706c3c7 100644
--- a/Digitigrade/LinkPreview.php
+++ b/Digitigrade/LinkPreview.php
@@ -29,38 +29,30 @@ class LinkPreview implements \JsonSerializable {
return false;
}
- $d = new \DOMDocument();
+ // TODO: Respect Content-Type header from response, maybe set an Accept header in the request?
+ // I was able to find a URL serving SHIFT-JIS, but they do not specify a charset in the Content-Type header.
+ // https://www2d.biglobe.ne.jp/~msyk/charcode/cp932/Windows-31J-charset.html
$c = @file_get_contents($this->url);
if (!$c)
return false;
- @$d->loadHTML($c);
+ $d = \Dom\HTMLDocument::createFromString($c, LIBXML_NOERROR);
$url = $this->url;
$siteName = hostname_from_uri($this->url);
$style = 'text';
- $title = $d->getElementsByTagName('title')->item(0)?->textContent;
- $metas = $d->getElementsByTagName('meta');
- foreach ($metas as $tag) {
- if ($tag->attributes->getNamedItem('name')?->textContent == 'description') {
- //
- $description = $tag->attributes->getNamedItem('content')?->textContent;
- } elseif ($prop = $tag->attributes->getNamedItem('property')) {
- //
- $content = $tag->attributes->getNamedItem('content')?->textContent;
- match ($prop->textContent) {
- 'og:title' => $title = $content,
- 'og:description' => $description = $content,
- 'og:url' => $url = $content,
- 'og:site_name' => $siteName = $content,
- 'og:image' => $imageUrl = $content,
- default => null
- };
- } elseif ($tag->attributes->getNamedItem('name')?->textContent == 'twitter:card'
- && $tag->attributes->getNamedItem("content")?->textContent == 'summary_large_image') {
- //
- $style = 'largeImage';
- }
+ // opengraph
+ $title = $d->querySelector("meta[property='og:title']")?->getAttribute('content');
+ $description = $d->querySelector("meta[property='og:description']")?->getAttribute('content');
+ $url = $d->querySelector("meta[property='og:url']")?->getAttribute('content');
+ $siteName = $d->querySelector("meta[property='og:site_name']")?->getAttribute('content');
+ $imageUrl = $d->querySelector("meta[property='og:image']")?->getAttribute('content');
+ // fallbacks
+ $title = $title ?? $d->querySelector('title')?->textContent;
+ $description = $description ?? $d->querySelector('meta[name=description]')?->getAttribute('content');
+
+ if ($d->querySelector("meta[name='twitter:card'][content=summary_large_image]") != null) {
+ $style = 'largeImage';
}
// turn text into smallImage if an image is present
$style = ($style == 'text' && isset($imageUrl)) ? 'smallImage' : $style;
@@ -88,4 +80,4 @@ class LinkPreview implements \JsonSerializable {
'imageUrl' => $this->imageUrl
];
}
-}
\ No newline at end of file
+}
--
cgit v1.3