WordPress’s wptexturize filter is silently mangling inline JavaScript, turning the logical && operator into the HTML entity && and breaking scripts that run inside shortcodes.
Проблема виникла у розробника, який підтримує набір шорткодів для калькуляторів. Після тижнів бездоганної роботи кнопки відправки перестали реагувати. Жодних попереджень PHP, жодних помилок у консолі, а HTML-код виглядав чистим — аж поки перегляд вихідного коду не виявив if (!isNaN(bf) && bf > 0). Одна синтаксична помилка завадила виконанню всього блоку скриптів.
Чому цей фільтр важливий
WordPress обробляє вміст дописів через серію фільтрів, перш ніж він потрапить у браузер. wptexturize — це перший із цих фільтрів; він перетворює прямі лапки на типографічні кутові лапки, замінює подвійні дефіси на довгі тире та очищує амперсанди. Фільтр припускає, що має справу з прозою, а не з кодом. Коли шорткод вставляє вбудований тег <script>, фільтр все одно запускається, сприймаючи JavaScript як звичайний текст. Тому амперсанд у && екранується до &, що браузер інтерпретує як літеральний рядок, а не логічний оператор AND.
Розробники, які вбудовують будь-який JavaScript безпосередньо у вміст допису — калькулятори, валідатори форм, інтерактивні віджети — перебувають у зоні ризику. Проблема не обмежується лише калькуляторами; будь-який вбудований скрипт, що використовує &&, & або подібні символи, може бути пошкоджений. Оскільки трансформація відбувається на стороні сервера, браузер ніколи не бачить оригінального коду, і помилка не з'являється як типовий виняток JavaScript.
Кого це стосується і що вони втрачають
- Власники сайтів: зламаний калькулятор або форма можуть роздратувати відвідувачів, збільшити показник відмов і підірвати довіру.
- Розробники: години, витрачені на пошук «примарних» багів, які не залишають слідів у логах або виводі консолі.
- Редактори контенту: можуть ненавмисно зламати функціональність під час редагування сторінок, що містять шорткоди.
Ціна — це не лише час; це може призвести до втрати конверсій, особливо на сайтах, які використовують кастомні калькулятори для розрахунку цін, оцінки кредитів або медичних показників.
Що саме робить фільтр (простими словами)
- Виявляє прямі лапки – замінює
'та"на «розумні» типографічні версії. - Очищує амперсанди – перетворює
&на&, якщо він не є частиною вже існуючої HTML-сутності. - Застосовується до всього рядка вмісту – включаючи все всередині тегів
<script>, які генеруються шорткодами.
Коли фільтр зустрічає &&, він бачить два амперсанди, які не є частиною існуючої HTML-сутності, тому екранує кожен з них окремо, що в результаті дає &&.
Як зупинити пошкодження
1. Вимкніть фільтр для сторінок, що містять код
add_action( 'template_redirect', function () {
if ( is_page() ) {
remove_filter( 'the_content', 'wptexturize' );
remove_filter( 'widget_text_content', 'wptexturize' );
}
} );
Цей фрагмент коду вимикає wptexturize лише для шаблонів сторінок, зберігаючи типографічні покращення для дописів та інших типів контенту. Він також видаляє фільтр із тексту віджетів, який може бути вторинним джерелом вбудованих скриптів.
2. Перепишіть логіку, щоб уникнути &&
Якщо видалення фільтра є небажаним, проведіть рефакторинг JavaScript так, щоб логічний оператор AND не був потрібен:
// Original
if (a && b) { … }
// Refactored
var ok = a;
if (ok) { ok = b; }
if (ok) { … }
Хоча це додає кілька зайвих рядків, це усуває амперсанд, який активує фільтр. Такий підхід працює для простих умов, але може стати громіздким для складних виразів.
3. Винесіть усі скрипти в окремі файли
Найбільш надійним рішенням є використання enqueue для JavaScript-файлів замість вбудовування коду безпосередньо в сторінку:
wp_enqueue_script( 'my-calculator', get_template_directory_uri() . '/js/calculator.js', [], null, true );
Скрипти, додані через enqueue, повністю оминають фільтри the_content. Вони також отримують переваги кешування браузером і можуть бути мініфіковані або об'єднані з іншими активами.
Як виявити проблему на практиці
Якщо скрипт перестає працювати без очевидних помилок, перегляньте вихідний код сторінки (не через інспектор DOM) і знайдіть &. Якщо ви знайдете його всередині блоку <script>, причиною є фільтр. Проблема не з'явиться в консолі, оскільки браузер ніколи не отримує синтаксично правильний скрипт для парсингу.
Контраргумент: навіщо залишати wptexturize?
wptexturize покращує читабельність на фронтенді. Кутові лапки та правильні символи тире надають прозі охайного вигляду, і багато власників сайтів вважають це важливою естетичною особливістю. Повне видалення фільтра поверне текст до його сирого, типографічно простого стану.
Компромісом є вибіркове вимкнення: вимикайте фільтр лише там, де міститься код, або використовуйте власний шорткод, який явно позначає свій вивід як такий, що не потребує текстуризації. WordPress уже надає wp_kses_post та інші допоміжні функції для санітизації; розробники можуть поєднувати їх із викликами remove_filter, щоб отримати найкраще з обох варіантів.
На що звернути увагу далі
Ядро WordPress не оголошувало про зміни в wptexturize, які б автоматично виключали теги <script>. Доки такі зміни не будуть впроваджені, розробники мають захищати свій інлайновий код вручну. Стежте за трекером розробки ядра на предмет будь-яких пропозицій щодо того, щоб зробити фільтр контекстно-залежним. Тим часом проведіть аудит будь-яких шорткодів або елементів конструкторів сторінок, які впроваджують JavaScript, і застосуйте одне з трьох вищезгаданих виправлень.
Підсумок: якщо ваш сайт на WordPress виконує інлайновий JavaScript, переконайтеся, що wptexturize не переписує його непомітно. Один лише екранований амперсанд може зробити цілу функцію непрацездатною, а виправлення зазвичай полягає у кількох рядках PHP або переході на зовнішні скрипти.
