(no recomendado) Sobrescribir las plantillas de Discourse desde un Theme o Plugin

Idealmente, al personalizar Discourse a través de temas/plugins, deberías usar CSS, la API de plugins de JavaScript o salidas de plugin. Si ninguna de estas opciones funciona para tu caso de uso, no dudes en abrir una PR para el núcleo de Discourse o iniciar un tema de Dev aquí en Meta. Siempre estamos contentos de discutir la adición de nuevas salidas/APIs para facilitar la personalización.

Si has agotado todas las demás opciones, es posible que necesites recurrir a la anulación de plantillas. Esta técnica te permite anular toda la plantilla de cualquier componente Ember o ruta desde tu tema/plugin.

:rotating_light: Esta no es una forma recomendada de personalizar Discourse. Los cambios diarios en el núcleo de Discourse entrarán en conflicto con tu anulación de plantilla eventualmente, lo que podría causar errores catastróficos al renderizar el foro.

Si decides tomar este enfoque, asegúrate de tener suficientes pruebas automatizadas y procesos de control de calidad para detectar regresiones. Si distribuyes un tema/plugin con anulaciones de plantilla, asegúrate de que los administradores del foro sean conscientes de los riesgos de estabilidad que conlleva tu tema/plugin.

:rotating_light: :rotating_light: :rotating_light: Actualización de octubre de 2023: Para nuevas funcionalidades, Discourse se está moviendo cada vez más hacia el uso de componentes creados con el formato de archivo .gjs de Ember. Las plantillas para estos componentes se definen en línea y no pueden ser anuladas por temas/plugins.

En el futuro, todas las personalizaciones de plantillas deben hacerse utilizando Salidas de Plugin

Entiendo que esto fallará en un futuro cercano, muéstrame las docs de todos modos

Anulación de plantillas de componentes

Para anular una plantilla de componente Ember (es decir, cualquier cosa bajo components/* en el núcleo de Discourse), debes crear un archivo .hbs con el mismo nombre en tu tema/plugin. Por ejemplo, para anular la plantilla del componente badge-button en el núcleo de Discourse, crearías un archivo de plantilla en tu tema/plugin en esta ubicación:

:art: {theme}/javascripts/discourse/templates/components/badge-button.hbs

:electric_plug: {plugin}/assets/javascripts/discourse/templates/components/badge-button.hbs

La anulación siempre debe anidarse dentro del directorio /templates, incluso si el componente principal tiene una plantilla ‘colocada’.

Anulación de plantillas de rutas

La anulación de plantillas de rutas (es decir, todas las plantillas que no son de componentes bajo templates/*) funciona de la misma manera que los componentes. Crea una plantilla con el mismo nombre en tu tema/plugin. Por ejemplo, para anular discovery.hbs en el núcleo, crearías un archivo como:

:art: {theme}/javascripts/discourse/templates/discovery.hbs

:electric_plug: {plugin}/assets/javascripts/discourse/templates/discovery.hbs

Anulación de plantillas ‘Raw’ (.hbr)

El sistema de plantillas “raw” de Discourse será pronto reemplazado por componentes Ember regulares. Pero mientras tanto, la anulación de plantillas raw funciona de la misma manera que las plantillas Ember. Por ejemplo, para anular topic-list-item.hbr en el núcleo, podrías crear un archivo como:

:art: {theme}/javascripts/discourse/templates/list/topic-list-item.hbr

:electric_plug: {plugin}/assets/javascripts/discourse/templates/list/topic-list-item.hbr

Interacción entre múltiples temas / plugins

Si varios temas/plugins instalados anulan la misma plantilla, el ‘ganador’ es el que tiene el número de clasificación más bajo en esta lista:

  1. Anulaciones de temas (gana el ‘id’ de tema más alto)
  2. Anulaciones de plugins (gana el nombre de plugin alfabético más reciente)
  3. Núcleo

Esta precedencia también significa que puedes anular plantillas de plugins desde temas. Técnicamente, también puedes anular plantillas de temas desde otros temas, y plantillas de plugins desde otros plugins, pero el comportamiento puede ser sorprendente debido a la dependencia del nombre del plugin y el id del tema.

¿Cómo funciona esto?

Discourse ensambla y prioriza las plantillas en la clase DiscourseTemplateMap. Para las plantillas de componentes colocados, esa información se utiliza durante la inicialización de la aplicación para reemplazar las asociaciones de plantillas principales. Para todas las demás plantillas, el mapa es utilizado por el resolvedor en tiempo de ejecución para obtener la plantilla correcta.


Este documento está controlado por versiones - sugiere cambios en github.

17 Me gusta

¿Y qué hay de las plantillas móviles? ¿Cuál es la estructura de directorios para reescribir plantillas del núcleo?

Debería funcionar exactamente igual: coincide con el nombre de la plantilla principal. Por lo tanto, si tiene /mobile, inclúyalo en su anulación.

Intento reescribir la plantilla mobile login.hbs y no funciona Imgur: The magic of the Internet, ¿tengo la ruta correcta?

La ruta completa no es visible en tu captura de pantalla, hasta donde puedo ver. Por favor, ¿puedes pegarla aquí como texto?

themeroot/javascripts/mobile/modal/login.hbs

Te falta discourse/templates en tu ruta

Por lo tanto, en tu caso, sería {theme}/javascripts/discourse/templates/mobile/modal/login.hbs

2 Me gusta

¿Sigue siendo así?

Me entristece un poco que se esté eliminando la capacidad de anular gran parte del código.

Tiene sentido reemplazar el sistema de Widgets a medida, hasta cierto punto, pero eso nos dio la capacidad de conectarnos al código existente en múltiples niveles, reduciendo el riesgo de cambios disruptivos, ya que podíamos apuntar solo a pequeños bloques de maneras inteligentes que nos permitirían:

  • añadir funcionalidades
  • no perturbar nada más.

Por ejemplo, acabo de tener que eliminar DOS funcionalidades significativas de Discourse Journal, que se basaban en anulaciones de grano fino de widgets porque la única forma de haberlas recreado en Glimmer es a través de un par de anulaciones de plantillas (incluido un intento de cambiar un archivo .gjs) que aparentemente ya no es compatible.

Incluso si esto fuera compatible, nos quedaríamos anulando tramos de código más grandes que con el marco de widgets, con un aumento asociado en el riesgo de que los cambios principales entren en conflicto con las anulaciones.

Esto no es saludable para la extensibilidad de la plataforma.

¿Se puede hacer algo al respecto?

7 Me gusta

Sí, te entiendo. Había cosas buenas en las API de extensibilidad de widgets.

Pero la otra cara de la moneda es que ha sido increíblemente difícil para nosotros modificar CUALQUIER interfaz de usuario basada en widgets en el núcleo, porque no tenemos idea de qué métodos/decoraciones aleatorias podrían estar introduciendo las personas. Es por eso que las personalizaciones de widgets han parecido relativamente estables: hemos tenido demasiado miedo de tocar las implementaciones principales.

Nuestra solución para esto en el futuro son los Wrapper Plugin Outlets. Estos permiten que los temas y complementos reemplacen opcionalmente fragmentos muy pequeños de plantillas con su propia implementación.

Por ejemplo, mira cómo Chat reemplaza condicionalmente el logo de inicio con un componente personalizado. Eso funciona para el encabezado existente basado en widgets y el nuevo encabezado basado en Glimmer (¡próximamente! :tm:).

En general, estamos contentos de aceptar PRs para agregar nuevos wrapper outlets en varios lugares. Si no está seguro de un caso de uso en particular, no dude en abrir un tema de Dev con los detalles.

10 Me gusta

De acuerdo, eso parece un camino a seguir, gracias.

Necesitaré asimilar las implicaciones de eso y ajustar una estrategia en esa dirección.

¡Agradezco la respuesta!

6 Me gusta