(sconsigliato) Sovrascrivere i template di Discourse da un Tema o un Plugin

Idealmente, quando si personalizza Discourse tramite temi/plugin, si dovrebbero usare CSS, l’API dei Plugin JavaScript o gli outlet dei plugin. Se nessuno di questi funziona per il tuo caso d’uso, sentiti libero di aprire una PR nel core di Discourse o di avviare un topic Dev qui su Meta. Siamo sempre lieti di discutere l’aggiunta di nuovi outlet/API per semplificare la personalizzazione.

Se hai esaurito tutte le altre opzioni, potresti dover ricorrere alle sostituzioni di template. Questa tecnica ti consente di sostituire l’intero template di qualsiasi Componente Ember o Route dal tuo tema/plugin.

:rotating_light: Questo NON è un modo consigliato per personalizzare Discourse. Le modifiche quotidiane nel core di Discourse entreranno in conflitto con la tua sostituzione di template alla fine, causando potenzialmente errori catastrofici durante il rendering del forum.

Se decidi di adottare questo approccio, assicurati di disporre di sufficienti test automatizzati e processi di QA per rilevare le regressioni. Se distribuisci un tema/plugin con sostituzioni di template, assicurati che gli amministratori del forum siano consapevoli dei rischi di stabilità che il tuo tema/plugin comporta.

:rotating_light: :rotating_light: :rotating_light: Aggiornamento di Ottobre 2023: Per le nuove funzionalità, Discourse si sta muovendo sempre più verso l’uso di componenti creati utilizzando il formato di file .gjs di Ember. I template per questi componenti sono definiti inline e non possono essere sostituiti da temi/plugin.

In futuro, tutte le personalizzazioni dei template dovrebbero essere eseguite utilizzando Plugin Outlets

Capisco che questo si romperà a breve, mostrami comunque la documentazione

Sostituzione dei Template dei Componenti

Per sostituire un template di Componente Ember (ovvero tutto ciò che si trova sotto components/* nel core di Discourse), dovresti creare un file .hbs con lo stesso nome nel tuo tema/plugin. Ad esempio, per sostituire il template del componente badge-button nel core di Discourse, creeresti un file di template nella tua posizione di tema/plugin:

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

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

La sostituzione deve essere sempre nidificata all’interno della directory /templates, anche se il componente core ha un template ‘colocato’.

Sostituzione dei Template delle Route

La sostituzione dei template delle route (ovvero tutti i template non-componente sotto templates/*) funziona allo stesso modo dei componenti. Crea un template con lo stesso nome nel tuo tema/plugin. Ad esempio, per sostituire discovery.hbs nel core, creeresti un file come

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

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

Sostituzione dei Template ‘Raw’ (.hbr)

Il sistema di template “raw” di Discourse sarà presto sostituito dai normali componenti Ember. Ma nel frattempo, la sostituzione dei template raw funziona allo stesso modo dei template Ember. Ad esempio, per sostituire topic-list-item.hbr nel core, potresti creare un file come:

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

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

Interazione tra temi/plugin multipli

Se temi/plugin installati multipli sostituiscono lo stesso template, il ‘vincitore’ è quello con il ranking numerico più basso in questo elenco:

  1. Sostituzioni del tema (vince l’ID del tema più alto)
  2. Sostituzioni del plugin (vince il nome del plugin alfabetico più recente)
  3. Core

Questa precedenza significa anche che puoi sostituire i template dei plugin dai temi. Tecnicamente puoi anche sostituire i template dei temi da altri temi, e i template dei plugin da altri plugin, ma il comportamento può essere sorprendente a causa della dipendenza dal nome del plugin e dall’ID del tema.

Come funziona?

Discourse assembla e dà priorità ai template nella classe DiscourseTemplateMap. Per i template dei componenti colocati, tali informazioni vengono utilizzate durante l’inizializzazione dell’app per sostituire le associazioni dei template core. Per tutti gli altri template, la mappa viene utilizzata da il resolver a runtime per recuperare il template corretto.


Questo documento è controllato in versione - suggerisci modifiche su github.

17 Mi Piace

E per quanto riguarda i modelli per dispositivi mobili? Qual è la struttura delle directory per riscrivere i modelli dal core

Dovrebbe funzionare esattamente allo stesso modo: si abbina il nome del modello principale. Quindi, se ha /mobile, includilo nella tua sovrascrittura.

Sto provando a riscrivere il template mobile login.hbs e non funziona Imgur: The magic of the Internet, ho il percorso giusto?

Il percorso completo non è visibile nel tuo screenshot, per quanto posso vedere. Puoi incollarlo qui come testo.

themeroot/javascripts/mobile/modal/login.hbs

Manca discourse/templates nel tuo percorso

Quindi, nel tuo caso, sarebbe {theme}/javascripts/discourse/templates/mobile/modal/login.hbs

2 Mi Piace

È ancora così?

Sono un po’ triste che la capacità di sovrascrivere molto codice venga rimossa.

Ha senso sostituire il sistema di Widget su misura, in una certa misura, ma questo ci ha dato la capacità di agganciarci al codice esistente a più livelli, riducendo molti rischi di modifiche che rompono, poiché potevamo puntare solo a piccoli blocchi in modi intelligenti che ci avrebbero permesso di:

  • aggiungere funzionalità
  • non disturbare nient’altro.

Ho appena dovuto rimuovere DUE funzionalità significative da Discourse Journal, ad esempio, che si basavano su sovrascritture a grana fine dei widget perché l’unico modo per averle ricreate in Glimmer è tramite una coppia di sovrascritture di template (incluso un tentativo di modificare un file .gjs) che apparentemente non è più supportato.

Anche se questo fosse supportato, ci rimarrebbe la sovrascrittura di tratti di codice più ampi rispetto al framework widget, con un aumento associato del rischio che le modifiche principali entrino in conflitto con le sovrascritture.

Questo non fa bene all’estensibilità della piattaforma.

Si può fare qualcosa al riguardo?

7 Mi Piace

Sì, ti capisco: c’erano alcune cose interessanti nelle API di estensibilità dei widget.

Ma il rovescio della medaglia è che è stato incredibilmente difficile per noi modificare QUALSIASI interfaccia utente basata su widget nel core, perché non abbiamo idea di quali metodi/decorazioni casuali le persone potrebbero introdurre. Ecco perché le personalizzazioni dei widget sono sembrate relativamente stabili: eravamo troppo spaventati per toccare le implementazioni principali.

La nostra soluzione per questo in futuro sono i Plugin Outlets Wrapper. Questi consentono a temi e plugin di sovrascrivere facoltativamente piccoli frammenti di template con la propria implementazione.

Ad esempio, vedi come Chat sovrascrive condizionalmente il logo della home con un componente personalizzato. Questo funziona per l’intestazione esistente basata su widget e per la nuova intestazione basata su glimmer (in arrivo! :tm:).

Siamo generalmente felici di accettare PR per aggiungere nuovi wrapper outlets in vari punti. Se non sei sicuro di un particolare caso d’uso, non esitare ad aprire un topic Dev con i dettagli!

10 Mi Piace

OK, questo sembra un modo per andare avanti, grazie.

Dovrò digerire le implicazioni di ciò e adattarmi a una strategia in quella direzione.

Apprezzo la risposta!

6 Mi Piace