Liens internes, dans le même onglet !


Votre site

·

3–4 minutes

Ça faisait un bail que je programmais les liens internes de ce site pour qu’ils s’ouvrent dans un nouvel onglet. D’où m’étais-je fait cette mauvaise représentation ? En étudiant les critères d’accessibilité, je me suis rendu compte que c’était une bêtise. Réparée !

Ne pas perdre le fil de l’article de départ

C’était ce que je croyais pertinent pourtant. Je m’étais convaincu tout seul : si je propose dans un article un lien vers un une autre page du site, alors le lecteur ou la lectrice va perdre le fil de sa lecture initiale.

Du coup pour chaque lien je demandais « ouvrir dans un nouvel onglet ». Anodin ? Pas tant que ça.

Ouvrir dans un nouvel onglet pose problème

Je ne comprenais pas l’alerte de Wave (là j’ai mis un lien vers un nouvel onglet, c’est un lien externe).

En fait, j’ai compris que c’était un souci d’abord d’accessibilité :

  • difficile pour une personne qui voit mal et utilise peut-être la loupe de comprendre que le lien s’est ouvert à l’extérieur
  • chaque navigateur est doté d’un bouton page précédente et suivante qui du coup se trouve inopérant
  • pour un certain nombre de personnes, gérer une collection d’onglets ne facilite pas la navigation
  • selon les outils, tablette ou smartphone, les choses peuvent vite se compliquer.

Depuis un moment j’essaie de veiller à l’accessibilité du site, de favoriser une navigation claire et fluide pour toute personne.

Dans le même esprit j’ai compris qu’il vaut mieux laisser l’attribut title d’un lien WordPress vide pour éviter la redondance. Les lecteurs d’écran lisent souvent à la fois l’ancre du lien et l’attribut title. Cela force les utilisateurs malvoyants à entendre deux fois la même information c’est un peu ennuyeux.

Corriger 1691 articles ?

Oui mais sans compter les pages, il y a déjà un nombre conséquents d’articles et de liens concernés. Je suis certes masochiste, mais je ne vais pas consacrer mes nuits à ce travail.

J’évite aussi d’aller chercher des plugins WordPress qui alourdissent vite un site. Alors, oui dans ce cas très précis j’ai fait travailler l’automatisation probabiliste et j’ai appliqué deux bouts de code avec l’extension WP Code. Il faudra que j’aille les coller dans mon Codeberg. Là comme c’est un espace personnel j’ai gardé le lien dans la page. Êtes vous revenu·e pour voir les bouts de code ?

code php pour corriger l’ouverture de liens en la forçant sur la même page

add_filter( 'the_content', function ( $content ) {
    if ( false === strpos( $content, '_blank' ) ) {
        return $content;
    }

    $site_host = preg_replace( '/^www\./', '', wp_parse_url( home_url(), PHP_URL_HOST ) );
    $p = new WP_HTML_Tag_Processor( $content );

    while ( $p->next_tag( 'a' ) ) {
        if ( '_blank' !== $p->get_attribute( 'target' ) ) {
            continue;
        }
        $href = $p->get_attribute( 'href' );
        if ( ! is_string( $href ) || preg_match( '/\.pdf($|\?)/i', $href ) ) {
            continue; // on laisse les PDF s'ouvrir dans un nouvel onglet
        }
        $host = wp_parse_url( $href, PHP_URL_HOST );
        if ( null === $host || preg_replace( '/^www\./', '', $host ) === $site_host ) {
            $p->remove_attribute( 'target' );
        }
    }

    return $p->get_updated_html();
}, 20 );

Retirer le title uniquement quand il est identique au texte du lien (code php)

Je ne retire que les title qui répètent exactement le texte du lien pas ceux qui apportent une information différente.

add_filter( 'the_content', function ( $content ) {
    if ( false === strpos( $content, 'title=' ) ) {
        return $content;
    }

    // Normalise un texte pour la comparaison : sans balises, entités décodées,
    // espaces insécables et multiples ramenés à une espace, casse ignorée.
    $normalize = function ( $s ) {
        $s = wp_strip_all_tags( $s );
        $s = html_entity_decode( $s, ENT_QUOTES | ENT_HTML5, 'UTF-8' );
        $s = str_replace( "\xC2\xA0", ' ', $s );
        $s = preg_replace( '/\s+/u', ' ', $s );
        return mb_strtolower( trim( $s ) );
    };

    return preg_replace_callback(
        '#<a\b([^>]*)>(.*?)</a>#is',
        function ( $m ) use ( $normalize ) {
            if ( ! preg_match( '/\s+title\s*=\s*(?:"([^"]*)"|\'([^\']*)\')/i', $m[1], $t ) ) {
                return $m[0];
            }

            $title = ( isset( $t[2] ) && '' !== $t[2] ) ? $t[2] : $t[1];
            $title = $normalize( $title );

            if ( '' !== $title && $title === $normalize( $m[2] ) ) {
                $attrs = preg_replace( '/\s+title\s*=\s*(?:"[^"]*"|\'[^\']*\')/i', '', $m[1], 1 );
                return '<a' . $attrs . '>' . $m[2] . '</a>';
            }

            return $m[0];
        },
        $content
    );
}, 20 );

J’utilise ça sur mon site WordPress version 7.1.2 avec un thème FSE. Il faut au moins WordPress 6.2

À noter encore :

Les deux filtres agissent sur l’affichage : le contenu enregistré n’est pas modifié. Si on désactive le code on, revient au choix de départ.
Les menus, widgets ou modèles du thème FSE ne sont pas concernés.

Si vous avez un cache ce qui est probable et souhaitable, il faut le vider !


Je vis en pays de Rouergue. Je partage ici chaque jour ou presque, un journal, de la fiction, de la poésie ou des chansons. Garanti « fait » à la main, ce site ne vous piste pas. Si vous aimez, partagez !


VOUS POURRIEZ AIMER AUSSI

dernières publications

Les commentaires

Commentez, ou publiez une réponse sur votre blog (avec un lien vers cet article) ou sur le Fediverse (Mastodon, etc.) : elle apparaîtra ici après modération.

Un mot en retour ?

Vous souhaitez citer cet article sur votre site ? Indiquez simplement votre lien ici.