استبدال الصورة الرمزية واسم المستخدم لمنشع معين

المشكلة: أريد أن أتمكن المستخدمين من النشر باسم شخصياتهم في لعبة الأدوار الجماعية (RPG). أود أن يكون بإمكانهم إدراج قالب في المنشور — شيء ما يشبه ما يلي:

[wrap="characterpost"]
[characterav]https://image.link.example.png[/characterav]
[charactername][[اسم الشخصية]][/charactername]
[/wrap]

ثم استخدام سكربت بحيث تُستبدل الصورة بالأفاتار الأصلي، وتُضاف رابط موضوع اسم الشخصية قبل اسم المستخدم. على سبيل المثال، إذا كان المنشور يعرض عادةً «اسم المستخدم»، فأريد استبداله بـ «اسم الشخصية، يلعبها اسم المستخدم».
(سيشمل «اسم الشخصية» رابطًا إلى موضوع يحتوي على ورقة الشخصية، آملًا في استخدام مكوّن wikilinks theme لمجرد سهولة الاستخدام.)

لقد ألصقت هيكل منشور في Codepen وتمكنت من كتابة بعض جافاسكريبت يقوم بذلك بالضبط. ومع ذلك، عندما حان وقت إضافته إلى مُزيّن المنشورات (post decorator) وجعله يعمل مباشرةً مع واجهة البرمجة (API)، اصطدمت بجدار.

إليك ما لدي حاليًا في common>header:

<script type="text/discourse-plugin" version="0.8">
api.decorateCookedElement(
  element => {
    
    // ابحث عن وسم characterpost داخل المنشور
    const characterPost = element.querySelector('[data-wrap="characterpost"]');
	
    // ابحث عن الوالد لوسم characterpost، الذي يحتوي على الأفاتار واسم المستخدم
    const characterPostParent = characterPost.closest('article');
	
    // اجعله أحمر لرؤية ما إذا كان يعمل
    characterPostParent.style.backgroundColor = "red";
    
  },
  {
    id: 'render-character-post', onlyStream: true, afterAdopt: true
  }
);
</script>

كان هذا يعرض خطأ. هل من الممكن الوصول إلى غلاف «article» للمنشورات باستخدام decorateCookedElement حتى أتمكن من الوصول إلى اسم المستخدم والأفاتار؟ وإذا لم يكن ذلك ممكنًا، فكيف يمكنني القيام بذلك؟

مرحباً، يا غير عادل،

لقد عثرت على هذا المنشور، واعتقدت أنني أستطيع تجربته!

إليك الإصدار الأول؛ آمل ألا يكون الكود فظيعًا جدًا. :slightly_smiling_face:
لم أختبر جميع الحالات الطرفية بشكل شامل. إنها نقطة انطلاق.

  • التنسيق المتوقع للغلاف: [wrap=character avatar=\"<URL>\"]<Name>[/wrap]
  • تأكد من وجود سطر فارغ أسفل [wrap]
  • يمكنك تخصيص اسم الشخصية باستخدام CSS (انظر فئات character و character-extra)

أخبرني إذا واجهت أي مشاكل :slight_smile:

الرأس
<script type="text/discourse-plugin" version="0.8.13">

let characters = new Map();

function searchTag(obj, tag) {
  if (!obj || !obj.firstObject) return;
  
  const firstObj = obj.firstObject;
  return firstObj.tagName === tag ? firstObj : searchTag(firstObj.children, tag);
}
            
api.addPostTransformCallback(post => 
{
    if (post.post_number <= 1 || post.post_type !== 1) {
        return;
    }

    const matches = post.cooked.match(/data-wrap="character"\s+data-avatar="(?<avatar>[^"]+)"\s+data-name="(?<name>[^"]+)"/i);
    
    if (!matches) {
        characters.delete(post.id);
        return;
    }
    
    // TODO: sanity check for avatar/name
    
    const {name, avatar} = matches.groups;
    
    characters.set(post.id, {name, avatar});
    
});

api.reopenWidget("post-avatar", {
    html(attrs) {
        const html = this._super(attrs);
        
        if (attrs.id && characters.has(attrs.id)) {
            const imageHtml = searchTag(html, 'IMG');
    
            if (imageHtml) {
                imageHtml.properties.attributes.src = characters.get(attrs.id).avatar;
            }
        }
        
        return html;
    }
});

api.reopenWidget("poster-name", {
    html(attrs) {
        let html = this._super(attrs);
        
        if (attrs.id && characters.has(attrs.id)) {
            const h = require("virtual-dom").h;
            
            html = [
                h('span.character', this.userLink(attrs, characters.get(attrs.id).name)),
                h('span.character-extra', 'played by'), // optional
                ...html
            ];
        }
        
        return html;
    }
});

</script>
CSS
.names {
    .character a {
        font-weight: bold;
        color: var(--tertiary-high);
    }
    
    .character-extra {
        
    }
}

.cooked, .d-editor-preview {
    p:has(> [data-wrap="character"]) {
        display: none;
    }
    
    p:has(> [data-wrap="character"]) + * {
        margin-top: 0;
    }
}

إليك عرض توضيحي صغير لكيف بدا الأمر:

هذا رائع جدًا، شكرًا لك على المشاركة! كنت أبحث عن شيء مشابه أيضًا. هل تعرف ما إذا كان هذا يؤثر على كيفية ظهور المنشورات في البحث أيضًا؟

سؤال جيد! اسم العلامة ومحتواها جزء من محتوى المنشور؛ قد يؤثر هذا على نتيجة البحث.
سأجرب شيئًا أنظف، مثل استخدام نافذة منبثقة والحفظ في حقول مخصصة بدلاً من ذلك.

تعديل: أعتقد أنني أسأت الفهم :ابتسامة: إذا كنت تتحدث عن ظهور التغييرات في نتيجة البحث، فالإجابة هي لا (ولن يظهر كود HTML أيضًا).

هذا رائع جداً. الفيديو الخاص بك يمر بسرعة. هل الرابط موجود على موقع المنتدى؟

يا دان. ماذا تقصد؟

عنوان الصورة الرمزية. هل هو مجرد صورة تم تحميلها أم يشير إلى موقع خارجي؟

هذا عنوان URL خارجي. يجب أن يكون من الممكن العمل مع عنوان URL محلي.

شكرا لك

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