Incrustar widget dentro del texto en un tema

Discourse es una aplicación de una sola página. El problema que estás experimentando ocurre porque el script que estás utilizando no es consciente de ello. Cuando visitas la página de inicio o cualquier otra página en Discourse, obtienes algo como esto.

<html>
  <head>
    contenido del head, incluido tu script
  </head>
  <body>
    <section id="main">
      contenido de la página
    </section>
  </body>
</html>

Cuando navegas a otra página, lo único que se vuelve a cargar es el contenido dentro de

<section id="main">

Por lo tanto, el DOM ha cambiado y tu script personalizado no se ejecuta nuevamente. Si intentas visitar la página del tema directamente, verás que se carga correctamente.

.

Entonces, ahora la pregunta es cómo hacer que funcione con Discourse.

La API de plugins tiene un método que puedes usar para “decorar” publicaciones.

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

Puedes usarlo para ejecutar scripts de terceros cuando se renderiza una publicación.

Aquí está el código que necesitarías. Agrega esto a la pestaña common > header de tu 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 decorador de publicaciones
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>

Luego necesitarías agregar un par de dominios para CSP. Agrega estos a tu

content_security_policy_script_src

configuración del sitio

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

finalmente, necesitarías agregar un poco de CSS para la vista previa estática del compositor

Esto va en la pestaña common > CSS de tu 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);
  }
}

Luego puedes simplemente agregar

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

a cualquier publicación, y los widgets se renderizarán y serán totalmente funcionales.

Si observas el JavaScript, notarás que tiene dos opciones en la parte superior.

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

Cambia WOXO_SCRIPT_SRC por el src que te proporcione Woxo. Debería ser el mismo para todos los incrustados que crees.

Cambia PREVIEW_ICON por el nombre del ícono que deseas usar en la vista previa del compositor. Ejecutar este código en el compositor es un poco costoso, por lo que el compositor tiene una vista previa estática que se ve así.

El ícono que elijas aparecerá en el centro.

Aquí tienes una copia comentada del código si quieres seguir lo que está sucediendo

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

// usamos la librería Load script de Discourse para asegurar que los scripts se carguen
// correctamente. No te preocupes, es lo suficientemente inteligente como para no duplicar el script
// si ya está cargado
const loadScript = require("discourse/lib/load-script").default;

// cargamos la función iconHTML de Discourse para obtener el SVG del ícono
// que queremos usar en la vista previa estática del compositor
const { iconHTML } = require("discourse-common/lib/icon-library");

// configuramos el ícono de vista previa del compositor
const composerPreviewIcon = iconHTML(PREVIEW_ICON, {
  class: "woxo-preview-icon"
});

// creamos una función auxiliar para el marcado de vista previa del compositor
const previewMarkup = () => {
  const markup = `<div class="woxo-preview">${composerPreviewIcon}</div>`;

  return markup;
};

// creamos un decorador de publicaciones
api.decorateCookedElement(
  post => {
    // ¿tiene esta publicación widgets de woxo?
    const woxoWidgets = post.querySelectorAll("div[data-mc-src]");

    // Sí, entonces hagamos algo de trabajo.
    if (woxoWidgets.length) {
      // para cada widget de woxo
      woxoWidgets.forEach(woxoWidget => {
        // si es un widget del compositor, reemplázalo por una vista previa estática y
        // salimos temprano
        if (post.classList.contains("d-editor-preview")) {
          woxoWidget.innerHTML = previewMarkup();
          return;
        }

        // si no está en el compositor, cargamos el script de woxo.
        loadScript(WOXO_SCRIPT_SRC).then(() => {
          // El script de woxo es muy extraño. No funcionará a menos que la etiqueta
          // script tenga un atributo data-usrc vacío. Así que agregémoslo
          const script = document.head.querySelector(
            `script[src*="cdn2.woxo.tech"]`
          );
          script.dataset.usrc = "";

          // todo está listo, llamemos al método init en el script de woxo
          window.MC.Loader.init();
        });
      });
    }
  },
  // agrega un id al decorador para evitar fugas de memoria
  { id: "render-woxo-widgets" }
);

</script>
3 Me gusta