Safesprite Icons؛ چرا یک افزونهٔ آیکون SVG دیگر نوشتم
تقریباً در هر پروژهٔ وردپرسی به آیکون اختصاصی میرسیم: آیکونهای برند، آیکون آیتمهای منو، آیکون کارتها. معمولاً دو راه جلوی آدم است. یکی فعالکردن آپلود SVG در کتابخانهٔ رسانه با یک افزونه، دیگری چسباندن کد خام SVG در قالب یا صفحهساز.
راه اول یعنی باز کردن دری که وردپرس عمداً بسته نگه داشته. فایل SVG در واقع XML است و میتواند اسکریپت، استایل یا ارجاع به منابع بیرونی داشته باشد. راه دوم یعنی تکرار همان کد SVG هر جایی که آیکون استفاده شده؛ یک آیکون که در منو و حلقهٔ کارتها میآید، ممکن است دهها بار در HTML صفحه تکرار شود.
Safesprite Icons را برای همین مشکل نوشتم. نسخهٔ ۱.۰.۰ آن شهریور ۱۴۰۵ در مخزن افزونههای وردپرس منتشر شد و کدش در گیتهاب هست. هنوز افزونهٔ تازهای است و کاربران زیادی ندارد؛ این نوشته بیشتر توضیح میدهد چرا و چطور ساخته شده.
چه کاری میکند#
- یک کتابخانهٔ آیکون جدا در پیشخوان میسازد که آیکونها را در مجموعهها (پوشهها) نگه میدارد. آپلود SVG فقط از همینجا ممکن است.
- آپلود SVG را در کتابخانهٔ رسانه فعال نمیکند. یعنی از نوع افزونههایی مثل Safe SVG یا SVG Support نیست.
- یک انتخابگر آیکون مشترک دارد که در بلاک گوتنبرگ، ویجت المنتور، ویرایشگر کلاسیک (TinyMCE) و آیتمهای منو کار میکند.
- برای توسعهدهندهها شورتکد
[sfsi_icon slug="my-icon"]و تابع PHPsfsi_icon()دارد. - اسم آیکون و مجموعه را میشود عوض کرد بدون اینکه اسلاگ تغییر کند، پس شورتکدها و بلاکهای قبلی خراب نمیشوند. حذف هم اول به زبالهدان میرود.
چطور کار میکند#
۱. پاکسازی هنگام آپلود#
هر فایل اول از نظر حجم بررسی میشود؛ سقف حجم در تنظیمات افزونه قابل تغییر است. بعد با کتابخانهٔ enshrined/svg-sanitize پاکسازی میشود که داخل خود افزونه قرار دارد.
بعد از آن یک مرحلهٔ دیگر هم اضافه کردم: تگهای <style>، ویژگیهای style و هر href که به یک شناسهٔ داخلی (#...) اشاره نکند حذف میشوند. در آخر یک بررسی نهایی انجام میشود که اگر هنوز چیزی مثل استایل یا لینکی به http:، data: یا javascript: در فایل مانده باشد، فایل را کلاً رد میکند. ترجیح دادم در موارد مشکوک فایل رد شود تا اینکه چیزی از زیر دست در برود.
فایلهای پاکشده در زیرپوشههایی با نام تصادفی داخل wp-content/uploads/safesprite-icons/ ذخیره میشوند و اطلاعاتشان در جدولهای اختصاصی افزونه است، نه در قالب پستتایپ.
۲. خروجی سبک با <use>#
وقتی آیکونی در صفحه استفاده میشود (از بلاک، شورتکد یا کد PHP)، خروجی آن فقط یک SVG کوچک است که به یک symbol ارجاع میدهد:
<?php echo sfsi_icon( 'my-icon', array( 'size' => 24 ) ); ?>
خروجی این کد تقریباً این است:
<svg class="sfsi-icon" viewBox="0 0 24 24" aria-hidden="true" focusable="false" style="width:24px;height:24px">
<use href="#sfsi-icon-my-icon" xlink:href="#sfsi-icon-my-icon"></use>
</svg>
اندازهٔ عددی بین ۱۶ تا ۲۵۶ پیکسل محدود میشود و رنگ یا از متن اطراف به ارث میرسد یا یک رنگ دلخواهِ پاکسازیشده است. همزمان اسلاگ آیکون در یک فهرست داخلی برای همان درخواست ثبت میشود.
۳. ساخت اسپرایتشیت در فوتر#
در هوک wp_footer، افزونه فقط آیکونهایی را که در همان صفحه ثبت شدهاند برمیدارد و برای هر کدام یک <symbol> داخل یک SVG مخفی چاپ میکند. پس هر آیکون فقط یک بار در صفحه میآید، هر چند بار هم که استفاده شده باشد.
قبل از چاپ، هش SHA-256 فایل با هشی که موقع آپلود ذخیره شده مقایسه میشود. اگر فایل روی دیسک تغییر کرده باشد، آن آیکون چاپ نمیشود.
چیزهایی که در مسیر پیش آمد#
بیشتر کار وقتی شروع شد که خواستم انتخابگر در ویرایشگرها درست کار کند. مثلاً بوم ویرایشگر المنتور اسپرایتشیت فوتر را ندارد، پس آنجا باید پیشنمایش آیکون بهصورت درونخطی نشان داده شود. یک باگ هم داشتم که با ذخیرهکردن منو، آیکونهای آیتمها پاک میشدند؛ اینها در تغییرات نسخهها ثبت شدهاند.
محدودیتها#
- در نسخهٔ فعلی فقط آیکونهای خود سایت پشتیبانی میشود و از CDN یا کتابخانههای آیکون آماده خبری نیست.
- به PHP 7.4 به بالا با افزونههای
domوlibxmlو وردپرس ۶.۰ به بالا نیاز دارد. - با حذف افزونه، دادهها بهطور پیشفرض باقی میمانند. اگر بخواهید جدولها و فایلها هم پاک شوند، باید گزینهاش را در تنظیمات روشن کنید.
اگر امتحانش کردید و مشکلی دیدید یا پیشنهادی داشتید، در گیتهاب یا انجمن پشتیبانی وردپرس بنویسید، یا مستقیم ایمیل بزنید.