特定の投稿のためにアバターとユーザー名を置き換える

こんにちは、unfairestさん

この投稿を見つけて、試してみようと思いました!

最初のバージョンです。コードがあまりひどくないことを願っています。:slightly_smiling_face:
すべてのエッジケースを広範囲にテストしたわけではありません。これは出発点です。

  • 期待されるラップ形式: [wrap=character avatar=\"<URL>\” name=\"<Name>\"][/wrap]
  • [wrap] の下に空行があることを確認してください。
  • CSS でキャラクター名をカスタマイズできます (character および character-extra クラスを参照)。

何か問題があればお知らせください :slight_smile:

Head
<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;
    }
}

これはどのように見えるかの簡単なデモです: