いずれ消え行く無駄な情報を、密やかに発信する装置。つまり日記。
tDiaryのバージョンが上がっていたのでアップデートしようとしたら、ものの見事に失敗しました。かなりスクリプトのあちこちを弄ってしまっていたので、時間をかければ動くとは思うのですが、今後も毎回バージョンアップのたびに弄り回すのはキツイので、日記用のスクリプトを自作することにしました。
毎日会社から帰ってきてから少しずつ書いていたので、こんなコードを書くのに1週間もかかってしまいました。徹夜で遊べた学生時代が懐かしいなぁ。
個人的に日記を動的に生成する必要性は全くないので、日記データをただひたすらパースするだけのスクリプトになります。特に設計もせずに書いたので、少しコードを整理出来たらドキュメントをマトモに書いて公開しようかなぁ。
#!/usr/local/bin/ruby require "erb" require "time" require "date" require "fileutils" class Entries def initialize(diary_file_list) @diary_file_list = diary_file_list end #すべての日記データからエントリーを作成する。 #すべて処理が終わると、すべてのエントリーリストを返す。 def each html = "<ul>\n" @diary_file_list.each_with_index{|file, count| data = parse_html(file) entry = Hash.new entry[:file_path] = file entry[:count] = count + 1 entry[:date] = parse_date(file) entry[:title] = data[0] entry[:tags] = data[1] entry[:text] = data[2] entry[:next_link] = make_link_next_entry(file) entry[:prev_link] = make_link_prev_entry(file) entry[:permalink] = make_link_permalink(file) entry[:tag_link] = make_link_tags(data[1]) yield(entry) html << "<li>" + entry[:date] + "<br><a href=\"" + File.basename(entry[:file_path], ".txt") + ".html\">" + entry[:title] + "</a></li>\n" } html << "</ul>\n" return html end private def make_link_tags(tags) html = "<a href=\"" + ERB::Util.u(Diary::TAG_ALL_LIST) + ".html\">" + Diary::TAG_ALL_LIST + "</a>" tag_arr = tags.split(" ") tag_arr.each{|tag| html << ", <a href=\"" + ERB::Util.u(tag) + ".html\">" + tag + "</a>" } return html end def make_link_permalink(diary_file_path) file_name = File.basename(diary_file_path, ".txt") return "<a href=\"" + file_name + ".html\">" + Diary::LINK_PERMALINK + "</a>" end def make_link_next_entry(diary_file_path) index = @diary_file_list.index(diary_file_path) if(index+1 < @diary_file_list.length) file_name = File.basename(@diary_file_list[index+1], ".txt") return "<a href=\"" + file_name + ".html\">" + Diary::LINK_NEXT_ENTRY + "</a>" else return Diary::LINK_NEXT_ENTRY_EMPTY end end def make_link_prev_entry(diary_file_path) index = @diary_file_list.index(diary_file_path) if(index-1 >= 0) file_name = File.basename(@diary_file_list[index-1], ".txt") return "<a href=\"" + file_name + ".html\">" + Diary::LINK_PREV_ENTRY + "</a>" else return Diary::LINK_PREV_ENTRY_EMPTY end end def parse_date(diary_path) date = File.basename(diary_path, ".txt") date = date[0,8] date.insert(8, Diary::DATE_DAY) date.insert(6, Diary::DATE_MONTH) date.insert(4, Diary::DATE_YEAR) return date end def parse_html(diary_path) parse_data = Array.new(3) data = File.open(diary_path){|f| f.readlines} data << "\n" #日記タイトルを取得 parse_data[0] = data[0].chomp data.delete_at(0) #タグ情報を取得 parse_data[1] = data[0].chomp data.delete_at(0) #日記データの構文解析 html = Array.new flag_p = false flag_html = false flag_pre = false data.each{|line| line = line.chomp #空行時の処理 #通常モードとHTMLモード(非整形モード)を解除する if(line == "") if(flag_p) html << "</p>" elsif(flag_pre) html << ERB::Util.h(line) end flag_p = false flag_html = false ##空行でないときの処理 else #フラグが立っている場合の処理 if(flag_html) html << line elsif(flag_pre) #preモードの終わりを示す"?"があれば、モードを終了し</pre>タグを挿入する if(line[0,1] == "?") flag_pre = false html[html.length-1] = html.last + "</pre>" else html << ERB::Util.h(line) end #特殊文字"<", "?", "!"の処理 elsif(line[0,1] == "<" and line[1,1] != "%") flag_html = true html << line elsif(line[0,1] == "?") flag_pre = true line = line[1,line.length] html << "<pre>" + ERB::Util.h(line) elsif(line[0,1] == '!') if(flag_p) html << "</p>" flag_p = false end if(line[1,1] == "!") if(line[2,1] == "!") if(line[3,1] == "!") if(line[4,1] == "!") html << "<h6>" + line[4,line.length] + "</h6>" end else html << "<h5>" + line[3,line.length] + "</h5>" end else html << "<h4>" + line[2,line.length] + "</h4>" end else html << "<h3>" + line[1,line.length] + "</h3>" end #文頭が特殊文字でない場合の通常処理 else #特殊文字を無効化する際に使う行頭スペースのの処理 if(line[0] == " ") line = line[1,line.length] end #すでにパラグラフ内にいれば"<br>"を付け、そうでなければ"<p>"を付けパラグラフ内であるフラグを立てる。 if(flag_p) html << "<br>" html << line else html << "<p>" html << line flag_p = true end end end } html_string = "" html.each{|line| html_string << line html_string << "\n" } parse_data[2] = html_string return parse_data end end class Tag def initialize @tag_list = Hash.new end def add(tags, diary_path, date, title) tag_arr = tags.split(" ") tag_arr.each{|tag| path_arr= @tag_list[:"#{tag}"] if(path_arr == nil) @tag_list[:"#{tag}"] = Array.new @tag_list[:"#{tag}"] << [diary_path, date, title] else @tag_list[:"#{tag}"] << [diary_path, date, title] end } end def each yield({:name => Diary::TAG_ALL_LIST, :list => make_all_list, :num => @tag_list.length}) @tag_list.each_key{|key| yield({:name => key.to_s, :list => make_list(key), :num => @tag_list[key].length}) } end private def make_list(tag) html = "<ul>\n" @tag_list[tag].each{|items| html << "<li>" + items[1] + " <a href=\"" + File.basename(items[0], ".txt") + ".html\">" + items[2] + "</a></li>\n" } html << "</ul>\n" return html end def make_all_list html = "<ul>\n" @tag_list.each_key.sort{|a, b| a.to_s <=> b.to_s}.each{|key| html << "<li><a href=\"" + ERB::Util.u(key.to_s) + ".html\">" + key.to_s + "</a> (" + @tag_list[key].length.to_s + ") </li>" } html << "</ul>\n" return html end end class Image attr_accessor :thumb def initialize(diary_file_list, html_path, thumb_size,image_size, flag_overwrite, jpg_quality) @thumb = Hash.new make_images(diary_file_list, html_path, thumb_size,image_size, flag_overwrite, jpg_quality) end def make_images(diary_file_list, html_path, thumb_size,image_size, flag_overwrite, jpg_quality) diary_file_list.each{|txt_file| dir = File.dirname(txt_file) + "/" + File.basename(txt_file, ".txt") + "/" next if(!File.exist?(dir)||File.ftype(dir)!="directory") @thumb[File.basename(txt_file, ".txt").to_sym] = Array.new index = 0 Dir.entries(dir).sort.each{|img_file| next if("."==img_file||".."==img_file||!(File.ftype(dir+img_file)=="file"&&File.extname(img_file).downcase==".jpg")) thumb_file = File.basename(txt_file, ".txt") + "-thumb-" + index.to_s + ".jpg" if(flag_overwrite||!File.exist?(html_path + thumb_file)) p thumb_file cmd = "convert -quality \"#{jpg_quality}\" -geometry \"#{thumb_size}\" \"#{dir+img_file}\" \"#{html_path + thumb_file}\"" %x(#{cmd}) end image_file = File.basename(txt_file, ".txt") + "-image-" + index.to_s + ".jpg" if(flag_overwrite||!File.exist?(html_path + image_file)) p image_file cmd = "convert -quality \"#{jpg_quality}\" -geometry \"#{image_size}\" \"#{dir+img_file}\" \"#{html_path + image_file}\"" %x(#{cmd}) end index += 1 @thumb[File.basename(txt_file, ".txt").to_sym] << "<span class=\"center\"><a href=\"" + image_file + "\"><img src=\"" + thumb_file + "\" alt=\"Thumbnail Image [" + img_file + "]\"></a></span>" } } end end class Diary def initialize #外部コンフィグファイルの読み込み eval( File.open("./diary.conf"){|f| f.read }) #日記データファイル名の一覧を取得 @diary_file_list = Array.new Dir.entries(@diary_path).sort{|a,b| (a<=>b)*-1}.each{|f| next if(("."==f)||(".."==f)||(File.ftype(@diary_path+f)!="file")) @diary_file_list << @diary_path + f } #タグ一覧を作るためのクラスの初期化 @tags = Tag.new #画像を処理するクラスの初期化 @img = Image.new(@diary_file_list, @html_path, @thumb_size, @image_size, @flag_overwrite, @jpg_quality) end def make_rss @rss_items = "" @rss_item_num.times{|index| break if index >= @entries.length @rss_items << "<item>" @rss_items << "<title>" + @entries[index][:title] + "</title>" @rss_items << "<link>" + @rss_base_url + File.basename(@entries[index][:file_path],".txt") + ".html</link>" @rss_items << "<pubDate>" + Time.parse(DateTime.strptime("#{@entries[index][:date].to_s}+9", "%Y#{DATE_YEAR}%m#{DATE_MONTH}%d#{DATE_DAY}%Z").to_s).rfc822.to_s + "</pubDate>" @rss_items << "</item>" } write_html(@rss_filename, @template_rss) end def make_top write_html(@top_page_filename, @template_top) end def make_tag_list @tags_list = Array.new @tags.each{|@tag| @tags_list << @tag #@tag_name = tag; @tag_list = list; @tag_num = num; write_html(@tag[:name] + ".html", @template_tag_list) } end def make_entries @entries = Array.new entries = Entries.new(@diary_file_list) @entries_title_list = entries.each{|@entry| @entries << @entry @tags.add(@entry[:tags], @entry[:file_path], @entry[:date], @entry[:title]) html_filename= File.basename(@entry[:file_path], ".txt") + ".html" write_html(html_filename, @template_entry) } end def make_stylesheet write_html(File.basename(@template_stylesheet), @template_stylesheet) end def write_html(html_filename, template_path) p "html=" + html_filename + " template" + template_path html = template_match(File.open(template_path){|f| f.read}) html = template_match(html) File.open(@html_path + html_filename, "w"){|f| f.write(html)} end def template_match(template) erb = ERB.new(template) return erb.result(binding) end def copy_files FileUtils.cp_r(@files_path, @html_path) end end diary = Diary.new diary.make_entries diary.make_tag_list diary.make_top diary.make_stylesheet diary.make_rss diary.copy_files
#!/usr/local/bin/ruby #diaryの名前 @title="意伝子発信器" #著者の名前 @author="gaso" #日記のヘッダー @header="<p>いずれ消え行く無駄な情報を、密やかに発信する装置。つまり日記。</p>" #日記のフッター @footer=\ "<p>このページ内で掲載している画像、文章等の転載・転用は自由に行ってください。</p> <address>author : gaso<br> address : gaso@gaso.jpn.org<br> Copyright 2003-2009 gaso All rights reserved. </address> <p>Generated by SiRuDiar<br> Powerd by Ruby ver <%= RUBY_VERSION %><br> Output Date <%= Time.now.rfc822.to_s %> </p>" #日記データの場所(最後のスラッシュを忘れずに!) @diary_path="./data/" #htmlを書き出す場所(最後のスラッシュを忘れずに!) @html_path="./html/" #topページのファイル名 @top_page_filename = "index.html" #rss2.0のファイル名 @rss_filename="index.rdf" #webページの場所(最後のスラッシュを忘れずに!) @rss_base_url="http://gaso.jpn.org/receptive-field/diary/html/" #日記に使う素材や雑多なファイルの場所(最後のスラッシュを忘れずに!) #ファイルは@html_path+"files"という名前のディレクトリにコピーされる @files_path="./data/files/" #作成するサムネイルのサイズ @thumb_size = "320x240>" #作成する画像ファイルのサイズ @image_size = "1024x768>" #常に新しく画像を生成するか @flag_overwrite = false #JPEGファイルの画質 @jpg_quality = "95" ##diaryのテンプレートの場所 #新しいエントリーをまとめて表示するページのテンプレート @template_top="./template/top.rhtml" #個々のエントリーのテンプレート @template_entry="./template/entry.rhtml" #エントリーのタイトル一覧を表示するページのテンプレート @template_entirs_list="./template/entries_list.rhtml" #タグ一覧を表示するページのテンプレート @template_tag_list="./template/tag.rhtml" #スタイルシートを保存してある場所 @template_stylesheet="./template/stylesheet.css" #rss2.0のテンプレート @template_rss="./template/rss2_0.rhtml" #rssファイルに書くitemの数 @rss_item_num=10 #RSSの概要 @rss_description="日常的な記録情報を発信します" LINK_NEXT_ENTRY="Next" LINK_NEXT_ENTRY_EMPTY="None" LINK_PREV_ENTRY="Prev" LINK_PREV_ENTRY_EMPTY="None" LINK_PERMALINK="Permalink" DATE_YEAR="年" DATE_MONTH="月" DATE_DAY="日" TAG_ALL_LIST = "カテゴリー"
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"> <html lang="ja"> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <meta name="format-detection" content="telephone=no"> <link rel="stylesheet" type="text/css" href="stylesheet.css"> <title><%= @title %></title> </head> <body> <h1><a href="./index.html"><%= @title %></a></h1> <div class="header"><%= @header %></div> <hr> <div class="side"> <div class="menu"> <h2>タイトル一覧 <a href="./index.rdf"><img src="./files/rss_icon.png" alt="rss icon" title="rss icon"></a></h2> <%= @entries_title_list %> </div> <div class="menu"> <h2><%= @tags_list[0][:name] %></h2> <%= @tags_list[0][:list] %> </div> </div> <div class="main"> <% 10.times{|index| %> <div class="entry"> <div class="date"><%= @entries[index][:date] %></div> <h2><%= @entries[index][:title] %></h2> <%= @entries[index][:text] %> <p class="footer"><%= @entries[index][:permalink] %> - <%= @entries[index][:tag_link] %></p> </div> <% } %> <p class="entry_link"><%= @entries[10][:next_link] %></p> </div> <hr> <div class="footer"> <%= @footer %> </div> </body> </html>