/ 最近 .rdf 追記 設定 本棚

脳log[tDiary: 2012-11-28~]



2012年11月28日 (水) 新gTLD. 個人でとれるものではないみたいだけど。.desuとか日本語で汎用性高そう。.nidaとかあったら特徴が出過ぎてて笑っちゃう。漢字も使えるみたいだけど入力にハードルがあるからローカルなものにしかならない気がする。だったらローマ字で。■ ATOKでアクサンやらウムラウトを付けるのが難しくって、「ATOKのヘルプ」やら「ATOKのマニュアル」(※こういうメニューが並んでるんだけど違いがわかる?)で方法を調べて、わかったんだけど入力モードの切り替えが面倒くさい。eの変換候補に追加してくれた方が簡単(だが自分では登録しない)。

最終更新: 2013-11-08T01:03+0900

[tDiary] Wikiスタイル(hikidoc.rb)にルビを。(impl_ruby_markup.rev1.1.patch)

表意文字で文章を書いていて使わない手はないでしょう(ローマ字がないと交差点の名前とか読めませんから)。こんなかんじで書くと、

ルビを付けたいテキスト(ルビ)
ルビを付けたいテキスト(ルビ1 / ルビ2)

こういう HTMLになる(※インデントとコメントは後から追加した)。

<ruby>
  <rb>ルビを付けたいテキスト</rb>
  <rp>(</rp>
  <rt>ルビ</rt>
  <rp>)</rp>
</ruby>
<ruby>
  <rbc><rb>ルビを付けたいテキスト</rb></rbc>
  <rp>(</rp><!--本当ならここに rpタグは使えません-->
  <rtc><rt>ルビ1</rt></rtc>
  <rp> / </rp><!--本当ならここに rpタグは使えません-->
  <rtc><rt>ルビ2</rt></rtc>
  <rp>)</rp><!--本当ならここに rpタグは使えません-->
</ruby>

2番目はうまく表示されないね。

  1. 葵井 巫女子(あおいい みここ)
  2. 紫木 一姫(ゆかりき いちひめ / シグナル イエロー)

シグナルイエローには《危険信号》っていう字があるから、本名と二つ名をルビで並記しようとするとルビのルビが必要になる。が、rb,rt要素は rubyを除いたインライン要素しか包含できない。

2番目の複雑形式は非サポートブラウザ向けのフォールバックがない(www.w3.org)らしいから rpタグを挿入するのは間違いだった。1.2.3 Complex ruby markupの最後に The rp element is not availableってしっかり書いてある。Firefoxも Operaもルビをサポートしないなりに期待通りの表示をしてくれたので良しとしておくが、よくよく考えてみれば、対応ブラウザには表示しないことを求め、非対応ブラウザにはタグを無視して中身をそのまま表示してもらうことを期待したタグなんだから、細かい出現規則(単純形式だけとか 0回か 2回(※rt要素の前後に限る)しか出現できないとか)を決めるのも従うのも意味がないのではないか。HTML5(dev.w3.org)は1番目の形式だけ、それも rbタグを取り除いたものがサポートされるらしい(ただしテキスト-rt要素の並びが1つの ruby要素の中に複数出現可能。だがベーステキストとルビがインターリーブされることで読み上げ、スタイルの適用、スクリプト操作、コピペなどに不都合があるとも)。ドラフトを読むと rubyタグのネストとか連続する rt要素で複合(double-sided)ルビにも対応しそう(だけどこれだと表現できない変態的なルビの付け方があるみたい。EPUBが絡んでくるから切実なの?)。rbタグを出力しないオーサリングツールが以前から存在してたみたいで、HTML5でなくても rbタグなしで不都合はないかもしれない。今日のこれは XHTML1.1。ルビ関連タグは出現パターンがごく少数に規定されてる。

細かい補足。パッチは別のパッチをあてた hikidoc.rbがベースだから素直にはあたらない。変更点の参考程度に。二重かっこでマークすることにしたけどかっこの対応は気にしてない(このいい加減さが rubyタグのネストを防いでたりする)。rtcタグが一度に1回か2回しか出現できないと知らなくて、ルビをいくつでも振れるかのようなコードになってるのが良くない。URLはリンクになるし強調とか打ち消しとかの装飾も、ベースになるテキストとルビ双方で有効みたい(hikidoc的にも XHTML的にも)。ルビに装飾って有用性がわからんけど、実は単なるインラインのテーブルだからできちゃいました(※後で苦労するフラグ)ってことなんか?

rubyforge.orgは Subversionサポートをやめたのかな。http://hikidoc.rubyforge.org/svn/ にリソースが見つからない。hikidocの最新版はどこから?

octocatいいよね(最後にこれはちゃぶ台返し?)。

 HTML Ruby :: Add-ons for Firefox (addons.mozilla.org)


 @2012-12-01

自分でそういう書き方をするつもりがない(見た目が嫌いだ)から配慮しなかったけど、熟語単位でルビを付けつつ、ルビを個々の文字の上に配置したいかもしれない。熟語の上にじゅくごではなく、熟の上にじゅく、語の上にごを置きたいが、熟(じゅく)語(ご)みたいには書くのも表示されるのも嫌だという場合。セパレータを何か決めて、

熟,語(じゅく,ご)
火,継,ぎの,祭,祀,場(ほ,つ,,さい,し,じょう)

こうかな?2番目はひらがな部分のルビを省略してるからフォールバックがうまくいかないだろうな。かといってルビで単語を分断したくないからこういう書き方を考案してるわけで、ひらがなにもルビをつけるしかないのか@2013-11-08

hikidocで表のセルを横方向に連結する文字が > だから、 > や >> で区切ったときはその直前のセルが2マス3マス分に伸びるとか?

蟷 螂(とう ろう / かまきり>)
大 人 気(だい にん き / おとな>げ)

入力のしやすさやノイズとしてあまり目立たないことからいえばスペースで区切りたいけど、ルビの部分に英語がきたり、空白で区切った姓名にルビを振るときに困る。とりあえず、使わないのに無用な複雑さは導入しない(さっさと決めないとアップデートで既存の文章を壊す危険性が増すとも考えられるが)。TODOにしとく。

 @2012-12-06

1998年のルビの文書「ルビ(www.doraneko.org)」(翻訳されたW3Cワーキングドラフト)を読んでたら ruby-devで見かける名前を見つけた。バナナの下の力持ち。えらい人だなあ。

ルビのために(hp.vector.co.jp)」という文書を読んでいたら最後にぼんやりと見覚えのある名前(筆者)を発見。そうだこの名前はここで見た。「JintrickのマイクロWeb日記, 2012 秋

狭いなあというよりは。怖いなあ。

 @2013-10-06 記法の決まり方

  1. HikiDocのインラインマークアップの基本型が、記号の繰り返し(二重、三重)で囲むというものである。
  2. ルビはよくかっこ書きされる。
  3. 二重かっこで括ろう。
  4. ルビを振りたいテキストとルビの区切りは )( でいいだろう。

という経過を辿った。1分も考えなかった。ルビを振りたいテキストを囲むかっこはなくても困らないんだろうけど、1番目の理由によって存在している。

@2013-11-08 [[2.4. Autohiding Annotations(www.w3.org)|http://www.w3.org/TR/2013/WD-css3-ruby-20130919/#autohide]]

というよりは [[大規模ネットワークの性質と先端グラフアルゴリズム|http://www.slideshare.net/iwiwi/ss-15517666/7]]


2012年01月15日 (日)

最終更新: 2012-01-17T01:44+0900

[tDiary] SourceForge.net: tDiary: TDiary::Plugin の多重初期化を減らしたい

自分の稼働中の tdiary.rbを見てみると該当部分はこうなっていた。

def load_plugins
	calendar
	@lazy_diaries.update( @diaries )
	if @plugin
		@plugin.diaries = @lazy_diaries
		@plugin.date = @date
		@plugin.last_modified = last_modified
		@plugin.comment = @comment
		return @plugin
	end
	@plugin = Plugin::new(
		'conf' => @conf,
		'mode' => mode,
		'diaries' => @lazy_diaries,
		'cgi' => @cgi,
		'years' => @years,
		'cache_path' => cache_path,
		'date' => @date,
		'comment' => @comment,
		'last_modified' => last_modified,
		'logger' => @logger
	)
end

if @plugin ... end部分はたしか kazuhikoさんのコードだったような……。

そうそうこれこれ*。>>脳log[2009-08-06-p01] tdiary.rbと plugin/navi_user.rbにパッチあて(plugin/recent_list.rbの分は使用してないのでスルー) + セクションごとの最終更新日時に一票 >>[tDiary-devel] all_filtersとかload_pluginsが呼ばれ過ぎで遅い件


@plugin.diariesと @plugin.dateと @plugin.comment、それとたぶん @plugin.last_modifiedに更新が必要なのはすでにわかってた話なんじゃないの、ってことなんだけど、このコードは tDiary-3.0.1になったときに失われてる。svn logは「Merge branch 'master' into svn」なので経緯は不明。


>>Re: [tDiary-devel] #194 blog-category.rbが動作しない

* 「@plugin」で引っかからなかったので「捨ておけぬ」でサイト検索して見つけた。


2011年10月04日 (火) [COSMOS] HDT722525DLA380に不良セクタ発生。2006年3月から、5年と半年の寿命であった。うち 4年はバックアップディスクとして月イチ稼働だったけど。

最終更新: 2011-10-28T14:10+0900

[tDiary] リファラ置換リスト(対google)晒し。

^http://www\.google\.(?:[^/]+)/url\?.*?[&;]cd=(1\d)\b.*?[&;]url=[^&;]*?(\d{6}[\dpct]*).*?[&;]q=([^&;]+).*$ google検索 \1th of「\3」→ \2
^http://www\.google\.(?:[^/]+)/url\?.*?[&;]cd=(\d*1)\b.*?[&;]url=[^&;]*?(\d{6}[\dpct]*).*?[&;]q=([^&;]+).*$ google検索 \1st of「\3」→ \2
^http://www\.google\.(?:[^/]+)/url\?.*?[&;]cd=(\d*2)\b.*?[&;]url=[^&;]*?(\d{6}[\dpct]*).*?[&;]q=([^&;]+).*$ google検索 \1nd of「\3」→ \2
^http://www\.google\.(?:[^/]+)/url\?.*?[&;]cd=(\d*3)\b.*?[&;]url=[^&;]*?(\d{6}[\dpct]*).*?[&;]q=([^&;]+).*$ google検索 \1rd of「\3」→ \2
^http://www\.google\.(?:[^/]+)/url\?.*?[&;]cd=(\d+).*?[&;]url=[^&;]*?(\d{6}[\dpct]*).*?[&;]q=([^&;]+).*$ google検索 \1th of「\3」→ \2
  • 適用する順番が大事。
  • Google、検索リファラを変更、検索ランキングデータが取得可能に::SEM R
  • 高機能なリファラプラグインであれば対応してるのかも。(使ってないので知らない)
  • (愚痴) リファラをクリックして自分のサイトが出ても嬉しくないんだよね。検索画面が出れば高確率で自分が関心を持つであろう他のサイトを見つけられるし、自分のサイトが何番なのか画面外なのかもどうせわかるのに。
  • 気付かないふりをしたかったけど、cd, url, qパラメータがこの順番で出現しないと置換に失敗する。数は少ないものの失敗するリファラがこの日記にも届いてる。Ruby 1.8では名前付きキャプチャ、使えないのかなー。
  • これらの正規表現って URLを相手にしてるもんだとばっかり思ってたけど、tdiary.rbの disp_refererメソッドを見るに、%HHをデコードしたあとのどうしようもない文字列が相手のような……。(理解が正しければ)

パラメータの順番を仮定しないために、結局こうなった。名前付きキャプチャは関係なくて、繰り返し付きキャプチャに最終的に入るものを把握することが大事。

^http://www\.google\.(?:[^/]+)/url(?:[?&;](?:url=[^&;]*?(\d{6}[\dpct]*)[^&;]*|q=([^&;]+)|cd=(1\d)|(?!cd=)[^&;]*))*$ google検索 \3th of「\2」→ \1
^http://www\.google\.(?:[^/]+)/url(?:[?&;](?:url=[^&;]*?(\d{6}[\dpct]*)[^&;]*|q=([^&;]+)|cd=(\d*1)|(?!cd=)[^&;]*))*$ google検索 \3st of「\2」→ \1
^http://www\.google\.(?:[^/]+)/url(?:[?&;](?:url=[^&;]*?(\d{6}[\dpct]*)[^&;]*|q=([^&;]+)|cd=(\d*2)|(?!cd=)[^&;]*))*$ google検索 \3nd of「\2」→ \1
^http://www\.google\.(?:[^/]+)/url(?:[?&;](?:url=[^&;]*?(\d{6}[\dpct]*)[^&;]*|q=([^&;]+)|cd=(\d*3)|(?!cd=)[^&;]*))*$ google検索 \3rd of「\2」→ \1
^http://www\.google\.(?:[^/]+)/url(?:[?&;](?:url=[^&;]*?(\d{6}[\dpct]*)[^&;]*|q=([^&;]+)|cd=(\d+)|(?!cd=)[^&;]*))*$ google検索 \3th of「\2」→ \1

 自己言及

リファラ周りを覗いたついでに、セルフリンクの記録を解禁した。my-sequel.rbプラグインの機能を代替できるかな、と。

tdiary.confのベースとした tdiary.conf.sampleに最初からセルフリンクよけがあるのでこれを削除。dayモードからのリンクでないものを除外するように(=dayモードからのリンクだけを記録するように)ブラウザで設定した。(index.rbの有無とか日付を ?date=形式で渡してるかどうかとかサイトに合わせた調整が必要)

リンク元記録除外リスト
^http://vvvvvv\.sakura\.ne\.jp(?!/ds14050/diary/\d{8})

最新の日記にだけ表示される「以前の日記へのリンク元」からのリンクは自己言及とは言えずノイズでしかないので 05referer.rbの referer_save_currentに次のコードを挿入した。

# reject self-reference from (maybe) volatile list
return if referer.start_with?(@conf.base_url) and (date = referer.scan(/\b(\d{4})(\d\d)(\d\d)\b/).last) and latest_day?(Struct.new(:date).new(Time.local(*date)))

期待通り動いてるか動いてないかはまだ観察できてない。

「以前の日記へのリンク元」へセルフリンクを記録しない方法をとらなかったのは、そこで過去の日記の動きを観察したかったから。でもリストに記録された日からどこへ移動したかはわからないね。リファラを集約するときに「どこへ(のリンクか)」という情報を蔑ろにしたせいだ。余計なお世話だと思ってた googleの新しい形式(といっても2009年)のリファラがその情報を与えてくれてたりする。

 除外リスト

tdiary.conf.beginnerには FeedReaderからのリンクを記録しない設定が予め用意されている。俺も除外したいと思った。でも tdiary.conf.sampleには用意されていない。beginnerの定義、.beginnerと .sampleを分ける法が知りたい。

 2011-10-28

どうやら volatile referer listからのリンクの除外に失敗してる。原理的にリファラを表示したときとリンクを踏んだときの間に日記の投稿があった場合には除外できないんだけど、それにしては数が多い。volatile referer listは特別に内部リンクを表示しないことにする。

plugin/05referer.rb: referer_of_today_long
@referer_volatile.each_referer( limit ) do |count,ref|
	next if ref.start_with?(@conf.base_url) # この一行。
	result << %Q[<li>#{count} <a rel="nofollow" href="#{h ref}">#{h disp_referer( @referer_table, ref )}</a></li>\n]
end

2011年08月03日 (水) はてブで『耳刈ネルリ』の文字をみかけた。売れるといいね。次作を待ってるんだけどファミ通文庫は『荒野の恋』や『暴風ガールズファイト』『カーリー』を最後まで出せなかった根性なしだからなあ。『ヒツギでSOSO!』の人も続刊がないし、森橋ビンゴの『ラビオリ・ウェスタン』も単発で終わっちゃった。売れる物を売るだけじゃ先細りするばかりなのに。もっと、俺好みのを。

最終更新: 2011-08-04T03:29+0900

[tDiary] PageDownキーによるスクロール量をごにょごにょするプラグイン。

日と日の境が行き過ぎてしまわないようにスクロール量を制限する。

うっとうしいかな? スムーズスクロールも効かないしな。でも AutoPagerizeの機能の一部としてあってもいいような気もする。

動作確認済み> Firefox 5.0, Internet Explorer 9, Safari 5.0.2, Opera 11.50

* この日記(tDiary-2.3.3.20091124)にはまだ js_urlメソッドとか enable_jsメソッドとか無いのです。


2011年05月24日 (火) パンストの続編見たいな。

最終更新: 2017-09-15T10:23+0900

[tDiary] 同カテゴリのセクションへのリンクを表示するプラグイン(sections_of_a_category.rb)。

なんというか……ばっちい(だから非公開(書き直すつもりがないので観念した))。だらだら書き下すとこうなるのね、っていう。申し訳のように抜き出したカスタマイズポイントもうまく分離できなかった記憶がある。たんに切り取って別の場所に貼り付けただけだろう、と。svn logを見てみたら 2009年3月に書いたものらしい。最初はセクションごとに表示する仕様で、それだと日記を分断して邪魔なので一日の最後に表示するオプションを付けたとか。……logによれば。とりあえずこの日記(tDiary-2.3.3.20091124, Ruby-1.8.7-p248)では動いてるみたい。

「カテゴリ[……]の他の日記」リンクの URLはこの日記に特有の、最新表示とカテゴリ表示をくっつけたもののだから他の日記では使えないね(それも非公開の理由)。

2007年や 2009年の日記のタイトルが 2011年のこの日記から参照できてるのは「プラグインが自由に日記データを取得できる手段を提供した」恩恵を my-exプラグインが受けているからじゃないかと推測してる。

 @2017-09 書き直した(リンクはそのまま)。


2011年02月12日 (土) テイラー展開とかマクローリン展開。言葉は出てこなかったけど積分の演習問題として高校で出てきてた(ことを後に知った)。コンピュータ向けの計算だよね。展開して多くの項を計算すればするだけ精度のいいπが求まるとか。昨日の Q57から連想したんだけど、平方根の計算はまた別っぽい。手計算で平方根を求める方法は俺の時代の教科書からは消えてたよ。消えてたといえば行列を使った回転も消えてたよ。高校数学は新しく習う概念がバラバラのままなんだよ。統合してよ。///「冪剰余 - Wikipedia」っていう言葉があるのね。(ギブアップした Q250関連) 「剰余」から「n-進展開 (Wikipedia(ja):剰余)」→「p進数 - Wikipedia」とんでもないところに飛んでしまった。

最終更新: 2012-12-12T02:17+0900

[tDiary] MathMLが使いたかったので。>「ひらくの工房 - tDiary XHTML化キット

  • HTMLモードなんていらないから拡張子は xhtmlでなく htmlで、とか
  • \times より × って書きたい、とか
  • <option selected="selected"> <input checked="checked"> みたいに属性名を省略してない HTMLもあるのよ、置換しすぎないで、とか

適当にカスタマイズして設置した。

XHTML化キットの存在は投稿されたアナウンスを読んで知ってたんだけど、XHTML好きにもかかわらず今まで導入してなかったのは、日記に数式を書く機会がなかったのと、出力段階での文字列置換による XHTML化が乱暴に思えたから。結局、他に方法がないので目をつぶったが。

閲覧不可能になった日記がないか月別表示で全日記を表示してみたら 10か所くらい見つかった。パターンは以下の通り。

  • プラグインが埋め込む JavaScriptに含まれる & 記号
  • etDiaryスタイルがエスケープしてくれなかった本文中の & 記号
  • プラグイン記法( {{~}} )で直接埋め込んだ HTML片に含まれる & 記号

 JavaScriptの &

<script>タグの中であっても & は &amp; と書かなければいけない。不等号も。でも if(a &amp;&amp; b) {} とか置換してしまったらアホだ。CDATAセクションを使う。

scriptタグが解釈できないブラウザなんて PCを手に入れた当時から持ってなかったので

<script><!--
--></script>

なんて最初から書かなかったし、XHTMLを知ってからは下のように書くことにしてる。

<script>/*<![CDATA[*/
/*]]>*/</script>

コメントで囲うのは JavaScriptとして正しくあるため。より字数の少ない行コメントにしないのは、なにかでエラーになったから。MSがリリースしてた JavaScriptを暗号化(難読化)するツールに <script>タグを含んだ HTMLファイルを通したときだったか……。

 etDiaryの &

但し書きを付けても無駄。HTMLと日本語は混ぜるな危険。中途半端な HTMLの隠蔽は悪。tDiaryスタイルと etDiaryスタイルより Wikiスタイル。

 手書き HTMLの &

自業自得。さすがに、タグに挟まれた部分に & や <, > を放置してたわけではない。

<a href="ttp://hoge/script.cgi?a=b&c=d">
<img src="ttp://hoge/script.cgi?a=b&c=d">

すべてこの形の & がエラーになっていた。HTMLを出力するスクリプトでは、属性値は機械的に必ず HTMLエスケープするようにしてるんだけど、手書きだと上のような (X)HTMLは正しく見えてしまうのか、忘れられてた。こんなことがあるとやっぱりセミコロンで区切りたいねえ。

それにしても、ちらちら目に入る古い日記が恥ずかしくて死ねる。読む人間も、そもそも読める内容もないのであえて気づかぬふりで放置するけども。


2010年04月16日 (金) ここまで読んだ。「【コラム】3Dグラフィックス・マニアックス (53) 水面の表現(2)~動的なさざ波 | パソコン | マイコミジャーナル」今や隔世の感があるバーチャファイターや FF7からの道のりを辿れる。

最終更新: 2010-05-01T17:13+0900

[tDiary] Hatenaスタイル

リストをネストしたときだけ生のテキストに<p>タグが付くのがオリジナルのはてなと違うんだそう。ついでに空の<p>タグが生成されるのも気になるけどそれは別。

最初に。<li>はブロック要素もインライン要素も包含可能らしいけど両方を並べて含んでいいのかはわからなかった。読めない(block or inlineの 0以上の繰り返し、だという気はする)。Another HTML-lintが文句を言わなかったのでいいものとしよう。

次に、CodeReposの hatena_style.rbの中を見てみる。Hatena::Blockがなにやら特別な位置を占めてるけど、一応 Hatena::Inlineと同じように振る舞うみたい。ところで、Hatena::Blockはブロック要素の連なり、Hatena::Inlineはインライン要素の連なりを表してるけど、その両方の連なり(<li>の中身とか)を表すクラスがない。

てっとりばやく済ませるために、Hatena::BlockAndorInlineというクラスを用意して Hatena::Blockが行っていた仕事をごっそり移動するそれだけでなく。Hatena::BlockAndorInlineにはインライン要素を含んでいいのかを示すフラグを initializeを通して与え、それにより何が何でも<p>タグで囲むのかそのままにするのかという動作を変えることにした。現状、求められてるのがその違いだけだから。

Hatenaスタイルは使ってないからあからさまなバグがあっても気付かない可能性が大きいです。

suppress_ptag_in_nested_list.patch (7.1KiB, 2010-04-16, r37217との差分)古くなりました。


順序付きリストや定義リストの対応を忘れてる。

<dt>の中はインライン要素の 0以上の繰り返し、<dd>の中はインライン要素とブロック要素の 0以上の繰り返しっぽい。Hatenaスタイルでは定義リストにはインライン要素しか認めていないので対応は必要なし。順序付きリストだけ。

suppress_ptag_in_nested_list.rev2.patch (8.2KiB, 2010-04-16)

svn diffで -x -p (-x <ARG>: diffに渡すオプション, -p: Cの関数名を表示)を初めて付けてみたけど、Rubyスクリプトであってもクラス名は拾ってくれるみたい。


 @2010-04-18 MLに書いた件

次々空いてくる穴をふさぐのはどちらかといえば好きだけど……。

suppress_ptag_in_nested_list.rev3.patch (8.4KiB, 2010-04-18)
r37218に対して。rev2パッチ + (無限ループになっていた例での)段落の分割を防ぐ。
suppress_ptag_in_nested_list.rev3-2.patch (2.9KiB, 2010-04-18)
r37218に対して。(無限ループになっていた例での)段落の分割を防ぐ、だけのパッチ。

 @2010-04-20 「stack level too deep (SystemStackError)」になるらしい。

それはそれとして、

  • Hatena::Block#title_is_dummy?のロジックが反対。(誤:==/正:!=)
  • r37240はリストが必要以上に深くなる。
  • Hatena::Section#bodyは期待通りうごかないかも。(目的がデバッグ出力だったなら OKだけど)

      def body
        @tree.body.to_s
      end

    @treeは以前は Hatena::Blockか Hatena::Inlineだった、俺の変更で Hatena::BlockAndorInlineか Hatena::Inlineになった。カスタマイズされた to_sメソッドを持っているのは Hatena::Blockだけ。

  • 空のサブタイトルでエラー。Hatena::Block#initializeでの配慮が足りなかった。

肝心の深すぎる再帰は再現できない。自分自身を子要素に持ってるなんてことはないはずだから convertメソッドが自分自身を呼び出すしかない。その可能性があったのは Hatena::Block#convertのみ。そのときは if @body == selfでチェックして @body(Hatena::Block).convertを回避していたし、今は @bodyに Hatena::Inlineか Hatena::BlockAndorInlineしか入っていないから自分自身を呼ぶことは考えられない。わからん。キャッシュのせいだったら拍子抜けだなあ。<<<以前は @bodyに Hatena::Blockが入っていたんだから、古いデータと新しいコードの組み合わせで無限再帰は十分ありうる話。.parserキャッシュにはクラス名やインスタンス変数も入ってるし。

 とりあえず
  • fix_c37239.patch (623B, c37239の修正)

    サブタイトルの有無の判断が間違って反対になっていた。

    サブタイトルのみのときにエラーになっていた。

  • fix_c37240.patch (955B, c37240の修正)

    順序付き、順序なしリストの階層が勝手に深くなっていた。

    セクションの分割に失敗していた。


 「<p>はなくなったが空行が……」

たぶん HTMLソースレベルの空行なんだと思う。Hatena::BlockAndorInline#convertでインライン要素の後だけは改行を付加しないようにすればなくせるが、<p>の有無と違って(white-space:preとかしない限り)見た目に関与しないのでこだわらない。(<p>の後ろと</p>の前にも改行が挿入される、だとか考え始めるときりがない)

スレ主は hatena_style.rbを使うことにこだわってはいないという。こちらは楽しんでやってるんだけど、いつまでもデバッグに付き合ってもらうわけにもいかないだろう。はてなはウクレレ記法ができてこそのはてなだと思ってるので、それができない hatena_style.rbから乗り換えるのも悪くないと思う。

「ウクレレ記法」で検索したら主犯が見つかった。最初は Hikiに実装したって書いてるよ。(始めて一か月ほどだったとも書かれていて)つくづくプログラミングは何に使うかが大事だと思う。(英語なんかと一緒でツール)


 @2010-04-25

http://coderepos.org/share/ に書かれている通りにメールを送ってみたが音沙汰がない。スパム判定されたか。comitterってそのページに書かれてるので全てだよね。行動力のある人間なら(というか人並みの人でも) Twitterなり IRCなり blogなりでアクションを起こすんだろうが……。(だから手続きが自動化されてなさそうなのが嫌だったんだ。漏れるし遅れるし。それにサービス自体個人の奉仕に依存してる)

気になる。自分のバグも他人のバグも気になる。


 @2010-05-01: c37240のバグは c37332で本人の手によって修正されたみたい。

Hatena::Section#initializeの部分の修正は、既に行頭の *で分割された文字列が与えられるから問題ないとして先のファイル(fix_c37240.patch)に含めてなかったけど、まあ subが gsubになったって減るもんじゃなし。

それだけでなく 実は一行だけ buffer = '' を buffer = lines.shiftに書き換えた。これがないと無限ループに陥るケース(「>>>」という本文。3文字目は他の文字でもいい)があるみたいなので。


2010年04月15日 (木) 「新快速 ○○行き HH:MM △分遅延」結局何時に着くのだろう? 5分後の HH:MMなのか 5+△分後なのか。電光掲示で知りたい(またそれだけのスペースしかない)のは次の電車がいつ来るかなので遅延も織りこみ済みだろうと思いかけたが、すぐに、正確さが売りの日本の電車のこと、あれはいつ着くはずであったのかを示す時刻だろうと考え直した。(その通りだった。それに発着時刻は電車のIDでもあるし(あっち行き/こっち行きだけで済む駅ばかりではないだろう))

最終更新: 2010-05-07T12:01+0900

[tDiary] 非同期ファイルアップロード

設定画面に jQueryが仕込まれたのと、JavaScriptの置き場所が用意されたので、ファイルのアップロードを非同期に行う準備が整ったのではないか。独自のサブミットボタンを編集画面に貼り付けるプラグインが全部非同期になれば、プレビュー画面にアップロードフォームを表示しても(編集中の本文が消えたと)怒られないだろう。

ジャンクだけど Firefox3.6と Internet Explorer8と Google Chrome4.1で動くものをこの日記(最新じゃないので jQuery対応ではない)に仕込んでみた。

  1. アップロードフォームの targetをこっそり作成した iframeにすることで編集画面が遷移するのを防ぐ。
  2. iframe.{onload|onreadystatechange}をつかまえて、レスポンス(新しい編集画面)から目当ての要素(アップロード済みのファイル一覧とか)を取り出す。(iframe.{contentDocument|contentWindow.document}.getElementById("image_file_list"))
  3. replaceChildは問題が起きるかも?と思ったので .innerHTML = .innerHTMLでざっくりページの一部を更新。
  4. ファイル一覧の数が 0個と 1個を行き来するときは画面が痙攣したようになるのでアニメーションにできると良さげ。

これで本文を書きながらプレビューもできるしファイルのアップロードもできる。


クリップボードアクセスのために Flashを使うよりはましだけど、<iframe>に頼らなければいけないというのもわりと屈辱的。<frameset><frame>以上に、これまで存在を認めてこなかったのに。


何となくできないものと思っていたけど <iframe>の中から外のドキュメントにアクセスすることができるみたい。それができたら編集画面が無制限に入れ子になる(編集画面の<iframe>の中の編集画面の<iframe>の中の……)ことを今より簡単に防止できて、スクリプトももうちょっと使いやすく書き換えられる。


 Firefoxが(3.6になっても)テキストエリアのスクロール位置をリセットしてしまう件。

Karetta|[JavaScript] Firefoxでtextareaのカーソル位置に文字列を挿入した後にスクロールが先頭に戻ってしまう問題(karetta.jp)」で紹介されている通りで直った。といってもできるだけ余計なことをしないように条件を付けたが。

var scrollTop = textarea.scrollTop;
/*
  ここで、テキストエリアに文字列を挿入する。
*/
if(0 == textarea.scrollTop && 0 < scrollTop) {
  // スクロール位置がリセットされていたので復元する。
  textarea.scrollTop = scrollTop;
}

ところで、Internet Explorer 8だけはテキストエリアのキャレット位置を保存しようなんてことを考えなかったみたいで、いったんテキストエリアがフォーカスを失うとキャレットが必ず末尾に移動する。スクロール位置がどうこうどころではないわな。


 @2010-05-07

「何となくできないものと思っていたけど <iframe>の中から外のドキュメントにアクセスすること」 < HTML5 sanbbox属性


2010年03月08日 (月) obsoleteって形容詞だと思うんだけど推測辞書に obsoletedや obsoletingが含まれてるんだよね(辞書には載っていないが)。obsoleted - Wiktionaryによれば nonstandardだけど一部の分野で使われている、ということらしい。

最終更新: 2014-12-05T17:23+0900

[tDiary] spam絨毯爆撃対策

送信元が限られてるのかワンパターンだったので、これまでは </a> を NGワードにしてほとんどの spamを防いでいたんだけど、今日は手ひどくやられた。

フィルタはインストール方法がよくわからない。Comment-key Filterを tdiary/filter/ に設置したがエラーが出るので、とりあえず最新の 2.3.3.20091124にアップデートした。そうすると plugin/60sf.rbが有効になっているはずなので misc/filter/ にフィルタスクリプトを、misc/filter/plugin/ にフィルタに関連する設定などを表示するプラグインスクリプトを、misc/filter/plugin/ja/ などにプラグインの言語リソースをインストールし、設定画面でフィルタを有効にするといずれのスクリプトも読み込まれるようになる。

 スパムフィルタ1: Comment-key Filter & Plugin version 0.5.0

コメントフォームにキー文字列を埋め込み、コメントが HTMLフォームを通して投稿されたことを確認する。キーは日記設置者の決めた文字列と日記の日付によって一意に決められるので、ある日のキー文字列を一度取得すればその日には何件でも機械的に投稿することができる。GETして HTMLを切り刻む手間をかければ最初から機械的に投稿することもできる。そんなのは防げない。

tDiary-2.3.3.20091124にインストールするのなら key.rbを misc/filter/key.rbへ、comment_key.rbを misc/filter/plugin/key.rbへ、ja/comment_key.rbを misc/filter/plugin/ja/key.rbへコピーすれば良い。key.rbというファイル名と KeyFilterというクラス名は対応しているので、key.rbから comment_key.rbへの改名はやめたほうがいい。コピー後にフィルタを有効にし、キー文字列を設定する。

 スパムフィルタ2: limit_freq.rb

連投対策。同じ IPアドレスからの連続する投稿をはじく。30分につき 3件までしか許可しない、など。

# coding: utf-8
#
# limit_freq.rb: 
#
#  a spam-filtering plugin of tDiary
#  rejects frequent comments posted from an IP address.

module TDiary::Filter
	class LimitFreqFilter < Filter

		def comment_filter( diary, comment )
			now = Time.now.to_i
			comment_i = Comment_t.new( now, @cgi.remote_addr )

			# 数値形式の日時と文字列形式の IPアドレスの二要素
			# 配列の配列を、日時をもとに昇順にソートしたもの。
			# log = [[123456, "1.2.3.4"], [234567, "5.6.7.8"],...]
			log = []

			require 'pstore'
			ps = PStore.new( cache_path )
			ps.transaction( false ) { |db|
				log = db.fetch( DBRoot, log )

				# 新しいコメントを logに追加する。
				log.insert( ArrayExtension.lower_bound(log){|pair| pair.first - comment_i.time }, [comment_i.time, comment_i.ipaddr] )

				# 古い logを捨てる。
				oldest = now - time_span
				log.slice!( 0 ... ArrayExtension.lower_bound(log){|pair| pair.first - oldest } )

				db[DBRoot] = log
				db.commit
			}

			# 残った logに投稿者の IPアドレスがいくつ含まれるか数え、
			# その数が閾値を超えていないか確かめる。
			count = 0
			if log.all?{|pair|
				count += 1 if pair.last == comment_i.ipaddr
				count < threshold
			} then
				return this_is_not_a_spam( comment )
			else
				debug("limit_freq.rb: spam: the # of comments posted from #{comment_i.ipaddr} exceeds threshold:#{threshold} within the last #{time_span.to_i}seconds.")
				return this_is_a_spam( comment )
			end
		rescue
			debug("limit_freq.rb: BUG: #{$!}")
			return this_is_not_a_spam( comment )
		end

	private
		DBRoot = 'LimitFreqLog'
		Comment_t = Struct.new(:time, :ipaddr)

		def cache_path
			return File.join( (@conf.cache_path || "#{@conf.data_path}cache"), 'limit_freq.data' )
		end

		# どれだけの期間(秒単位)、コメントの投稿頻度の判定に
		# 利用するログ(日時とIPアドレスのペア)を保存するか。 
		def time_span
			30 * 60
		end

		# time_span当たり、何件目の投稿からを拒否するか。
		def threshold
			4
		end

		module ArrayExtension
			# ソート済みだという前提を活かしていない!
			def lower_bound( arr, &block )
				index = 0
				arr.length.times{
					return index if 0 <= yield( arr[index] )
					index += 1
				}
				return index
			end
			module_function :lower_bound
		end
	end
end

やめればいいのに本体もちょろちょろと変更。

  • 設定画面における [セキュリティ]>[spamフィルタ]>「spamの扱い spamと判定されたツッコミを{非表示にする|捨てる}」という項目は tdiary/filter/spam.rbに固有の設定らしいのだが、そんなこととは夢にも思わないので、最初は自作のフィルタでスパム判定したコメントが捨てられることに困惑した。設定を本体に取り込んで他のフィルタからも利用しやすくした。
  • limit_freq.rbや limit-freq.rbや limit_--_freq.rb というフィルタに対しては LimitFreqFilterという名前のクラスを要求するようにした。(これらのファイルが複数存在するときは困るなあ。読み込み順で最終定義が変わりそう)
  • どういうわけか無名クラスの下に定義された TDiary::Filter定数を参照してエラーになるので ::TDiary::Filterとした。
Index: core/tdiary.rb
===================================================================
--- core/tdiary.rb	(リビジョン 44436)
+++ core/tdiary.rb	(作業コピー)
@@ -342,6 +342,22 @@
 
 				@logger.info("#{@cgi.remote_addr}->#{(@cgi.params['date'][0] || 'no date').dump}: #{msg}")
 			end
+
+		private
+			# config: hide or drop spam comment
+			def hide_spam?
+				return @conf.options.include?('spamfilter.filter_mode') && @conf.options['spamfilter.filter_mode']
+			end
+
+			def this_is_a_spam( comment )
+				comment.show = false
+				return hide_spam?
+			rescue
+				return false # comment could be a String(@cgi.referer).
+			end
+			def this_is_not_a_spam( comment )
+				return true
+			end
 		end
 	end
 
@@ -1303,7 +1319,7 @@
 			filter_path = @conf.filter_path || "#{PATH}/tdiary/filter"
 			Dir::glob( "#{filter_path}/*.rb" ).sort.each do |file|
 				require file.untaint
-				@filters << TDiary::Filter::const_get( "#{File::basename( file, '.rb' ).capitalize}Filter" )::new( @cgi, @conf, @logger )
+				@filters << TDiary::Filter::const_get( "#{File::basename( file, '.rb' ).split(/[-_]+/).map{|x|x.capitalize}.join('')}Filter" )::new( @cgi, @conf, @logger )
 			end
 		end
 
Index: core/plugin/60sf.rb
===================================================================
--- core/plugin/60sf.rb	(リビジョン 44436)
+++ core/plugin/60sf.rb	(作業コピー)
@@ -4,10 +4,9 @@
 # Modified by KURODA Hiraku.
 
 SF_PREFIX = 'sf'
-@sf_path = ( @conf["#{SF_PREFIX}.path"] || "#{::TDiary::PATH}/misc/filter" ).to_a
-@sf_path = @sf_path.collect do |path|
-	/\/$/ =~ path ? path.chop : path
-end
+@sf_path = ( @conf["#{SF_PREFIX}.path"] || "#{::TDiary::PATH}/misc/filter" ).to_a.map{|path|
+	path.chomp('/')
+}
 
 # get plugin option
 def sf_option( key )
@@ -128,7 +127,7 @@
 			if File.readable?( path ) then
 				begin
 					require path
-					@sf_filters << TDiary::Filter::const_get("#{File::basename(filename, ".rb").capitalize}Filter")::new(@cgi, @conf, @logger)
+					@sf_filters << ::TDiary::Filter::const_get("#{File::basename(filename, ".rb").split(/[-_]+/).map{|x|x.capitalize}.join('')}Filter")::new(@cgi, @conf, @logger)
 					plugin_path = "#{dir}/plugin/#{filename}"
 					load_plugin(plugin_path) if File.readable?(plugin_path)
 				rescue Exception

 @2010-03-09: IPアドレスブロック

一件二件すり抜けるぐらいはいいかと思っていたがここ数日は毎日なのでいいかげん腹が立つ。なによりアクセスログを見たらヒット数、転送量トップが spammerだというのが決定的に許せない。節度を知れ。iptablesはいじれないので .htaccessで Apacheに拒否してもらう。


 @2010-03-11: 対応が早いね

spamコメントがくる月っていうのは、いつもの決まった 2、3か国からのアクセスではなく 10近い国から少数ずつアクセスがあるもんだけど、日単位では固定の IPアドレスから数十件の spamがくるのが常だった。でも今日は一件一件みごとに IPアドレスが異なっている。IPアドレスブロックで次のステージに進んでしまったのか。

spamコメントの目的が特定の URLへの誘導であるかぎりは、コメントに含まれる URLのドメインが白か黒かを判定する方法が有効でしょうね。外部に問い合わせるのは避けたかったんだけど、spamコメントの内容が URLも含めてワンパターンだから実際の問い合わせはごくごく限られた回数にできそうだし、悪くないかな。

 CodeRepos

ここで上記の comment-keyフィルタも含めてスパムフィルタの最新版が管理されていた。 >http://coderepos.org/share/browser/platform/tdiary/filter


 こぼれ話: rel="true"

plugin/00default.rbに含まれるメソッド navi_itemを自分でも使っていたのだけど、tDiaryをアップデートしたら三番目の引数が真偽値からリンクの rel属性文字列へと変更されているせいで rel="true" なるリンクができていた。こうする。

def navi_item( link, label, rel = nil )
	rel = "nofollow" if rel == true # backward compatibility

 @2010-03-09: 日記の編集もキャッシュベース?

スパムコメント一掃のために YYYYMM.tdcを削除したけど日記の編集画面からコメントが消えない。YYYYMM.parserを開くとコメントが含まれていたし、これを削除すると編集画面からもコメントが消えた。原因はデータファイルを直接削除するというイレギュラーな操作だけど、日記の編集はマスターデータに対して行いたい気もする。


2009年12月06日 (日) [C++]「ヘッダファイルの依存を減らす」<端緒。パフォーマンスの本といえば『Efficient C++』だけかと思っていた(『Boost』にそのように書かれていた)ら、目当ての本の横に『C++パフォーマンス戦略』という本が。これまでのところ大垣書店はすごくよくやっている。Amazonで注文する前にとりあえずのぞいてみて、一度も期待を裏切られていない。

最終更新: 2013-05-21T00:39+0900

[tDiary] つれづれに書き連ねるとリンクしにくいらしいので……(誰の話でしょうね。それにあそこははてな)

<h4>と <h5>にもアンカー(<a name="..."></a>)を与える。href属性や中のテキスト(&nbsp;)は URLをコピーしやすくするためのおまけ。そもそも <h4>や <h5>に id属性を付加するのでなく <a>を利用しているところからが利便性目的以外のなにものでもない。<h4>と <h5>の中に <a>を置くことには、highlight.rbを修正しなくてもハイライトが機能するというメリットもある。デメリットは見出し語の先頭に余分な空白が挿入されている、ということ。セクションタイトル右端の編集用リンク「✍」は、<h3>に含まれないように気をつかっているのですよ。

 core/tdiary/wiki_style.rb, TDiary::WikiSection#do_html4

def do_html4( date, idx, opt )
	strdump = lambda{|s| s.dump.gsub( /%/, '\\\\045' ) }

	r = @html.lstrip
	r.sub!( %r!<h3>(.+?)</h3>!m ) do
		"<h3><%= subtitle_proc( Time::at( #{date.to_i} ), #{strdump.call $1} ) %></h3>"
	end or r.sub!( %r!^<p>(.+?)</p>$!m ) do
		"<p><%= subtitle_proc( Time::at( #{date.to_i} ), #{strdump.call $1} ) %></p>"
	end

	serial = [nil, nil, nil, '%02d'%idx, '00', '00']
	dumped_param = strdump.call "#{date.strftime( '%Y%m%d' )}#p#{'%02d' % idx}"
	header_t = Struct.new(:opentag, :level)
	bqlevel = 0
	r.gsub!( %r!(<blockquote\b)|(</blockquote>)|<h(4|5)[^>]*>!i ) do
		bqlevel += 1 if $1
		bqlevel -= 1 if $2
		next $& if bqlevel != 0 or $3.nil?

		h = header_t.new($&, $3.to_i)
		serial[h.level, serial.length-h.level] = Array.new(serial.length-h.level){|i| i==0 ? serial[h.level].succ : '00' }
		frag = 'p' + serial[3 .. h.level].join('.')
		%!#{h.tag}<a name="#{frag}" href="<%=anchor(#{dumped_param}).gsub(/#p#{'%02d'%idx}/, #{strdump.call('#'+frag)}) %>">&nbsp;</a>!
	end

	r.gsub( /<(\/)?tdiary-section>/, '<\\1p>' )
end

2段階に評価されるせいで、すんごく読みにくい。

ハッシュテーブルのキーがシンボルか文字列か気にしたくないのと、括弧や引用符やコロンがじゃまくさいので、. ひとつで済む Structに登場してもらった。

lambdaの .call() も嫌いだなあ。[] で () を代用するおぞましさよりはマシだが。

試してないけど、「end or r.sub!(...」を複数の行に分けるとシンタックスエラーになりそうなのも嫌。

破壊的メソッドが返す nilを利用するコードを初めて書いた!

 @2013-05-21 URLが変わる大きな修正

H4のシリアルナンバーが増加したときに H5のシリアルをリセットするように変更した。以前はこういう連番だった。

  • p01.01
    • p01.01.01
  • p01.02
    • p01.02.02

最後が p01.02.01になるように。


 @2009-12-09

URLフォーマットが変わると影響範囲が広くて困る。自分の日記へのリンクを検出する正規表現をあちこちで書き直した。

Index: core/tdiary/wiki_style.rb
===================================================================
--- core/tdiary/wiki_style.rb	(リビジョン 43193)
+++ core/tdiary/wiki_style.rb	(作業コピー)
@@ -149,7 +149,7 @@
 			hikihtml = HikiDoc::HTMLOutput.new
 			html.gsub!( %r!<a href="(.*?)">(.*?)</a>! ) do
 				k, u = hikihtml.unescape_html($2), hikihtml.unescape_html($1)
-				if /^(\d{4}|\d{6}|\d{8}|\d{8}-\d+)[^\d]*?#?([pct]\d+)?$/ =~ u then
+				if /^(\d{4}|\d{6}|\d{8}|\d{8}-\d+)\D*([pct]\d+(?:\.\d+)*)?$/ =~ u then
 					%Q[<%=my '#{$1}#{$2}', '#{escape_quote CGI.escapeHTML k}' %>]
 				elsif /:/ =~ u
 					scheme, path = u.split( /:/, 2 )
Index: core/plugin/00default.rb
===================================================================
--- core/plugin/00default.rb	(リビジョン 43193)
+++ core/plugin/00default.rb	(作業コピー)
@@ -480,7 +480,7 @@
 # make anchor string
 #
 def anchor( s )
-	if /^([\-\d]+)#?([pct]\d*)?$/ =~ s then
+	if /^([\-\d]+)#?([pct][\d\.])?$/ =~ s then
 		if $2 then
 			"?date=#$1##$2"
 		else
@@ -540,7 +540,7 @@
 # make anchor tag in my diary
 #
 def my( a, str, title = nil )
-	date, frag = a.scan( /^(\d{8}-\d+|\d{8}|\d{6}|\d{4}|)\D*([pct]\d+)?$/ )[0]
+	date, frag = a.scan( /^(\d{8}-\d+|\d{8}|\d{6}|\d{4})\D*([pct]\d+(?:\.\d+)*)?$/ )[0]
 	anc = frag ? "#{date}#{frag}" : date
 	index = /^https?:/ =~ @index ? '' : @conf.base_url
 	index += @index.sub(%r|^\./|, '')
Index: plugin/html_anchor.rb
===================================================================
--- plugin/html_anchor.rb	(リビジョン 43193)
+++ plugin/html_anchor.rb	(作業コピー)
@@ -14,7 +14,7 @@
 if @conf.index.empty? or /\/$/ =~ @conf.index
 
 def anchor( s )
-	if /^([\-\d]+)#?([pct]\d*)?$/ =~ s then
+	if /^([\-\d]+)#?([pct][\d\.]*)?$/ =~ s then
 		if $2 then
 			"#$1.html##$2"
 		else
Index: plugin/my-sequel.rb
===================================================================
--- plugin/my-sequel.rb	(リビジョン 43193)
+++ plugin/my-sequel.rb	(作業コピー)
@@ -487,7 +487,7 @@
 	alias :my_sequel_orig_my :my unless defined?(my_sequel_orig_my)
 	def my(*args)
 		if @my_sequel_active and @my_sequel_date and @my_sequel_anchor and @mode != 'preview' then
-			dst_date, frag = args[0].scan(/^(\d{8})\D*(?:p(\d+))?$/)[0]
+			dst_date, frag = args[0].scan(/^(\d{8})\D*(?:p(\d+)(?:\.\d+)*)?$/)[0]
 			if dst_date and dst_date < @my_sequel_date then
 				dst_anchor = "#{dst_date}#{frag ? "#p%02d" % frag.to_i : ''}"
 				@my_sequel.add(@my_sequel_anchor, dst_anchor)
Index: plugin/my-ex.rb
===================================================================
--- plugin/my-ex.rb	(リビジョン 43193)
+++ plugin/my-ex.rb	(作業コピー)
@@ -13,9 +13,10 @@
 
 unless @conf.mobile_agent?
 
+alias :my_overwritten_by_my_ex :my
 def my( a, str, title = nil )
 	m = /^(\d{8})\D*(?:([pct])(\d+))?$/.match( a )
-	return '' unless m
+	return my_overwritten_by_my_ex( a, str, title ) unless m
 	_, date, place, frag = *m
 
 	if title.nil? and date and frag and @diaries[date] then

 @2010-03-08: 「ツッコミを入れる」リンクが無効になってしまっていた。

misc/plugin/html_anchor.rbと plugin/00default.rbプラグインを再び修正。

元々if /^([\-\d]+)#?([pct]\d*)?$/ =~ s then
修正ミスif /^([\-\d]+)#?([pct]\d+(?:\.\d+)*)?$/ =~ s then
OKif /^([\-\d]+)#?([pct][\d\.]*)?$/ =~ s then

「ツッコミを入れる」リンクは YYYYMMDD#c へのリンクなので、cの後ろに数字が続いていない。これをうっかり除外してしまっていた。


2009年11月05日 (木) [Vista] まただ。カーソル移動がもっさりすると思ったら。

最終更新: 2014-12-05T17:24+0900

[tDiary] フィードが空になっている。

理由は makerss.cacheが hiddenな spamコメントで埋め尽くされたから。問題です。

本日のツッコミ(全25件) ツッコミを入れる

Before...

ななしデバッグモードでコンパイルすると、4883行で、 error C2440: 'int' から 'CLayoutInt..

ななしrev8です。 あいうえお 1かきくけこ 0123456789 「い」の右側から、3行全部を0幅選択してスペース..

ななしrev8.1でOKな気がします。 いい感じ (^^)

anonymouse「1文字のTAB/SPACE入力が必ずインデント扱いになってしまっていて変」 (2009年11月10日 (火) 10..

ななし念のため。 上記の、 ・タブキーとスペースキーに割り付けられた機能を削除すると、  複数行選択したときのタブやスペ..

ds14050ええと、具体的にどういう動作が不満で、どういう結果になるのがよいのでしょうか。rev.9版のバイナリは http:/..

ななし行末を超えた位置にも通常文字は入る。 SPACEキーにインデントを割り付けて*いない*ときは、 行末を超えた位置には..

ds14050この部分ですね。 ---- if( nDataLen == 1 && IsIndentChar( pData[0] ..

ななしnDataLen == 1 && IsIndentChar( pData[0] ) なんていう条件だと、 クリッ..

ななし> 選択範囲が一行だけだったとき、Command_INDENT_TAB()は Command_INDENTの代わりに..

ds14050>1字のSPACE/TABという条件は、コードをはじめて見た >瞬間におかしいと思ったし、誰でも同じことが想像できる..

ds14050どうしようもないな。「元の挙動を残し」た。<<<大嘘

ds14050なんかもうぐだぐだだけど気づいてしまってので訂正。 >知らないのは事実です。最初のコメントに書いたとおり。 最初のコ..


2009年11月04日 (水)

最終更新: 2009-11-05T05:03+0900

[tDiary] リンク>「tDiary用目次プラグイン - にっき (2009-11-04)

いやらしいプラグインだなあ(笑)

しかしこの変哲のないただリンクに見えるもののどこに着目して、googleは小見出しを作成してるんだ。


2009年08月28日 (金) はてなの引用は元ページのタイトルを自動取得できるのねん。「404 Not Found」からの引用になってる日記(マジックリン!)を見て気付いた。日記ブログの書かれた当時は当然 404ではなかったはずで、どういうタイミングでページ取得を行ってるんだろう。■■■@2013-09-14「Hatena Pagetitle Agent/1.0」っていうのがそうかな?

最終更新: 2013-09-14T00:17+0900

[tDiary] 一日のタイトルを HikiDocフォーマットで HTML化。

使えないのを知っていて以前から HikiDocフォーマットでタイトルを書いていた。>>20090823 >>20090403

これを HTML化するのは意外と簡単。プラグインでできる。

add_title_proc {|date, title|
  if title.index('<')
    title.sub(/<span class="title">([^<>]+)<\/span>/){
      %/<div class="title">#{WikiSection.new(CGI.unescapeHTML $1).body_to_html}<\/div>/
    }
  else
    WikiSection.new(CGI.unescapeHTML title).body_to_html
  end
}

今日のタイトルに含まれる「==日記==ブログ」という部分があまりにわかりにくかったので、HTML化してみた次第。URL自動リンクも有効になって、うまうま。


勘違い発覚。Headingがブロック要素を包含できる気がしていたが、Heading自身がブロック要素だということの記憶違い。<div>を含めちゃだめだ。

修正。

add_title_proc {|date, title|
  inline_or_nil = lambda{|src|
    lines = src.split(/\r?\n/)
    return nil if 1 < lines.length
    html = WikiSection.new(lines.first).body_to_html
    return nil if html[0,3] != '<p>' or html[-4,4] != '</p>'
    return html
  }
  if title.index('<')
    title.sub(/<span class="title">([^<>]+)<\/span>/){|_0|
      html = inline_or_nil.call(CGI.unescapeHTML $1)
      html ? %/<span class="title">#{html}<\/span>/ : _0
    }
  else
    inline_or_nil.call(CGI.unescapeHTML title) or title
  end rescue title
}

それなりにチェックはしてるけど、ブロック要素を返すプラグインを呼んだりしたら(HTMLの文法的に)即アウト。