aboutsummaryrefslogtreecommitdiffhomepage
path: root/Digitigrade/LinkPreview.php
diff options
context:
space:
mode:
authorpostie2026-03-07 00:29:27 +0000
committerjade (winter)2026-04-16 16:08:10 +0100
commit6f1367de09c05e48aefb5a8fb28cb663e88f3fa3 (patch)
treee5c928a98a0603b0edd194ae63562677d6214401 /Digitigrade/LinkPreview.php
parentc81ca4c3018090dd510cbb8e94e3e262816acd6a (diff)
Use Dom\HTMLDocument to generate link previews
Diffstat (limited to 'Digitigrade/LinkPreview.php')
-rw-r--r--Digitigrade/LinkPreview.php42
1 files changed, 17 insertions, 25 deletions
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') {
- // <meta name="description" content="...">
- $description = $tag->attributes->getNamedItem('content')?->textContent;
- } elseif ($prop = $tag->attributes->getNamedItem('property')) {
- // <meta property="og:..." content="...">
- $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') {
- // <meta name="twitter:card" content="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
+}