Inserir widget dentro do texto em um tópico

O Discourse é um aplicativo de página única. O problema que você está enfrentando ocorre porque o script que você está usando não está ciente disso. Quando você visita a página inicial — ou qualquer outra página — no Discourse, você obtém algo assim.

<html>
  <head>
    conteúdo do head incluindo seu script
  </head>
  <body>
    <section id="main">
      conteúdo da página
    </section>
  </body>
</html>

Quando você navega para outra página, a única coisa que é recarregada é o conteúdo dentro de

<section id="main">

Portanto, o DOM mudou e seu script personalizado não é acionado novamente. Se você tentar visitar a página do tópico diretamente, verá que ela carrega normalmente.

.

Agora, a questão é como fazê-lo funcionar com o Discourse.

A plugin-api possui um método que você pode usar para “decorar” postagens.

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

Você pode usá-lo para acionar scripts de terceiros quando uma postagem for renderizada.

Aqui está o código que você precisará. Adicione isso à aba common > header do seu 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;
};

// cria um decorador de postagem
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>

Em seguida, você precisará adicionar alguns domínios para CSP. Adicione-os à sua

content_security_policy_script_src

configuração do site

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

finalmente, você precisará adicionar um pouco de CSS para a pré-visualização estática do editor

Isso vai na aba common > CSS do seu 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);
  }
}

Depois, basta adicionar

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

a qualquer postagem, e os widgets serão renderizados e totalmente funcionais.

Se você observar o JavaScript, notará que ele possui duas opções no topo.

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

Altere WOXO_SCRIPT_SRC para o src que o woxo fornece. Deve ser o mesmo para todos os embeds que você criar.

Altere PREVIEW_ICON para o nome do ícone que você deseja usar na pré-visualização do editor. Executar este código no editor é um pouco custoso, então o editor possui uma pré-visualização estática que se parece com isto.

O ícone que você escolher aparecerá no centro.

Aqui está uma cópia comentada do código, caso queira acompanhar o que está acontecendo

código comentado
<script type="text/discourse-plugin" version="0.8">
// opções
const WOXO_SCRIPT_SRC = "https://cdn2.woxo.tech/a.js#616348fb53c1e8001686c619";
const PREVIEW_ICON = "heart";

// usamos a biblioteca Discourse Load script para garantir que os scripts sejam carregados
// corretamente. Não se preocupe, isso é inteligente o suficiente para não duplicar o script
// se já estiver carregado
const loadScript = require("discourse/lib/load-script").default;

// carregamos a função Discourse Icon HTML para obter o svg do ícone
// que queremos usar na pré-visualização estática do editor
const { iconHTML } = require("discourse-common/lib/icon-library");

// configura o ícone de pré-visualização do editor
const composerPreviewIcon = iconHTML(PREVIEW_ICON, {
  class: "woxo-preview-icon"
});

// cria uma função auxiliar para o markup de pré-visualização do editor
const previewMarkup = () => {
  const markup = `<div class="woxo-preview">${composerPreviewIcon}</div>`;

  return markup;
};

// cria um decorador de postagem
api.decorateCookedElement(
  post => {
    // esta postagem tem widgets woxo?
    const woxoWidgets = post.querySelectorAll("div[data-mc-src]");

    // Sim, então vamos fazer algum trabalho.
    if (woxoWidgets.length) {
      // para cada widget woxo
      woxoWidgets.forEach(woxoWidget => {
        // se for um widget do editor, substitua-o por uma pré-visualização estática e
        // saia antecipadamente
        if (post.classList.contains("d-editor-preview")) {
          woxoWidget.innerHTML = previewMarkup();
          return;
        }

        // se não estiver no editor, carregue o script woxo.
        loadScript(WOXO_SCRIPT_SRC).then(() => {
          // O script woxo é muito estranho. Não funcionará a menos que a tag script
          // tenha um atributo data-usrc vazio. Então, vamos adicioná-lo
          const script = document.head.querySelector(
            `script[src*="cdn2.woxo.tech"]`
          );
          script.dataset.usrc = "";

          // tudo está pronto, vamos chamar o método init no script woxo
          window.MC.Loader.init();
        });
      });
    }
  },
  // adicione um id ao decorador para evitar vazamentos de memória
  { id: "render-woxo-widgets" }
);

</script>