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

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

Если вы исчерпали все остальные варианты, возможно, вам придется прибегнуть к переопределению шаблонов (template overrides). Эта техника позволяет вам переопределить весь шаблон любого компонента или маршрута 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. Ядро

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

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

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 лайков