Redmine Includeマクロ拡張マクロを拡張してテーブル表示できるようにした


この記事は Redmine Advent Calendar 2022 13日目です。

RedmineにはWikiページを挿入する include というマクロがありますが、以前それを拡張してWikiページの特定のセクションだけを挿入できるようにした Redmine Include Macro Extension というプラグインを作りました。これをさらに拡張して、複数のWikiページの同じ名前のセクションを表で表示する機能を追加しました。

使い方

まず、Redmine組み込みの include マクロはこんな感じです。「Child1」というWikiページ全体が挿入されます。

1
{{include(Child1)}}

「Child1」というWikiページの「Sec1」というセクションだけを挿入する場合は以下のように第2引数にセクション名「Sec1」を指定します。セクションのタイトル行も含まれますので、これを除く場合は noheading オプションを追加します。また、子のセクションがある場合(例えば、## Sec1 の後ろに ### Sec1.1 がある場合)は子セクションごと挿入されるので、これを除く場合は nosubsection オプションを追加します。Wikiページやセクションがない場合はエラーメッセージが表示されますが、 noraise オプションを指定することでエラーを表示せずに空欄にすることができます。

1
2
3
4
5
{{include(Child1, Sec1)}}
{{include(Child1, Sec1, noheading)}}
{{include(Child1, Sec1, nosubsection)}}
{{include(Child1, Sec1, noraise)}}
{{include(Child1, Sec1, noheading, nosubsection, noraise)}}

ここからが追加した機能です。

複数のページの同じセクションを表で表示する場合は、以下のように記述します。ページが行、セクションが列で表示されます(編集時に記述する行列とレンダリングされる行列が同じ)。また include_by_table では、上記の noheading, nosubsection, noraise を指定したのと同様の動きになります。

1
2
3
4
5
{{include_by_table(Sec1, Sec2)
Child1
Child2
Child3
}}

また、セクションを行、ページを列としたい場合は、 include_by_table_transpose を使用します。これも編集時とレンダリング語の行列が同じであることに変わりありません。

1
2
3
4
{{include_by_table_transpose(Child1, Child2, Child3)
Sec1
Sec2
}}

ただし、includeマクロを力技でゴリゴリ回しているだけなので、あまり多いと遅くなります。体感として、300セル程度の表になると表示が遅く感じられるようになります。

作った理由

私は、同じテンプレのWikiページを書いて、それを台帳的に見せる用途で使っています。

チケットでやればいいじゃん?そうですね。ですが、カスタムフィールドを含め、チケットの入力項目はキチンと設計しないと将来負債になりかねませんよね。たとえば、あるカスタムフィールドが不要になったから削除したいけど、削除しちゃうと過去のデータも失われてしまう、だから名前を「ほげほげ(廃止)」にしてお茶を濁す、のように。そして、長期運用するとそんな項目が増えていきます。

そういう経験をして、「チケットのフィールドは必要最小限にすべき」という境地1に達すると、おいそれとフィールドを増やすことができなります。チケットにフィールドを増やさなくなった結果、「チケットの説明欄に特定のフォーマットで書く」というルールができ、情報へのアクセスが悪くなり、「チケットとは…?」という状況になります。少なくとも私はなりました。

私は、「項目を追加すること」「項目を削除すること」へのハードルを上げたくない、項目を増減することへの恐怖をなくしたい、項目の増減を心理的なハードルなくトライアンドエラーできるようにしたかった。それに、せっかくチケット起票者のことを考えて作ったフィールドが将来厄介者になってしまうのは悲しいし、チケット画面が不要な入力項目だらけになってしまって使い勝手が悪くなるのも悲しいし、思い切ってフィールドを消してこれまで頑張って入力してきたデータがなくなってしまうのも悲しい。

ともあれ、「説明欄に記述する」ということになるのであれば、MarkdownもTextileも構造化テキストなので、本来であれば構造化テキストのメリットを享受できるはず→チケットの説明欄だとやりづらい→WikiにはincludeマクロあるしWikiで書いてincludeマクロでぶっこぬけばよい、という考えでこの機能を作りました。

Wikiであれば、項目が不要になった際にも、新しいページには不要項目は書かずに、既存のWikiページはそのままにできます。既存ページから項目を削除しても履歴には残ります。Wikiは複数のページをまたいで俯瞰してみることができない弱みがありましたが、このマクロで表形式で一覧表示させれば…なんということでしょう、思い描いた未来がそこにあるではありませんか。

もし、Wikiページを一括更新したければ、Rest APIでゴリゴリ更新することもできますしね。

そんなカンジです。

おまけ:高速化案

試してませんが、設定に「テキスト書式の変換結果をキャッシュ(Cache formatted text)」という設定があって、これをONにすることで事前にHTMLに変換されるので遅さはなくなります。ただ、元のページが更新されても、マクロが記述されたページは更新されません(組み込みのincludeマクロにも同じ問題はあると思います)。この場合は、Rest APIを叩いて定期的に該当ページを更新する対応が必要になると思います。


  1. 私は「チケットのフィールドは必要最小限であるべき」派です。 ↩︎