فیلتر wptexturize وردپرس به‌طور بی‌صدا در حال خراب کردن جاوااسکریپت‌های درون‌خطی (inline) است؛ این فیلتر عملگر منطقی && را به موجودیت HTML یعنی && تبدیل می‌کند و باعث از کار افتادن اسکریپت‌هایی می‌شود که داخل شورت‌کدها اجرا می‌شوند.

این مشکل برای توسعه‌دهنده‌ای که مجموعه‌ای از شورت‌کدهای (shortcodes) ماشین‌حساب را مدیریت می‌کند، خود را نشان داد. پس از هفته‌ها عملکرد بی‌نقص، دکمه‌های ارسال دیگر پاسخگو نبودند. هیچ هشدار PHP، هیچ خطای کنسولی و هیچ مشکلی در بررسی HTML دیده نمی‌شد—تا زمانی که بررسی سورس رندر شده نشان داد: if (!isNaN(bf) && bf > 0). همین یک خطای سینتکس مانع از اجرای کل بلوک اسکریپت شد.

چرا این فیلتر اهمیت دارد

وردپرس محتوای نوشته‌ها را پیش از رسیدن به مرورگر، از طریق مجموعه‌ای از فیلترها پردازش می‌کند. wptexturize اولین مورد از این فیلترهاست؛ این فیلتر کوتیشن‌های مستقیم را به کوتیشن‌های تایپوگرافیک منحنی تبدیل می‌کند، چندین خط تیره را با em-dash جایگزین می‌کند و علامت‌های ampersand را اصلاح می‌کند. این فیلتر فرض را بر این می‌گذارد که با یک متن نوشتاری سروکار دارد، نه کد. وقتی یک شورت‌کد یک تگ <script> درون‌خطی تزریق می‌کند، فیلتر همچنان اجرا می‌شود و با جاوااسکریپت مانند یک متن معمولی برخورد می‌کند. بنابراین علامت ampersand در && به &#038; تبدیل (escape) می‌شود که مرورگر آن را به جای عملگر منطقی AND، به عنوان یک رشته متنی ساده تفسیر می‌کند.

توسعه‌دهندگانی که هرگونه جاوااسکریپت را مستقیماً در محتوای نوشته‌ها قرار می‌دهند—مانند ماشین‌حساب‌ها، اعتبارسنج‌های فرم یا ویجت‌های تعاملی—در معرض این خطر هستند. این مسئله محدود به ماشین‌حساب‌ها نیست؛ هر اسکریپت درون‌خطی که از && ، & یا کاراکترهای مشابه استفاده کند، می‌تواند خراب شود. از آنجایی که این تغییر در سمت سرور رخ می‌دهد، مرورگر هرگز کد اصلی را نمی‌بیند و خطا به صورت یک استثنای (exception) معمولی در جاوااسکریپت ظاهر نمی‌شود.

چه کسانی تحت تأثیر قرار می‌گیرند و چه چیزی از دست می‌دهند

  • صاحبان سایت: یک ماشین‌حساب یا فرم خراب می‌تواند باعث ناامیدی بازدیدکنندگان، افزایش نرخ پرش (bounce rate) و کاهش اعتماد شود.
  • توسعه‌دهندگان: ساعت‌ها وقت صرف جستجو برای باگ‌های «شبح» می‌شود که هیچ اثری در لاگ‌ها یا خروجی کنسول باقی نمی‌گذارند.
  • ویرایشگران محتوا: ممکن است هنگام ویرایش صفحاتی که حاوی شورت‌کد هستند، ناآگاهانه عملکرد سایت را از کار بیندازند.

هزینه این مشکل فقط زمان نیست؛ بلکه می‌تواند منجر به از دست رفتن نرخ تبدیل (conversion) شود، به‌ویژه در سایت‌هایی که برای قیمت‌گذاری، تخمین وام یا ارزیابی‌های سلامت به ماشین‌حساب‌های سفارشی متکی هستند.

عملکرد فیلتر به زبان ساده

  1. تشخیص کوتیشن‌های مستقیم – جایگزینی ' و " با نسخه‌های تایپوگرافیک «هوشمند».
  2. پاکسازی ampersandها – تبدیل & به &amp; مگر اینکه از قبل یک موجودیت HTML معتبر باشد.
  3. اعمال بر کل رشته محتوا – شامل هر چیزی که داخل تگ‌های <script> قرار دارد و توسط شورت‌کدها تولید شده است.

وقتی فیلتر با && مواجه می‌شود، دو علامت ampersand را می‌بیند که بخشی از یک موجودیت HTML موجود نیستند، بنابراین هر کدام را به‌طور جداگانه escape می‌کند که منجر به &#038;&#038; می‌شود.

چگونه جلوی این خرابی را بگیریم

۱. غیرفعال کردن فیلتر برای صفحاتی که حاوی کد هستند

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

این قطعه کد wptexturize را فقط در قالب‌های صفحه (page templates) غیرفعال می‌کند و بهبودهای تایپوگرافیک را برای نوشته‌ها و سایر انواع محتوا حفظ می‌کند. همچنین این فیلتر را از متن ویجت‌ها حذف می‌کند، که می‌تواند منبع ثانویه اسکریپت‌های درون‌خطی باشد.

۲. بازنویسی منطق برای اجتناب از &&

اگر حذف فیلتر مطلوب نیست، جاوااسکریپت را به‌گونه‌ای بازسازی (refactor) کنید که نیازی به عملگر منطقی AND نباشد:

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

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

اگرچه این کار چند خط کد اضافه می‌کند، اما علامت ampersand را که باعث فعال شدن فیلتر می‌شود، حذف می‌کند. این روش برای شرایط ساده کار می‌کند اما می‌تواند برای عبارت‌های پیچیده دشوار شود.

۳. خارجی کردن تمام اسکریپت‌ها

مطمئن‌ترین راه حل، استفاده از enqueue برای فایل‌های جاوااسکریپت به جای قرار دادن کد به‌صورت درون‌خطی است:

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

اسکریپت‌های Enqueue شده به‌طور کامل از فیلترهای the_content عبور می‌کنند. آن‌ها همچنین از قابلیت کش مرورگر بهره می‌برند و می‌توان آن‌ها را فشرده (minify) یا با سایر دارایی‌ها (assets) ترکیب کرد.

تشخیص مشکل در محیط واقعی

وقتی اسکریپتی بدون خطاهای واضح از کار می‌افتد، سورس صفحه (نه DOM inspector) را مشاهده کرده و به دنبال &#038; بگردید. اگر آن را داخل یک بلوک <script> پیدا کردید، مقصر همان فیلتر است. این مشکل در کنسول ظاهر نمی‌شود زیرا مرورگر هرگز یک اسکریپت از نظر سینتکسی معتبر برای تجزیه (parse) دریافت نمی‌کند.

دیدگاه مقابل: چرا wptexturize را نگه داریم؟

wptexturize خوانایی را در بخش فرانت‌اند بهبود می‌بخشد. کوتیشن‌های منحنی و کاراکترهای خط تیره مناسب، به متن ظاهری صیقل‌خورده می‌دهند و بسیاری از صاحبان سایت آن را یک ویژگی زیبایی‌شناختی غیرقابل مذاکره می‌دانند. حذف کلی این فیلتر، متن را به حالت خام و از نظر تایپوگرافیک ساده بازمی‌گرداند.

راه حل میانه، غیرفعال‌سازی انتخابی است: فیلتر را فقط در جاهایی که کد قرار دارد غیرفعال کنید، یا از یک شورت‌کد سفارشی استفاده کنید که خروجی خود را به‌طور صریح به‌عنوان ایمن در برابر texturizing علامت‌گذاری کند. وردپرس از قبل wp_kses_post و سایر ابزارهای کمکی پاک‌سازی (sanitisation) را ارائه می‌دهد؛ توسعه‌دهندگان می‌توانند این‌ها را با فراخوانی‌های remove_filter ترکیب کنند تا از مزایای هر دو روش بهره‌مند شوند.

آنچه باید در ادامه دنبال کنید

هسته وردپرس تغییری در wptexturize اعلام نکرده است که تگ‌های <script> را به‌طور خودکار مستثنی کند. تا زمانی که چنین تغییری اعمال شود، توسعه‌دهندگان باید از کدهای درون‌خطی (inline code) خود به‌صورت دستی محافظت کنند. پیگیر ردیاب توسعه هسته (core development tracker) برای هرگونه پیشنهاد جهت هوشمندسازی فیلتر نسبت به زمینه (context-aware) باشید. در این میان، هر شورت‌کد یا المان صفحه‌ساز را که جاوااسکریپت تزریق می‌کند بررسی (audit) کرده و یکی از سه راه حل بالا را اعمال کنید.

خلاصه کلام: اگر سایت وردپرس شما جاوااسکریپت درون‌خطی اجرا می‌کند، بررسی کنید که wptexturize به‌طور بی‌صدا آن را بازنویسی نکند. یک علامت ampersand که escape شده باشد می‌تواند یک قابلیت کامل را از کار بیندازد، و راه حل معمولاً چند خط کد PHP یا انتقال به اسکریپت‌های خارجی است.