(não recomendado) Substituir templates do Discourse por um Tema ou Plugin

Idealmente, ao personalizar o Discourse por meio de temas/plugins, você deve usar CSS, a API de Plugins JavaScript ou saídas de plugin. Se nenhuma dessas opções atender ao seu caso de uso, sinta-se à vontade para abrir um PR no núcleo do Discourse ou iniciar um tópico em Development aqui no Meta. Sempre estamos 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 ser necessário recorrer a substituições de modelos (template overrides). Essa técnica permite que você substitua o modelo inteiro de qualquer Componente ou Rota Ember a partir do seu tema/plugin.

:rotating_light: Esta não é uma maneira recomendada de personalizar o Discourse. As alterações diárias no núcleo do Discourse conflitarão com a sua substituição de modelo em algum momento, potencialmente causando erros catastróficos ao renderizar o fórum.

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

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

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

Eu entendo que isso quebrará em um futuro próximo, mas me mostre a documentação mesmo assim

Substituindo Modelos de Componentes

Para substituir um modelo de Componente Ember (ou seja, qualquer coisa sob components/* no núcleo do Discourse), você deve criar um .hbs com o mesmo nome no seu tema/plugin. Por exemplo, para substituir o modelo do componente badge-button no núcleo do Discourse, você criaria um arquivo de modelo 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 do núcleo tenha um modelo ‘co-localizado’ (colocated).

Substituindo Modelos de Rotas

Substituir modelos de rotas (ou seja, todos os modelos que não são componentes sob templates/*) funciona da mesma forma que para componentes. Crie um modelo com o mesmo nome no seu tema/plugin. Por exemplo, para substituir o 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 modelo, o ‘vencedor’ é aquele com a classificação de menor número nesta lista:

  1. Substituições de tema (o maior ‘id’ do tema vence)
  2. Substituições de plugin (o nome do plugin mais recente em ordem alfabética vence)
  3. Núcleo (Core)

Essa precedência também significa que você pode substituir modelos de plugins a partir de temas. Tecnicamente, você também pode substituir modelos de temas a partir de outros temas, e modelos de plugins a partir de 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 modelos na classe DiscourseTemplateMap. Para modelos de componentes co-localizados, essas informações são usadas durante a inicialização do aplicativo para substituir as associações de modelos do núcleo. Para todos os outros modelos, o mapa é usado pelo resolvedor em tempo de execução para buscar o modelo correto.


Este documento é controlado por 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