(не рекомендуется) Переопределение шаблонов Discourse из темы или плагина

В идеале при кастомизации Discourse с помощью тем или плагинов следует использовать CSS, JavaScript Plugin API или plugin outlets. Если ни один из этих методов не подходит для вашего случая, не стесняйтесь открыть PR в ядро Discourse или создать тему с тегом Development здесь, на Meta. Мы всегда рады обсудить добавление новых outlets/API для упрощения кастомизации.

Если вы исчерпали все остальные варианты, возможно, вам придётся прибегнуть к переопределению шаблонов. Этот метод позволяет полностью переопределить шаблон любого компонента Ember или маршрута из вашей темы/плагина.

:rotating_light: Это не рекомендуемый способ кастомизации Discourse. Ежедневные изменения в ядре Discourse в конечном итоге приведут к конфликтам с вашим переопределением шаблона, что может вызвать катастрофические ошибки при отображении форума.

Если вы решите использовать этот подход, убедитесь, что у вас есть достаточные процессы автоматизированного тестирования и контроля качества для обнаружения регрессий. Если вы распространяете тему или плагин с переопределением шаблонов, пожалуйста, убедитесь, что администраторы форумов осведомлены о рисках нестабильности, которые несёт ваша тема/плагин.

:rotating_light: :rotating_light: :rotating_light: Обновление за октябрь 2023 года: Для новых функций Discourse всё чаще переходит к использованию компонентов, созданных с использованием формата файлов .gjs в Ember. Шаблоны для этих компонентов определяются внутри файла и не могут быть переопределены темами или плагинами.

В дальнейшем вся кастомизация шаблонов должна выполняться с помощью Plugin Outlets

Я понимаю, что это сломается в ближайшем будущем, но покажите мне документацию всё равно

Переопределение шаблонов компонентов

Чтобы переопределить шаблон компонента Ember (то есть любого файла из components/* в ядре Discourse), создайте файл .hbs с таким же именем в вашей теме или плагине. Например, чтобы переопределить шаблон компонента badge-button в ядре Discourse, создайте файл шаблона в вашей теме/плагине по следующему пути:

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

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

Переопределение всегда должно находиться внутри директории /templates, даже если у компонента ядра есть «колокальный» (colocated) шаблон.

Переопределение шаблонов маршрутов

Переопределение шаблонов маршрутов (то есть всех не-компонентных шаблонов из templates/*) работает так же, как и для компонентов. Создайте шаблон с таким же именем в вашей теме или плагине. Например, чтобы переопределить discovery.hbs в ядре, создайте файл по пути:

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

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

Взаимодействие между несколькими темами / плагинами

Если несколько установленных тем или плагинов переопределяют один и тот же шаблон, «победителем» становится тот, у которого наименьший номер ранга в следующем списке:

  1. Переопределения тем (побеждает тема с наибольшим «id»)
  2. Переопределения плагинов (побеждает плагин с наибольшим алфавитным именем)
  3. Ядро

Это правило приоритетов также означает, что вы можете переопределять шаблоны плагинов из тем. Технически вы также можете переопределять шаблоны тем из других тем и шаблоны плагинов из других плагинов, но поведение может быть неожиданным из-за зависимости от имени плагина и идентификатора темы.

Как это работает?

Discourse собирает и расставляет приоритеты шаблонам в классе DiscourseTemplateMap. Для колокальных шаблонов компонентов эта информация используется во время инициализации приложения для замены ассоциаций шаблонов ядра. Для всех остальных шаблонов карта используется разрешителем во время выполнения для получения правильного шаблона.


Этот документ находится под контролем версий — предложите изменения на GitHub.

17 лайков

А как насчет мобильных шаблонов? Какова структура каталогов для переписывания шаблонов из ядра?

Это должно работать точно так же — вы сопоставляете имя базового шаблона. Поэтому, если в нём есть /mobile, включите это в ваш переопределённый вариант.

Я пытаюсь переписать шаблон mobile login.hbs, но он не работает Imgur: The magic of the Internet. Правильно ли я указал путь?

Полный путь, насколько я вижу, не виден на вашем скриншоте. Пожалуйста, вставьте его здесь в виде текста.

themeroot/javascripts/mobile/modal/login.hbs

В вашем пути отсутствует discourse/templates

Таким образом, в вашем случае это будет {theme}/javascripts/discourse/templates/mobile/modal/login.hbs

2 лайка

Это всё ещё актуально?

Мне немного жаль, что возможность переопределять значительную часть кода исчезает.

Отчасти это логично, если заменить собственную систему виджетов, но она давала нам возможность подключаться к существующему коду на нескольких уровнях, что значительно снижало риск разрушительных изменений, так как мы могли точечно воздействовать на небольшие блоки, используя хитрые приёмы, позволяющие:

  • добавлять новые функции;
  • не затрагивать остальной код.

Например, мне только что пришлось удалить две важные функции из Discourse Journal, которые базировались на тонких переопределениях виджетов, поскольку единственный способ воссоздать их в Glimmer — это использование пары переопределений шаблонов (включая попытку изменить файл .gjs), что, судя по всему, больше не поддерживается.

Даже если бы это поддерживалось, нам пришлось бы переопределять гораздо большие фрагменты кода, чем в рамках системы виджетов, что сопряжено с повышенным риском конфликтов изменений ядра с нашими переопределениями.

Это вредно для расширяемости платформы.

Можно ли что-то с этим сделать?

7 лайков

Да, я вас понимаю — в API расширяемости виджетов были свои преимущества.

Однако обратная сторона медали в том, что нам невероятно сложно вносить какие-либо изменения в UI на основе виджетов в ядре, так как мы не знаем, какие случайные методы или декорации могут добавлять пользователи. Именно поэтому кастомизации виджетов кажутся относительно стабильными — мы слишком боялись трогать реализации в ядре.

Нашим решением на будущее станут Wrapper Plugin Outlets. Они позволяют темам и плагинам по желанию переопределять очень небольшие фрагменты шаблонов собственными реализациями.

Например, посмотрите, как чат условно переопределяет логотип главной страницы с помощью кастомного компонента. Это работает как для существующего заголовка на основе виджетов, так и для нового заголовка на базе Glimmer (скоро! :tm:)

Мы в целом готовы принимать PR с добавлением новых wrapper outlets в различных местах. Если вы не уверены в конкретном случае использования, пожалуйста, не стесняйтесь открыть тему в Development с подробностями!

10 лайков

Хорошо, это звучит как верное направление, спасибо.

Мне нужно обдумать последствия этого и скорректировать стратегию в этом направлении.

Благодарю за ответ!

6 лайков