「Ruby on Rails 教育関連 Trac」 Redmine化計画 (Redmine wikiの機能拡張)

EY-OfficeのRuby on Rails教育で作っている、Ruby on Rails 教育関連 TracTrac から Redmine に移行しようとしています。

Tracは完成度も高いのですが、やはり何か機能を変更したいと思った場合、Pythonで書かれているので私には敷居が高すぎます。また Railsの実行環境として Passenger が出てきて環境の構築が簡単になった事もあり ey-office.com にある Trac
Redmine に変更しようと考えています。


まず、コンテンツの移行ですが、Redmine には Trac からコンテンツを移行する機能を持っています ^^)/

ドキュメント -> 英語 , 日本語

Tracの動いている環境のあるサーバーまたは、Tracのプロジェクトをコピーしてきて

rake redmine:migrate_from_trac RAILS_ENV="production"

を実行し、質問に答えていくだけでコンテンツが移行でききました。 完全にTracWiki記法に対応しているわけではないですが、リンク等を少し変更するだけで済みました。


さて、Ruby on Rails 教育関連 Tracでは 練習問題の解答例が書かれていますが、以下のように追加部分を赤字で表示しています。

これは絶対にRedmineでも対応したいポイントです。 TracWikiはHTMLを直接書ける機能があるので、それを使って赤字を表示しています。 しかし、 RedmineWikiにはこのような機能はありません。

RedmineWikiには Macro で機能を追加できるようになっていますが、インライン要素用で コードの表示等には使えそうもありません。

      # Builtin macros
      desc "Sample macro."
      macro :hello_world do |obj, args|
        "Hello world! Object: #{obj.class.name}, " + (args.empty? ? "Called with no argument." : "Arguments: #{args.join(', ')}")
      end

      desc "Displays a list of all available macros, including description if available."
      macro :macro_list do
        out = ''
        @@available_macros.keys.collect(&:to_s).sort.each do |macro|
          out << content_tag('dt', content_tag('code', macro))
          out << content_tag('dd', textilizable(@@available_macros[macro.to_sym]))
        end
        content_tag('dl', out)
      end
   ....

RedmineWikiTextileに独自機能を追加しています。追加機能の1つに (Ruby)コードのシンタックスハイライトがあります。 <pre><code class="ruby"> ..... のように書くと 拡張部分でシンタクスハイライト機能を呼び出すようになっています。

      # Patch to add code highlighting support to RedCloth
      def smooth_offtags( text )
        unless @pre_list.empty?
          ## replace <pre> content
          text.gsub!(/<redpre#(\d+)>/) do
            content = @pre_list[$1.to_i]
            if content.match(/<code\s+class="(\w+)">\s?(.+)/m)
              content = "<code class=\"#{$1} CodeRay\">" + 
                CodeRay.scan($2, $1.downcase).html(:escape => false, :line_numbers => :inline)
            end
            content
          end
        end
      end

この部分に手を入れて、<pre><code="color">の場合は、独自の色づけができるようなコードを追加すれば良さそうです。
そこで、プラグインを作ってみました。

module Redmine
  module WikiFormatting

    class TextileFormatter < RedCloth
      alias :smooth_offtags_orgin :smooth_offtags

      private :smooth_offtags
      def smooth_offtags( text )
        unless @pre_list.empty?
          ## replace <pre> content
          text.gsub!(/<redpre#(\d+)>/) do
            content = @pre_list[$1.to_i]
            if content.match(/<code\s+class="(color)">\s?(.+)/m)
              content = "<code>" + $2.gsub('##(', '<span style="color:#F00">').gsub(')##', '</span>')
            elsif content.match(/<code\s+class="(\w+)">\s?(.+)/m)
              content = "<code class=\"#{$1} CodeRay\">" + 
                CodeRay.scan($2, $1.downcase).html(:escape => false, :line_numbers => :inline)
            end
            content
          end
        end
      end
    end

    def self.to_html(text, options = {}, &block)
      TextileFormatter.new(text).to_html(&block)
    end

  end
end

これで、Redmine でも赤字が表示できました ^^)/〜

ただし、プラグインコードの最後の def self.to_html コードがなぜ必要なのかが分かりません・・・ これがないと元のWikiFormattingモジュールにはto_htmlメソッドがあるのに、 to_htmlメソッドがないというエラーになってしまいます。
分かる方教えて下さい m(__)m