Problemas al cargar un asset js desde un Theme Component

Hola, es la primera vez que desarrollo en Discourse, así que disculpa las preguntas tontas.
Estoy creando un componente de tema para mostrar PGNs (tableros de ajedrez y partidas).
El componente no es teóricamente difícil, hay un componente de js para esto (PGNViewer.js) y he podido traducir las etiquetas [wrap] a los bloques \u003cscript\u003evar x='pgn here'; ...\u003c/script\u003e y \u003cdiv class='pgn-blahblah'\u003e\u003c/div\u003e apropiados.
Hasta aquí todo bien, pero ahora necesito cargar el js.
Descubrí que puedo usar import loadScript from \"discourse/lib/load-script\"; y await loadScript(settings.theme_uploads_local.pgnviewer_js); para cargarlo en el momento de la inicialización desde el directorio /assets/.
Pero tengo algunos problemas aquí.
A pesar de que puedo cargar el componente en la instalación de desarrollo, no puedo hacerlo en mi servidor de producción, porque dice que el activo es demasiado grande. ¿Hay alguna manera de solucionar esto?
En segundo lugar, en la instalación de desarrollo, veo una advertencia que dice que no pudo cargar /theme-javascripts/dist.js.map. No tengo idea de dónde viene. ¿Hay algo que deba proporcionar?
En general, ¿es este enfoque correcto, o sería mejor implementar un plugin en su lugar?
Gracias
Saludos cordiales

FF

2 Me gusta

Bienvenido a Meta, @happycactus :wave:

Sí, probablemente. La única razón por la que necesitarías un plugin sería si estuvieras intentando cambiar la API (es decir, el backend).

He tenido un problema similar en el pasado.

Sí, necesitas cambiar app.yml para permitir que los archivos grandes pasen a través del proxy inverso (nginx).

Afortunadamente, esta es una configuración simple, upload_size:, aquí en contexto:

params:
  ## ¿Qué revisión de Git debe usar este contenedor? (predeterminado: tests-passed)
  version: tests-passed

  ## Tamaño máximo de carga (predeterminado: 10m)
  upload_size: 20m

Una vez que hayas cambiado esto, necesitarás reconstruir para que tenga efecto:

./launcher rebuild app

Por supuesto, esto asume que tienes el acceso apropiado al servidor…

2 Me gusta

¡Gracias, Robert!

Tengo dudas, probablemente porque tengo cero experiencia con este tipo de plataformas.
Mi duda es:

mi enfoque es “incrustar” el pequeño fragmento de javascript necesario para llenar el bloque div con el contenido, pero veo que tal vez podría ejecutarlo desde una función “cookPgn”, como se hace en el componente mermaid:

async function applyMermaid(element, key = "composer") {
  const mermaids = element.querySelectorAll("pre[data-code-wrap=mermaid]");
  ...
  await loadScript(settings.theme_uploads_local.mermaid_js);
  ...
  mermaids.forEach((mermaid) => {
    if (mermaid.dataset.processed) {
      return;
    }

    const spinner = document.createElement("div");
    spinner.classList.add("spinner");
    ...
    mermaid.append(spinner);
  });

De esta manera, si entiendo correctamente, no necesito cargar el script desde la página (¿usando loadScript quizás?), sino que puedo importarlo en el js del tema. ¡O es probable que esté totalmente equivocado!
Quiero decir, ¿cuál es la diferencia entre loadScript y una simple importación?
¿Puedes dirigirme a algún recurso web donde pueda entender esto mejor?
¡Disculpa de nuevo si las preguntas son triviales o estúpidas!

Otra cosa, el límite es por defecto de 10M, pero mi activo es de alrededor de 300kb, y todo el zip es de 337kb, aún así durante la carga dice que es más de 512kb.

Gracias,

FF

¿Has probado una importación? No creo que puedas importar un script externo.

Loadscript es el enfoque correcto y asegura que el script se cargue completamente antes de que tu código continúe y lo utilice (por eso devuelve una promesa).

¿Puedes compartir el error exacto? ¿Está en la consola del navegador?

Tu problema real es que intentas usar JS en línea, lo cual está prohibido por CSP.

Pon este código en una función auxiliar en el código de tu componente de tema, y no lo inyectes dentro de las publicaciones.

Sube tu tema actual a GitHub y también podremos echarle un vistazo.

5 Me gusta

Echa un vistazo al componente Discourse Mermaid, que carga una biblioteca y hace que sucedan cosas en las publicaciones.

2 Me gusta

Gracias, @Falco, esta era una de mis dudas.

Claro, aquí está: GitHub - studiofuga/discourse-pgn-component: A theme component for Discourse to display PGN blocks
También hay una versión de plugin, pero creo que no seguiré este enfoque y me quedaré con el componente del tema.

Gracias @pfaffman, de hecho me inspiré en él, y noté que hace exactamente lo que necesito y de la manera correcta, sin inyectar el código como se sugirió anteriormente.

Gracias a todos, probaré con sus sugerencias y volveré con los resultados. Por supuesto, mi código es de código abierto, por lo que cualquier contribución o crítica es muy bienvenida.

1 me gusta

Mi culpa, olvidé que había limitado el tamaño del archivo adjunto a 512kB, lo aumenté al valor predeterminado (4096) y funcionó bien. Gracias y disculpa la pregunta tonta.

2 Me gusta

Ok, he arreglado todo y el componente funciona. Pero tenemos un problema, una “evaluación insegura” en la biblioteca que estoy usando. Supongo que debería arreglar la biblioteca original, no tengo idea de cómo empaquetarla.
Para aquellos interesados, he subido todos mis cambios a mi repositorio anterior, y aquí están los detalles del error.

y la línea es esta (en el módulo js original)

let isBrowser=new Function("try {return this===window;}catch(e){ return false;}")

aquí.

1 me gusta

Tu script está fallando con la Política de Seguridad de Contenido en Producción.

Necesitas añadir 'unsafe-eval' como un elemento en la configuración del sitio: content security policy script src

Gracias, estoy revisando la documentación para ver cómo hacer esto. :slight_smile: Estoy aprendiendo mucho, gracias.

1 me gusta

Ok, lo hice, solo que necesité usar el ’ … lol… De todos modos, mi script casi funcionó, subí todo a main y de alguna manera funcionó, parece que tengo un problema con la renderización pero al menos se llama al componente principal (sospecho que ahí está el problema).
Gracias a todos… Volveré pronto con más preguntas LOL. ¡Gracias!

1 me gusta

Teniendo en cuenta que añadir unsafe-eval a tu CSP básicamente elimina el propósito de CSP y hace que tu sitio sea menos seguro como resultado.

Usar eval es un “code smell” (indicador de un problema potencial en el código) y debería corregirse aguas arriba, como señalaste anteriormente.

4 Me gusta

Sí, definitivamente. No puedo arreglarlo en este momento, pero mi plan es primero arreglar mi componente, luego arreglar la biblioteca upstream y eliminar la anulación de CSP. ¡Gracias por el consejo!

Ya casi termino. Pude mostrar “algo”, pero funciona de forma aleatoria.
La biblioteca de JavaScript que estoy usando funciona de esta manera:

Primero, necesitamos definir un bloque <div id='board'> con un ID único. Luego, necesitamos ejecutar una función para poblar el div, algo como esto: PGNV.pgnBoard('board', {});. El script requiere el mismo ID para poblarlo.

Si entiendo correctamente, no puedo hacer esto mientras decoro el bloque cocido, porque el documento aún no está poblado y el objeto PGNV no puede encontrar el bloque. Así que primero usé un widget (no funciona, porque la función HTML debe devolver el bloque y yo no lo tengo), luego cambié a una función debounced: debounceFunction(this, renderPgn, attrs, 200);.

Pero funciona “a veces”.

¿Qué me estoy perdiendo?

Gracias

debounceFunction retrasa la llamada al método de destino hasta que haya transcurrido el período de debounce sin llamadas de debounce adicionales, a veces puede que no funcione porque

debounce puede no ser la solución en su caso de uso

Intente usar las opciones afterAdopt

1 me gusta

Hola Hawn, ¡gracias por tu sugerencia!
Parece ser exactamente lo que estaba buscando. Probé dos enfoques diferentes:

  • primero usar el “decorateCooked” normal para analizar y adjuntar el bloque div y luego el afterAdopt para renderizar llamando a PGNV.pgnviewer() o
  • usar solo la opción afterAdopt para adjuntar y renderizar
    Ninguno funcionó, todavía hay otro problema que no puedo entender del todo, parece que la biblioteca interna falla con un error, aparentemente no puede encontrar el atributo className en un elemento DOM. Estoy un poco perdido :slight_smile: . He visto que alguien usa loadScript, pero yo solo importo la biblioteca y la función debounce funcionó. ¿Cuál es la diferencia entre los dos métodos?

¡Gracias!

Hola @hawm, he descubierto por qué no funciona y estoy atascado.
Por supuesto, soy totalmente nuevo en Ember y en JavaScript reciente en general. Así que estudié un poco y descubrí la razón.
PgnViewerJs espera funcionar en el DOM real, no en el DOM virtual. Por lo tanto, incluso después de que el elemento cocinado haya sido adoptado, no está presente en el DOM real, y PGNV busca IDs usando document.getElementById.
Estudié todo lo que pude encontrar: los componentes de Ember parecen satisfacer mis necesidades, pero no estoy seguro de cómo manejarlo.
¿O quizás API.onAppEvent?

Gracias.

Usé later() de Ember y, aunque es una solución improvisada, funciona. ¿Alguna mejor solución?

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.