Incorpora widget nel testo di un argomento

Discourse è un’applicazione a pagina singola. Il problema che stai riscontrando si verifica perché lo script che stai utilizzando non ne è a conoscenza. Quando visiti la home page o qualsiasi altra pagina in Discourse, ottieni qualcosa di simile a questo.

<html>
  <head>
    contenuto dell'head, incluso il tuo script
  </head>
  <body>
    <section id="main">
      contenuto della pagina
    </section>
  </body>
</html>

Quando navighi verso un’altra pagina, l’unica cosa che viene ricaricata è il contenuto all’interno di

<section id="main">

Quindi, il DOM è cambiato e il tuo script personalizzato non viene eseguito nuovamente. Se provi a visitare direttamente la pagina dell’argomento, vedrai che si carica correttamente.

.

Ora la domanda è: come farlo funzionare con Discourse?

Il plugin-api ha un metodo che puoi utilizzare per “decorare” i post.

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

Puoi usarlo per eseguire script di terze parti quando un post viene renderizzato.

Ecco il codice di cui hai bisogno. Aggiungi questo alla scheda common > header del tuo tema.

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

// crea un decoratore per i post
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>

Dovrai quindi aggiungere un paio di domini per CSP. Aggiungi questi alla tua

content_security_policy_script_src

impostazione del sito

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

Infine, dovrai aggiungere un po’ di CSS per l’anteprima statica del compositore.

Questo va nella scheda common > CSS del tuo tema.

.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);
  }
}

Poi puoi semplicemente aggiungere

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

a qualsiasi post e i widget verranno renderizzati e saranno pienamente funzionali.

Se osservi il JavaScript, noterai che ha due opzioni in cima.

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

Modifica WOXO_SCRIPT_SRC con l’URL fornito da Woxo. Dovrebbe essere lo stesso per tutti gli embed che crei.

Modifica PREVIEW_ICON con il nome dell’icona che desideri utilizzare nell’anteprima del compositore. L’esecuzione di questo codice nel compositore è piuttosto costosa, quindi il compositore ha un’anteprima statica che appare così.

L’icona che scegli verrà visualizzata al centro.

Ecco una copia commentata del codice, se vuoi seguire passo passo cosa sta accadendo.

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

// utilizziamo la libreria Discourse Load script per garantire che gli script
// vengano caricati correttamente. Non preoccuparti, è abbastanza intelligente
// da non duplicare lo script se è già stato caricato
const loadScript = require("discourse/lib/load-script").default;

// carichiamo la funzione HTML delle icone di Discourse per ottenere l'SVG dell'icona
// che vogliamo usare nell'anteprima statica del compositore
const { iconHTML } = require("discourse-common/lib/icon-library");

// impostiamo l'icona dell'anteprima del compositore
const composerPreviewIcon = iconHTML(PREVIEW_ICON, {
  class: "woxo-preview-icon"
});

// creiamo una funzione di supporto per il markup dell'anteprima del compositore
const previewMarkup = () => {
  const markup = `<div class="woxo-preview">${composerPreviewIcon}</div>`;

  return markup;
};

// creiamo un decoratore per i post
api.decorateCookedElement(
  post => {
    // questo post contiene widget Woxo?
    const woxoWidgets = post.querySelectorAll("div[data-mc-src]");

    // Sì, quindi procediamo con alcune operazioni.
    if (woxoWidgets.length) {
      // per ogni widget Woxo
      woxoWidgets.forEach(woxoWidget => {
        // se si tratta di un widget del compositore, sostituiscilo con un'anteprima statica e
        // esci subito
        if (post.classList.contains("d-editor-preview")) {
          woxoWidget.innerHTML = previewMarkup();
          return;
        }

        // se non è nel compositore, carica lo script Woxo.
        loadScript(WOXO_SCRIPT_SRC).then(() => {
          // Lo script Woxo è molto particolare. Non funzionerà a meno che il tag script
          // non abbia un attributo data-usrc vuoto. Quindi aggiungiamolo
          const script = document.head.querySelector(
            `script[src*="cdn2.woxo.tech"]`
          );
          script.dataset.usrc = "";

          // tutto è pronto, chiamiamo il metodo init nello script Woxo
          window.MC.Loader.init();
        });
      });
    }
  },
  // aggiungiamo un ID al decoratore per evitare perdite di memoria
  { id: "render-woxo-widgets" }
);

</script>
3 Mi Piace