تضمين عنصر واجهة مستخدم ضمن نص في موضوع

مرحباً!! :slight_smile:

آمل أن يكون هذا مفيداً لشخص آخر: أحاول إنشاء موضوع “تغذية وسائل التواصل الاجتماعي”، حيث أريد تضمين أدوات واجهة المستخدم (widgets) لمنصات مختلفة حتى يتمكن المستخدمون (والمشرفون!) من الاطلاع عليها جميعاً بسرعة في صفحة واحدة، مما يسمح لهم بالبقاء داخل المنتدى، ويتجنب الحمل الزائد الناتج عن التبديل بين العديد من منصات التواصل الاجتماعي للحصول على تحديثات سريعة (مع الأخذ في الاعتبار أنها غالباً ما تشارك نفس المحتوى)، وبالتالي زيادة الدافع لاستخدام المنتدى كمركز لتطوير المجتمع.

وجدت أداة جيدة لتوليد الواجهات تسمى Woxo، وهي نظيفة وبسيطة بما يكفي لهذا الغرض. المشكلة الآن هي أنني غير قادر على معرفة كيفية تضمين الأداة في الموضوع. أحاول البحث عن حل بديل باستخدام إطارات مضمنة (iframes) أو شيء مشابه، لكنني أردت الآن السؤال لمعرفة ما إذا كان ذلك ممكناً أصلاً.

هذا هو الكود الذي أحصل عليه من Woxo لتغذية إنستغرام:

<div data-mc-src="f4b43a8f-c188-4f80-8206-36d9f7529f13#instagram"></div>
        
<script 
  src="https://cdn2.woxo.tech/a.js#616348fb53c1e8001686c619" 
  async data-usrc>
</script>

ما جربته حتى الآن:

  • وضع <script> في قسم <body>، <footer> و <header> (تركتها في الرأس)
  • التأكد من أن عنوان URL الذي يأتي منه السكربت مدرج في القائمة البيضاء (https://cdn2.woxo.tech/ في هذه الحالة)
  • إضافة defer لم تُجدِ نفعاً (أحتفظ بها احتياطياً)

إذا قمت بفحص الصفحة، يظهر السكربت في أسفل قسم الجسم (داخله)، وبما أن المصدر مدرج في القائمة البيضاء، فيجب أن يعمل. تحققت مما إذا كانت المشكلة من متصفحي، لكن إذا نفذت HTML هنا W3Schools Tryit Editor فإنه يعمل بشكل مثالي.

لقد ضيقت نطاق الخطأ إلى دالة محددة داخل ملف الجافا سكريبت. الاستدعاء التالي يعيد قيمة فارغة (null). هذا هو خطأ وقت التشغيل الوحيد:

e=document.querySelector("div[data-mc-src]")
e is null

هذا العنصر div مكتوب في الموضوع (جزء <div data-mc-src="f4b43a8f-c188-4f80-8206-36d9f7529f13#instagram"></div>). يبقى ككود HTML خالص، لذا يجب أن يكون قابلاً للقراءة. لسبب ما، يفشل السكربت في العثور عليه.

مع سمة defer، ومع وجود السكربت في التذييل، لا يطرح السكربت أي خطأ (حقيقة أنه طرح خطأ من قبل تثبت أن عنوان URL لملف الجافا سكريبت مدرج بالفعل في القائمة البيضاء)، لذا فأنا الآن في حيرة من أمري حول سبب عدم فعله لأي شيء.

أي مدخلات ستكون موضع تقدير كبير، شكراً لكم على وقتكم مقدماً! :slight_smile:
ليساندرو

تعديل: في النهاية اضطررت للتخلي عن الفكرة. بما أن الإطارات المضمنة (iframes) فقط هي المدعومة، أنا حالياً أبحث عن خدمة ويب جيدة يمكنها توفير واحدة. معظم الخدمات المجانية محدودة للغاية، والإصدارات المدفوعة تكلف أكثر من ضعف تكلفة استضافة المنتدى. آسف على الشكوى، كان لا بد لي من البكاء بصوت عالٍ هنا لعدم قدرتي على مجرد إدراج كود HTML المجاني :cry:

إعجابَين (2)

Discourse هو تطبيق صفحة واحدة. المشكلة التي تواجهها تحدث لأن السكربت الذي تستخدمه غير مدرك لذلك. عندما تزور الصفحة الرئيسية - أو أي صفحة أخرى - في Discourse، ستحصل على شيء مثل هذا.

<html>
  <head>
    محتوى الرأس بما في ذلك السكربت الخاص بك
  </head>
  <body>
    <section id="main">
      محتوى الصفحة
    </section>
  </body>
</html>

عند التنقل إلى صفحة أخرى، فإن الشيء الوحيد الذي يتم إعادة تحميله هو المحتوى داخل

<section id="main">

لذلك، تغيرت بنية DOM، ولا يعمل السكربت المخصص مرة أخرى. إذا حاولت زيارة صفحة الموضوع مباشرة، فسترى أنها تُحمّل بشكل صحيح.

.

إذن، السؤال الآن هو كيفية جعلها تعمل مع Discourse.

يحتوي plugin-api على طريقة يمكنك استخدامها لـ “تزيين” المنشورات.

https://github.com/discourse/discourse/blob/main/app/assets/javascripts/discourse/app/lib/plugin-api.js#L282-L318

يمكنك استخدام ذلك لتشغيل سكربتات جهات خارجية عند عرض منشور.

إليك الكود الذي ستحتاجه. أضف هذا إلى تبويب common > header في سمةك.

<script type="text/discourse-plugin" version="0.8">
const WOXO_SCRIPT_SRC = "https://cdn2.woxo.tech/a.js#616348fb53c1e8001686c619";
const PREVIEW_ICON = "heart";

const loadScript = require("discourse/lib/load-script").default;
const { iconHTML } = require("discourse-common/lib/icon-library");

const composerPreviewIcon = iconHTML(PREVIEW_ICON, {
  class: "woxo-preview-icon"
});

const previewMarkup = () => {
  const markup = `<div class="woxo-preview">${composerPreviewIcon}</div>`;
  return markup;
};

// إنشاء مُزيّن للمنشورات
api.decorateCookedElement(
  post => {
    const woxoWidgets = post.querySelectorAll("div[data-mc-src]");

    if (woxoWidgets.length) {
      woxoWidgets.forEach(woxoWidget => {
        if (post.classList.contains("d-editor-preview")) {
          woxoWidget.innerHTML = previewMarkup();
          return;
        }

        loadScript(WOXO_SCRIPT_SRC).then(() => {
          const script = document.head.querySelector(
            `script[src*="cdn2.woxo.tech"]`
          );
          script.dataset.usrc = "";
          window.MC.Loader.init();
        });
      });
    }
  },
  { id: "render-woxo-widgets" }
);
</script>

ثم ستحتاج إلى إضافة بعض النطاقات لـ CSP. أضف هذه إلى إعداد موقعك

content_security_policy_script_src
https://*.woxo.tech/
https://us-central1-core-period-259421.cloudfunctions.net/availableComponentTracks

أخيرًا، ستحتاج إلى إضافة قليل من CSS للعرض الثابت في المحرر

يذهب هذا إلى تبويب common > CSS في سمةك.

.woxo-preview {
  height: 400px;
  width: 100%;
  background: var(--primary-low);
  display: flex;
  align-items: center;
  justify-content: center;
  .woxo-preview-icon {
    font-size: var(--font-up-4);
    color: var(--primary-high);
  }
}

ثم يمكنك فقط إضافة

<div data-mc-src="f4b43a8f-c188-4f80-8206-36d9f7529f13#instagram"></div>

إلى أي منشور، وستتم تصيير الودجات وستعمل بكامل طاقتها.

إذا نظرت إلى JavaScript، فستلاحظ أن لديه خيارين في الأعلى تمامًا.

const WOXO_SCRIPT_SRC = "https://cdn2.woxo.tech/a.js#616348fb53c1e8001686c619";
const PREVIEW_ICON = "heart";

غيّر WOXO_SCRIPT_SRC إلى المصدر الذي يقدمه لك woxo. يجب أن يكون نفسه لجميع التضمينات التي تنشئها.

غيّر PREVIEW_ICON إلى اسم الأيقونة التي تريد استخدامها في معاينة المحرر. تشغيل هذا الكود في المحرر مكلف بعض الشيء، لذا يحتوي المحرر على معاينة ثابتة تبدو مثل هذا.

ستظهر الأيقونة التي تختارها في المنتصف.

إليك نسخة مُعلّقة من الكود إذا أردت متابعة ما يحدث

الكود المعلق
<script type="text/discourse-plugin" version="0.8">
// الخيارات
const WOXO_SCRIPT_SRC = "https://cdn2.woxo.tech/a.js#616348fb53c1e8001686c619";
const PREVIEW_ICON = "heart";

// نستخدم مكتبة تحميل السكربت في Discourse لضمان تحميل السكربتات بشكل صحيح. لا تقلق، فهي ذكية بما يكفي لعدم تكرار السكربت إذا كان محمّلًا بالفعل
const loadScript = require("discourse/lib/load-script").default;

// نحمّل دالة HTML للأيقونة في Discourse للحصول على SVG للأيقونة التي نريد استخدامها في معاينة المحرر الثابتة
const { iconHTML } = require("discourse-common/lib/icon-library");

// إعداد أيقونة معاينة المحرر
const composerPreviewIcon = iconHTML(PREVIEW_ICON, {
  class: "woxo-preview-icon"
});

// إنشاء دالة مساعدة لمحتوى معاينة المحرر
const previewMarkup = () => {
  const markup = `<div class="woxo-preview">${composerPreviewIcon}</div>`;

  return markup;
};

// إنشاء مُزيّن للمنشورات
api.decorateCookedElement(
  post => {
    // هل يحتوي هذا المنشور على ودجات woxo؟
    const woxoWidgets = post.querySelectorAll("div[data-mc-src]");

    // نعم، إذن دعنا نقوم ببعض العمل.
    if (woxoWidgets.length) {
      // لكل ودجة woxo
      woxoWidgets.forEach(woxoWidget => {
        // إذا كانت ودجة في المحرر، استبدلها بمعاينة ثابتة واخرج مبكرًا
        if (post.classList.contains("d-editor-preview")) {
          woxoWidget.innerHTML = previewMarkup();
          return;
        }

        // إذا لم تكن في المحرر، حمّل سكربت woxo.
        loadScript(WOXO_SCRIPT_SRC).then(() => {
          // سكربت woxo غريب جدًا. لن يعمل إلا إذا كان وسم السكربت يحتوي على سمة data-usrc فارغة. لذا، دعنا نضيفها
          const script = document.head.querySelector(
            `script[src*="cdn2.woxo.tech"]`
          );
          script.dataset.usrc = "";

          // كل شيء جاهز، دعنا نستدعي دالة init في سكربت woxo
          window.MC.Loader.init();
        });
      });
    }
  },
  // أضف معرفًا للمُزيّن لتجنب تسرب الذاكرة
  { id: "render-woxo-widgets" }
);

</script>
3 إعجابات

أولاً: يا إلهي، شكرًا جزيلاً جداً :exploding_head:
أنا مذهول من مستوى الاستجابة، والوحيد الذي يواسيني عند رؤية هذا القدر من العمل هو أنه من المؤكد أن هذا سيكون ذا فائدة كبيرة للكثيرين. هذا يفتح العديد من الاحتمالات الجديدة، وكلها لصالح تطوير المنتدى كمركز للمجتمع.

ثانياً: أنا آسف جداً على التأخر في الرد لأنك أجبت بسرعة. أولاً لم أتمكن من الوصول إلى حاسوبي في وقت أبكر، وثانياً أردت أن أرد فقط بعد أن انتهيت بالفعل من مراجعة الكود الذي قمت بشرحه بلطف (سطراً بسطر :flushed:، يا إلهي، شكرًا جزيلاً لك). بالطبع، عمل كل شيء بشكل مثالي، ويحمّل البث بأكمله بسرعة كبيرة… أنا مدين لك :pray:

شكرًا مرة أخرى يوهان، آمل حقًا أن أتمكن من المساهمة من جهتي بخبرتي الخاصة :pray:

ملاحظة: سأحتفظ بالقلب للمعاينة الثابتة تمامًا.

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

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.