2
2

GROWIカレンダー表示プラグインの紹介

Posted at

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

今回は、GROWIプラグインとして作ったカレンダー表示プラグインを紹介します。Pukiwikiでも人気のあったプラグインなので、真似してみました。

calendar.jpg

プラグインを追加する

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

Admin

使い方

利用する際には、ページの中で $calendar と書きます。記述した場所にカレンダーが表示されます。

$calendar

日付をクリックすると、その日付で新しいページが作成できます。日報や日記などに利用できます。

new-page.jpg

オプション

利用できるオプションは以下があります。

表示する年月を変更する

1つ目の引数に月、2つ目の引数に年を指定することで、表示する年月を変更できます。

$calendar(12,2021)

表示言語を変更する

デフォルトは英語ですが、表示言語を lang オプションで変更できます。日本語は ja です。

$calendar(lang=fr)

French

日付をクリックした際のページ名生成基準を変える

デフォルトでは日付をクリックすると YYYY/MM/DD というページ名が生成されます。つまり階層構造になります。これを変更することができます。

$calendar(separator=-)

上記の指定だと、 2024-10-02 のようなページが生成されます。階層構造が嫌な場合は、こちらを利用してください。

設定の組み合わせ

上記オプションは組み合わせて利用できます。

$calendar(12,2021,lang=fr,separator=-)
$calendar(12,2021,separator=-)

コードについて

コードはgoofmint/growi-plugin-calendar: GROWI plugin shows calendar
にあります。見るべきファイルとしては、以下の2つになります。

client-entry.tsxについて

client-entry.tsxはプラグインの登録部分です。カレンダープラグインをRemarkプラグインとして登録しています。

const activate = (): void => {
  if (growiFacade == null || growiFacade.markdownRenderer == null) {
    return;
  }

  const { optionsGenerators } = growiFacade.markdownRenderer;

  optionsGenerators.customGenerateViewOptions = (...args) => {
    const options = optionsGenerators.generateViewOptions(...args);
    options.remarkPlugins.push(plugin as any); // プラグイン登録
    return options;
  };
};

src/calendar.tsについて

カレンダー表示は Vanilla Calendar - Lightweight calendar on pure JavaScript を利用しています。HTMLで表示する必要があるので、JavaScriptで利用できるものを採用しています。

import VanillaCalendar from 'vanilla-calendar-pro';
import 'vanilla-calendar-pro/build/vanilla-calendar.min.css';

Remarkプラグインの場合、描画処理がすべて visit 関数に送られてきますので、この中からカレンダー表示を行う部分だけを抜き出しています。

export const plugin: Plugin = function() {
  return (tree) => {
    visit(tree, (node) => {
      const n = node as unknown as GrowiNode;
      try {
        if (n.type === 'leafGrowiPluginDirective' && n.name === 'calendar') {
					// この中で処理
				}
			} catch (e) {
				n.type = 'html';
        n.value = `<div style="color: red;">Error: ${(e as Error).message}</div>`;
      }
		});
	});
};

オプションの取得

オプションデータは node.attributes で取得できます。

const [month, year] = Object.keys(n.attributes);
const lang = n.attributes.lang || 'en';
const separator = n.attributes.separator || '/';

そして、一旦カレンダーのタグだけ出力して終了します。

n.type = 'html';
n.value = '<div id="calendar"></div>';

HTMLのレンダリングが行われて、 #calendar があるのを確認してから描画処理に入ります。

const id = setInterval(() => {
	if (document.querySelector('#calendar') != null) {
		// カレンダーオブジェクト作成
		const cal = new VanillaCalendar('#calendar', {
			settings: {
				lang, // 表示言語
				// 表示年月
				selected: {
					month: isNaN(month as unknown as number) ? new Date().getMonth() : parseInt(month) - 1,
					year: isNaN(year as unknown as number) ? new Date().getFullYear() : parseInt(year),
				},
			},
			actions: {
				// 日付クリック時の処理
				async clickDay(event, self) {
					const page = self.selectedDates[0].replaceAll(/-/g, separator);
					const path = await getPagePath();
					location.href = `${path}${page}`;
				},
			},
		});
		// 表示
		cal.init();
		// 終了
		clearInterval(id);
	}
}, 100);

日付をクリックした際の処理

日付をクリックした際に、ページ情報を取得してページ名を正しく取得しています。

const getPagePath = async() => {
	if (location.pathname === '/') return '/';
	const pageId = location.pathname.replace(/\//, '');
	const res = await fetch(`/_api/v3/page?pageId=${pageId}`);
	const json = await res.json();
	const { path } = json.page;
	return `${path}/`;
};

まとめ

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

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

2
2
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
2
2