Discourse には、Discourse UI に新しいコンテンツを注入したり、既存のコンテンツを置換したりするために使用できる数百のプラグインアウトレットが含まれています。コンテキストに基づいてコンテンツをカスタマイズできるよう、「アウトレット引数」が利用可能になっています。
アウトレットの選択
プラグインアウトレットの名前を見つけるには、Discourse コア内で「<PluginOutlet」を検索するか、プラグインアウトレット場所 テーマコンポーネントを使用してください(例:topic-above-posts)。
ラッパーアウトレット
コア内の一部のアウトレットは <PluginOutlet @name="foo" /> のように見えます。これらは新しいコンテンツを注入することを可能にします。他のアウトレットは以下のように既存のコア実装を「ラップ」します。
<PluginOutlet @name="foo">
コア実装
</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 ガイド をご覧ください。
仮想的な「ブランド公式トピック」コネクタの場合、ファイルは以下のようになります。
<template>
<div class="alert alert-info">
このトピックは
<a href="https://discourse.org/team">Discourse チーム</a>
のメンバーによって作成されました
</div>
</template>
アウトレット引数の使用
プラグインアウトレットは、@outletArgs を介して周囲のコンテキストに関する情報を提供します。各アウトレットに渡される引数は異なります。引数を確認する簡単な方法は、テンプレートに以下を追加することです。
{{log @outletArgs}}
これにより、引数がブラウザの開発者コンソールにログ出力されます。これらは Proxy オブジェクトとして表示されます。引数のリストを調べるには、プロキシの [[Target]] を展開してください。
topic-above-posts の例では、レンダリングされたトピックは @outletArgs.model で利用可能です。したがって、チームメンバーのユーザー名を以下のように追加できます。
<template>
<div class="alert alert-info">
このトピックは
{{@outletArgs.model.details.created_by.username}}
によって作成されました
(
<a href="https://discourse.org/team">Discourse チーム</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.displayName}}
によって作成されました
(
<a href="https://discourse.org/team">Discourse チーム</a>
のメンバー)
</div>
</template>
}
条件付きレンダリング
特定の条件下でのみコンテンツをレンダリングしたい場合、テンプレートをハンドルバーズの {{#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";
}
// ... (その他のロジック)
<template>{{! ... }}</template>
}
これで、コネクタはトピックの最初の投稿がチームメンバーによって作成された場合のみレンダリングされます。
shouldRender は Glimmer の自動トラッキングコンテキストで評価されます。参照されているプロパティ(例:outletArgs)の将来の変更により、関数が再評価されます。
新しいアウトレットの導入
まだ存在しないアウトレットが必要な場合は、プルリクエストを作成するか、Development でトピックを開いてください。
このドキュメントはバージョン管理されています。変更を GitHub で提案してください。