anti scroll

ブラウザと小説の新しい関係を模索する

はてなブログに移転しました

古いブログの記事をそのままインポートしたので、ところどころおかしなところもあるかもしれません。

旧ブログの記事もそのまま残してあるので、2013/08/21以前の記事はそっちを見たほうが良いかもです。*1

*1:やっぱり混乱するので削除しました。コメントとかも消えてしまいますがゴメンナサイ。

ウェブサイトをページ送りで閲覧できるGoogle Chrome拡張「Nehan Reader」をリリースしました

見ているサイトをページ送り表示に変えてしまうgoogle chrome用の拡張「Nehan Reader」を公開しました。

» Nehan ReaderをインストールするChromeウェブストア)

使い方は、ブラウザーバーに表示される「涅」というアイコンをクリックするだけ。

f:id:convertical:20130820184517p:plain

nehan.js previewer を公開しました

nehan.js previewer(β) を公開しました。

Chrome/Firefox などではドラッグ&ドロップでページ出力された結果をプレビューできます(IEの場合はテキストフォームから)。

もともとテスト用に作ったものですが、一般の人にも便利かもと思って公開してみました。

nehan.jsにおける関数値を設定するセレクタについて

nehan.jsではセレクタの値に「関数値」を設定できるものがあります。

例えばcssの擬似クラスにnth-childというものがありますが、これに2n+1とか-n+10とかいう値を設定するよりは、nを受け取る関数にしたほうがわかりやすいので、nehan.jsではnth-child, nth-type-of-childなどは関数で指定するようになっています。

以下はnth-childを使って、「先頭から10番以内かつ奇数」なら、背景色をピンクにするスタイル宣言です(ちなみにここではnehan.jsの基本的な扱い方については説明しません)。

var engine = Nehan.setup();

engine.setStyle(".my-list li", {
  "nth-child": function(n, markup, ctx){
    if(n < 10 && n % 2 == 1){
      return {"background-color":"pink"};
    }
  }
});

続けて「cssで書くとどうなるか」を書きたいところですが、擬似クラスで奇数かつ10以内とか一発指定できるんでしょうか。ちょっと書き方がわからないのでごめんなさい。

もちろん全ての擬似クラスが関数を取るわけじゃなく、firstのような「点」で指定できるものは、cssと同様の文法で指定できます。

// 先頭だけ赤くてデカい文字
engine.setStyle(".my-list li:first", {
  "font-size":"2em",
  "color":"#ff0000"
});

ちなみにnehan.jsでは、より汎用性のあるやり方として「onload」というフックをスタイルにセットできるようになっています。

// 三番目だけ太字に
engine.setStyle(".my-list li", {
  "onload":function(markup, ctx){
    var nth = markup.getChildNth();
    if(nth === 2){
      return {"font-weight":"bold"};
    }
  }
});

上のサンプルでは、onloadの引数に入ってくるmarkupクラスを使ってnth-childを取得し、三番目なら太字にするスタイルを返しています(ゼロから数えるので、2が三番目であることに注意)。

ちなみに二番目の引数ctxですが、この中にはドキュメントの情報が色々と入っています。

例えばhtmlのmetaヘッダとか、ドキュメントのアウトライン構造とか、anchorが貼られたリンク集合みたいなものです。

以下はこのctxからhtml headerに含まれるmetaタグの個数を取得し、デバッグ出力するタグを作るサンプルです。

engine.setStyle("meta-debug", {
  "display":"block",
  "border-width":"2px",
  "border-style":"solid",
  "border-color":"black",
  onload:function(markup, ctx){
    var meta_count = ctx.getHeader().getMetas().length;
    if(meta_count === 0){
      markup.setContentRaw("no meta!");
      return {"color":"red", "font-weight":"bold"};
    } else {
      markup.setContentRaw("meta count=" + meta_count);
      return {"color":"blue"};
    }
  }
});

上のサンプルでは、metaタグの数に応じて異なるスタイルを返すと共に、markupの中身も書き換えています。

ocamlのネットワークライブラリでfile_descrリークするものが多い理由

ocamlの通信系ライブラリでUnix.open_connectionを使っているライブラリは、Unix.shutdown_connectionを呼ぶだけで切断処理を終わらせているものが多いなあと思いました。

最近さわったredis用のclient libraryとmemcached用のclient libraryはどっちもそういう感じでした。

redis用のライブラリに至っては、サーバーにQUITコマンドを送るだけで終わらせていたりとか。

結果、CLOSE_WAITなsocketが無限に増え続け、いつしかウェブサーバーが起動しなくなったりとかします。

Unix.shutdown_connectionは、名前から想像できるように、内部でsocketのshutdownが呼ばれているわけですが、そもそもshutdownってのはhalf closeと呼ばれていて、「こちら側は終了するつもりですよ」と相手方に教え、相手に先にcloseさせてから、こちらをcloseする前段階として呼び出すものです。

それでこちらのsocket file_descrがcloseされるわけではないので、shutdownだけで終わらせてると、接続するたびに閉じられないfile_descrが増え続けることになります。

で、OSが開くことの出来るファイルハンドルの数には限りがあるので、それが限界を突破した時、ウェブサーバーがエラーログのfileを開くことが出来なくて起動不可な状態になってたり……とかは、割と良くあるパターンです。

じゃあどうやってcloseするかというと、shutodown後に受信用ソケットを0が返るまで読み続け、Unix.close socketするだけ。

でもOCaml標準ライブラリのUnix.open_connectionは、socketのin_channelとout_channelのタプルを返すだけで、socketそのものを返さないので、そうやってsocketを隠蔽しているからには、in_channelを受け取るshutdown_connectionという関数が内部で全てよろしくやってくれるように見えなくもないのですが……

unix.mlの内部を見るとこうなっています。

let shutdown_connection inchan =
  shutdown (descr_of_in_channel inchan) SHUTDOWN_SEND

shutdownと付いているのだから当たり前なのですが、half closeしているだけです。

この後にUnix.closeする処理を付け加えるのは、アプリケーション作成者の責任というわけですね……

書くなら(ブロッキングする処理ですが)こんな感じでしょうか。

let close_connection inchan =
  let buffer = String.create 256 in
  let rec safe_close sock =
    if Unix.read sock buffer 0 256 = 0 then
      Unix.close sock
    else
      safe_close sock in
  safe_close (Unix.descr_of_in_channel inchan)

もちろんshutdownした後に呼ぶ関数です。

「red」は#f00、「blue」は#00f、「green」は?

redは#ff0000だし、blueは#0000ff。

となればgreenは#00ff00だと思うじゃないですか。

でも違くて、Gの成分がffの色名は「lime」というらしく。

色名の「green」は、Gの成分がlimeの半分で#008000なのだそうです。

色相を語るときのGと、色名を語るときのgreenは意味するものが違うのですね……

この辺を勘違いしてたので、unit testが通らなくて焦ったという話しです。

全ての表紙画像を縦書き文庫でホストするようにしました

先月から表紙画像を縦書き文庫にアップロードできるようになっていますが、これまではリモートにリンクされていた画像はそのままにしていました。

ただ最近ImageShackへのアクセスが重くなっていて、ページの読み込みが遅くなっていました。

そこで、リモートにリンクされた画像を、すべて縦書き文庫にダウンロードしてしまうことにしました。

で、その過程で、ダウンロードに失敗した表紙が(けっこう)あって、それらのリンクは迷ったのですが削除しました。読み込めない画像がリンクされていると、ページの表示速度が落ちて、全ユーザーに影響が出てしまうからです。

どんな画像がダウンロードできなくなっているのか、法則はよくわかりませんが、たぶん大きすぎる画像とかが駄目になってるのでは……と思います。

運悪く消されてしまった表紙のある人は、お手数ですが今度はImageshackではなく、縦書き文庫に直接アップロード願います。