(non recommandé) Remplacer les modèles Discourse depuis un Thème ou un Plugin

Idéalement, lors de la personnalisation de Discourse via des thèmes/plugins, vous devriez utiliser du CSS, l’API de Plugin JavaScript ou des plugin outlets. Si aucune de ces méthodes ne convient à votre cas d’utilisation, n’hésitez pas à ouvrir une PR dans le cœur de Discourse ou à démarrer un sujet Dev ici sur Meta. Nous sommes toujours heureux de discuter de l’ajout de nouveaux outlets/APIs pour faciliter la personnalisation.

Si vous avez épuisé toutes les autres options, vous devrez peut-être recourir aux remplacements de modèles (template overrides). Cette technique vous permet de remplacer le modèle entier de n’importe quel composant Ember ou Route depuis votre thème/plugin.

:rotating_light: Ce n’est pas une méthode recommandée pour personnaliser Discourse. Les changements quotidiens dans le cœur de Discourse entreront en conflit avec votre remplacement de modèle à terme, provoquant potentiellement des erreurs catastrophiques lors du rendu du forum.

Si vous décidez d’adopter cette approche, assurez-vous de disposer de suffisamment de tests automatisés et de processus d’assurance qualité (AQ) pour détecter les régressions. Si vous distribuez un thème/plugin avec des remplacements de modèles, veuillez vous assurer que les administrateurs du forum sont conscients des risques de stabilité que comporte votre thème/plugin.

:rotating_light: :rotating_light: :rotating_light: Mise à jour d’octobre 2023 : Pour les nouvelles fonctionnalités, Discourse s’oriente de plus en plus vers l’utilisation de composants rédigés à l’aide du format de fichier .gjs d’Ember. Les modèles pour ces composants sont définis en ligne et ne peuvent pas être remplacés par des thèmes/plugins.

À l’avenir, toutes les personnalisations de modèles doivent être effectuées à l’aide des Plugin Outlets

Je comprends que cela va bientôt casser, montrez-moi la documentation quand même

Remplacement des modèles de composants

Pour remplacer un modèle de composant Ember (c’est-à-dire tout ce qui se trouve sous components/* dans le cœur de Discourse), vous devez créer un fichier .hbs de nom identique dans votre thème/plugin. Par exemple, pour remplacer le modèle du composant badge-button dans le cœur de Discourse, vous créeriez un fichier de modèle dans votre thème/plugin à cet emplacement :

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

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

Le remplacement doit toujours être imbriqué dans le répertoire /templates, même si le composant principal a un modèle « colocalisé ».

Remplacement des modèles de routes

Le remplacement des modèles de routes (c’est-à-dire tous les modèles non-composants sous templates/*) fonctionne de la même manière que pour les composants. Créez un modèle portant le même nom dans votre thème/plugin. Par exemple, pour remplacer discovery.hbs dans le cœur, vous pourriez créer un fichier comme

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

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

Remplacement des modèles « bruts » (.hbr)

Le système de modèle « brut » de Discourse sera bientôt remplacé par des composants Ember réguliers. Mais en attendant, le remplacement des modèles bruts fonctionne de la même manière que pour les modèles Ember. Par exemple, pour remplacer topic-list-item.hbr dans le cœur, vous pourriez créer un fichier comme :

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

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

Interaction entre plusieurs thèmes / plugins

Si plusieurs thèmes/plugins installés remplacent le même modèle, le « gagnant » est celui qui a le rang numérique le plus bas dans cette liste :

  1. Remplacements de thèmes (l’« id » de thème le plus élevé l’emporte)
  2. Remplacements de plugins (le nom de plugin alphabétique le plus récent l’emporte)
  3. Cœur

Cette précédence signifie également que vous pouvez remplacer les modèles de plugins à partir de thèmes. Techniquement, vous pouvez également remplacer des modèles de thèmes par d’autres thèmes, et des modèles de plugins par d’autres plugins, mais le comportement peut être surprenant en raison de la dépendance au nom du plugin et à l’ID du thème.

Comment cela fonctionne-t-il ?

Discourse assemble et priorise les modèles dans la classe DiscourseTemplateMap. Pour les modèles de composants colocalisés, cette information est utilisée pendant l’initialisation de l’application pour remplacer les associations de modèles de base. Pour tous les autres modèles, la carte est utilisée par le résolveur au moment de l’exécution pour récupérer le modèle correct.


Ce document est contrôlé par version - suggérez des modifications sur github.

17 « J'aime »

Et qu’en est-il des modèles mobiles ? Quelle est la structure de répertoire pour réécrire les modèles du cœur

Cela devrait fonctionner exactement de la même manière : vous faites correspondre le nom du modèle de base. Donc, s’il contient /mobile, incluez-le dans votre remplacement.

J’essaie de réécrire le modèle mobile login.hbs et ça ne fonctionne pas Imgur: The magic of the Internet, est-ce que le chemin est correct ?

Le chemin complet n’est pas visible sur votre capture d’écran, d’après ce que je peux voir. Pouvez-vous le coller ici sous forme de texte.

themeroot/javascripts/mobile/modal/login.hbs

Il vous manque discourse/templates dans votre chemin

Donc, dans votre cas, ce serait {theme}/javascripts/discourse/templates/mobile/modal/login.hbs

2 « J'aime »

Est-ce toujours le cas ?

Je suis un peu triste que la possibilité de remplacer une grande partie du code soit supprimée.

Il est logique de remplacer le système de widgets sur mesure, dans une certaine mesure, mais cela nous donnait la possibilité de nous connecter au code existant à plusieurs niveaux, réduisant ainsi le risque de changements majeurs, car nous pouvions cibler de petits blocs de manière intelligente, ce qui nous permettait de :

  • ajouter des fonctionnalités
  • ne rien déranger d’autre.

Je viens de devoir supprimer DEUX fonctionnalités importantes de Discourse Journal, par exemple, qui étaient basées sur des remplacements de widgets à grain fin, car la seule façon de les recréer en Glimmer était via une paire de remplacements de modèles (y compris une tentative de modification d’un fichier .gjs), ce qui n’est apparemment plus pris en charge.

Même si cela était pris en charge, nous serions laissés avec le remplacement de plus grandes portions de code qu’avec le framework de widgets, avec une augmentation associée du risque que les changements de base entrent en conflit avec les remplacements.

Ce n’est pas sain pour l’extensibilité de la plateforme.

Peut-on faire quelque chose à ce sujet ?

7 « J'aime »

Oui, je vous entends bien - il y avait de bonnes choses dans les API d’extensibilité des widgets.

Mais le revers de la médaille est qu’il nous a été incroyablement difficile de modifier N’IMPORTE QUEL élément de l’interface utilisateur basée sur les widgets dans le cœur, car nous n’avons aucune idée des méthodes/décorations aléatoires que les gens pourraient introduire. C’est pourquoi les personnalisations de widgets ont semblé relativement stables - nous avons eu trop peur de toucher aux implémentations de base.

Notre solution pour l’avenir est les sorties de plugin Wrapper. Celles-ci permettent aux thèmes et aux plugins de remplacer facultativement de très petits morceaux de modèles par leur propre implémentation.

Par exemple, voyez comment Chat remplace conditionnellement le logo d’accueil avec un composant personnalisé. Cela fonctionne pour l’en-tête existant basé sur les widgets, et le nouvel en-tête basé sur glimmer (bientôt disponible ! :tm:).

Nous sommes généralement heureux d’accepter les PR pour ajouter de nouvelles sorties wrapper à divers endroits. Si vous n’êtes pas sûr d’un cas d’utilisation particulier, n’hésitez pas à ouvrir un sujet Dev avec les détails !

10 « J'aime »

OK, cela semble être une voie à suivre, merci.

Je devrai digérer les implications de cela et ajuster une stratégie dans ce sens.

J’apprécie la réponse !

6 « J'aime »