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