テキストに含まれる http://〜〜を ハイパーリンクするように変換

●何がしたいのか
たとえば、

必読! http://gettingreal.37signals.com/GR_jpn.php ど う ぞ

というテキストを

必読! <a herf="http://gettingreal.37signals.com/GR_jpn.php">http://gettingreal.37signals.com/GR_jpn.php</a> ど う ぞ

というように、aタグをつけて変換したい。


●作ってみた
・hyperlink_for_url.rb

=begin
Example:
    require 'hyperlink_for_url'
    
    str = "必読! http://gettingreal.37signals.com/GR_jpn.php ど う ぞ"
    converted =  HyperlinkForUrl::Conversion.conversion(str)

Note:
    It made it on November 28, 2007
    It made it with Ruby 1.8.6
    The character-code is utf8
    It corresponds to http: and https:
=end

module HyperlinkForUrl
  class Conversion
    def self.number_of_checks_of_http(str)
      str << "\n"
      i = count = 0
      check = ""
      @delimitation = []
      str.each_byte {|c|
        if check == "http:" || check == "https:"
          @delimitation[i] = count-5 if check == "http:"
          @delimitation[i] = count-6 if check == "https:"
          i = i + 1
          check = ""
        end
      
        if check == "http" || check == "https"
          check << ":" if c == 58   # 58=>:
          check << ":" if c == 115  # 115=>s
        end
       
        if check == "htt"
          check << "p" if c == 112  # 112=>p
        end

        if check == "ht"
          check << "t" if c == 116  # 116=>t
        end
        
        if check == "h"
          check = check + "t" if c == 116  # 116=>t
        end
        
        check = "h" if c == 104  # 104=>h
        
      count = count + 1
      }
      @delimitation
    end

    def self.hyperlink_for_url(str,url)
      cutting_url = []
      y   = 0
      url.each do |@delimitation_start|
      
      #(httpから数えて、最初の「半角空白」もしくは「改行」の場所を取得)
        i = count =0
        @delimitation = []
        str.each_byte {|c|
          if 32 == c  # 32=>SP
            @delimitation[i] = count
            i = i + 1
          end

          if 10 == c  # 10=>\n
            @delimitation[i] = count
            i = i + 1
          end

          if 13 == c  # 13=>\r
            @delimitation[i] = count
            i = i + 1
          end
        count = count + 1
        }

        #(配列のなかから、@delimitation_startより数字が大きい中で、一番数が小さいものを探す。)
        @delimitation.delete_if {|x| x <= @delimitation_start}
        
        #配列が空だったら count を代入
        if @delimitation == []
          @delimitation[0] = count
        end

        #(URL切り出し)
        cutting_url[y] = str[@delimitation_start..@delimitation[0]-1]
        y = y + 1
      end

      n = 0
      record = []
      cutting_url.each do |u|
        #aタグを使ってハイパーリンクにする
        if record == []
            #str = str.gsub(/#{u}\s|#{u}\r|#{u}\r\n|#{u}\n/, "<a href='#{u}'>#{u}</a>")
            str = str.gsub("#{u}", "<a href='#{u}'>#{u}</a>")
            record[n] = u
            n = n + 1
        else
          record.each do |r|
            @check = false
            if r != u
              @check = true
            end
          end
          
          if @check
            #str = str.gsub(/#{u}\s|#{u}\r|#{u}\r\n|#{u}\n/, "<a href='#{u}'>#{u}</a>")
            str = str.gsub("#{u}", "<a href='#{u}'>#{u}</a>")
            record[n] = u
            n = n + 1
          end
        end
      end
      str
    end

    def self.conversion(str)
      address = self.number_of_checks_of_http(str)
      str = self.hyperlink_for_url(str,address)
      str = str.chomp
      str
    end
  end
end


●テスト
・test_hyperlink_for_url.rb

require 'test/unit'
require 'hyperlink_for_url'

class ConversionTest < Test::Unit::TestCase

  def setup
  end

  def test_when_the_url_back_is_a_blank
    str = "must read! http://gettingreal.37signals.com/GR_jpn.php please"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "must read! <a href='http://gettingreal.37signals.com/GR_jpn.php'>http://gettingreal.37signals.com/GR_jpn.php</a> please"
  end

  def test_when_the_url_back_is_a_n
    str = "must read! http://gettingreal.37signals.com/GR_jpn.php\nplease"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "must read! <a href='http://gettingreal.37signals.com/GR_jpn.php'>http://gettingreal.37signals.com/GR_jpn.php</a>\nplease"
  end

  def test_when_the_url_back_is_a_r
    str = "must read! http://gettingreal.37signals.com/GR_jpn.php\rplease"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "must read! <a href='http://gettingreal.37signals.com/GR_jpn.php'>http://gettingreal.37signals.com/GR_jpn.php</a>\rplease"
  end

  def test_when_the_url_back_is_a_n_r
    str = "must read! http://gettingreal.37signals.com/GR_jpn.php\r\nplease"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "must read! <a href='http://gettingreal.37signals.com/GR_jpn.php'>http://gettingreal.37signals.com/GR_jpn.php</a>\r\nplease"
  end

  def test_when_the_url_back_is_none
    str = "must read! http://gettingreal.37signals.com/GR_jpn.php"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "must read! <a href='http://gettingreal.37signals.com/GR_jpn.php'>http://gettingreal.37signals.com/GR_jpn.php</a>"
  end

  def test_for_two_or_more_lines
    str = "must read! http://gettingreal.37signals.com/GR_jpn.php\r\nyes http://google.com/ \r\n and https://google.com/"
    count = 0
    s = []
    str.each_line {|line| 
      s[count] = HyperlinkForUrl::Conversion.conversion(line)
      count = count + 1
    }
    assert_equal s[0], "must read! <a href='http://gettingreal.37signals.com/GR_jpn.php'>http://gettingreal.37signals.com/GR_jpn.php</a>\r\n"
    assert_equal s[1], "yes <a href='http://google.com/'>http://google.com/</a> \r\n"
    assert_equal s[2], " and <a href='https://google.com/'>https://google.com/</a>"
  end

  def test_when_there_are_two_or_more_url_in_one_line
    str = "must read! http://gettingreal.37signals.com/GR_jpn.php http://google.com/"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "must read! <a href='http://gettingreal.37signals.com/GR_jpn.php'>http://gettingreal.37signals.com/GR_jpn.php</a> <a href='http://google.com/'>http://google.com/</a>"
  end

  def test_when_same_url_exists
    str = "must read! http://google.com/ http://google.com/"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "must read! <a href='http://google.com/'>http://google.com/</a> <a href='http://google.com/'>http://google.com/</a>"
  end

  def test_when_same_url_is_in_another_line
    str = "must read! http://google.com/ http://google.com/\r\n http://google.com/"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "must read! <a href='http://google.com/'>http://google.com/</a> <a href='http://google.com/'>http://google.com/</a>\r\n <a href='http://google.com/'>http://google.com/</a>"
  end

  def test_when_same_url_is_in_another_line_2
    str = "aa http://google.com/ aa \r\naa http://yahoo.co.jp/ \r\n http://google.com/ http://live-revolution.co.jp a"

    count = 0
    s = []
    str.each_line {|line| 
      s[count] = HyperlinkForUrl::Conversion.conversion(line)
      count = count + 1
    }
    assert_equal s[0], "aa <a href='http://google.com/'>http://google.com/</a> aa \r\n"
    assert_equal s[1], "aa <a href='http://yahoo.co.jp/'>http://yahoo.co.jp/</a> \r\n"
    assert_equal s[2], " <a href='http://google.com/'>http://google.com/</a> <a href='http://live-revolution.co.jp'>http://live-revolution.co.jp</a> a"
  end

  def test_when_there_is_https
    str = "https://google.com/"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "<a href='https://google.com/'>https://google.com/</a>"
  end

  def test_when_http_exists_together_to_https
    str = "https://google.com/ http://google.com/"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "<a href='https://google.com/'>https://google.com/</a> <a href='http://google.com/'>http://google.com/</a>"
  end

  def test_when_there_is_question_mark
    str = "http://google.com/?test=test"
    str = HyperlinkForUrl::Conversion.conversion(str)
    assert_equal str, "<a href='http://google.com/?test=test'>http://google.com/?test=test</a>"
  end
end

●使い方

require 'hyperlink_for_url'

str = "必読! http://gettingreal.37signals.com/GR_jpn.php ど う ぞ"
converted =  HyperlinkForUrl::Conversion.conversion(str)
p converted  #=> 必読! <a herf="http://gettingreal.37signals.com/GR_jpn.php">http://gettingreal.37signals.com/GR_jpn.php</a> ど う ぞ