@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] . '' . $m[4] . '>';
}, $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);
// Add rel="noopener noreferrer" and target="_blank" to external links
$contentBody = preg_replace_callback('/
]*href=["\']https?:\/\/(?!' . preg_quote(request()->getHost(), '/') . ')[^"\']*["\'][^>]*)>/i', function($m) {
$tag = $m[1];
if (strpos($tag, 'target=') === false) {
$tag .= ' target="_blank"';
}
if (strpos($tag, 'rel=') === false) {
$tag .= ' rel="noopener noreferrer"';
}
return '';
}, $contentBody);
@endphp
{!! $contentBody !!}
@endif
{{-- Pagination (multi-page posts only) --}}
@if($totalPages > 1)