GROWIでYouTubeのURLを埋め込み表示するプラグインを作成しました

[オープンソースの社内WikiであるGROWI](https://growi.org/ja/)ではプラグイン機能が用意されています。自社のデータを表示したり、表示をカスタマイズするのに利用できます。

今回、はじめてGROWIプラグインを開発してみたので、その手順を解説します。

## 開発したプラグイン

開発したのは、[YouTubeのURLを埋め込み表示するGROWIプラグイン](https://github.com/goofmint/growi-plugin-embed-youtube)です。GROWIのページにYouTubeのURLを貼り付けると、埋め込み表示されるようになります。

表示する際には、そのリンクが文章埋め込みか判別できないため、もし埋め込み表示にしたくない場合は youtu.be ドメインを利用してください。

```markdown
// 埋め込みになります
https://www.youtube.com/watch?v=XXXXXXXXXXX

// 埋め込みになりません
https://youtu.be/XXXXXXXXXXX

// 以下は埋め込みになりません
動画を見たい方は、[こちらのリンク](https://youtu.be/XXXXXXXXXXX)からご覧ください。
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/197026/f420950f-b692-ed3b-9830-77ea45c41c09.png)


## 元ネタ

このプラグインは[GrowiでYoutubeの動画を埋め込む #Crowi - Qiita](https://qiita.com/Nobuto/items/adb34585d11418aec69a)の記事を読んで思いついたネタです。当時はプラグイン機構があったかは不明ですが、今はプラグインで解決するのが良さそうです。

## プラグインの開発

プラグインの開発時には、[先日紹介したテンプレート](https://qiita.com/goofmint/items/497ea7dd722528cfa0cb)をベースにしています。

[goofmint/growi-plugin-script-template: This is a template for creating a GROWI script plugin.](https://github.com/goofmint/growi-plugin-script-template)

### 名前の変更

プラグインの名前を変更します。

```json "package.json"
{
	"name": "growi-plugin-youtube-embed", // 変更
	"version": "1.0.0",
	"description": "GROWI plugin for embedding YouTube videos", // 変更
	:
}
```

プラグインの開発に必要なライブラリをインストールします。

```bash
$ yarn
```

### ファイル名の変更

`src/Hello.tsx` と `src/Hello.css` を `src/EmbedYouTube.tsx` と `src/EmbedYouTube.css` に変更します。

### src/EmbedYouTube.tsxの編集

この中では、リンクの内容に応じて通常のリンクか埋め込みリンクかを判別しています。

```tsx:src/EmbedYouTube.tsx
import innerText from 'react-innertext';

import './EmbedYouTube.css';

const getYouTubeId = (href: string): string | null => {
  const url = new URL(href);
  const videoId = url.searchParams.get('v');
  if (videoId) return videoId;
  return null;
};

export const EmbedYouTube = (A: React.FunctionComponent<any>): React.FunctionComponent<any> => {
  return ({ children, href, ...props }) => {
    const videoId = getYouTubeId(href);
		// 通常のリンク
    if (!videoId) {
      return (
        <>
          <A {...props}>{children}</A>
        </>
      );
    }
		// 埋め込み表示に変換
    return (
      <div className="youtube">
        <iframe
          width="560"
          height="315"
          src={`https://www.youtube.com/embed/${videoId}`}
          title="YouTube video player"
          allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share"
          referrerPolicy="strict-origin-when-cross-origin"
          allowFullScreen
        ></iframe>
      </div>
    );
  };
};
```

### src/EmbedYouTube.cssの編集

動画をレスポンシブにするためのCSSを記述します。

```css:src/EmbedYouTube.css
.youtube {
  width: 100%;
  aspect-ratio: 16 / 9;
}
.youtube iframe {
  width: 100%;
  height: 100%;
}
```

### client-entry.tsxの編集

`client-entry.tsx` を編集して、 `a` タグの処理を上書きします。これですべての `a` タグに関する処理が `EmbedYouTube` に送られます。

```ts:client-entry.tsx
const activate = (): void => {
  if (growiFacade == null || growiFacade.markdownRenderer == null) {
    return;
  }
  const { optionsGenerators } = growiFacade.markdownRenderer;
  optionsGenerators.customGenerateViewOptions = (...args) => {
    const options = optionsGenerators.generateViewOptions(...args);
    const A = options.components.a;
    // replace
    options.components.a = EmbedYouTube(A); // 処理を上書き
    return options;
  };
};
```

## コードについて

今回のプラグインは以下にて公開しています。利用する際には、GROWIのプラグイン管理にて `https://github.com/goofmint/growi-plugin-embed-youtube` を指定してください。

[goofmint/growi-plugin-embed-youtube: YouTube URLを埋め込みに変更するGROWIプラグインです](https://github.com/goofmint/growi-plugin-embed-youtube)

## まとめ

GROWIのプラグインは、表示内容をカスタマイズするのがとても簡単に実現できます。今回は `a` タグですが、他にも `img` タグや `table` タグなどもカスタマイズできます。

ぜひプラグインを開発して、GROWIをより便利にしましょう！

[OSS開発wikiツールのGROWI | 快適な情報共有を、全ての人へ](https://growi.org/ja/)