読者です 読者をやめる 読者になる 読者になる

Rote::Format::HTML#link_relを勝手にかけてくれるRote::Filters::AutoLinkRel

昨日に引き続き、roteを使ってみて不便だったところを拡張してみました。

標準ではRote::Format::HTML#link_rel(or relative)というメソッドをつかうとROOTからの相対パスにして返してくれるというメソッドがあるのですが、ほとんどのURIを記述する場面でこれを使った方がよいと思われたので/から始まるパスを記述すると相対リンクに勝手に変換をしてくれるRote::Filters::AutoLinkRelというのを書きました。

post_filterで使わないとレイアウトテンプレートのリンクが変換されないのに注意してください。

昨日のと合わせてこれも作者さんに送ってみるつもり。

require 'rubygems'
require 'rote/format/html'
require 'rote/filters/base'

# If you write URI whitch was start from '/' in double quote in markup,
# convert URI to relative path to use Rote::Format::HTML#link_rel(link)
#
#= SYNOPSYS
# # in your project's Rakefile
#   ws = RDocTask.new(:doc) do |site|
#     ...
#     site.ext_mapping(...) do |page|
#       page.post_filter Filters::AutoLinkRel.new
#     end
#   end
#
# URI in ERB markup tag is ignored. So you can escape auto link
# with this.
# 
#   <a href="<%= "//hoge/hoge.html" %>" >...</a> 
#
module Rote
  module Filters
    class AutoLinkRel < TextFilter
      include ::Rote::Format::HTML
      ABSOLUTE_PATH_REGEX = %r{<[^%]*?"(/.*?)".*?>} # ex. <some_tag "/images/hoge.png">

      attr_accessor :template_name # for Format Hack

      def initialize *options
        super()
        @options = options
        @template_name = ""
      end

      def handler text, page
        @template_name = page ? page.template_filename : ""
        text.map do |line|
          line.scan(ABSOLUTE_PATH_REGEX).flatten.each do |abs_link|
            line.sub!(abs_link, link_rel(abs_link))
          end

          line
        end.join 
      end
    end
  end
end

if $PROGRAM_NAME == __FILE__
  require 'spec'

  context "Filter Test: " do
    setup do
      @filter = Rote::Filters::AutoLinkRel.new
    end

    def one_url_data link
      %{<a href="#{link}">...</a>}
    end

    specify "absolute link should be changed to relative link" do
      @filter.filter(one_url_data("/hoge/hoge.html"), nil)\
          .should_be_equal(one_url_data("hoge/hoge.html"))
    end

    specify "relative link should not be changed" do
      @filter.filter(one_url_data("hoge/hoge.html"), nil)\
          .should_be_equal(one_url_data("hoge/hoge.html"))

      @filter.filter(one_url_data("./hoge/hoge.html"), nil)\
          .should_be_equal(one_url_data("./hoge/hoge.html"))
    end

    specify "not quoted absolute link should not be changed" do
      @filter.filter("/hoge/hoge.html", nil)\
          .should_be_equal "/hoge/hoge.html"
    end

    specify "absolute links in ERB tag should not be changed" do
      @filter.filter(%{<%= link_rel "/hoge/hoge.html" %>}, nil)\
          .should_be_equal %{<%= link_rel "/hoge/hoge.html" %>}
    end

    def two_url_data link1, link2
      %{<a href="#{link1}"><img src="#{link2}" /></a>}
    end

    specify "many absolute links should be change" do
      @filter.filter(
          two_url_data("/hoge/hoge.html", "/images/hoge.png"), nil)\
          .should_be_equal(
              two_url_data("hoge/hoge.html", "images/hoge.png"))
  
    end
  end

end

true

テストは最近っぽくrspecを使ってみました。