استبدال أيقونات SVG الافتراضية في Discourse بأيقونات مخصصة داخل السمة

يمكنك استبدال أيقونات SVG الافتراضية في Discourse بشكل فردي أو كحزمة كاملة بأيقونات SVG مخصصة لك، وتجاوزها داخل سمة أو مكوّن سمة.

الخطوة 1 - إنشاء ورقة رموز SVG (SVG Spritesheet)

للبداية، يجب عليك إنشاء ورقة رموز SVG. يمكن أن تحتوي هذه الورقة على أي شيء، بدءًا من أيقونة SVG مخصصة واحدة إضافية وصولاً إلى مجموعة كاملة من الاستبدالات المكونة من مئات الأيقونات.

يجب حفظ ورقة الرموز كملف SVG. من حيث المبدأ، تقوم بتضمين محتوى وسم <svg> من ملف أيقونة SVG الأصلي داخل وسوم <symbol> ومنحها معرّفًا (identifier) مناسبًا.

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="my-theme-icon-1">
    <!--
      الكود الموجود داخل وسم <svg> من ملف أيقونة SVG المصدر
      هذا عادةً كل ما بين وسوم <svg>
      (وليس وسم SVG نفسه، حيث يتم استبداله بـ <symbol> أعلاه)
      يمكنك نقل أي سمات (مثل ViewBox="0 0 0 0") إلى وسم <symbol>
      -->
  </symbol>

  <symbol id="my-theme-icon-2">
    <!-- كود SVG هنا. أضف المزيد من كتل <symbol> حسب الحاجة.
      -->
  </symbol>
</svg>
  • تأكد من إضافة معرّف مخصص (ID) لكل رمز في ورقة الرموز. من المفيد على الأرجح لسلامتك العقلية أن تضع بادئة (prefix) لمعرّفاتك باسم سمتك my-theme-icon.

  • لجعل لون الأيقونة ديناميكيًا مثل الأيقونات الموجودة، اضبط التعبئة (fill) على currentColor بدلاً من لون ثابت (مثل #333)

  • لتكبير أو تصغير أيقونتك أو توسيطها بشكل صحيح، استخدم سمة viewBox على وسم <symbol>. راجع How to Scale SVG | CSS-Tricks لمزيد من المعلومات.

  • كن حذرًا من تعارضات الأنماط (style collisions) داخل ملفات SVG الخاصة بك. على سبيل المثال، غالبًا ما تحتوي ملفات SVG على نمط مضمن مثل .st0{fill:#FF0000;}. إذا كان لديك عدة ملفات SVG تستخدم نفس الفئات، فقد يسبب ذلك مشاكل (لمعالجة هذه المشاكل، عدّل الفئات لتكون فريدة لكل أيقونة).

  • إذا كان لديك العديد من الأيقونات، فهناك طرق لأتمتة هذه العملية. https://www.npmjs.com/package/svg-sprite-generator هو أداة سطر أوامر بسيطة لدمج ملفات SVG في ورقة رموز.

مثال - ورقة رموز لأيقونة مخصصة واحدة

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
  <symbol id="bat-icon" viewBox="6 6 36 36">
    <path
      fill="currentColor"
      d="M24,18.2c0.7,0,0.9,0.2,0.9,0.2l0.4-1.7c0,0,0.4,1.5,0.4,2.8c0.2,1.1,2.2,0.4,3.9,0C31.4,19.1,32,16,32,16h16c0,0-9.4,3.5-7,10c0,0-14.8-2-17,7l0,0c-2.2-9-17-7-17-7c2.4-6.5-7-10-7-10h16c0,0,0.6,3.1,2.3,3.5c1.7,0.4,3.9,1.1,3.9,0c0.2-1.1,0.4-2.8,0.4-2.8l0.4,1.7C23.1,18.4,23.4,18.2,24,18.2L24,18.2L24,18.2z"
    />
  </symbol>
</svg>

الخطوة 2 - إضافة ورقة الرموز إلى سمتك

بمجرد بناء ورقة الرموز، تحتاج إلى إضافة ملف SVG إلى مكوّنك/سمتك. هذا سهل من خلال واجهة المستخدم (UI)، أو يمكنك ترميزه يدويًا في مكوّن/سمة.

:information_source: بمجرد رفعه إلى أي مكوّن/سمة مثبّت، يصبح متاحًا في جميع أنحاء مثيلتك باستخدام المعرّف الموجود في وسم <symbol>.

من خلال واجهة المستخدم (UI)

انتقل إلى قسم الرفع (Uploads) في إعدادات السمة/المكوّن وأضف ملف الـ sprite الخاص بك مع اسم متغير SCSS هو icons-sprite:

الترميز اليدوي في سمة / مكوّن

أضف ملف ورقة الرموز إلى مجلد /assets الخاص بالسمة. ثم حدّث ملف assets.json في المجلد الجذر.
لأيقونة SVG تسمى my-icons.svg، يجب أن يتضمن ملف about.json الخاص بك ما يلي:

"assets": {
  "icons-sprite": "/assets/my-icons.svg"
}

الخطوة 3 (اختياري) - تجاوز الأيقونات الافتراضية

الآن بعد ضبط ورقة الرموز، يمكنك إخبار Discourse باستبدال الأيقونات. إليك الطريقة للقيام بذلك من مهيئ API (api-initializer):

// {theme}/javascripts/discourse/api-initializers/init-theme.gjs

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  api.replaceIcon("bars", "my-theme-icon-bars");
  api.replaceIcon("link", "my-theme-icon-link");
  // إلخ.
});

المعرّف الأول، bars، هو معرّف الأيقونة الافتراضية في Discourse، والثاني هو معرّف أيقونة الاستبدال الخاصة بك. أسهل طريقة لإيجاد معرّف إحدى أيقوناتنا هو فحص الأيقونة في متصفحك.

هنا يتبع اسم الأيقونة بادئة d-icon-. لذا في هذا المثال هو d-unliked

تتبع معظم أيقوناتنا أسماء الأيقونات من https://fontawesome.com/، لكن هناك استثناءات (وهذا هو السبب في أن التحقق من المعرّف في أداة الفحص هو الطريقة الأكثر موثوقية). يمكنك رؤية جميع الاستثناءات في كتلة const REPLACEMENTS هنا على github.

هذا كل شيء. يمكنك الآن تنسيق Discourse بأيقونات مخصصة لك!


هذا المستند يخضع للتحكم في الإصدارات - اقترح تغييرات على github.

58 إعجابًا

كيف يمكن استهداف أيقونة معينة في عنصر معين؟ في حالتي، أود استبدال أيقونة المستندات في قائمة الشريط الجانبي بأيقونة FA أخرى.

إعجاب واحد (1)

سأقوم بإخفائه باستخدام CSS وإضافة زر جديد له.

Common / CSS

.sidebar-section-wrapper {
  li[data-list-item-name=docs] {
    display: none !important;
  }
}

أضف زرًا جديدًا في المزيد > تخصيص هذا القسم

4 إعجابات

هذا لا يعمل. حاولت القيام بـ:

<script type="text/discourse-plugin" version="0.8">
    api.replaceIcon("shield-halved", "hat-wizard");
</script>

من هنا، ولكن يبدو أنه لا يعمل. أعتقد أن طريقة وسم النص البرمجي معطلة، لأن هذا لا يعمل مع رابط المعاينة. بصراحة لست متأكدًا.

إعجاب واحد (1)

يعمل معي :woman_shrugging:t2:


هل تضعه في علامة التبويب head؟ لقد قمت أيضًا باستبدال الروبوت في الرأس الخاص بي:

قد تحتاج إلى إضافة الأيقونة إلى إعداد SVG icon subset الخاص بالمسؤول.

إعجابَين (2)

[اقتباس=“Lilly، المشاركة: 40، الموضوع: 115736”]
هل تضعها في علامة تبويب الرأس؟
[/اقتباس]

نعم، علامة تبويب الرأس. وعلامة تبويب الرأس (header tab)، لأن الدليل يقول ذلك.

[اقتباس=“Lilly، المشاركة: 40، الموضوع: 115736”]
SVG icon subset
[/اقتباس]
تم. إنه يعمل الآن. شكرا!

إعجاب واحد (1)

@NateDhaliwal هل يمكنك مراسلتي من فضلك؟ أحتاج إلى مساعدة في شيء ما ولا أرى خيار دردشة في ملفك الشخصي. شكراً لك!

إعجاب واحد (1)
بالنسبة للقائمة اليسرى، نعيد تعريف خلفية العنصر بفئة prefix-span داخل فئة Audi */
.navigation-category [data-category-id="6"] .prefix-span {
  background: url("https://raw.githubusercontent.com/tima4502/car-icons/bb0d0fae3e5b66c512a27a130b219ec0ee342ada/audi.svg") center/contain no-repeat !important;

عندما أنقر على الصفحة الرئيسية، يظهر الرمز المربع مرة أخرى! هل يمكنك إخباري بما أفعله بشكل خاطئ؟ وعلى صفحة الفئة نفسها، يعمل الأمر.

مرحباً، هل يمكن لأي شخص توضيح العلاقة بين اسم السمة/المكون، واسم الملف، واسم متغير SCSS، ومعرف الرمز…؟

أحاول استبدال أيقونة المشرف shield-halved بأيقونة خاصة بنا، لكن التعليمات غير واضحة بعض الشيء.

في الخطوة 2:

  • لقطة الشاشة “عبر واجهة المستخدم” تعرض اسم ملف baticonsprite.svg مع اسم متغير SCSS icons-sprite
  • ولكن بعد ذلك في “التشفير الثابت في سمة”، تخبرك بتشفيره الثابت في سمة/مكون
  • ولكن كيف؟ لا أرى ملف assets.json في المحرر. إذا قمت بتصدير المكون، أرى about.json، والذي يعرض الـ sprite الذي قمت بتحميله عبر واجهة المستخدم
  • ولكن هذا المثال يعرض أيضًا اسم ملف مختلف /assets/my-icons.svg - هل المقصود أن يكون هذا هو نفس ملف baticonsprite.svg؟
  • هل هذان طريقتان بديلتان للقيام بنفس الشيء، وتحتاج فقط إلى القيام بواحد أو الآخر، وليس كليهما…؟

في الخطوة 3:

  • ولكن الآن، في api.replaceIcon(), المعامل الثاني لا يستخدم أيًا من المعرفات السابقة، لا icons-sprite أو bat-icon أو baticonsprite.svg أو my-icons.svg. بدلاً من ذلك، نحصل على my-theme-icon-bars جديد تمامًا… مرتبك.
  • هل البادئة my-theme مطلوبة، وإذا كان الأمر كذلك، فمن أين يأتي هذا السلسلة “اسم السمة”؟ مثل هل يجب أن يكون my-theme-bat-icon؟ وماذا لو كان مكونًا، وليس سمة؟
  • وبالنسبة لجزء icon-bars، هل يجب أن يكون:
    • معرف الرمز من XML الخاص بـ SVG spritesheet
    • اسم ملف ملف SVG
    • اسم متغير SCSS الذي تعطيه له
    • مزيج من ما سبق (مثل icons-sprite-bat-icon؟)

وأين تضع فعليًا استدعاء api.replaceIcon()؟ هل من المقبول وضعه في علامة التبويب “JS” لمكون مخصص، والذي يحتوي بالفعل على الكود الأساسي:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
   // your code here
});

أم أنه من الضروري إنشاء علامة <script type=”discourse/plugin”> مخصصة ووضعها في علامة التبويب <head> بدلاً من ذلك؟


آسف لهذا الارتباك.

لقد جربت عدة مجموعات مما سبق ولم أتمكن من عرض الـ sprite الخاص بي مهما حاولت…

ملف XML الخاص بالـ sprite الخاص بي يبدو كالتالي:

<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">


<symbol id="my-logo" viewBox="0 0 94.652 95.261"><defs><linearGradient id="a" y1="47.631" x2="94.652" y2="47.631" gradientUnits="userSpaceOnUse"><stop offset="0" stop-color="#ff593d"/><stop offset="1" stop-color="#ff7751"/></linearGradient></defs><title>d_only</title><path d="M47.326,0H0V95.261H47.326c23.67,0,47.326-21.326,47.326-47.624S71,0,47.326,0Zm0,69.274a21.644,21.644,0,1,1,21.65-21.637A21.635,21.635,0,0,1,47.326,69.274Z" fill="url(#a)"/></symbol>

</svg>

اسم الملف هو my-logo.svg واسم متغير SCSS هو أيضًا my-logo

وفي علامة التبويب “JS” للمكون المخصص، لدي:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
    api.replaceIcon("shield-halved", "my-logo")
});

ولكن لا يبدو أن شيئًا ما يظهر. هل هناك خطوة فاتنيها، أو نوع من استيفاء السلسلة السحري الذي أسأت فهمه…؟

إعجاب واحد (1)

هل تمكن أي شخص من حل هذه المشكلة؟ ما زلت أعاني مع هذا…

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
    api.replaceIcon("shield-halved", "my-logo")
});

لست متأكدًا من أين يأتي المعرّف الثاني (“my-logo”) إذا قمت بتحميل الملف عبر واجهة المستخدم:

لا يعمل كل من $my-logo، و$test، وmy-logo.svg، أو عنوان URL المطلق لملف SVG على القرص، وما إلى ذلك. يتم استبدال الدرع، ولكن لا شيء محله. يصبح SVG مجرد <use href=”#my-logo”> فارغ بدون محتويات.

إعجاب واحد (1)

أخيرًا اكتشفت الأمر (شكرًا لك، كلود)!

إذًا:

  1. لا يهم اسم ملف SVG.

  2. داخل ورقة سبرايت SVG، فإن مُعرِّف الرمز (id) هو ما يحدد اسم الأيقونة النهائي، مثل <symbol id=”my-logo” …>

  3. ولكن يجب أن يكون اسم متغير SCSS بالضبط icons-sprite، وليس له علاقة بمعرِّفات ورقة السبرايت النهائية:

  4. بعد التحميل، سيبدو الأمر كما يلي:


    (لاحظ أنه لا يوجد أثر لاسم ورقة السبرايت / المتغير. يجب أن يكون بالضبط $icons-sprite، مع إضافة علامة الدولار $ تلقائيًا وعدم إدخالها في الخطوة السابقة)

  5. ثم، أخيرًا، في علامة التبويب “JS” في السمة (وليس في <head>)، هذا هو المكان الذي تستخدم فيه مُعرِّف ورقة السبرايت من الخطوة 1:

    import { apiInitializer } from “discourse/lib/api”;
    
    export default apiInitializer((api) => {
    api.replaceIcon(“shield-halved”, “my-logo”)
    });
    

لذا يجب أن يكون اسم متغير SCSS بالضبط icons-sprite، ولا يهم اسم الملف، ويتم تحديد اسم أيقونة API بواسطة مُعرِّف الرمز داخل ورقة السبرايت.

3 إعجابات