オープンソースのWikiであるGROWIにはプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。
今回は、GROWIプラグインとして、GROWIの別なページの内容を表示するプラグインを作りました。共通テンプレートにしたり、お知らせを別なページに表示したりするのに使えます。
プラグインの動作
Remark Directiveとして、以下のように記述します。 []
には表示するページのパスを入力します。
::include[/Shared/Message]
そうすると、以下のように表示されます。 出しておきたいメッセージ
やリストなどは別ページの内容を持ってきています
注意点として、include内ではGROWIプラグインは利用できません。また、 code
タグのように追加の装飾が発生する表示には対応していません。
以下は共通テンプレートのページの内容です。リストや見出しくらいであれば問題ありません。
プラグインを追加する
利用する際には、GROWIの管理画面の プラグイン
にて追加してください。URLは https://github.com/goofmint/growi-plugin-include
です。
コードについて
コードはgoofmint/growi-plugin-includeにて公開しています。ライセンスはMIT Licenseになります。
最初に ::include
というRemark Directiveを処理します。この記述があれば、 a
タグに変換します。また、 include = true
を追加して、他の a
タグとの区別をつけています。
vist
メソッドで、RemarkのAST leafDirective
を処理します。2つ目の引数を指定すると、そのディレクティブの場合のみ呼び出されるので便利です。 leafDirective
は、行頭で ::
から始まるディレクティブです。
export const remarkPlugin: Plugin = () => {
return (tree: Node) => {
visit(tree, 'leafDirective', (node: Node) => {
const n = node as unknown as GrowiNode;
if (n.name !== 'include') return;
console.log(n);
const data = n.data || (n.data = {});
// Render your component
const { value } = n.children[0] || { value: '' };
data.hName = 'a'; // Tag name
data.hChildren = [{ type: 'text', value }]; // Children
// Set properties
data.hProperties = {
href: 'https://example.com/rss',
title: JSON.stringify({ ...n.attributes, ...{ include: true } }), // Pass to attributes to the component
};
});
};
};
外部データを取得して表示
GROWI 7.2から、React Hooksに対応しました。今回のプラグインではそれを使って別なページの内容を取得&表示に反映しています。
export const helloGROWI = (Tag: React.FunctionComponent<any>): React.FunctionComponent<any> => {
return ({ children, ...props }) => {
try {
const { include } = JSON.parse(props.title);
if (include) {
const { react } = growiFacade;
const { useEffect, useState } = react;
const [contents, setContents] = useState('');
const getContent = async() => {
// ページの内容を取得する処理
};
useEffect(() => {
getContent();
}, []);
return (
<>
<div dangerouslySetInnerHTML={{ __html: contents }} />
</>
);
}
}
catch (err) {
// console.error(err);
}
// Return the original component if an error occurs
return (
<Tag {...props}>{children}</Tag>
);
};
};
ページを取得する処理
getContent
では、GROWI JS SDKを使ってページの内容を取得しています。ページの内容を取得するためには、 growi.page
でページを取得し、 contents
で内容を取得します。
取得した内容はMarkdownなので、 unified
でHTMLに変換しています。
const getContent = async() => {
const page = await growi.page({ path: children });
const contents = await page.contents();
const file = await unified()
.use(remarkParse)
.use(remarkRehype)
.use(rehypeStringify)
.process(contents);
setContents(String(file));
};
GROWIコミュニティについて
プラグインの使い方や要望などがあれば、ぜひGROWIコミュニティにお寄せください。実現できそうなものがあれば、なるべく対応します。他にもヘルプチャンネルなどもありますので、ぜひ参加してください!
まとめ
GROWIプラグインを使うと、表示を自由に拡張できます。足りない機能があれば、どんどん追加できます。ぜひ、自分のWikiをカスタマイズしましょう。