細かいことは以前の日記に書いてあるので、ここではビャッとソースを引用。
# index_list.rb
#
# 「最新」「月」表示に対応した目次を表示。
# recent_listやtitle_listと違い日付のリンク先は日別表示でなくページ内。
# その為に、diary.rhtmlをいじって日付にアンカーを付ける必要がある。
# 骨格にrecent_list.rbを使用。
# [2005-06-15] tdiary-2.1.1 N日表示対応
# [2005-04-20] 月表示では昇順に。
def index_list(date_format = nil, show_title = true)
if(@mode == 'latest')
limit = @conf.latest_limit;
elsif(@mode == 'month')
limit = 31;
else
return '';
end
date_format ||= @date_format;
latest_start_ymd = @date.strftime('%Y%m%d');
result = %Q[<ul class="index-list">\n];
b = lambda {|ymd|
next if(@mode == 'latest' && latest_start_ymd < ymd);
break if(limit <= 0);
diary = @diaries[ymd];
next unless(diary.visible?);
result << %Q[\t<li><a href="##{ymd}">#{diary.date.strftime(date_format)}</a>];
if(show_title && diary.title)
result << %Q[ #{diary.title}];
end
result << %Q[\n\t\t<ul class="index-list-item">\n];
i = 1;
if(!@plugin_files.grep(/\/category.rb$/).empty? && diary.categorizable?)
diary.each_section{|section|
result << "\t\t<li>";
result << section.categories.collect{|c| category_anchor("#{c}")}.join;
result << ' '+section.stripped_subtitle_to_html if(section.stripped_subtitle);
result << "</li>\n";
i += 1;
}
else
diary.each_section{|section|
if(section.subtitle)
result << %Q[\t\t<li>#{section.subtitle_to_html}</li>\n];
end
i += 1;
}
end
result << "\t\t</ul>\n\t</li>\n";
limit -= 1;
}
begin
@diaries.keys.sort.send( (@mode=='latest' ? :reverse_each : :each), &b);
rescue LocalJumpError # <- break
# Procオブジェクトで breakは使えないのだろうけど
# それをブロックとして渡してるんやからエラーにせんでもええやん。> ruby-1.8.2
end
result << "<ul>";
return apply_plugin(result);
end
最終更新: 2011-02-13T07:59+0900
末尾の " をURLの一部だとみなすせい。wiki_parser.rbの 198行目辺りの
r = %r<(((https?|ftp):[\(\)%#!/0-9a-zA-Z_$@.&+-,'"*=;?:~-]+)|([0-9a-zA-Z_.-]+@[\(\)%!0-9a-zA-Z_$.&+-,'"*-]+\.[\(\)%!0-9a-zA-Z_$.&+-,'"*-]+))>
を
r = %r<(((https?|ftp):[\(\)%#!/0-9a-zA-Z_$@.&+-,'*=;?:~-]+)|([0-9a-zA-Z_.-]+@[\(\)%!0-9a-zA-Z_$.&+-,'"*-]+\.[\(\)%!0-9a-zA-Z_$.&+-,'"*-]+))>
に変更。メールの方はいじってないけど不都合があるならそっちも " を削ればいい。
tDiary-2.1.3から採用される新Wikiスタイル(HikiDoc)では末尾の " が URLには含まれない模様。つまり修正の必要なし。
このページを読む限りダブルクォーテーションをURIの一部と見なす必要はないような。
山形括弧 "<" と ">" そして二重引用符 (") は排除されます。なぜなら、これらはしばしばURI周辺の区切り子として文書や作法の分野で使われるからです。 "#" 記号は排除されます。なぜなら、これはURIを、URI参照中のフラグメント識別子(第4項)から区切るのに使われるからです。 百分率記号は排除されます。なぜなら、これは回避された文字の符号化に使われるからです。
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
♭ セルフツッコミ昇順降順を考慮するように(index_list.rb)。表示数の制限が効いてない(recent_update.rb)..