class TDiaryUpdate < TDiaryAdmin def initialize( cgi, rhtml, conf ) @title = conf.to_native( cgi.params['title'][0] ) @body = conf.to_native( cgi.params['body'][0] ) @hide = cgi.params['hide'][0] == 'true' ? true : false super end protected def do_eval_rhtml( prefix ) super @plugin.instance_eval { update_proc } @diary.eval_rhtml({'date_format'=>''}, PATH) rescue nil; # この行を追加 anchor = @plugin.instance_eval( %Q[anchor "#{@diary.date.strftime('%Y%m%d')}"].untaint ) clear_cache( /(latest|#{@date.strftime( '%Y%m' )})/ ) raise ForceRedirect::new( "#{@conf.index}#{anchor}" ) end end
一行追加した。更新時の負荷増加なんて無問題でしょ。optが手抜きなのは気にしない方向で。
加えて、カテゴリを使った場合は update_procで category.rbによって section.bodyが評価されるので更にゴニョゴニョしないと「更新時に一度だけ実行」というわけにはいかない。
ここでハタと気付く。update_procでできるなら tdiary.rbをいじることないやん。category.rbの真似しよう。
コレ(↓)。category.rbのより簡単なのは、category.rbでは Pluginクラスとは違うクラス(のインスタンス)の中で評価するために bindingを受け渡したりしてるから。
add_update_proc{ diary = @diaries[@date.strftime('%Y%m%d')]; diary.each_section do |s| apply_plugin(s.subtitle_to_html); apply_plugin(s.body_to_html); end }
変更点は
# user_css2.rb: $Revision3% lastupdate:2005-05-10 # # Append CSS fragment via Preferences Page. # add_header_proc do [@conf["user_css2..css"], @conf["user_css2.#{@conf.theme}.css"]].map{|css| next unless(css); <<-STYLE <style type="text/css"><!-- #{css.gsub(/\x0d\x0a|\x0a|\x0d/, "\n\t\t")} --></style> STYLE }.join(''); end unless @resource_loaded then def user_css2_label 'テーマの微調整' end def user_css2_desc <<-HTML <h3>CSS断片</h3> <p>下から選んだテーマに、スタイルシートを追加設定する場合、以下にCSSの断片を入力してください。</p> HTML end def user_css2_buttonlabel1 'このテーマを修正する' end def user_css2_buttonlabel2 'CSSファイルを開く' end end if(!@conf_theme_list && @mode =~ /^(conf|saveconf)$/ && @cgi.params['conf'][0] == 'user_css2') # plugin/00default.rb からのコピー @conf_theme_list = [] Dir::glob( "#{::TDiary::PATH}/theme/*" ).sort.each do |dir| theme = dir.sub( %r[.*/theme/], '') next unless FileTest::file?( "#{dir}/#{theme}.css".untaint ) name = theme.split( /_/ ).collect{|s| s.capitalize}.join( ' ' ) @conf_theme_list << [theme,name] end end add_conf_proc( 'user_css2', user_css2_label ) do if @mode == 'saveconf' then if(@cgi.params['user_css2.css'].empty? || @cgi.params['user_css2.css'][0].empty?) @conf.delete("user_css2.#{@cgi.params['user_css2.theme'][0]}.css"); else @conf["user_css2.#{@cgi.params['user_css2.theme'][0]}.css"] = @cgi.params['user_css2.css'][0]; end end theme = (@cgi.params['user_css2.theme'][0] or @conf.theme); theme_hash = Hash[* @conf.options.map{|thm,css| (thm =~ /^user_css2\.(.+)\.css$/) ? [$1, $1.split(/_/).collect{|s| s.capitalize}.join(' ')+' (deleted)'] : nil}.compact.flatten ].update( Hash[* @conf_theme_list.flatten] ); theme_hash[''] = '* All Theme *'; theme_url = theme_url(); theme_url += '/' if(theme_url[-1] != ?/); <<-HTML #{user_css2_desc} <select name="user_css2.theme"> #{theme_hash.keys.sort.map{|t| %(<option value="#{CGI::escapeHTML(t)}"#{' selected' if t == theme}>#{CGI::escapeHTML(theme_hash[t])}</option>)}.join} </select> <input type="submit" value="#{user_css2_buttonlabel1}"> <input type="button" value="#{user_css2_buttonlabel2}" onclick="window.open('#{theme_url}'+this.form['user_css2.theme'].value+'/'+this.form['user_css2.theme'].value+'.css')" > <p><textarea name="user_css2.css" cols="70" rows="15">#{CGI::escapeHTML( @conf["user_css2.#{theme}.css"].to_s )}</textarea></p> HTML end
Amazon Webサービスを使ってキャッシュをXMLで保存する以外は amazon.rbと大体*一緒。ひとつだけ新しいメソッド追加。
5に意味は無くて、2とか3は既にありそうだな〜ってことで。
キャッシュが効いてなかったり、nilに対して存在しない呼び出しをしてたり、AssociateIDを一か所埋め込んでなかったり、widthとheightを間違えてたり、amazon.rbのisbn()を呼び出してたりしたのを修正。多分 amazon.rbなしでも動くんじゃないかな (この日記では両方オンにして二種類キャッシュしてXMLの方だけ使って表示してる)。
ruby-amazon(RAA)なんてあるんな。知らんかった。標準添付じゃないから使わなくてもいいかな。
* では何が違うかっていうとバグが潜んでそうなところが違う。
引用ってのは改行も空白も含めてそのまま写したいから、全てのテーマに
blockquote { white-space: pre; }
を適用した上で、wiki_parser.rbの
when /^""\s*(.*)/ # block quote
を
when /^""(.*)/ # block quote
に変更。IE6.0の互換モードでは white-space:preが効かないらしいが tDiaryは HTML4.01Strictな HTMLを吐くので互換モードにはならず問題なし。
結局は改行を挿入する方法が欲しかったわけだけど、今日、やっと、その方法がわかった。Wikiスタイルの書き方の、
「
」(2つの二重引用符)で始まる行は、引用(<blockquote>扱い)となる。文中の改行は、通常段落の行頭に「」を付けたものとして扱う。
と書いてある意味が今になってわかりました。行頭の「""」を取り除いた部分を通常の段落と同じように扱うという意味なのね。
""段落1:単一の改行は無 ""視されます。 "" ""段落2:空改行は段落の区切りになります。
↓
段落1:単一の改行は無 視されます。
段落2:空改行は段落の区切りになります。
squeeze.rb を index.rbと同じフォルダにコピーした後、CGIとしてsqueeze.rbを実行すると Internal Server Errorになる。
原因は tdiary.confを一行ずつ読み込んで @option のある行だけを eval() してることにある。
tdiary.conf.sample には
@options['bot'] = [
'^(Naverbot|Cowbot)-', '^BlogLines/', '^blogmap', '^FAST-WebCrawler/', '^Hatena Antenna/', 'MI[CK]AN/', '^msnbot/', '^NG/', '^Openbot/', '^samidare', '^TAMATEBAKO/', '^TomSoftAntenna']
ってのがあって、一行目だけではRubyスクリプトとしては不完全なので eval()したときに Syntax Errorがでる。そしてエラーはキャッチされずにそのまま Internal Server Error へとつながる。
普通に使ってるだけでエラーが出るようになってるってわけだ。どうして TDiary::Configを使わないのだろう。
つまり現状
2005/04/01#p01 サブタイトル
と表示されるのを
2005/04/01#p01 [カテゴリ] サブタイトル
と表示するようにする。
但し、カテゴリA をリスト表示してるときに、[カテゴリA] なんて表示しても無意味だし、やらない。2つ以上のカテゴリに属す場合に [カテゴリB] というのを表示する。
↓misc/plugin/category.rb ($Revision: 1.21 $) の変更点
# categorized[c][ymd] << [idx, s.stripped_subtitle_to_html, shorten] nonstripped_subtitle = s.categories.collect{|c2| (c2 != c) ? %Q[<%=category_anchor("#{c2}")%>] : '' }; nonstripped_subtitle.push(' ', s.stripped_subtitle_to_html); nonstripped_subtitle = nonstripped_subtitle.join(''); categorized[c][ymd] << [idx, nonstripped_subtitle, shorten]
コメントアウトされた1行目がオリジナルで、2-5行目が追加部分。
↓skel/diary.rhtml ($Revision: 1.21 $ / 3行目)
<h2><span class="date"><a name="<%=date.strftime("%Y%m%d")%>" href="<%= opt['index'] %><%%=anchor "<%= @date.strftime( '%Y%m%d' ) %>" %>"><%= @date.strftime( opt['date_format'] ) %></a></span> <span class="title"><%= title %></span><%
↓misc/plugin/index_list.rb →tDiary-2.1.1(N日表示)対応版
# index_list.rb # # 「最新」「月」表示に対応した目次を表示。 # recent_listやtitle_listと違い日付のリンク先は日別表示でなくページ内。 # その為に、diary.rhtmlをいじって日付にアンカーを付ける必要がある。 # 骨格にrecent_list.rbを使用。 # [2005-04-20] 月表示では昇順に。 def index_list(date_format = nil, show_title = true) date_format ||= @date_format; if(@mode == 'latest') limit = @conf.latest_limit; elsif(@mode == 'month') limit = 31; else return ''; end result = ''; @diaries.keys.sort.send(@mode == 'latest' ? :reverse_each : :each) {|date| break if(limit <= 0); diary = @diaries[date]; next unless(diary.visible?); result << %Q[<p class="recentitem"><a href="##{date}">#{diary.date.strftime(date_format)}</a>\n]; if(show_title && diary.title) result << %Q[ #{diary.title}]; end result << %Q[</p>\n<div class="recentsubtitles">\n]; i = 1; if(!@plugin_files.grep(/\/category.rb$/).empty? && diary.categorizable?) diary.each_section{|section| result << section.categories.collect{|c| category_anchor("#{c}")}.join; result << ' '+section.stripped_subtitle_to_html if(section.stripped_subtitle); result << "<br>\n"; i += 1; } else diary.each_section{|section| if(section.subtitle) result << %Q[#{section.subtitle_to_html}<br>\n]; end i += 1; } end result << "</div>\n"; limit -= 1; } return apply_plugin(result); end
↓recent_update.rb
# recent_update.rb # # 「追記」「編集」時に、日記の日付と実際の時刻を記録。 # プラグインで最近更新された日記を表示。 # [2005-04-20] 表示数の制限がきいてなかったのを修正。 def recent_update(limit=5) result = ''; uplist = RecentUpdateCache.new(@cache_path); uplist.each{|d, up, ar| break if(limit == 0); date = d.strftime('%Y%m%d'); result << %Q[<p class="recentitem"><a href="#{@index}#{anchor date}">#{d.strftime('%Y-%m-%d')}</a> <span class="recentupdate_lm">(更新日:#{up.strftime('%Y-%m-%d %H:%M:%S')} /#{ar})</span></p>\n]; limit -= 1; } result; end add_update_proc(){ uplist = RecentUpdateCache.new(@cache_path); d = @date; up = Time.now(); ar = @mode; uplist.append(d, up, ar); uplist.save(30); } class RecentUpdateCache def initialize(cache_path) @path = File.join(cache_path, 'recent_update'); @update_list = []; begin File.open(@path, 'r') {|f| f.each_line{|line| line.chomp!; date, up_date, ar = line.split(/\s*,\s*/); date = Time.local($1, $2, $3) if(date =~ /(\d{4})-(\d{2})-(\d{2})/); up_date = Time.local($1, $2, $3, $4, $5, $6) if(up_date =~ /(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})/); @update_list.push([date, up_date, ar]); } } rescue end end def append(d, up, ar) @update_list.unshift([d, up,ar]); end def save(limit=-1) begin File.open(@path, 'w'){|f| @update_list.each(){|d, up, ar| break if(0 == limit); d = d.strftime('%Y-%m-%d') if(d.kind_of?(Time)); up = up.strftime('%Y-%m-%d %H:%M:%S') if(up.kind_of?(Time)); f.puts([d,up,ar].join(',')); limit -= 1; } } rescue end end def each(&block) @update_list.each{|d, up, ar| yield(d, up, ar) } end end
どういうわけだか 2005/200503.td2ファイルは存在してない。悲しい。
categoryキャッシュとamazonキャッシュから購入履歴だけは復元(できたと思う)。
要望リストから発見。自分も欲しい。古い日記もちょこちょこ修正するから。
appendとreplaceを捉まえて日付をファイルに記録していく方式になるだろうね。
↓tdiary.rb (Revision: 1.195.2.2。TDiaryLatestクラスだけ抜粋。変更点はそこだけ)
# # class TDiaryLatest # show latest mode view # class TDiaryLatest < TDiaryView def initialize( cgi, rhtml, conf ) super ym = latest_month #↓追加 if(@cgi.valid?('from') && @cgi.params['from'][0] =~ /(\d\d\d\d)(\d\d)(\d\d)/) date_from = Time::local($1.to_i, $2.to_i, $3.to_i) ym = [date_from.year, date_from.month] @date = nil else date_from = nil end #↑ unless @date then @date = ym ? Time::local( ym[0], ym[1] ) : Time::now @io.transaction( @date ) do |diaries| @diaries = diaries #↓追加 if(date_from) (date_from.day+1..31).each{|day| self.delete(Time::local(date_from.year, date_from.month, day)) } end #↑ @diary = @diaries[@diaries.keys.sort.reverse[0]] DIRTY_NONE end end if ym then y = ym[0].to_i m = ym[1].to_i oldest = oldest_month calc_diaries_size while ( oldest and @diaries_size < @conf.latest_limit ) date = if m == 1 then Time::local( y -= 1, m = 12 ) else Time::local( y, m -= 1 ) end break if date < Time::local( *oldest ) @io.transaction( date ) do |diaries| @diaries.update( diaries ) calc_diaries_size DIRTY_NONE end end #↓追加 date_to = date_from; latest(@conf.latest_limit) {|diary| date_to = diary.date; } if(date_to && date_from != date_to) if(date_to.day == 1) if(date_to.month == 1) date_to = Time::local(date_to.year-1, 12, 31); else date_to = Time::local(date_to.year, date_to.month-1, 31); end else date_to = Time::local(date_to.year, date_to.month, date_to.day-1); end @conf['date_to'] = date_to; end #↑ end end protected def calc_diaries_size @diaries_size = 0 @diaries.each_value do |diary| @diaries_size += 1 if diary.visible? end end def latest( limit = 5 ) idx = 0 @diaries.keys.sort.reverse_each do |date| break if idx >= limit diary = @diaries[date] next unless diary.visible? yield diary idx += 1 end end def cache_file( prefix ) #↓条件文追加 if(@cgi.valid?('from')) nil else "#{prefix}#{@rhtml.sub( /\.rhtml$/, '.rb' )}" end #↑ end end
↓misc/plugin/next_diaries.rb (EUCで保存後、選択して使用可能にする)
# next_diaries.rb # # <概要> 「最新」表示の時に「次の○日分」へのリンクを表示する。 # <条件> tdiary.rbのTDiaryLatestクラスに細工してあることが前提。 def next_diaries(label=nil) if(@mode == 'latest' && @conf['date_to']) %Q[<a href="#{@conf.index}?from=#{@conf['date_to'].strftime('%Y%m%d')}">#{(label || next_diaries_label)}</a>] else '' end end def next_diaries_label() "次の#{@conf.latest_limit}日分" end
MLを読んでたわけではないのにこのカブりよう。
EUCで保存して misc/plugin/ へ放り込む。その後使用可能にするのを忘れない。
# footnote2.rb $Revision: 1.0 $ (footnote.rb $Revision: 1.8 $ を改変) # # 日別表示に飛ばずに同一ページ内のアンカーに飛ぶように変更 # # footnote.rb $Revision: 1.8 $ # # fn: 脚注plugin # パラメタ: # text: 脚注本文 # mark: 脚注マーク('*') # # Copyright (c) 2001,2002 Junichiro KITA kita@kitaj.no-ip.com> # Distributed under the GPL # =begin ChangeLog 2002-05-06 MUTOH Masao <mutoh@highway.ne.jp> * change file encoding from ISO-2022-JP to EUC-JP. 2002-03-12 TADA Tadashi <sho@spc.gr.jp> * runable in secure mode. =end # initialize instance variable as taint @footnote_name = "" @footnote_name.taint @footnote_url = "" @footnote_url.taint @footnote_mark_name = "" @footnote_mark_name.taint @footnote_mark_url = "" @footnote_mark_url.taint @footnotes = [] @footnotes.taint @footnote_index = [0] @footnote_index.taint def fn(text, mark = '*') # if @footnote_name and /^append|replace$/ !~ @mode then if @footnote_name @footnote_index[0] += 1 @footnotes << [@footnote_index[0], text, mark] r = %Q|<span class="footnote"><a | # r << %Q|name="#{@footnote_mark_name % @footnote_index[0]}" | if @mode == 'day' r << %Q|name="#{@footnote_mark_name % @footnote_index[0]}" | r << %Q|href="#{@footnote_url % @footnote_index[0]}" title="#{CGI::escapeHTML text}">#{mark}#{@footnote_index[0]}</a></span>| else "" end end add_body_enter_proc(Proc.new do |date| date = date.strftime("%Y%m%d") # @footnote_name.replace "f%02d" @footnote_name.replace "f#{date}-%02d" # @footnote_url.replace "#{@index}#{anchor date}##{@footnote_name}" @footnote_url.replace "##{@footnote_name}" # @footnote_mark_name.replace "fm%02d" @footnote_mark_name.replace "fm#{date}-%02d" # @footnote_mark_url.replace "#{@index}#{anchor date}##{@footnote_mark_name}" @footnote_mark_url.replace "##{@footnote_mark_name}" @footnotes.clear @footnote_index[0] = 0 "" end) add_body_leave_proc(Proc.new do |date| if @footnote_name and @footnotes.size > 0 %Q|<div class="footnote">\n| + @footnotes.collect do |fn| r = %Q| <p class="footnote"><a | r << %Q|name="#{@footnote_name % fn[0]}" | r << %Q|href="#{@footnote_mark_url % fn[0]}">#{fn[2]}#{fn[0]}</a> #{fn[1]}</p>| end.join("\n") + %Q|\n</div>\n| else "" end end)
タイムアウトになってブラウザの用意したエラーページが表示される。
設定とか一日表示とか他の部分は正常だから「最新」表示だけがダメっぽい。キャッシュが壊れたか?
「前の日記」をたどって一日ずつ日記を確認していったら、一日だけ「2004/06/30 (水)の日記はありません。」って表示された。
「前の日記」は単なる前日を表示するリンクじゃないから 6/30の日記は無いんじゃなくて失くなったとみるべきかも。
結局、最新表示は今日も復活してない。キャッシュを消すのが面倒臭いのだ。学校にダイアルアップする必要があるので。
考えたら、latestのキャッシュが壊れてるなら、この13日の日記を書いて保存した時点でキャッシュが書き換わって表示も復活するはずなのに、そうはなってない。
それなら次の手は 6/30の日記を空白でも何でもいいので上書きすることだ。結果は...直りました。
Ruby で書かれてるからと Tiki 入れてみたけどよくわからん。一応動いてるけどロゴ画像は表示されへんし、Nodeの作り方とか今イチやし。
あと tDiary からアクセスする方法も見つからん。キーワードからリンクを作成して、そこからアクセスする都合上 GET で新規ページを作りたいねんけど、WelcomeVisitors ページの[編集]インプットボックスを参考にパラメータをいろいろ試したけど駄目やった。
YukiWiki (Perl) は InternalServerError が解決できなかった。インストールまでのドキュメントは親切。
PukiWiki (PHP) は Tiki に比べて機能も劣ってないし、ドキュメントも含めた全体の完成度が高そうだ。GET による新規ページ作成も、オフィシャルサイトで試したところパラメータ2つで出来た。
Ruby が入ってるんやし、と期待したが PHP 動かない。
Tiki で ページ表示 or ページ新規作成 するには tiki.cgi?p=〜 でOKみたい。c=〜 とかいらんことする前に試せよ、って言いたい。
♭ セルフツッコミ昇順降順を考慮するように(index_list.rb)。表示数の制限が効いてない(recent_update.rb)..