ククログ

株式会社クリアコード > ククログ > RedmineのMarkdownで箇条書きを書きやすく

RedmineのMarkdownで箇条書きを書きやすく

RedmineのデフォルトのテキストフォーマッタはTextileですが、社内でMarkdownを使いたいという声が大きかったのでMarkdownを使えるようにして運用しています。 しかし、RedmineのMarkdownはRedcarpetを使用しているため3レベル以上のリストを書くときのインデントが辛い感じでした。 Redmineで3レベル以上の箇条書きでも2インデントでよくしたい · Issue #8 · clear-code/statistics

そこで、ククログでも使用しているCommonMarkerを使えるようにしてみました。

インストール方法はリンク先を参照してください。

Redmineを新しい記法に対応させる方法

上記プラグインを実装している過程でRedmineを新しい記法に対応させる方法をソースコードを読んで調べました。 ソースコードはdd9c0a82を使いました。

Redmine::WikiFormatting.map do |format|
  format.register :commonmark # :新しい記法の名前
                  Redmine::WikiFormatting::CommonMark::Formatter # 新しい記法で使うフォーマッタのクラス
                  Redmine::WikiFormatting::CommonMark::Helper # 新しい記法で使うヘルパーのクラス
                  Redmine::WikiFormatting::CommonMark::HtmlParser # 新しい記法で使うHTMLパーサーのクラス
end

という感じで登録すればよいです。 あとは必要なクラスを実装していけば、新しい記法を追加することができます。 一番最後の引数にハッシュを指定すると、追加のオプションを指定できます。調べた時点だと:labelというキーで、設定画面に表示するラベルを変更できるだけでした。1

新しい記法で使うフォーマッタのクラスは、以下のインスタンスメソッドを実装している必要があります。

  • initialize(text)

  • to_html(*args)

  • get_section(index)

  • update_section(index, update, hash=nil)

  • extract_section(index)

セクションごとの更新が不要であれば、*_section系のメソッドは何もしないようにすることも可能でしょう。

新しい記法で使うヘルパーのクラスは、編集画面で使用するツールバーを読み込むためのヘルパーメソッドを定義します。

  • wikitoolbar_for(field_id)

  • initial_page_content(page)

  • heads_for_wiki_formatter

編集画面にツールバーが不要であれば、何もしないようにすることも可能でしょう。

新しい記法で使うHTMLパーサーのクラスでは、HTMLを新しい記法のテキストに変換するためのルールを定義します。 MarkdownやTextileだとHTMLタグと記法の対応が決まっているので、その対応が定義されていました

CommonMarkと(Redcarpetの)Markdownは、ほぼ同じなのでredmine_common_markではRedmineのMarkdown記法で使われているRedmine::WikiFormatting::Markdown::HelperRedmine::WikiFormatting::Markdown::HtmlParserを流用しました。

非互換

互換性のないところがいくつかあります。

`#prefer_delayed_commit`| `#prefer_buffered_processing`|      結果
:----------------------:|:----------------------------:|:---------------------:
      false             |           false              |     non-buffered
      false             |           true               | buffered synchronous
      true              |           true               | buffered asynchronous
      true              |           false              |      選択不可

上のようなテーブルを書くと、3行目以降が整形済みテキストになってしまいます。 以下のように行頭にパイプを追加することで回避できます。

|`#prefer_delayed_commit`| `#prefer_buffered_processing`|      結果
|:----------------------:|:----------------------------:|:---------------------:
|      false             |           false              |     non-buffered
|      false             |           true               | buffered synchronous
|      true              |           true               | buffered asynchronous
|      true              |           false              |      選択不可

CommonMarkerで使っているgithub/cmarkにオートリンクのバグがありました。既に報告済みで、報告してから11時間くらいで修正されていました。

まとめ

このようにRedmineは、ちょっとした改造なら本体に手を入れなくても、プラグインを作れば実現できてとても便利です。

  1. redmine_common_markで使っています