@extends('layouts.site')
@php
// Une page « builder » contient les classes de grille du thème WordPress d'origine.
$isBuilder = $type === 'page' && \Illuminate\Support\Str::contains($item->content, ['content-section', 'col-sm-', 'gridContainer']);
// Tous les articles ont un visuel (à la une, sinon image de marque via display_image).
// Articles dont le corps embarquait une image externe morte -> illustration promo locale.
$hasHero = $type === 'post';
$usesPromo = $type === 'post' && \App\Support\BlogImages::hasExternalImage($item->content);
$rawHero = $type === 'post'
? ($usesPromo ? \App\Support\BlogImages::forSlug($item->slug.'-hero') : $item->display_image)
: null;
$heroImg = $rawHero
? (\Illuminate\Support\Str::startsWith($rawHero, 'http') ? $rawHero : url($rawHero))
: null;
// Titre nettoyé : retire l'emoji de tête (🏙️, etc.) et les espaces - titres modernes, sans pictos démodés.
$displayTitle = trim(preg_replace('/^[\x{1F000}-\x{1FAFF}\x{2190}-\x{27BF}\x{2B00}-\x{2BFF}\x{FE00}-\x{FE0F}\x{200D}\s]+/u', '', $item->title)) ?: $item->title;
// Icônes Lucide (trait fin) pour la navigation « Les trucs en + ».
$tIco = fn($p) => '';
// Navigation « Les trucs en + » (bas de page) - [icône Lucide, libellé, url]
$trucs = [
[$tIco(''),'La plage','/plage-du-moulleau'],
[$tIco(''),'La jetée','/jetee-du-moulleau-navette-cap-ferret'],
[$tIco(''),'Restaurants','/quelques-adresse-de-restaurant'],
[$tIco(''),'Boutiques','/quelques-boutiques'],
[$tIco(''),'Balades à vélo','/les-meilleures-balades-a-velo-autour-du-moulleau'],
[$tIco(''),'Spots sportifs','/quelques-spots-pour-faire-du-sport-autour-du-moulleau'],
[$tIco(''),'Activités','/quelques-activites'],
[$tIco(''),'Incontournables','/quelques-lieux-incontournables-a-visiter-autour-du-moulleau'],
[$tIco(''),'Loueurs de vélos','/quelques-adresse-de-loueurs-de-velos'],
[$tIco(''),'Les villes','/les-villes-aux-alentours'],
];
@endphp
@section('title', ($item->seo_title ?: $displayTitle).' - JavaPax')
@section('meta_description', $item->seo_description ?: \Illuminate\Support\Str::limit(trim(strip_tags($item->content)), 155))
{{-- Consolidation du contenu dupliqué : si canonical_url est défini, on pointe
le canonical vers la page de référence et on passe la page en noindex. --}}
@if(!empty($item->canonical_url))
@section('canonical', url($item->canonical_url))
@section('robots', 'noindex, follow')
@endif
@if($type === 'post')
@push('jsonld')
@php
$ld = array_filter([
'@context' => 'https://schema.org',
'@type' => 'BlogPosting',
'headline' => $displayTitle,
'datePublished' => optional($item->published_at)->toAtomString(),
'dateModified' => optional($item->updated_at)->toAtomString(),
'image' => $heroImg,
'author' => ['@type' => 'Organization', 'name' => 'JavaPax'],
'publisher' => ['@type' => 'Organization', 'name' => 'JavaPax'],
'mainEntityOfPage' => url('/'.$item->slug),
]);
@endphp
@endpush
@endif
{{-- Fil d'Ariane structuré (BreadcrumbList) --}}
@push('jsonld')
@php
$crumbs = [['name' => 'Accueil', 'url' => url('/')]];
if ($type === 'post') {
$crumbs[] = ['name' => 'Les trucs en +', 'url' => url('/faq-2')];
}
$crumbs[] = ['name' => $displayTitle, 'url' => url('/'.$item->slug)];
$breadcrumbLd = [
'@context' => 'https://schema.org',
'@type' => 'BreadcrumbList',
'itemListElement' => array_map(fn ($c, $i) => [
'@type' => 'ListItem',
'position' => $i + 1,
'name' => $c['name'],
'item' => $c['url'],
], $crumbs, array_keys($crumbs)),
];
@endphp
@endpush
@if($isBuilder)
@push('head')
@endpush
@endif
@push('head')
@endpush
@section('full')
@if($isBuilder)
{{-- Page vitrine (page-builder) : on laisse la grille d'origine s'exprimer --}}
{{ $displayTitle }}
@php
$builderHtml = str_replace('content);
// Sert du WebP via quand le fichier .webp existe localement (fallback JPG/PNG sinon).
$builderHtml = preg_replace_callback('/]*\bsrc="([^"]+\.(?:jpe?g|png))"[^>]*>/i', function ($m) {
$webp = preg_replace('/\.(jpe?g|png)$/i', '.webp', $m[1]);
$path = parse_url($webp, PHP_URL_PATH);
if ($path && file_exists(public_path($path))) {
// Variante 800 px quand elle existe : ces photos font 1500 px
// de large pour un ecran mobile de 412 px, soit trois fois le
// poids necessaire. Le navigateur choisit selon la largeur
// reelle d'affichage, sans qu'on ait a la deviner.
$petit = preg_replace('/\.webp$/i', '-800.webp', $webp);
$srcset = (parse_url($petit, PHP_URL_PATH) && file_exists(public_path(parse_url($petit, PHP_URL_PATH))))
? $petit.' 800w, '.$webp.' 1500w'
: $webp;
$sizes = ' sizes="(max-width: 900px) 100vw, 900px"';
return ''.$m[0].'';
}
return $m[0];
}, $builderHtml);
@endphp
{!! $builderHtml !!}