2
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でMarkdownテーブルにソート・検索・ページネーション機能を追加するプラグインを作成しました

Posted at

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

今回は、GROWIプラグインとして作ったTable Gridプラグインを紹介します。これは、Markdown記法で記述したテーブルにGrid.jsを適用して、ソート・検索・ページネーション機能を追加するものです。

FireShot Capture 148 - 66d9614f056cf96cc52c8a40 - GROWI - localhost.jpg

プラグインを追加する

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

Admin

使い方

利用する際には、編集画面でいつも通りMarkdown記法にてテーブルを記述します。

| Header1 | Header2 | Header3 |
| ------- | ------- | ------- |
| 1       | 2       | 3       |
| 4       | 5       | 6       |
| 7       | 8       | 9       |

そうすると、プレビュー画面にはGrid.jsを使った高機能なテーブルが表示されます。

FireShot Capture 146 - 66d9614f056cf96cc52c8a40 - GROWI - localhost.jpg

注意点

空の行があると、うまく描画できないようです。また、データの編集に対してリアルタイムに反映できない問題があります。反映したい場合には、一旦空白行を入れて(エラーにして)から、再度正しいデータを入力すると反映されます。

コードについて

今回はtableタグに対してプラグイン機構を追加しています。HTML構造に対して適用するので、Rehypeのプラグインとして実装しています。

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);
    options.rehypePlugins.push(plugin as any); // プラグインを追加
    return options;
  };

  // For preview
  optionsGenerators.customGeneratePreviewOptions = (...args) => {
    const preview = optionsGenerators.generatePreviewOptions(...args);
    preview.rehypePlugins.push(plugin as any); // プラグインを追加
    return preview;
  };
};
export const plugin: Plugin = function() {
  return (tree) => {
    visit(tree, (node) => {
      const n = node as unknown as GrowiNode;
      try {
		// tableタグ以外は無視
        if (n.type !== 'element' || n.tagName !== 'table') {
          return;
        }
		// この中で実装
      }
      catch (e) {
        n.type = 'html';
        n.value = `<div style="color: red;">Error: ${(e as Error).message}</div>`;
      }
    });
  };
};

変換処理について

tableタグの中身から、thead/tbodyを取得します。そして、それぞれをGrid.jsの形に合わせて変換します。

const [thead, tbody] = n.children;
const columns = thead.children[0].children.map(c => c.children[0].value);
// ["Header1", "Header2", "Header3"] となる
const data = tbody.children.map(row => row.children
	.map(cell => cell.children[0].value));
// [["1", "2", "3"], ["4", "5", "6"], ["7", "8", "9"]] となる

そして、それをGrid.jsに対して適用します。オプションはなるべく多くしています。スタイルは、GROWIのテーマに合わせています。

const grid = new Grid({
	columns,            // ヘッダー
	data,               // データ
	pagination: true,   // ページネーション
	search: true,       // 検索
	sort: true,         // ソート
	resizable: true,    // カラムサイズ変更
	// スタイル
	style: {
		table: {
			border: '2px solid var(--bs-secondary-bg)',
		},
		th: {
			color: 'var(--bs-body-color)',
			backgroundColor: 'var(--bs-body-bg)',
		},
		td: {
			color: 'var(--bs-body-color)',
			backgroundColor: 'var(--bs-body-bg)',
		},
		footer: {
			backgroundColor: 'var(--bs-secondary-bg)',
		},
	},
});

この時点ではまだHTMLにDOMが追加されていないので、追加を確認でき次第Grid.jsでレンダリングしています。

// 識別用のクラス
const className = `table-grid-${Math.random().toString(36).slice(2)}`;
n.properties.className = `${n.properties.className} ${className}`;
// DOMが追加されるまで待つ
const id = setInterval(() => {
	const el = document.querySelector(`.${className}`);
	if (el) {
		clearInterval(id);
		el.innerHTML = ''; // 元々表示されているHTMLを削除
		grid.render(el); // Grid.jsでレンダリング
	}
}, 1000);

スタイルについて

GROWIではテーマを選択できるので、選択したテーマによって色が異なります。また、テーマによってダークモード・ライトモードもあります。そのため、スタイルはCSS変数を使ってテーマに合わせています。

特にカラムのソートアイコン(画像)はダークモードだと背景色と同じ色になってしまうので、CSSフィルターを使って反転させています。

@media (prefers-color-scheme: dark) {
  .gridjs-sort {
    filter: invert(100%);
  }
}

.gridjs-input {
  color: var(--bs-body-color) !important;
  background-color: var(--bs-body-bg) !important;
}

.gridjs-pages button {
  color: var(--bs-body-color) !important;
  background-color: var(--bs-body-bg) !important;
}

まとめ

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

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

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