preに行番号、の別解(cssで)

ここの pre ブロックが不思議でね…。

以下、不思議だ、と思う人は、結構 html 良く書いてきてる人と思う。

# -*- coding: utf-8 -*-
import sys
import os
sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "."))
import json
try:
    import StringIO
    StringIO = StringIO.StringIO
except ImportError:
    # python 3
    import io
    from io import StringIO
    if sys.stdin.encoding != "utf-8":
        # Windows?
        sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding="utf-8")

ダブルクリックとか選択とか、違和感あります? ないです? コード部分をどうにか全選択して、「コピー」して、何かメモ帳とかに貼り付けてみれば、なお不思議に感じるかと。

要はこの振る舞いが欲しいわけですよ。「行番号」は、コードの一部ではないからね、行番号もろともコピーしたいヤツぁいない。

何か新しいシカケを使っているのかと思ったら、昔からの css で出来るヤツなんだな、これ。:before 擬似要素も随分昔から使えたよな、確か。こんななのよ:

 1 <style>
 2 .linenumbered {
 3   counter-reset: my-counter;
 4 }
 5 .linenumbered code:before {
 6   counter-increment: my-counter 1;
 7   content: counter(my-counter, decimal);
 8   float: left; clear: both; min-width: 2.5em;
 9 
10   font-size: large;
11   background-color: #ddd;
12 }
13 .linenumbered code {
14   font-size: large;
15 }
16 </style>
17 <pre class="linenumbered">
18 <code># -*- coding: utf-8 -*-</code>
19 <code>import sys</code>
20 <code>import os</code>
21 <code>sys.path.append(os.path.join(os.path.dirname(os.path.abspath(__file__)), "."))</code>
22 <code>import json</code>
23 <code>try:</code>
24 <code>    import StringIO</code>
25 <code>    StringIO = StringIO.StringIO</code>
26 <code>except ImportError:</code>
27 <code>    # python 3</code>
28 <code>    import io</code>
29 <code>    from io import StringIO</code>
30 <code>    if sys.stdin.encoding != "utf-8":</code>
31 <code>        # Windows?</code>
32 <code>        sys.stdin = io.TextIOWrapper(sys.stdin.buffer, encoding="utf-8")</code>
33 </pre>

そうなんだけど、アラインメント(位置揃え)問題はやっぱりあって。min-width でいいはいいんだけれど、float: left; clear: both; 入れないと効かない。それと数値が左揃えなのは、「行番号」用途にはやっぱし見栄え悪い。こことかでは中央揃え出来てるんだけど、どうやってるのかソースみてもわかんないんだよねぇ…。

ワタシのpygmentizeでこれを取り込むことが出来ると、多分表示速度上げれるんだけれども、pygments とはあまり相性良くなくて。pygments の行番号は、「1行目始まりでない」のも可能なので、これと同じものを提供するには動的にやらなければいけないし、それに、「各行を何かでくるむ(上の例では毎行 code で包まれてる)」オプションとの兼ね合いもあるし。けどやってやれないことはないし、やれば快適とは思う。