Модернизация тегов inline-скриптов для шаблонов и JS API

Использование <script type='text/discourse-plugin'> или <script type='text/x-handlebars'> в темах теперь устарело. Любое использование этих тегов в темах следует обновить в соответствии с инструкциями ниже.

Обычные <script> и <script type='text/javascript'> не затронуты этим изменением.

Сроки

Это приблизительные оценки, они могут быть изменены

  • Май 2025 — включены сообщения об устаревании в консоли

  • Июль 2025 — включены предупреждающие баннеры в админ-панели

  • Конец сентября 2025 Март 2026 — удаление функциональности

Конвертация <script type='text/x-handlebars'>

Шаблоны, созданные этим способом, следует перенести в отдельные файлы .hbs или переписать в файлы gjs.

Чтобы оставить их в формате HBS, шаблоны коннекторов можно разместить в:

{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.hbs

а шаблоны компонентов — в:

{theme}/javascripts/discourse/components/{component-name}.hbs

:warning: С марта 2026 года файлы .hbs также считаются устаревшими. После выполнения этой конвертации перейдите к инструкциям по ссылке: Deprecating .hbs file extension in themes and plugins

Чтобы создавать коннекторы и компоненты в современном формате .gjs, ознакомьтесь с этой главой руководства для разработчиков тем:

Конвертация <script type='text/discourse-plugin'>

Код внутри этих тегов можно перенести в отдельный JavaScript-файл.

Если вы разрабатываете тему через интерфейс админ-панели, скопируйте код из тега <script> и переместите его во вкладку JS (там, где написано // your code here).

Если вы разрабатываете тему локально, создайте новый файл по пути:

{theme}/javascripts/discourse/api-initializers/init-theme.js

затем добавьте этот обёрточный код и поместите свой код в указанное место:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  // Ваш код здесь
});

В тегах скриптов единственным способом импорта других JS-модулей был синтаксис require(). Хотя это всё ещё будет работать в файле .js, скоро этот способ также станет устаревшим, поэтому сейчас самое время перейти на современные импорты ES6. Например:

- const I18n = require("discourse-i18n").default;
+ import I18n from "discourse-i18n";
- const { h } = require("virtual-dom");
+ import { h } from "virtual-dom";

Дополнительная информация об инициализаторах JS:

19 лайков

Maybe a very dumb question, but I have a very very simple theme component that I put directly into the admin console under <head>:

<script type="text/x-handlebars" data-template-name="/connectors/top-notices/whos-online-below-site-header">
{{whos-online}}
</script>

If I’m following this post correctly, does it mean that I now have to create a separate theme component folder, host it on GitHub and add the component just for something as simple as adding to a plugin outlet?

I sure hope not, as it’ll break most of my simple theme components :grimacing:

There is the JS tab now, so you can probably use api.renderInOutlet now.

1 лайк

Ah, I didn’t see that this was possible to do with connectors/components as well, but in the linked article found this:

Maybe easier than I thought, thank you!

2 лайка

Thank you for this post!
May be a very basic question I believe:
Since we do not have a sandbox, I need to be sure before I proceed.
I have to update a theme affected so am I correct if say that all the code related to “Script” from “head” tab need to be moved into the JS tab as illustrated below:

Almost, but not quite. You’d want to remove the script tags, and change the imports to something like:

import { ajax } from "discourse/lib/ajax";

Then, paste all this in the JS tab, inside:

Our Discourse site (hosted by Discourse) is currently generating the following error bar (which is what led me to this thread):

I’m not aware that we’ve done any cutomization of the ‘Light’ theme of our own, and looking at its admin page, am not seeing anything suggesting this is anything more than the system-provided default (but could easily be missing something).

For a hosted site like ours, is this likely to self-resolve over time, or does it require some action on our part?

Thanks,
-Brad

You will need to take action to resolve this - it won’t go away on its own.

I took a quick look at your site in chrome dev tools, and it looks like the relevent code is related to adding the ‘chapel’ language to highlightjs.

If you visit your ‘Light’ theme, and hit ‘edit code’, you should be able to find this under one of the HTML tabs. Then you can follow the instructions in the OP of this topic to move it to the ‘JS’ tab.

1 лайк

Thanks @david! I’d forgotten that we’d done some customizations to get Chapel highlighting and am not sure I would’ve gotten there on my own from the error banner, so appreciate the assistance and pointers.

-Brad

1 лайк

I have a simple .html file:

<script type='text/x-handlebars' data-template-name='/connectors/below-site-header/oprs-top-container'>
    <div id='WW_T_D_1' class='oprs-top-leaderboard'></div>
</script>

I’m kind of confused with different ways to do this migration. Appreciate if someone explains what to do. Thanks

Just renderInOutlet to the connector

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  api.renderInOutlet("below-site-header", <template>
    <div id='WW_T_D_1' class='oprs-top-leaderboard'></div>
  </template>);
});
2 лайка

Thank you. I tried and it didn’t work :confused:

This my structure and these are

below-site-header.js


export function test() {
    let test2 = document.querySelector('.test');
    console.log('test ', test2);
}

And below-siteheader-connectors.hbs

<div class="test"></div>

I’m new to this so any help is appreciated. I took this repo from a previous dev.

Hi there, could you share the link to your Github repo? Thanks!

So I’ve slapped my tiny “make-avatar-bigger” script into the JS tab (out of Desktop - <head> ), and that works simply enough, but is there at least a quick ‘n dirty way to keep it only applying in Desktop? My mobile avatars are also now large and it all looks rather silly.

The code for ref is:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
 api.changeWidgetSetting('post-avatar', 'size', '70');
});

Hmm… maybe adjust this with CSS?

Or, maybe:

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  const site = api.container.lookup("service:site");
  if (!site.mobileView) {
    api.changeWidgetSetting('post-avatar', 'size', '70');
  }
});

Something from the top of my head.

3 лайка

That did the trick perfectly, thank you!

1 лайк

Just a friendly reminder: changeWidgetSetting on post-avatar is a deprecated API and will be removed soon.

Maybe you should change your code to this

import { apiInitializer } from "discourse/lib/api";

export default apiInitializer((api) => {
  const site = api.container.lookup("service:site");
  if (!site.mobileView) {
    api.modifyClass("component:post/avatar", (SuperClass) => class extends SuperClass {
      get size() { return "70"; } 
    });
  }
});
5 лайков

I think there’s also an official theme component for this as well? Avatar Size and Shape

Not sure if it fits the particular use case, but it seems like it should (with the added bonus that someone will fix it if it needs updating :slight_smile:)

7 лайков

I have upgraded all the way from quick 'n dirty to officially supported, thanks all!

4 лайка

Noting for people with legacy components (using separate Desktop/Mobile handling) that the JS tab is only available in the Common section - hopefully saves somebody else a few searches :slight_smile:

1 лайк