El "templating" de mi "componente" se rompió. ¿Cómo lo arreglo?

En una instancia de Discourse que mantengo, tengo un componente (heredado del mantenedor anterior de la instancia) para mostrar los logotipos de los patrocinadores de esa instancia en el pie de página. El componente solía funcionar bien hasta hace poco, pero ahora se renderiza incorrectamente, mostrando las directivas de control de la plantilla literalmente (y poniendo los marcadores de posición de los valores de la plantilla literalmente en el HTML, por lo que las rutas a las imágenes no se resuelven):

El componente no se mantiene en un repositorio git, sino que se configura directamente en “Administrador” → “Apariencia” → “Temas y componentes” → pestaña “Componentes”:

Código personalizado

Secciones personalizadas:

  • Común: CSS, Pie de página, JS

Cargas

Archivos adicionales

Exportar tema para ver estos archivos.
  • javascripts/discourse/api-initializers/theme-initializer.gjs

contenido de esas “secciones”

Tal como se ve al hacer clic en “Editar código”; ruta a los archivos correspondientes en la exportación indicada entre paréntesis

CSS (common/common.scss)
.sponsors {
    .inner {
        display: flex;
        align-items: center;
        justify-content: space-around;
        margin-bottom: 10px;
    }

    .heading {
        font-size: 1.75em;
    }

    .sponsor-image {
        max-height: 55px;
    }

    .geoaargau {
        max-height: 45px;
    }
}
Pie de página (common/footer.html)
  {{#if displaySponsors}}
    <div class="sponsors-wrapper wrap">
      <div class="inner">
        <h3 class="heading">Sponsoren</h3>
        <a href="http://www.asseco-berit.ch/"><img src="{{theme-setting "theme_uploads.asseco_berit"}}" alt="Asseco Berit" class="sponsor-image asseco-berit"></a>
        <a href="http://www.geoaargau.ch/"><img src="{{theme-setting "theme_uploads.geoaargau"}}" alt="GEOAargau" class="sponsor-image geoaargau"></a>
      </div>
    </div>
  {{/if}}
JS (javascripts/discourse/api-initializers/theme-initializer.gjs)
import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  // This is the plugin outlet, followed by a custom name for the component
  api.registerConnectorClass("above-footer", "sponsors", {

    setupComponent(args, component) {
        
     var topMenuRoutes = 
        component.siteSettings.top_menu.split('|')
        .map(function(route) {return '/' + route});
      
     var homeRoute = topMenuRoutes[0];
     
     api.onPageChange((url) => {

        if (url === "/" || url === homeRoute ){ 
          document.querySelector("html").classList.add("sponsors"); 
          component.set("displaySponsors", true); 
        } else {
          document.querySelector("html").classList.remove("sponsors"); 
          component.set("displaySponsors", false); 
        }
      });
    }
    
  });
});

La exportación además contiene:
about.json (466 Bytes)
que supongo que se genera sobre la marcha al exportar, por lo que no creo que sea relevante.

La parte relevante del DOM efectivo con este fallo es:

<div class="custom-footer-content">
    {{#if displaySponsors}}
    <div class="sponsors-wrapper wrap">
      <div class="inner">
        <h3 class="heading">Sponsoren</h3>
        <a href="http://www.asseco-berit.ch/"><img src="{{theme-setting " theme_uploads.asseco_berit"}}"="" alt="Asseco Berit" class="sponsor-image asseco-berit"></a>
        <a href="http://www.geoaargau.ch/"><img src="{{theme-setting " theme_uploads.geoaargau"}}"="" alt="GEOAargau" class="sponsor-image geoaargau"></a>
      </div>
    </div>
  {{/if}}
</div>

así que podemos ver que la directiva de control {{#if ...}}...{{/if}} y los marcadores de posición {{theme-setting "..."}} se usaron como HTML literal en lugar de ejecutarse / evaluarse / interpolarse.

¿Cómo y por qué cambió eso y cómo debería arreglarlo?

¿Quizás esté relacionado con Upcoming Header Changes - Preparing Themes and Plugins? (Aunque no veo cambios en la sintaxis de plantillas mencionados allí).

1 me gusta

(Con “cómo y por qué” me refiero a: ¿Cuál fue el cambio subyacente y me perdí alguna notificación al respecto? Estoy suficientemente seguro de que lo que sea que causó este cambio de comportamiento se introdujo en esa instancia mediante las actualizaciones automáticas de Discourse activadas, pero me gustaría saber cuál es la causa raíz).

¿Hay algún error o advertencia en la consola que pueda proporcionar más información?

1 me gusta

¿En la consola del navegador? Quizás — no estoy seguro de qué es “normal” allí y qué podría estar insinuando el problema. ¿Puedo simplemente pegar su contenido aquí o podría filtrar información confidencial?

Sí, la consola del navegador, ¡está bien pegarlo! A menudo, si algo está obsoleto, la consola mostrará información útil.

1 me gusta
Contenido completo de la consola del navegador al cargar https://www.geowebforum.ch/c/feedback/2
ℹ️ Discourse v2026.3.0-latest — https://github.com/discourse/discourse/commits/38ad2acd2c — Ember v6.6.0 chunk.f47b6dc1cc59c827db42.d41d8cd9.js:275:35231
[PLUGIN discourse-weekly-newsletter] Para evitar errores en las pruebas, añade una clave `pluginId` a tu llamada `modifyClass`. Esto asegurará que la modificación se aplique solo una vez. chunk.f47b6dc1cc59c827db42.d41d8cd9.js:209:136918
AVISO DE DEPRECATING: Definir clases de conector a través de registerConnectorClass está obsoleto. Consulta https://meta.discourse.org/t/32727 para ver patrones más modernos. [id de deprecación: discourse.register-connector-class-legacy] chunk.f47b6dc1cc59c827db42.d41d8cd9.js:134:74065
Error al analizar el valor de ‘-webkit-text-size-adjust’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:1:800
Error al analizar el valor de ‘-moz-text-size-adjust’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:1:827
Propiedad desconocida ‘text-size-adjust’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:1:849
Pseudo-clase o pseudo-elemento no reconocido ‘-moz-focus-inner’. Regla ignorada debido a selector incorrecto. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:1:1615
Se esperaba ‘none’, URL o función de filtro pero se encontró ‘alpha(’. Error al analizar el valor de ‘filter’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:622
Regla ignorada debido a selector incorrecto. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:36117
Error al analizar el valor de ‘justify-content’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:181379
Error al analizar el valor de ‘text-wrap’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:205516
Error al analizar el valor de ‘image-rendering’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:264428
Error al analizar el valor de ‘-webkit-text-size-adjust’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:268491
Error al analizar el valor de ‘-moz-text-size-adjust’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:268518
Propiedad desconocida ‘text-size-adjust’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:268540
Error al analizar el valor de ‘font-size’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:298136
Se esperaba ‘none’, URL o función de filtro pero se encontró ‘alpha(’. Error al analizar el valor de ‘filter’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:447258
Se esperaba ‘none’, URL o función de filtro pero se encontró ‘alpha(’. Error al analizar el valor de ‘filter’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:4:447681
Se esperaba ‘none’, URL o función de filtro pero se encontró ‘alpha(’. Error al analizar el valor de ‘filter’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:6:33799
Error al analizar el valor de ‘text-wrap’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:6:105390
Error al analizar el valor de ‘text-wrap’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:6:105471
Error al analizar el valor de ‘padding’. Declaración descartada. common_6dfc7bba61f3a7b80a86f119f30594abc84aaa6d.css:6:257744

Supongo que tengo que consultar Using Plugin Outlet Connectors from a Theme or Plugin

Entonces, creo que registerConnectorClass con setupComponent está obsoleto, mira tu registro de errores:

DEPRECATION NOTICE: Defining connector classes via registerConnectorClass is deprecated. See https://meta.discourse.org/t/32727 for more modern patterns. [deprecation id: discourse.register-connector-class-legacy] chunk.f47b6dc1cc59c827db42.d41d8cd9.js:134:74065

Y tampoco estoy seguro de que todavía toleremos el HTML sin procesar, como en tu componente de pie de página.

Así que este componente tendrá que ser reestructurado a patrones modernos, y aconsejaría moverlo a un componente adecuado también, en lugar de donde reside actualmente bajo Admin.

Para responder a tu otra pregunta

Se debe al trabajo continuo de modernización de Discourse y al cambio a nuevos estándares modernos con componentes Glimmer.

3 Me gusta

Si no es HTML sin formato (-template), ¿cuál es el contenido esperado de https://www.geowebforum.ch/admin/customize/themes/3/common/footer/edit? ¿Markdown, como en el contenido proporcionado por el usuario?

¿Puedes indicarme alguna guía sobre cómo hacer esto? Me siento un poco perdido con la documentación de Discourse que parece estar dispersa por todo el meta foro.

Para eso, ¿puedo simplemente desempaquetar la “exportación” y verificarla en un repositorio Git?

¿No es mi componente ya un componente Glimmer si tiene un archivo *.gjs en la exportación? ¿O es ese en realidad parte del problema: el Discourse actual confunde mi componente con un componente Glimmer (y por lo tanto lo exporta con ese nombre de archivo) aunque a nivel de código aún no lo sea?

(Por favor, disculpe mi ignorancia. No soy desarrollador web y sé casi nada sobre Ember y Glimmer).

1 me gusta

Quise decir: El HTML sin procesar ya no se analiza correctamente con la última versión, por lo que solo se muestra el HTML volcado en lugar de renderizarse.

Sí, el archivo .gjs de hecho indicaba un componente Glimmer, pero el método utilizado de registerConnectorClass en él no funcionará (ya no).

Esto es totalmente comprensible. Lo que Using Plugin Outlet Connectors from a Theme or Plugin esencialmente dice es que, para renderizar información en algún lugar de la página a través de ese método registerConnectorClass, la forma en que lo hacía su archivo footer.html, ahora usamos un elemento específico, llamado plugin outlet. Para un pie de página, el outlet above-footer funcionaría bien.

Probablemente sea una buena idea leer Beginner's guide to using Discourse Themes y Developing Discourse Themes & Theme Components

También puede ayudar echar un vistazo a un componente de tema simple, para entender la estructura. Por ejemplo: GitHub - discourse/discourse-minimal-footer · GitHub

Y finalmente, el bot de Discourse podría ayudarle en gran medida: conoce bien los patrones de Discourse, así que puede darle su código actual, explicarle el problema y pedirle que le ayude a refactorizarlo.

2 Me gusta