Avatar ndern & Benutzernamen für einen bestimmten Beitrag

Das Problem: Ich möchte, dass Benutzer als Rollenspielcharaktere posten können. Ich möchte, dass sie eine Vorlage in einen Beitrag einfügen können – so etwas wie das Folgende:

[wrap="characterpost"]
[characterav]https://image.link.example.png[/characterav]
[charactername][[Character Name]][/charactername]
[/wrap]

Und dann ein Skript verwenden, damit das Bild den ursprünglichen Avatar ersetzt und der Charaktername-Themenlink vor dem Benutzernamen steht. Wenn der Beitrag beispielsweise normalerweise „Username“ lautet, möchte ich dies durch „Character Name played by Username“ ersetzen.
(„Character Name“ würde einen Link zu einem Thema mit dem Charakterbogen enthalten, hoffentlich nur unter Verwendung der Wikilinks-Themenkomponente zur einfachen Verwendung.)

Ich habe ein Beitragsskelett in ein Codepen eingefügt und konnte etwas JavaScript schreiben, das genau das tut. Als es jedoch darum ging, es in einen Beitrag-Dekorator einzufügen und es mit der API live zum Laufen zu bringen, stieß ich auf eine Wand.

Hier ist, was ich derzeit in common>header habe:

<script type="text/discourse-plugin" version="0.8">
api.decorateCookedElement(
  element => {
    
    // finde das characterpost-Tag innerhalb des Beitrags
    const characterPost = element.querySelector('[data-wrap="characterpost"]');
	
    // finde das übergeordnete Element des characterpost-Tags, das Avatar und Benutzernamen enthält
    const characterPostParent = characterPost.closest('article');
	
    // färbe es rot, um zu sehen, ob es funktioniert
    characterPostParent.style.backgroundColor = "red";
    
  },
  {
    id: 'render-character-post', onlyStream: true, afterAdopt: true
  }
);
</script>

Dies hat einen Fehler verursacht. Ist es möglich, auf die „article“-Wrapper für Beiträge mit decorateCookedElement zuzugreifen, um zum Benutzernamen und Avatar zu gelangen? Wenn nicht, wie kann ich das angehen?

4 „Gefällt mir“

Hallo, unfairest,

Ich bin auf diesen Beitrag gestoßen und dachte, ich könnte ihn ausprobieren!

Hier ist die erste Version; ich hoffe, der Code ist nicht allzu schrecklich. :slightly_smiling_face:
Ich habe nicht alle Randfälle ausgiebig getestet. Es ist ein Ausgangspunkt.

  • Erwartetes Wrap-Format: [wrap=character avatar=\"<URL>\"]<Name>[/wrap]
  • Stellen Sie sicher, dass sich unter [wrap] eine Leerzeile befindet
  • Sie können den Charakternamen mit CSS anpassen (siehe Klassen character und character-extra)

Lassen Sie mich wissen, wenn Sie Probleme haben :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', 'gespielt von'), // 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;
    }
}

Hier ist eine kleine Demo, wie es aussah:

7 „Gefällt mir“

Das ist sehr cool, danke fürs Teilen! Ich habe auch nach etwas Ähnlichem gesucht. Weißt du, ob sich das auch darauf auswirkt, wie Beiträge in der Suche erscheinen?

Gute Frage! Der Tag-Name und sein Inhalt sind Teil des Beitragsinhalts; dies könnte das Suchergebnis beeinflussen.
Ich werde etwas Saubereres versuchen, wie die Verwendung eines Modals und das Speichern in benutzerdefinierten Feldern anstelle dessen.

EDIT: Ich glaube, ich habe das missverstanden :smile: Wenn Sie von Änderungen sprechen, die im Suchergebnis erscheinen, lautet die Antwort nein (noch wird das HTML erscheinen).

2 „Gefällt mir“

Das ist ziemlich cool. Dein Video scrollt schnell. Ist die URL auf der Forum-Seite?

Hallo Dan. Was meinst du?

Die Avatar-URL. Ist das nur ein hochgeladenes Bild oder verweist es auf eine externe Website?

Dies ist eine externe URL. Es sollte möglich sein, mit einer lokalen URL zu arbeiten.

2 „Gefällt mir“

Danke, cool

1 „Gefällt mir“

Es könnte eine Idee sein, im Community-Wiki einen Leitfaden für Forenvorlagen vorzuschlagen. Da die Leute oft nach Ideen für verschiedene Arten von Foreneinrichtungen suchen. In diesem Fall könnte es etwas speziell sein. Aber eine Tabletop-RPG-Vorlage, die dieses von Ihnen erstellte Feature enthält.