Discourse には、Discourse UI に新しいコンテンツを挿入したり既存のコンテンツを置き換えたりするために使用できる数百のプラグレットアウトレット(Plugin Outlet)が含まれています。文脈に基づいてコンテンツをカスタマイズできるように、「アウトレット引数」が利用可能です。
アウトレットの選択
プラグレットアウトレットの名前を見つけるには、Discourse コアで “<PluginOutlet” を検索するか、プラグレットアウトレットの場所テーマコンポーネントを使用してください(例:topic-above-posts)。
ラッパーアウトレット
コア内の一部のアウトレットは <PluginOutlet @name="foo" /> のように見えます。これらは新しいコンテンツの挿入を許可します。他のアウトレットは、次のように既存のコア実装を「ラップ」します。
<PluginOutlet @name="foo">
core implementation
</PluginOutlet>
この種の「ラッパー」アウトレットに対してコネクタを定義すると、コア実装が置き換えられます。ラッパープラグレットアウトレットに対してコネクタを提供できるのは、アクティブなテーマ/プラグレットが1つだけです。
ラッパープラグレットアウトレットの場合、{{yield}} キーワードを使用して元のコア実装をレンダリングできます。これは、特定の条件下でのみコア実装を置き換えたい場合や、何かでラップしたい場合に役立ちます。
コネクタの定義
アウトレットを選択したら、コネクタの名前を決定します。これは、特定のコミュニティにインストールされているすべてのテーマ/プラグレット間で一意である必要があります。例:brand-official-topics
テーマ/プラグレットで、次のような形式のパスを持つ新しい .gjs コネクタを定義します。
![]()
{theme}/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
![]()
{plugin}/assets/javascripts/discourse/connectors/{outlet-name}/{connector-name}.gjs
これらのファイルのコンテンツは Ember コンポーネントとしてレンダリングされます。Ember と .gjs 形式に関する一般的な情報については、Ember ガイド を参照してください。
私たちの仮想的な「brand official topics」コネクタの場合、ファイルは次のようになります。
<template>
<div class="alert alert-info">
This topic was created by a member of the
<a href="https://discourse.org/team">Discourse Team</a>
</div>
</template>
アウトレット引数の使用
プラグレットアウトレットは、@outletArgs を介して周囲の文脈に関する情報を提供します。各アウトレットに渡される引数は異なります。引数を表示する簡単な方法は、テンプレートにこれを追加することです。
{{log @outletArgs}}
これにより、引数がブラウザの開発者コンソールにログ出力されます。これらは Proxy オブジェクトとして表示されます。引数のリストを確認するには、プロキシの [[Target]] を展開します。
topic-above-posts の例では、レンダリングされたトピックは @outletArgs.model で利用可能です。したがって、次のようにチームメンバーのユーザー名を追加できます。
<template>
<div class="alert alert-info">
This topic was created by
{{@outletArgs.model.details.created_by.username}}
(a member of the
<a href="https://discourse.org/team">Discourse Team</a>)
</div>
</template>
より複雑なロジックの追加
時折、単純なテンプレートでは不十分な場合があります。コネクタに JavaScript ロジックを追加するには、.gjs ファイルをクラスベースのコンポーネントをエクスポートするようにアップグレードします。これは他のコンポーネント定義と同じように機能し、サービス注入を含めることができます。
topic-above-posts の例では、「UX でユーザー名を優先する」サイト設定に基づいてユーザーを異なる方法でレンダリングしたい場合があります。.gjs ファイルは次のようになります。
.../connectors/topic-above-posts/brand-official-topic.gjs:
import Component from "@glimmer/component";
import { service } from "@ember/service";
export default class BrandOfficialTopics extends Component {
@service siteSettings;
get displayName() {
const user = this.args.outletArgs.model.details.created_by;
if (this.siteSettings.prioritize_username_in_ux) {
return user.username;
} else {
return user.name;
}
}
<template>
<div class="alert alert-info">
This topic was created by
{{this.displayName}}
(a member of the
<a href="https://discourse.org/team">Discourse Team</a>)
</div>
</template>
}
条件付きレンダリング
コンテンツを特定の条件下でのみレンダリングしたい場合、多くの場合、テンプレートを handlebars の {{#if}} ブロックでラップするだけで十分です。それが不十分な場合は、shouldRender フックを使用して、コネクタテンプレートがレンダリングされるかどうかを制御できます。
まず、上記の説明に従ってクラスベースの .gjs コネクタを持っていることを確認します。次に、static shouldRender() 関数を追加します。例を拡張します。
import Component from "@glimmer/component";
export default class BrandOfficialTopics extends Component {
static shouldRender(outletArgs, helper) {
const firstPost = outletArgs.model.postStream.posts[0];
return firstPost.primary_group_name === "team";
}
// ... (any other logic)
<template>
{{! ... }}
</template>
}
これで、コネクタはトピックの最初の投稿がチームメンバーによって作成された場合にのみレンダリングされます。
shouldRender は Glimmer の自動追跡コンテキストで評価されます。参照されているプロパティ(例:outletArgs)への将来の変更は、関数が再評価される原因となります。
新しいアウトレットの導入
まだ存在しないアウトレットが必要な場合は、プルリクエストを作成するか、Development でトピックを開いてください。
このドキュメントはバージョン管理されています。変更提案は GitHub で行ってください。