目次
- はてな記法で静的コンテンツ生成のためにText::Hatenaを使うことにした
- わりとうまくいった
- なぜかTeX記法も見れた
- iPhone上での使いやすさが結構やばい
- 変換用のソースと一括変換用のソース
内容
Blogとか動的なコンテンツじゃなくて、静的なコンテンツを作りたいと思っている。MakeWebを利用しようかと思ったんだけど、はてな記法でいうリスト記法(かな?)を多用しまくる僕にはMakeWebの記法だとつらい。他のwikiの記法を学ぶコストもでかいし、何よりはてな記法になじみまくっているからはてな記法を使いたい。simple-hatena-modeとかなじみのあるやつで書けるっていうのも大きいな。で、Junya Kondo / Text-Hatena - search.cpan.orgがあるんだけど、昔cpanでインストールしようとするとこけた記憶があるし*1、Perlで3行以上もう書ける気しないというわけで探していたらRubyのやつを見つけた。
なお、はてぶコメントでid:noplansさんにhparserというのもあることを教えてもらいました。JavaScriptのやつは知ってたんだけどな。rake installしました。gemじゃないインストールは何気に初めて。Rubyなら分かる気がするので、書いてみた。こんな感じで実行すると
/Users/yasuhisa% ruby test.rb -i /Users/yasuhisa/hatena/syou6162/diary/2009-01-04.txt -o fuga.html
こんな感じのhtmlを吐いてくれる。cssは別途容易した。
追記
別ファイルにするのが面倒だったので、cssも一緒にした。
はてな記法で書いたテキストファイルの数を見ると
/Users/yasuhisa% ls hatena/syou6162/diary/*.txt hatena/syou6162/group/syou6162/*.txt hatena_keyword/syou6162/*.txt | wc -l 1275
とかなっている(はてなグループのキーワードもローカルから飛ばすようにしている)僕なので、かなり使えそうな感じである。あと、こんな感じで、TeX記法までできちゃうんだけど、これはいいんだろうか。。。いや、便利なんですが。
追記
見れるのはローカルだけっぽい。他のサイトにhtmlファイルを置いても見れないようになっているようだ。安心した(何。
See it on iPhone
いや、何を隠そうiPhoneで見たかったのです。
iPhoneだと操作性が限定されてくるので
- 上部に目次を作って下のページでもすぐに行けるようにする
- 下部のページにいても目次にすぐに戻れるようにする(エピソード3のまとめの右の■で戻れるようにしてある)
というどうでもよさげなライフハック(笑)を実行してあります。iPhoneに大量のhtmlを仕込むと容量を圧迫するので、DropBoxなど雲の上に置いておくといいかなーと思います。touchだったら仕込んだほうがいいかもしれないけど。
ソースは以下。
# -*- coding: utf-8 -*- require "rubygems" require "mechanize" require "optparse" require "text/hatena" require "pp" @options = { :i => nil, :i => nil, :s => "■", :p => true } opts = OptionParser.new opts.on('-i file', '--input file', 'specify the input file name') {|f| @options[:i] = f} opts.on('-o [file]', '--output [file]', 'specify the output file name') {|f| @options[:o] = f} opts.on('-s chat', '--sectionanchor char', 'specify the sectionanchor') {|c| @options[:s] = c } opts.on("-p", "--presentation", TrueClass){|boolean| @options[:p] = !boolean} opts.parse!(ARGV) if @options[:i].nil? puts "file name is needed." exit end sectionanchor = @options[:s] parser = Text::Hatena.new({ :parmalink => 'http://www.example.com/entry/123', :sectionanchor => sectionanchor }) file = @options[:i] title = File.basename(file,".*") f = open(file,"r") text = f.read f.close header =<<EOS <?xml version="1.0" encoding="utf-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <link rev="made" href="mailto:<-mail>" /> <link rel="index" href="index.html" /> <link href="./main.css" type="text/css" rel="stylesheet" /> <title>hogehoge</title> </head> <style type="text/css"> <!-- body { margin-left: 88px; margin-right: 7%; background-color: #fff; background-repeat: repeat-y; text-align: left; font-family: sans-serif; } h3 { font-size: 120%; color : #000000; text-align : left; background : #fefeee; padding : 0.3em 0.3em 0.3em 0.5em; border-width : 1px 1px 1px 1px; border-style : solid; border-color : #aa2; } h4 { font-size: 110%; margin: 1em 0 1em 0; padding-left : 0.2em; color : #000; text-align : left; background : transparent; border-width : 0em 0em 1pt 0pt; border-style : dashed; border-color : #aaa; } h5 { font-size: 100%; color : #000; text-align : left; background : transparent; border-width : 0em 0em 1pt 0pt; border-style : dotted; border-color : #274; margin-left : 0.4em; } img { border: 0pt; } .title { color: #fff; background-color: #225; border-color : #9ad; margin: 1em 0 1em 0; font-size: 170%; padding: 0.4em 0.6em; border-width : 0px 4px 4px 0px; border-style : solid; } a { text-decoration:none; } a:hover { background-color: #CCCCFF; } p, ul, ol, li, pre { margin-left: 1em; line-height: 120%; } pre.hatena-super-pre { padding: 0.5em 0.5em 0.5em 0.5em; background-color: #efd; font-size: 100%; } table { width: 90%; margin-left: 1em; border-spacing: 0.2em 0.5em; } th { border-color : #aaa; border-width : 0px 2px 2px 0px; border-style : solid; } td { border-color : #aaa; border-width : 0px 2px 2px 0px; border-style : solid; } tr { margin: 1em 0 1em 0; } blockquote { margin: 0 1em 0 2em; padding: 1em 1em 1em 1em; background-color: #efd; font-size: 90%; } .footer { border-top: gray thin solid; margin: 3em 0 0 0; padding: 1em 0 0 0; } --> </style> <body> <a name="top"></a> <h1 class="title">#{title}</h1> EOS footer =<<EOS </body> </html> EOS text.sub!(/\[:presentation\]/,"") if @options[:p] text.gsub!(/(asin:(.*?)):(title|detail|image)/){$1} parser.parse(text) source = Hpricot(parser.html) tableofcontents = "<ul>\n" (source/"div>h3").each_with_index{ |item,index| tableofcontents = tableofcontents + "\t<li><a href=\"#p#{index}\">" + item.inner_text.sub(/^#{@options[:s]}\s(.*?)/){$1} + "</a></li>\n" } tableofcontents = tableofcontents + "</ul>\n" html = header + tableofcontents + parser.html.gsub(/(<\/h3>)/){ "\s<a href=\"#top\"><span class=\"sanchor\">#{@options[:s]}</span></a>#{$1}" } + footer if @options[:o].nil? puts html else f = File.open(@options[:o],'w') f.puts html f.close end
ファイルを一斉にtxtからhtmlに変換
ターミナルで回せばよかったんだろうけど、なんか怖かったので(ぉ。
Dir.chdir("/Users/yasuhisa/hatena_keyword/syou6162") Dir.glob("*.txt").each{|f| path = "/Volumes/syou6162/Documents/" + File.basename(f,".txt") + ".html" system "ruby /tmp/aaa.rb -i \"#{f}\" -o \"#{path}\"" }
とやってもいいけど、100個くらいhtmlができて大変なことになるので、見たいやつだけ
Dir.chdir("/Users/yasuhisa/hatena_keyword/syou6162") ["Tsukuba.R:2:イントロダクション.txt","フュ−チャーリスト宣言.txt","我らクレイジー☆エンジニア主義.txt","頭がいい人、悪い人の仕事術.txt"].each{|f| path = "/Volumes/syou6162/Documents/" + File.basename(f,".txt") + ".html" system "ruby /tmp/aaa.rb -i \"#{f}\" -o \"#{path}\"" }
とかとするのがよさそう。
*1:今試しにインスコしてみたら入ったしwww