Browse Source

bug-fixes

imwald
Silberengel 2 days ago
parent
commit
e5962166e0
  1. 7
      assets/styles/layout.css
  2. 58
      src/Twig/ArticleCardCoverExtension.php
  3. 2
      templates/components/Organisms/HomeHighlightsAside.html.twig
  4. 16
      templates/pages/article.html.twig

7
assets/styles/layout.css

@ -748,17 +748,18 @@ aside { @@ -748,17 +748,18 @@ aside {
.home-aside-highlights__meta {
display: block;
font-size: 0.7rem;
font-size: 0.78rem;
font-style: normal;
font-weight: 500;
font-family: var(--font-family), system-ui, sans-serif;
color: color-mix(in srgb, var(--color-text-mid) 80%, var(--color-bg) 20%);
color: var(--color-primary);
letter-spacing: 0.02em;
transition: color 0.18s ease;
}
.home-aside-highlights__item-inner:hover .home-aside-highlights__meta,
.home-aside-highlights__item-inner:has(.home-aside-highlights__hit:focus-visible) .home-aside-highlights__meta {
color: color-mix(in srgb, var(--color-primary) 45%, var(--color-text-mid) 55%);
color: color-mix(in srgb, var(--color-secondary) 55%, var(--color-primary));
}
table {

58
src/Twig/ArticleCardCoverExtension.php

@ -7,6 +7,7 @@ namespace App\Twig; @@ -7,6 +7,7 @@ namespace App\Twig;
use App\Service\CacheService;
use App\Service\NostrPathHelper;
use Symfony\Component\Asset\Packages;
use Symfony\Component\HttpFoundation\RequestStack;
use Throwable;
use Twig\Extension\AbstractExtension;
use Twig\TwigFunction;
@ -22,6 +23,8 @@ final class ArticleCardCoverExtension extends AbstractExtension @@ -22,6 +23,8 @@ final class ArticleCardCoverExtension extends AbstractExtension
*/
private const DEFAULT_PACKAGE_IMAGE = 'icons/favicon-96x96.png';
private const OG_FALLBACK_PACKAGE_IMAGE = 'og-image.jpg';
/**
* @var array<string, string> lowercase 64-hex pubkey → resolved cover URL (author picture or site default)
*/
@ -31,6 +34,7 @@ final class ArticleCardCoverExtension extends AbstractExtension @@ -31,6 +34,7 @@ final class ArticleCardCoverExtension extends AbstractExtension
private readonly CacheService $cacheService,
private readonly NostrPathHelper $nostrPathHelper,
private readonly Packages $packages,
private readonly RequestStack $requestStack,
) {
}
@ -38,9 +42,63 @@ final class ArticleCardCoverExtension extends AbstractExtension @@ -38,9 +42,63 @@ final class ArticleCardCoverExtension extends AbstractExtension
{
return [
new TwigFunction('article_card_cover', $this->articleCardCover(...)),
new TwigFunction('article_og_image', $this->articleOgImage(...)),
];
}
/**
* Absolute URL + whether to emit og:image:width/height (1200×630) for the site default OG JPEG only.
*
* @return array{href: string, use_default_dimensions: bool}
*/
public function articleOgImage(?string $articleImage, ?string $pubkeyHex): array
{
$cover = $this->articleCardCover($articleImage, $pubkeyHex);
$defaultCover = $this->defaultSiteImageUrl();
$useDefaultDimensions = false;
$chosen = $cover;
if ($chosen === $defaultCover) {
try {
$chosen = $this->packages->getUrl(self::OG_FALLBACK_PACKAGE_IMAGE);
$useDefaultDimensions = true;
} catch (Throwable) {
$useDefaultDimensions = false;
}
}
return [
'href' => $this->absolutizeForOpenGraph($chosen),
'use_default_dimensions' => $useDefaultDimensions,
];
}
/**
* Crawlers require absolute https URLs; article/profile images are often https, //, or site-relative.
*/
private function absolutizeForOpenGraph(string $urlOrPath): string
{
$u = trim($urlOrPath);
if ($u === '') {
return '';
}
if (preg_match('#^https?://#i', $u) === 1) {
return $u;
}
if (str_starts_with($u, '//')) {
return 'https:'.$u;
}
$request = $this->requestStack->getMainRequest();
if ($request === null) {
return $u;
}
$base = $request->getSchemeAndHttpHost().$request->getBaseUrl();
if (str_starts_with($u, '/')) {
return $base.$u;
}
return $base.'/'.ltrim($u, '/');
}
/**
* @param string|null $articleImage Cover URL stored on the article, if any
* @param string|null $pubkeyHex 64-char hex (lowercase) Nostr public key, if any

2
templates/components/Organisms/HomeHighlightsAside.html.twig

@ -25,7 +25,7 @@ @@ -25,7 +25,7 @@
{% if _prew == '' %}{% set _prew = h.quoteExcerpt|default('')|trim %}{% endif %}
<div class="home-aside-highlights__quote home-aside-highlights__quote--plain">{{ _prew|u.truncate(200, '…') }}</div>
{% endif %}
<span class="home-aside-highlights__meta text-subtle">{{ art.title|default('')|u.truncate(52, '…') }}</span>
<span class="home-aside-highlights__meta">{{ art.title|default('')|u.truncate(52, '…') }}</span>
</div>
</li>
{% endif %}

16
templates/pages/article.html.twig

@ -8,18 +8,10 @@ @@ -8,18 +8,10 @@
{% endblock %}
{% block ogtags %}
{# Upstream main only outputs og:image when article.image is set — unfurlers often show a blank card. Always set an absolute image + JSON-LD. #}
{% set _img = article.image|default('')|trim %}
{% if _img == '' %}
{% set _og_image = absolute_url(asset('og-image.jpg')) %}
{% set _og_default_dims = true %}
{% elseif _img starts with '//' %}
{% set _og_image = 'https:' ~ _img %}
{% set _og_default_dims = false %}
{% else %}
{% set _og_image = absolute_url(_img) %}
{% set _og_default_dims = false %}
{% endif %}
{# Same resolution as card heroes (article image → kind-0 picture → site OG JPEG); absolute URL for unfurlers. #}
{% set _og = article_og_image(article.image, article.pubkey) %}
{% set _og_image = _og.href %}
{% set _og_default_dims = _og.use_default_dimensions %}
{% set _desc = article.summary|default('')|striptags|u.truncate(159, '…') %}
{% set _canonical = url('article', { npub: npub|default(npub_from_hex(article.pubkey)), slug: article.slug }) %}
{% set _author_name = '' %}

Loading…
Cancel
Save