3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

GROWIで別ページの内容を表示するプラグインを作りました

Posted at

オープンソースのWikiであるGROWIにはプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。

今回は、GROWIプラグインとして、GROWIの別なページの内容を表示するプラグインを作りました。共通テンプレートにしたり、お知らせを別なページに表示したりするのに使えます。

FireShot Capture 635 - Include - GROWI - localhost.jpg

プラグインの動作

Remark Directiveとして、以下のように記述します。 [] には表示するページのパスを入力します。

::include[/Shared/Message]

そうすると、以下のように表示されます。 出しておきたいメッセージ やリストなどは別ページの内容を持ってきています

FireShot Capture 635 - Include - GROWI - localhost.jpg

注意点として、include内ではGROWIプラグインは利用できません。また、 code タグのように追加の装飾が発生する表示には対応していません。

以下は共通テンプレートのページの内容です。リストや見出しくらいであれば問題ありません。

image.png

プラグインを追加する

利用する際には、GROWIの管理画面の プラグイン にて追加してください。URLは https://github.com/goofmint/growi-plugin-include です。

Admin

コードについて

コードは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 Slackへの参加はこちらから

まとめ

GROWIプラグインを使うと、表示を自由に拡張できます。足りない機能があれば、どんどん追加できます。ぜひ、自分のWikiをカスタマイズしましょう。

OSS開発wikiツールのGROWI | 快適な情報共有を、全ての人へ

3
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?