1
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内のURLをページタイトルに変換するプラグインを作りました。ページタイトルの変更にも追従するので、意外と便利に使えるかなと思います。

プラグインの動作

インストールすると、以下のようになります。URLを貼り付けると、そのページタイトルが表示されます。

image.png

コードについて

コードはgoofmint/growi-plugin-replace-link-nameにて公開しています。ライセンスはMIT Licenseになります。

プラグインを追加する

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

Admin

使い方

利用する際には、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 Slackへの参加はこちらから

まとめ

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

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

1
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
1
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?