オープンソースのWikiであるGROWIにはプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。
今回は、GROWIプラグインとしてGROWI内のURLをページタイトルに変換するプラグインを作りました。ページタイトルの変更にも追従するので、意外と便利に使えるかなと思います。
プラグインの動作
インストールすると、以下のようになります。URLを貼り付けると、そのページタイトルが表示されます。
コードについて
コードはgoofmint/growi-plugin-replace-link-nameにて公開しています。ライセンスはMIT Licenseになります。
プラグインを追加する
利用する際には、GROWIの管理画面の プラグイン
にて追加してください。URLは https://github.com/goofmint/growi-plugin-replace-link-name
です。
使い方
利用する際には、GROWIのページURLをそのまま貼り付けてください。
https://YOUR_GROWI_URL/673da0dc7f208f8050a2b965
そうすると、プレビュー画面やページ表示の際には Test Page
といったGROWIページのタイトルが表示されます。
注意点
URLは https://
または http://
から始まるものに限ります。 パス (/673da0dc7f208f8050a2b965
のような)だけでは反応しません。
コードについて
今回は a タグに対してプラグイン機構を追加しています。Reactコンポーネントとして、デフォルトの動作をラップしています。
const activate = (): void => {
if (growiFacade == null || growiFacade.markdownRenderer == null) {
return;
}
const { optionsGenerators } = growiFacade.markdownRenderer;
// For page view
optionsGenerators.customGenerateViewOptions = (...args) => {
const options = optionsGenerators.generateViewOptions(...args);
const { a } = options.components;
options.components.a = replaceLinkName(a); // Wrap the default component
return options;
};
// For preview
optionsGenerators.customGeneratePreviewOptions = (...args) => {
const preview = optionsGenerators.generatePreviewOptions(...args);
const { a } = preview.components;
preview.components.a = replaceLinkName(a); // Wrap the default component
return preview;
};
};
変換処理について
aタグの中身を取得して、GROWIのURLかどうかを判定します。GROWIのURLであれば、ページタイトルを取得して返します。
export const replaceLinkName = (Tag: React.FunctionComponent<any>): React.FunctionComponent<any> => {
return ({ children, ...props }) => {
const { href } = props;
try {
// パスであれば処理を行わない
if (href.match(/^\//)) {
return <Tag {...props}>{children}</Tag>;
}
// あらかじめchildren(aタグの中身)が指定されている場合には、そのまま返す
if (href !== children) {
return <Tag {...props}>{children}</Tag>;
}
// GROWIのURLかどうか判断
const url = new URL(href);
if (url.hostname !== window.location.hostname) {
return <Tag {...props}>{children}</Tag>;
}
// ページのIDを取得
const id = url.pathname.replace(/^\//, '');
// ページのタイトルを取得
return <Async promiseFn={getPage} id={id}>
{({ data, error, isPending }) => {
if (isPending) return 'Loading...';
if (error) return `Something went wrong: ${error.message}`;
if (data) {
return <Tag {...props}>{data}</Tag>;
}
}}
</Async>;
}
catch (err) {
console.error(err);
}
// エラーがあれば、とりあえずそのまま返す
return (
<Tag {...props}>{children}</Tag>
);
};
};
ページタイトルの取得
ページのタイトルを取得する処理は非同期になります。その処理は react-async
を使って行っています。上記コードの <Async />
が非同期処理です。そして、 <Async />
で指定された promiseFn
が非同期処理を行います。
const getPage = async({ id }: any) => {
const res = await fetch(`/_api/v3/page?pageId=${id}`);
const json = await res.json();
const { page } = json;
const ary = page.path.split('/'); // 階層の場合、 ['チームA', '議事録', '2024年10月20日'] のようになります
return ary[ary.length - 1]; // 一番最後の要素を返します
};
GROWIのAPIドキュメントはこちらです。
GROWI REST API v3 | GROWI Docs
GROWIコミュニティについて
本プラグインは、GROWIコミュニティ(Slack)内で要望があり、開発に着手しました。プラグインで実現できそうなことであれば、XやSlackで要望を出してもらえれば、前向きに検討しますのでぜひ!
他にもヘルプチャンネルなどもありますので、ぜひ参加してください!
まとめ
GROWIプラグインを使うと、表示を自由に拡張できます。足りない機能があれば、どんどん追加できます。ぜひ、自分のWikiをカスタマイズしましょう。