hatena2.rb

Win専用。はてな記法をパースしてHTMLにしてIEで見る。
記法のパースの忠実度はhparserライブラリに依存。
スタイルは環境変数HATENA2_DIRかホームのディレクトリに
'.hatena2rc'という名前で置く。

#=hatena2
#
#==dependences
#- Windows
#- hparser

require 'win32ole'
require 'hparser'

def main
  path = nil
  Hatena2.write_temporary_file do |f|
    Hatena2.to_html(ARGF.read, f)
    path = File.expand_path(f.path)
  end
  Hatena2.local_browsing_thread(path).join
end



# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

module Hatena2
  TEMP_DIR = ENV['TMPDIR'] || ENV['TMP'] || ENV['TEMP'] || '/tmp'
  HOME_DIR = ENV['HATENA2_DIR'] || ENV['HOME'] || '.'
  RC_NAME = '.Hatena2rc'
  
  
  def write_temporary_file(&block)
    raise LocalJumpError, 'block not given' unless block_given?
    File.open(temp_path('__hatena2_preview__.html'), 'w', &block)
  end
  module_function :write_temporary_file
  
  
  def local_browsing_thread(path)
    Thread.new(browser(), local_uri(path)){|br, uri|
      br.visible = true
      br.navigate(uri)
    }
  end
  module_function :local_browsing_thread
  
  
  def to_html(src, io)
    io.puts HEADER
    parser = HParser::Parser.new
    #HParser seems not to be able to parse empty source.
    parser.parse(src.empty? ? 'No Content' : src).each do |e|
      io.puts e.to_html
    end
    io.puts FOOTER
    io
  end
  module_function :to_html
  
  
  
  class << self
    def browser
      WIN32OLE.new('InternetExplorer.Application')
    end
    
    def temp_path(base)
      File.join(TEMP_DIR, base)
    end
    
    def local_uri(*base)
      (['file://localhost'] + base).join('/')
    end
    
    def default_css
      if File.exist?(File.join(HOME_DIR, RC_NAME))
        css = local_uri(HOME_DIR, RC_NAME)
        %Q|<link href="#{css}" type="text/css" rel="stylesheet" />|
      else
        ''
      end
    end
  end
  
  
  HEADER = <<-Eos
<?xml version="1.0" ?>
<!DOCTYPE html 
  PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>Preview</title>
#{default_css()}
</head>
<body>
  Eos
  
  
  FOOTER = <<-Eos
</body>
</html>
  Eos
end

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #


#----------------
main