@extends('layouts.site') @php $trans = $post->translation($locale); $baseTitle = $trans?->meta_title ?: $trans?->title; if ($currentPage > 1 && $totalPages > 1 && !empty($globalToc[$currentPage - 1]['title'])) { $chapterTitle = $globalToc[$currentPage - 1]['title']; $pageTitle = $baseTitle . ' - ' . $chapterTitle . ' (' . $currentPage . '/' . $totalPages . ')'; } else { $pageTitle = $baseTitle; } $baseDescription = $trans?->meta_description ?: Str::limit(strip_tags($trans?->body), 160); if ($currentPage > 1 && $totalPages > 1) { $pageDescription = Str::limit(strip_tags($pageBody), 160); } else { $pageDescription = $baseDescription; } @endphp @section('title', $pageTitle) @section('meta_description', $pageDescription) @section('content')
{{-- Header --}}

{{ $trans?->title }}

{{-- Share button --}} @if($trans)
{{ __('Link copied!') }}
@endif {{-- Synthesis flipbook button --}} @if($post->allow_pdf && $trans?->pdf_synthesis_name) @php $synthPdfUrl = '/storage/PDF/' . ltrim($trans->pdf_synthesis_name, '/'); $synthConfig = json_encode([ 'pdfUrl' => $synthPdfUrl, 'title' => $trans->title ?? 'PDF', 'thumbnail' => $trans->mediaUrl('og_image') ?? '', ], JSON_HEX_APOS | JSON_HEX_QUOT); @endphp @php $synthDownloadUrl = '/download/' . preg_replace('/^[^_]+_/', '', str_replace('.pdf', '-pdf', basename($trans->pdf_synthesis_name))); @endphp
@endif {{-- PDF Download button --}} @if($post->allow_pdf && $trans) @endif {{-- Edit button (logged-in users only) --}} @auth @endauth
{{-- Global TOC (multi-page posts only) --}} @if($totalPages > 1)

{{ __('This article is divided into several pages:') }}

    @foreach($globalToc as $tocItem)
  1. @if($tocItem['page'] === $currentPage) {{ $tocItem['title'] }} @else {{ $tocItem['title'] }} @endif
  2. @endforeach
@endif {{-- Table of Contents (current page only) --}} @if($pageBody && preg_match_all('/<(h[1-3])[^>]*>(.*?)<\/h[1-3]>/i', $pageBody, $headings, PREG_SET_ORDER) && count($headings) >= 2) @php // Slug helper: converts heading text to a URL-friendly anchor $seenSlugs = []; $makeSlug = function (string $text) use (&$seenSlugs): string { $slug = strip_tags($text); $slug = \Illuminate\Support\Str::ascii($slug); $slug = str_replace(' ', '_', $slug); $slug = preg_replace('/[^A-Za-z0-9_]/', '', $slug); if ($slug === '') { $slug = 'heading'; } if (isset($seenSlugs[$slug])) { $seenSlugs[$slug]++; $slug .= '_' . $seenSlugs[$slug]; } else { $seenSlugs[$slug] = 1; } return $slug; }; // Build numbered TOC items with level info $counters = [0, 0, 0]; $tocItems = []; foreach ($headings as $i => $match) { $level = (int) substr($match[1], 1); $text = html_entity_decode(strip_tags($match[2]), ENT_QUOTES | ENT_HTML5, 'UTF-8'); $counters[$level - 1]++; for ($j = $level; $j < 3; $j++) $counters[$j] = 0; $parts = []; for ($j = 0; $j < $level; $j++) { if ($counters[$j] > 0) $parts[] = $counters[$j]; } $tocItems[] = ['number' => implode('.', $parts), 'text' => $text, 'slug' => $makeSlug($match[2]), 'level' => $level]; } // Build nested HTML $tocHtml = ''; $prevLevel = 0; foreach ($tocItems as $item) { if ($item['level'] > $prevLevel) { $tocHtml .= str_repeat('', $prevLevel - $item['level']) . ''; } else { if ($prevLevel > 0) $tocHtml .= ''; } $tocHtml .= '
  • ' . $item['number'] . '. ' . e($item['text']) . ''; $prevLevel = $item['level']; } $tocHtml .= str_repeat('
  • ', $prevLevel); @endphp
    {!! $tocHtml !!}
    @endif {{-- Content --}}
    @if($pageBody) @php // Build heading numbers and text-based slugs (same logic as TOC) $ctr = [0, 0, 0]; $contentSeenSlugs = []; $contentBody = preg_replace_callback('/<(h[1-3])([^>]*)>(.*?)<\/(h[1-3])>/i', function($m) use (&$ctr, &$contentSeenSlugs) { $lvl = (int) substr($m[1], 1); $ctr[$lvl - 1]++; for ($j = $lvl; $j < 3; $j++) $ctr[$j] = 0; $parts = []; for ($j = 0; $j < $lvl; $j++) { if ($ctr[$j] > 0) $parts[] = $ctr[$j]; } $num = implode('.', $parts); // Generate slug from heading text $slug = strip_tags($m[3]); $slug = \Illuminate\Support\Str::ascii($slug); $slug = str_replace(' ', '_', $slug); $slug = preg_replace('/[^A-Za-z0-9_]/', '', $slug); if ($slug === '') { $slug = 'heading'; } if (isset($contentSeenSlugs[$slug])) { $contentSeenSlugs[$slug]++; $slug .= '_' . $contentSeenSlugs[$slug]; } else { $contentSeenSlugs[$slug] = 1; } return '<' . $m[1] . ' id="' . $slug . '"' . $m[2] . '>' . $num . '. ' . $m[3] . ''; }, $pageBody); if (($post->template ?? 'default') === 'default') { $contentBody = wpautop($contentBody); $contentBody = downgrade_headings($contentBody); } // Restore flipbook HTML that was protected from wpautop via placeholders if (isset($shortcodeService)) { $contentBody = $shortcodeService->restorePlaceholders($contentBody); } // Lazy-load and async-decode all content images $contentBody = preg_replace('/]*loading=)/', ']*alt=)([^>]*)\/?>/i', '', $contentBody); @endphp {!! $contentBody !!} @endif
    {{-- Pagination (multi-page posts only) --}} @if($totalPages > 1) @endif
    @endsection