Le filtre wptexturize de WordPress corrompt silencieusement le JavaScript en ligne, transformant l'opérateur logique && en l'entité HTML && et cassant les scripts qui s'exécutent à l'intérieur des shortcodes.

Le problème est apparu pour un développeur qui gère un ensemble de shortcodes de calculatrices. Après des semaines de fonctionnement impeccable, les boutons de validation ont cessé de répondre. Aucun avertissement PHP, aucune erreur dans la console, et le code HTML inspecté semblait propre — jusqu'à ce que la source rendue révèle if (!isNaN(bf) && bf > 0). Cette unique erreur de syntaxe a empêché l'exécution de l'intégralité du bloc de script.

Pourquoi ce filtre est important

WordPress traite le contenu des articles via une série de filtres avant qu'il n'atteigne le navigateur. wptexturize est le premier de ces filtres ; il convertit les guillemets droits en guillemets typographiques incurvés, remplace les tirets multiples par des tirets cadratins et assainit les esperluettes (&). Le filtre part du principe qu'il traite de la prose, et non du code. Lorsqu'un shortcode injecte une balise <script> en ligne, le filtre s'exécute tout de même, traitant le JavaScript comme du texte ordinaire. L'esperluette dans && est donc échappée en &#038;, que le navigateur interprète comme une chaîne de caractères littérale plutôt que comme l'opérateur logique ET.

Les développeurs qui intègrent du JavaScript directement dans le contenu des articles — calculatrices, validateurs de formulaires, widgets interactifs — sont vulnérables. Le problème ne se limite pas aux calculatrices ; tout script en ligne utilisant &&, & ou des caractères similaires peut être corrompu. Comme la transformation s'effectue côté serveur, le navigateur ne voit jamais le code original, et l'erreur ne se manifeste pas comme une exception JavaScript typique.

Qui est affecté et ce qu'ils perdent

  • Propriétaires de sites : une calculatrice ou un formulaire défectueux peut frustrer les visiteurs, augmenter le taux de rebond et éroder la confiance.
  • Développeurs : des heures passées à traquer des bugs « fantômes » qui ne laissent aucune trace dans les journaux ou la console.
  • Éditeurs de contenu : peuvent casser des fonctionnalités sans le savoir en modifiant des pages contenant des shortcodes.

Le coût n'est pas seulement temporel ; il peut se traduire par une perte de conversions, en particulier sur les sites qui s'appuient sur des calculatrices personnalisées pour des tarifs, des estimations de prêt ou des évaluations de santé.

Ce que fait le filtre, en termes simples

  1. Détecte les guillemets droits – remplace ' et " par des versions typographiques « intelligentes ».
  2. Nettoie les esperluettes – convertit & en &amp; à moins qu'il ne forme déjà une entité HTML valide.
  3. S'applique à l'ensemble de la chaîne de contenu – y compris tout ce qui se trouve à l'intérieur des balises <script> générées par des shortcodes.

Lorsque le filtre rencontre &&, il voit deux esperluettes qui ne font pas partie d'une entité HTML existante, il échappe donc chacune d'elles individuellement, ce qui donne &#038;&#038;.

Comment arrêter la corruption

1. Désactiver le filtre pour les pages qui contiennent du code

add_action( 'template_redirect', function () {
    if ( is_page() ) {
        remove_filter( 'the_content', 'wptexturize' );
        remove_filter( 'widget_text_content', 'wptexturize' );
    }
} );

Cet extrait désactive wptexturize uniquement sur les modèles de page, préservant les améliorations typographiques pour les articles et autres types de contenu. Il supprime également le filtre du texte des widgets, qui peut être une source secondaire de scripts en ligne.

2. Réécrire la logique pour éviter &&

Si la suppression du filtre n'est pas souhaitable, refactorisez le JavaScript de manière à ce que l'opérateur logique ET ne soit pas nécessaire :

// Original
if (a && b) { … }

// Refactored
var ok = a;
if (ok) { ok = b; }
if (ok) { … }

Bien que cela ajoute quelques lignes supplémentaires, cela élimine l'esperluette qui déclenche le filtre. Cette approche fonctionne pour des conditions simples, mais peut devenir complexe pour des expressions élaborées.

3. Externaliser tous les scripts

La solution la plus robuste consiste à enfiler (enqueue) des fichiers JavaScript plutôt que d'intégrer le code en ligne :

wp_enqueue_script( 'my-calculator', get_template_directory_uri() . '/js/calculator.js', [], null, true );

Les scripts enfilés contournent entièrement les filtres de the_content. Ils bénéficient également de la mise en cache du navigateur et peuvent être minifiés ou regroupés avec d'autres ressources.

Détecter le problème sur le terrain

Lorsqu'un script cesse de s'exécuter sans erreur apparente, consultez la source de la page (et non l'inspecteur DOM) et recherchez &#038;. Si vous le trouvez à l'intérieur d'un bloc <script>, le filtre est le coupable. Le problème n'apparaîtra pas dans la console car le navigateur ne reçoit jamais de script syntaxiquement valide à analyser.

Contrepoint : pourquoi conserver wptexturize ?

wptexturize améliore la lisibilité côté client. Les guillemets incurvés et les tirets appropriés donnent à la prose un aspect soigné, et de nombreux propriétaires de sites considèrent cela comme une caractéristique esthétique non négociable. Supprimer le filtre globalement reviendrait à ramener le texte à son état brut et typographiquement simple.

Le compromis consiste en une désactivation sélective : désactivez le filtre uniquement là où se trouve le code, ou utilisez un shortcode personnalisé qui marque explicitement sa sortie comme étant protégée de la texturisation. WordPress propose déjà wp_kses_post et d'autres outils d'assainissement ; les développeurs peuvent les combiner avec des appels à remove_filter pour bénéficier du meilleur des deux mondes.

À surveiller ensuite

Le cœur de WordPress n'a pas annoncé de modification de wptexturize qui exempterait automatiquement les balises <script>. En attendant qu'un tel changement soit implémenté, les développeurs doivent protéger leur code en ligne manuellement. Gardez un œil sur le tracker de développement du cœur pour toute proposition visant à rendre le filtre sensible au contexte. En attendant, auditez tout shortcode ou élément de constructeur de page qui injecte du JavaScript et appliquez l'une des trois corrections ci-dessus.

En résumé : si votre site WordPress exécute du JavaScript en ligne, vérifiez que wptexturize ne le réécrit pas silencieusement. Une seule esperluette échappée peut rendre une fonctionnalité entière inerte, et la solution consiste généralement en quelques lignes de PHP ou en un passage à des scripts externes.