Allow heading tags (h1-h6) in ContentSanitizer so news editor headings render
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
<a href="{{ route('news.show', $article->slug) }}" class="block">
|
||||
<div class="relative aspect-[16/9] overflow-hidden bg-black/20">
|
||||
@if($article->cover_url)
|
||||
<img src="{{ $article->cover_url }}" @if($article->cover_srcset) srcset="{{ $article->cover_srcset }}" sizes="(max-width: 767px) 100vw, (max-width: 1279px) 50vw, 390px" @endif alt="{{ $article->title }}" class="h-full w-full object-cover transition duration-300 group-hover:scale-[1.04]">
|
||||
<img src="{{ $article->cover_mobile_url ?: $article->cover_url }}" @if($article->cover_srcset) srcset="{{ $article->cover_srcset }}" sizes="(max-width: 767px) 100vw, (max-width: 1279px) 50vw, 390px" @endif alt="{{ $article->title }}" class="h-full w-full object-cover transition duration-300 group-hover:scale-[1.04]">
|
||||
@else
|
||||
<div class="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(56,189,248,0.14),transparent_45%),linear-gradient(180deg,rgba(15,23,42,0.92),rgba(2,6,23,0.98))]"></div>
|
||||
@endif
|
||||
@@ -12,7 +12,7 @@
|
||||
|
||||
<div class="flex h-full flex-col p-5">
|
||||
<div class="flex flex-wrap items-center gap-2">
|
||||
<span class="inline-flex items-center rounded-full border border-white/[0.08] bg-white/[0.04] px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.14em] text-white/70">{{ $article->type_label }}</span>
|
||||
<a href="{{ route('news.type', $article->type) }}" class="inline-flex items-center rounded-full border border-white/[0.08] bg-white/[0.04] px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.14em] text-white/70 transition hover:border-white/20 hover:text-white">{{ $article->type_label }}</a>
|
||||
@if($article->category)
|
||||
<a href="{{ route('news.category', $article->category->slug) }}" class="inline-flex items-center rounded-full border border-sky-400/20 bg-sky-500/10 px-2.5 py-1 text-[11px] font-semibold uppercase tracking-[0.14em] text-sky-200">{{ $article->category->name }}</a>
|
||||
@endif
|
||||
|
||||
@@ -6,7 +6,8 @@
|
||||
</div>
|
||||
<div class="grid gap-4 md:grid-cols-2 xl:grid-cols-3">
|
||||
@foreach($relatedEntities as $entity)
|
||||
<a href="{{ $entity['url'] ?? '#' }}" class="group overflow-hidden rounded-[24px] border border-white/[0.08] bg-white/[0.03] transition hover:-translate-y-0.5 hover:border-white/[0.16]">
|
||||
@php($isExternalSource = ($entity['entity_type'] ?? null) === 'source')
|
||||
<a href="{{ $entity['url'] ?? '#' }}" @if($isExternalSource) target="_blank" rel="noopener noreferrer" @endif class="group overflow-hidden rounded-[24px] border border-white/[0.08] bg-white/[0.03] transition hover:-translate-y-0.5 hover:border-white/[0.16]">
|
||||
<div class="relative aspect-[16/9] overflow-hidden bg-black/20">
|
||||
@if(!empty($entity['image']))
|
||||
<img src="{{ $entity['image'] }}" alt="{{ $entity['title'] }}" class="h-full w-full object-cover transition duration-300 group-hover:scale-[1.04]">
|
||||
|
||||
@@ -85,7 +85,7 @@
|
||||
<div class="grid lg:grid-cols-[1.25fr_0.95fr]">
|
||||
<div class="relative min-h-[280px] overflow-hidden bg-black/20">
|
||||
@if($featured->cover_url)
|
||||
<img src="{{ $featured->cover_url }}" @if($featured->cover_srcset) srcset="{{ $featured->cover_srcset }}" sizes="(max-width: 1023px) 100vw, 768px" @endif alt="{{ $featured->title }}" class="h-full w-full object-cover transition duration-500 group-hover:scale-[1.03]">
|
||||
<img src="{{ $featured->cover_desktop_url ?: $featured->cover_url }}" @if($featured->cover_srcset) srcset="{{ $featured->cover_srcset }}" sizes="(max-width: 1023px) 100vw, 768px" @endif alt="{{ $featured->title }}" class="h-full w-full object-cover transition duration-500 group-hover:scale-[1.03]">
|
||||
@else
|
||||
<div class="absolute inset-0 bg-[radial-gradient(circle_at_top_left,rgba(56,189,248,0.14),transparent_45%),linear-gradient(180deg,rgba(15,23,42,0.96),rgba(2,6,23,0.98))]"></div>
|
||||
@endif
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
? url($article->effective_og_image)
|
||||
: url((string) config('seo.fallback_image_path', '/gfx/skinbase_back_001.webp'));
|
||||
$articleCoverSizes = '(max-width: 767px) calc(100vw - 3rem), (max-width: 1279px) calc(100vw - 5rem), 768px';
|
||||
$articleCoverPreloadHref = $article->cover_desktop_url ?: $article->cover_url;
|
||||
$articleCoverPreloadHref = $article->cover_large_url ?: ($article->cover_desktop_url ?: $article->cover_url);
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray([
|
||||
'title' => $article->meta_title ?: $article->title,
|
||||
'description' => $article->meta_description ?: Str::limit(strip_tags((string) $article->excerpt), 160),
|
||||
@@ -135,7 +135,7 @@
|
||||
>
|
||||
<x-slot name="actions">
|
||||
<div class="flex flex-wrap items-center gap-2 text-sm text-white/60">
|
||||
<span class="inline-flex items-center rounded-full border border-white/[0.08] bg-white/[0.04] px-3 py-1.5 text-white/75">{{ $article->type_label }}</span>
|
||||
<a href="{{ route('news.type', $article->type) }}" class="inline-flex items-center rounded-full border border-white/[0.08] bg-white/[0.04] px-3 py-1.5 text-white/75 transition hover:border-white/20 hover:text-white">{{ $article->type_label }}</a>
|
||||
@if($article->category)
|
||||
<a href="{{ route('news.category', $article->category->slug) }}" class="inline-flex items-center rounded-full border border-sky-400/20 bg-sky-500/10 px-3 py-1.5 text-sky-200">{{ $article->category->name }}</a>
|
||||
@endif
|
||||
@@ -173,15 +173,15 @@
|
||||
@if($article->cover_url)
|
||||
<div class="overflow-hidden rounded-[32px] border border-white/[0.06] bg-black/20 shadow-[0_24px_60px_rgba(0,0,0,0.24)]">
|
||||
<a
|
||||
href="{{ $articleCoverPreloadHref }}"
|
||||
href="{{ $article->cover_url }}"
|
||||
class="group block focus:outline-none focus-visible:ring-2 focus-visible:ring-sky-300/70 focus-visible:ring-offset-2 focus-visible:ring-offset-slate-950"
|
||||
aria-label="Open full cover image"
|
||||
data-news-image-preview
|
||||
data-news-image-src="{{ $articleCoverPreloadHref }}"
|
||||
data-news-image-src="{{ $article->cover_url }}"
|
||||
data-news-image-alt="{{ $article->title }}"
|
||||
>
|
||||
<div class="relative">
|
||||
<img src="{{ $article->cover_url }}" @if($article->cover_srcset) srcset="{{ $article->cover_srcset }}" sizes="{{ $articleCoverSizes }}" @endif alt="{{ $article->title }}" fetchpriority="high" loading="eager" decoding="async" class="h-auto max-h-[520px] w-full object-cover transition duration-300 group-hover:scale-[1.01]">
|
||||
<img src="{{ $article->cover_large_url ?: ($article->cover_desktop_url ?: $article->cover_url) }}" @if($article->cover_srcset) srcset="{{ $article->cover_srcset }}" sizes="{{ $articleCoverSizes }}" @endif alt="{{ $article->title }}" fetchpriority="high" loading="eager" decoding="async" class="h-auto max-h-[520px] w-full object-cover transition duration-300 group-hover:scale-[1.01]">
|
||||
<div class="pointer-events-none absolute inset-x-4 bottom-4 flex items-center justify-between gap-3 rounded-full border border-white/10 bg-slate-950/72 px-4 py-2 text-xs font-semibold uppercase tracking-[0.18em] text-white/82 backdrop-blur-sm">
|
||||
<span>Open Image</span>
|
||||
<span class="inline-flex items-center gap-2 text-sky-200/90">
|
||||
|
||||
61
resources/views/news/type.blade.php
Normal file
61
resources/views/news/type.blade.php
Normal file
@@ -0,0 +1,61 @@
|
||||
@extends('news.layout', [
|
||||
'metaTitle' => $typeLabel . ' — News',
|
||||
'metaDescription' => 'News articles of type ' . $typeLabel . '.',
|
||||
'metaCanonical' => route('news.type', $type),
|
||||
])
|
||||
|
||||
@section('news_content')
|
||||
@php
|
||||
$headerBreadcrumbs = collect([
|
||||
(object) ['name' => 'Community', 'url' => route('community.activity')],
|
||||
(object) ['name' => 'Announcements', 'url' => route('news.index')],
|
||||
(object) ['name' => $typeLabel, 'url' => route('news.type', $type)],
|
||||
]);
|
||||
|
||||
$seo = \App\Support\Seo\SeoDataBuilder::fromArray([
|
||||
'title' => $typeLabel . ' — News',
|
||||
'description' => 'Browse all news articles of type ' . $typeLabel . '.',
|
||||
'canonical' => route('news.type', $type),
|
||||
'breadcrumbs' => $headerBreadcrumbs,
|
||||
'structured_data' => [
|
||||
[
|
||||
'@context' => 'https://schema.org',
|
||||
'@type' => 'CollectionPage',
|
||||
'name' => $typeLabel . ' — News',
|
||||
'description' => 'Browse all news articles of type ' . $typeLabel . '.',
|
||||
'url' => route('news.type', $type),
|
||||
],
|
||||
],
|
||||
])->build();
|
||||
@endphp
|
||||
|
||||
<x-nova-page-header
|
||||
section="Community"
|
||||
:title="$typeLabel"
|
||||
icon="fa-newspaper"
|
||||
:breadcrumbs="$headerBreadcrumbs"
|
||||
:description="'Browse all ' . $typeLabel . ' articles.'"
|
||||
headerClass="pb-6"
|
||||
innerClass="mx-auto max-w-7xl"
|
||||
/>
|
||||
|
||||
<div class="mx-auto max-w-7xl px-6 pt-8 pb-16 md:px-10">
|
||||
<div class="grid gap-8 xl:grid-cols-[minmax(0,1fr)_320px]">
|
||||
<section>
|
||||
@if($articles->isEmpty())
|
||||
<div class="rounded-[28px] border border-white/[0.06] bg-white/[0.025] px-8 py-14 text-center text-white/45">No {{ $typeLabel }} articles have been published yet.</div>
|
||||
@else
|
||||
<div class="grid gap-5 md:grid-cols-2">
|
||||
@foreach($articles as $article)
|
||||
@include('news._article_card', ['article' => $article])
|
||||
@endforeach
|
||||
</div>
|
||||
<div class="mt-8 flex justify-center">{{ $articles->links() }}</div>
|
||||
@endif
|
||||
</section>
|
||||
<aside class="space-y-4">
|
||||
@include('news._sidebar', ['categories' => $categories, 'trending' => $trending, 'tags' => $tags])
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
@endsection
|
||||
Reference in New Issue
Block a user