(No recomendado) Sobrescribir plantillas de Discourse desde un tema o plugin

Idealmente, al personalizar Discourse mediante temas o complementos, debes utilizar CSS, la API de complementos de JavaScript o los outlets de complementos. Si ninguna de estas opciones funciona para tu caso de uso, no dudes en abrir una PR al núcleo de Discourse o iniciar un tema en Development aquí en Meta. Siempre estamos encantados de discutir la incorporación de nuevos outlets/APIs para facilitar la personalización.

Si has agotado todas las demás opciones, es posible que tengas que recurrir a la superposición de plantillas. Esta técnica te permite reemplazar la plantilla completa de cualquier componente o ruta de Ember desde tu tema o complemento.

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

Si decides seguir este enfoque, asegúrate de contar con procesos de pruebas automatizadas y control de calidad suficientes para detectar regresiones. Si distribuyes un tema o complemento con superposiciones de plantillas, asegúrate de que los administradores del foro sean conscientes de los riesgos de estabilidad que implica tu tema o complemento.

:rotating_light: :rotating_light: :rotating_light: Actualización de octubre de 2023: Para las nuevas funciones, Discourse está migrando cada vez más hacia el uso de componentes creados con el formato de archivo .gjs de Ember. Las plantillas de estos componentes se definen en línea y no pueden ser superpuestas por temas o complementos.

De ahora en adelante, todas las personalizaciones de plantillas deben realizarse utilizando Plugin Outlets

Sé que esto se romperá en el futuro cercano, pero muéstrame la documentación de todos modos

Superposición de plantillas de componentes

Para superponer la plantilla de un componente de 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 o complemento. Por ejemplo, para superponer la plantilla del componente badge-button en el núcleo de Discourse, crearías un archivo de plantilla en tu tema o complemento 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 superposición debe estar siempre anidada dentro del directorio /templates, incluso si el componente del núcleo tiene una plantilla “colocada” (colocated).

Superposición de plantillas de rutas

Superponer plantillas de rutas (es decir, todas las plantillas que no son de componentes bajo templates/*) funciona de la misma manera que con los componentes. Crea una plantilla con el mismo nombre en tu tema o complemento. Por ejemplo, para superponer 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

Interacción entre múltiples temas / complementos

Si varios temas o complementos instalados superponen la misma plantilla, el “ganador” es el que tenga el menor número de clasificación en esta lista:

  1. Superposiciones de temas (gana el tema con el mayor ‘id’)
  2. Superposiciones de complementos (gana el nombre de complemento más reciente alfabéticamente)
  3. Núcleo

Esta precedencia también significa que puedes superponer plantillas de complementos desde temas. Técnicamente también puedes superponer plantillas de temas desde otros temas, y plantillas de complementos desde otros complementos, pero el comportamiento puede ser sorprendente debido a la dependencia del nombre del complemento y del 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 del núcleo. Para todas las demás plantillas, el mapa es utilizado por el resolutor en tiempo de ejecución para obtener la plantilla correcta.


Este documento está bajo control de 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