(não recomendado) Sobrescrever templates do Discourse de um Tema ou Plugin

Idealmente, ao personalizar o Discourse por meio de temas ou plugins, você deve usar CSS, a API de Plugin JavaScript ou saídas de plugin. Se nenhuma dessas opções funcionar para o seu caso de uso, sinta-se à vontade para abrir um PR no núcleo do Discourse ou iniciar um tópico Development aqui no Meta. Estamos sempre felizes em discutir a adição de novas saídas/APIs para facilitar a personalização.

Se você esgotou todas as outras opções, pode precisar recorrer a substituições de template. Essa técnica permite que você substitua todo o template de qualquer Componente ou Rota Ember do seu tema/plugin.

:rotating_light: Isso não é uma maneira recomendada de personalizar o Discourse. Mudanças diárias no núcleo do Discourse vão eventualmente entrar em conflito com sua substituição de template, potencialmente causando erros catastróficos ao renderizar o fórum.

Se você decidir seguir essa abordagem, certifique-se de ter processos automatizados de teste e QA suficientes para detectar regressões. Se você distribuir um tema/plugin com substituições de template, por favor, garanta que os administradores do fórum estejam cientes dos riscos de estabilidade que seu tema/plugin carrega.

:rotating_light: :rotating_light: :rotating_light: Atualização de Outubro de 2023: Para novos recursos, o Discourse está cada vez mais migrando para o uso de componentes autorados no formato de arquivo .gjs do Ember. Os templates desses componentes são definidos inline e não podem ser substituídos por temas/plugins.

A partir de agora, todas as personalizações de template devem ser feitas usando Saídas de Plugin

Entendo que isso quebrará em breve, mostre-me a documentação mesmo assim

Substituindo Templates de Componentes

Para substituir um template de Componente Ember (ou seja, qualquer coisa em components/* no núcleo do Discourse), você deve criar um arquivo .hbs com o mesmo nome no seu tema/plugin. Por exemplo, para substituir o template do componente badge-button no núcleo do Discourse, você criaria um arquivo de template no seu tema/plugin neste local:

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

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

A substituição deve estar sempre aninhada dentro do diretório /templates, mesmo que o componente central tenha um template ‘co-localizado’.

Substituindo Templates de Rotas

A substituição de templates de rotas (ou seja, todos os templates não-componentes em templates/*) funciona da mesma maneira que os componentes. Crie um template com o mesmo nome no seu tema/plugin. Por exemplo, para substituir discovery.hbs no núcleo, você criaria um arquivo como:

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

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

Interação entre múltiplos temas / plugins

Se múltiplos temas/plugins instalados substituírem o mesmo template, o ‘vencedor’ será aquele com a classificação de número mais baixo nesta lista:

  1. Substituições de tema (o ‘id’ de tema mais alto vence)
  2. Substituições de plugin (o nome de plugin alfabeticamente mais recente vence)
  3. Núcleo

Essa precedência também significa que você pode substituir templates de plugins por temas. Tecnicamente, você também pode substituir templates de tema por outros temas e templates de plugin por outros plugins, mas o comportamento pode ser surpreendente devido à dependência do nome do plugin e do id do tema.

Como isso funciona?

O Discourse monta e prioriza os templates na classe DiscourseTemplateMap. Para templates de componentes co-localizados, essa informação é usada durante a inicialização do aplicativo para substituir as associações de template do núcleo. Para todos os outros templates, o mapa é usado pelo resolvedor em tempo de execução para buscar o template correto.


Este documento está sob controle de versão - sugira alterações no github.

17 curtidas

E quanto aos modelos para dispositivos móveis? Qual é a estrutura de diretórios para reescrever modelos do core

Deve funcionar exatamente da mesma forma - você corresponde ao nome do modelo principal. Portanto, se ele tiver /mobile, inclua isso em sua substituição.

Estou tentando reescrever o template de login do mobile.hbs e não está funcionando Imgur: The magic of the Internet, estou certo com o caminho?

O caminho completo não está visível na sua captura de tela, pelo que pude ver. Por favor, pode colá-lo aqui como texto.

themeroot/javascripts/mobile/modal/login.hbs

Você está perdendo discourse/templates no seu caminho

Portanto, no seu caso, seria {theme}/javascripts/discourse/templates/mobile/modal/login.hbs

2 curtidas

Isso ainda é verdade?

Fico um pouco triste que a capacidade de substituir muito código esteja sendo removida.

Faz sentido substituir o sistema de Widgets personalizado, em certa medida, mas isso nos deu a capacidade de nos conectar ao código existente em vários níveis, reduzindo muito o risco de alterações drásticas, pois poderíamos direcionar apenas pequenos blocos de maneiras inteligentes que nos permitiriam:

  • adicionar recursos
  • não perturbar mais nada.

Tive que remover DOIS recursos significativos do Discourse Journal, por exemplo, que eram baseados em substituições de granularidade fina de widgets porque a única maneira de recriá-los em Glimmer é por meio de um par de substituições de Template (incluindo uma tentativa de alterar um arquivo .gjs), o que aparentemente não é mais suportado.

Mesmo que isso fosse suportado, ficaríamos com a substituição de trechos maiores de código do que sob o framework de widgets, com um aumento associado no risco de alterações principais entrarem em conflito com as substituições.

Isso não é saudável para a extensibilidade da plataforma.

Algo pode ser feito a respeito?

7 curtidas

Sim, entendo você - havia algumas coisas boas nas APIs de extensibilidade de widgets.

Mas o outro lado é que tem sido incrivelmente difícil para nós modificar QUALQUER interface de usuário baseada em widget no núcleo, porque não temos ideia de quais métodos/decorações aleatórios as pessoas podem estar introduzindo. É por isso que as personalizações de widgets pareceram relativamente estáveis - ficamos com muito medo de tocar nas implementações principais.

Nossa solução para isso daqui para frente são os Plugin Outlets Wrapper. Eles permitem que temas e plugins substituam opcionalmente pedaços muito pequenos de templates com sua própria implementação.

Por exemplo, veja como o Chat condicionalmente substitui o home-logo com um componente personalizado. Isso funciona para o cabeçalho existente baseado em widget e para o novo cabeçalho baseado em glimmer (em breve! :tm:).

Geralmente estamos felizes em aceitar PRs para adicionar novos wrapper outlets em vários lugares. Se você tiver dúvidas sobre um caso de uso específico, sinta-se à vontade para abrir um tópico Dev com detalhes!

10 curtidas

OK, isso parece um caminho a seguir, obrigado.

Precisarei digerir as implicações disso e ajustar uma estratégia nessa direção.

Agradeço a resposta!

6 curtidas