From 71ee6d1bb6c63ca300c16b62b57eca71af7c9033 Mon Sep 17 00:00:00 2001 From: Nonimart Date: Thu, 21 Aug 2025 15:05:57 +0200 Subject: [PATCH] REFACTOR optimizing injecting id to h2 by injecting in php instead of javascript --- includes/article.php | 64 ++++++++++++++++++++++++++++++++ resources/js/singles/sommaire.ts | 52 -------------------------- 2 files changed, 64 insertions(+), 52 deletions(-) diff --git a/includes/article.php b/includes/article.php index 0f27373..3a62342 100644 --- a/includes/article.php +++ b/includes/article.php @@ -13,6 +13,7 @@ function dynamiques_article_save_post($post_id) if ($related_revue_ID && is_numeric($related_revue_ID) && $related_revue_ID !== '') { dynamiques_article_include_article_in_revue_articles_array($current_article_ID, $related_revue_ID); + update_post_meta($current_article_ID, 'revue_issue_number', get_field('issue_number', $related_revue_ID)); } } add_action('acf/save_post', 'dynamiques_article_save_post', 20); @@ -55,3 +56,66 @@ function dynamiques_article_remove_articles_from_all_revues($current_article_ID) update_field('articles', $revue_articles, $revue_ID); } } + + + +/** + * Injecte automatiquement des IDs aux titres H2 dans le contenu + * pour permettre la navigation par ancres + */ +function dynamiques_render_article_inject_ids_to_headings($content) +{ + // Ne traiter que si on est dans une page de contenu + if (!is_singular() || !in_the_loop()) { + return $content; + } + + // Utiliser la fonction native WordPress pour créer le slug + function create_slug($text) + { + $slug = sanitize_title($text); + + // S'assurer que l'ancre n'est pas vide + if (empty($slug)) { + $slug = 'anchor'; + } + + return $slug; + } + + // Utiliser DOMDocument pour parser le HTML + $dom = new DOMDocument(); + + // Supprimer les avertissements pour les entités HTML + libxml_use_internal_errors(true); + + // Encoder le contenu en UTF-8 et l'ajouter au DOM + $dom->loadHTML('' . $content, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD); + + // Restaurer les erreurs + libxml_clear_errors(); + + // Chercher tous les H2 et H3 + $headings = $dom->getElementsByTagName('h2'); + + // Traiter les H2 + foreach ($headings as $heading) { + if (!$heading->hasAttribute('id')) { + $text = $heading->textContent; + $slug = create_slug($text); + $heading->setAttribute('id', $slug); + } + } + + + // Récupérer le HTML modifié + $modified_content = $dom->saveHTML(); + + // Nettoyer l'encodage XML ajouté + $modified_content = preg_replace('/^/', '', str_replace(['', ''], '', $modified_content)); + + return $modified_content; +} + +// Appliquer le filtre sur le contenu +add_filter('the_content', 'dynamiques_render_article_inject_ids_to_headings', 20); diff --git a/resources/js/singles/sommaire.ts b/resources/js/singles/sommaire.ts index 1345521..4de4879 100644 --- a/resources/js/singles/sommaire.ts +++ b/resources/js/singles/sommaire.ts @@ -10,55 +10,3 @@ export function handleSmoothScrollToTitle(targetId: string): void { behavior: 'smooth', }); } - -// Fonction équivalente à sanitize_title() de WordPress -function sanitizeTitle(title: string): string { - // Convertir en minuscules - let slug = title.toLowerCase(); - - // Normaliser les caractères (supprimer les accents) - comme WordPress - slug = slug.normalize('NFD').replace(/[\u0300-\u036f]/g, ''); - - // Remplacer les ligatures (comme WordPress remove_accents) - slug = slug.replace(/œ/g, 'oe').replace(/æ/g, 'ae'); - - // Remplacer les points par des tirets (comme WordPress) - slug = slug.replace(/\./g, '-'); - - // Remplacer les caractères spéciaux - slug = slug.replace(/[«»"'?!:;,()[\]{}/\\|&@#$%*+=<>~`^°…—–−]/g, ''); - - // Remplacer leespaces et caractères de contrôle par des tirets - slug = slug.replace(/[\s\t\n\r]+/g, '-'); - - // Supprimer les caractères non alphanumériques restants (sauf tirets) - slug = slug.replace(/[^a-z0-9\-]/g, ''); - - // Remplacer les tirets multiples par un seul tiret - slug = slug.replace(/-+/g, '-'); - - // Supprimer les tirets en début et fin - slug = slug.replace(/^-+|-+$/g, ''); - - // S'assurer que l'ancre n'est pas vide - if (!slug) { - slug = 'anchor'; - } - - // Limiter la longueur (comme sanitize_title() de WordPress - 200 caractères) - if (slug.length > 200) { - slug = slug.substring(0, 200); - slug = slug.replace(/-+$/, ''); - } - - return slug; -} - -export function injectIdToNativeTitles(): void { - const titles = document.querySelectorAll('.content-area h2, .content-area h3'); - titles.forEach((title) => { - const titleText = title.textContent || ''; - const slug = sanitizeTitle(titleText); - title.setAttribute('id', slug); - }); -}