Come aggiungere HTML personalizzato dopo "post_1"

I post sono widget, il che significa che ciò che stai cercando di fare richiederà un po’ più di lavoro rispetto alla semplice aggiunta di HTML.

I temi di Discourse hanno la possibilità di decorare i widget, quindi puoi sfruttare questa funzionalità.

La decorazione di un widget è spiegata nel link sopra; concentriamoci invece su ciò che stai cercando di fare: aggiungere del markup dopo il primo post in ogni argomento.

Inizia aggiungendo il markup a tutti i post. Qualcosa del genere:

<script type="text/discourse-plugin" version="0.8">
api.decorateWidget("post:after", helper => {
  return helper.h("div", "test text");
});
</script>

alla sezione intestazione del tuo tema. Questo dovrebbe essere sufficiente per aggiungere “test text” sotto ogni post.

Analizziamo lo script sopra:

api.decorateWidget("post:after", helper => {

chiama il metodo decorateWidget, con il widget di destinazione post e la posizione di destinazione after. Quindi, dopo un widget di post.

helper è un helper integrato che ti dà accesso a diverse funzionalità che spiegherò più avanti.

return helper.h("div", "test text")

Questo è il markup aggiuntivo desiderato che vuoi aggiungere. Potresti notare che non c’è HTML lì dentro, e questo perché i widget di Discourse emettono nodi virtuali e non HTML grezzo.

Spiegare cosa sono i nodi virtuali o come funziona la sintassi esula dagli scopi di questo argomento, quindi lo salto. Ho aggiunto una nota per scrivere una guida su come creare nodi virtuali, ma ecco intanto un paio di esempi:

helper.h("div", "test text")

restituisce

<div>test text</div>

e

return helper.h("div#custom-ad", [
  helper.h(
    "a.custom-ad-link",
    { href: "example.com" },
    helper.h("img", { src: "https://picsum.photos/id/74/750/90" })
  )
]);

restituisce

<div id="custom-ad">
  <a href="example.com" class="custom-ad-link">
    <img src="https://picsum.photos/id/74/750/90">
  </a>
</div>

In sintesi, un nodo ha questo aspetto:

helper.h(selector, {properties}, children)

Spiegherò meglio questo nella guida sui nodi virtuali.

Quindi, ora che hai i nodi pronti, devi solo aggiungere l’intero script alla sezione intestazione del tuo tema, qualcosa del genere:

<script type="text/discourse-plugin" version="0.8">
  api.decorateWidget("post:after", helper => {
    return helper.h("div#custom-ad", [
      helper.h(
        "a.custom-ad-link",
        { href: "example.com" },
        helper.h("img", { src: "https://picsum.photos/id/74/750/90" })
      )
    ]);
  });
</script>

Tuttavia, c’è ancora un problema: l’annuncio verrà inserito sotto ogni post nel flusso, il che non è ideale.

È qui che l’helper si rivela utile: gli attributi del post vengono passati all’helper, quindi puoi eseguire rapidamente:

console.log(helper)

Potrai vedere tutti gli attributi del post disponibili per il tuo lavoro.

Questi sono solo esempi, ce ne sono molti altri.

Fortunatamente, l’attributo firstPost è disponibile per noi, quindi non ti resta che inserirlo in una condizione che renderizzerà il markup dell’annuncio solo se si tratta effettivamente del primo post; altrimenti non succederà nulla. Qualcosa del genere:

<script type="text/discourse-plugin" version="0.8">
api.decorateWidget("post:after", helper => {
  const firstPost = helper.attrs.firstPost;
  const h = helper.h;
  if (firstPost) {
    return h("div#custom-ad", [
      h(
        "a.custom-ad-link",
        { href: "example.com" },
        h("img", { src: "https://picsum.photos/id/74/750/90" })
      )
    ]);
  }
});
</script>

e questo inserirà il tuo annuncio solo dopo il primo post. Un’ulteriore cosa da fare qui è aggiungere un’altezza all’immagine, altrimenti causerà sfarfallio durante il caricamento. Quindi, come accennato brevemente sopra, l’attributo height per il tag immagine è una proprietà, quindi devi aggiungerlo accanto a src.

Mettendo tutto insieme, ecco il codice finale per ciò che stai cercando di ottenere:

<script type="text/discourse-plugin" version="0.8">
api.decorateWidget("post:after", helper => {
  const firstPost = helper.attrs.firstPost;
  const h = helper.h;
  if (firstPost) {
    return h("div#custom-ad", [
      h(
        "a.custom-ad-link",
        { href: "example.com" },
        h("img", { src: "https://picsum.photos/id/74/750/90", height: "90" })
      )
    ]);
  }
});
</script>

Un’ultima nota che voglio evidenziare è che puoi effettivamente utilizzare HTML grezzo se i nodi virtuali si rivelano troppo complessi, ma non è raccomandato ed è molto meglio utilizzare i nodi virtuali. Quindi lo stesso script con HTML grezzo apparirebbe così:

<script type="text/discourse-plugin" version="0.8">
  const RawHtml = require("discourse/widgets/raw-html").default;
  api.decorateWidget("post:after", helper => {
    const firstPost = helper.attrs.firstPost;
    if (firstPost) {
      return [
        new RawHtml({
          html: `<div id="custom-ad">
                   <a href="example.com">
                     <img src="https://picsum.photos/id/74/750/90" height="90">
                   </a>
                 </div>`
        })
      ];
    }
  });
</script>

ma, ancora una volta, questo non è raccomandato.