Javascript による自動番号付けと相互参照
2016-6-4(Sat)
html をエディタで編集して、ちょっとした文書を書こうと思うことがある。LaTeX で書くよりも多くの環境で見ることができるし、pdf への変換も簡単だ。ついでに、章節や図表に自動で番号付けして、これをラベルを使った引用できる仕組みがあればもっと便利だろうと考えた。さらに参考文献が引用順/著者名順にソートできれば申し分なしだ。それなら Javascript を使てクライアント側でやっちゃおう。この文書は、そういう試みのためにダミー文書として書いたものである。せっかくだから、いくらか読んで意味のありそうなものにしようと思ったら、なにやらドキュメントらしきものになってしまった。なお、外観もいくぶん LaTeX っぽくなるように、CSS を書いてみたりした。
目次
LaTeX が便利な点を 2 つにまとめるなら、数式が容易に組めるということと、ラベルによってさまざまな要素を参照できるということだろう。前者について html 界隈では W3C が MathML という規格を作っているが、対応していないユーザーエージェントもあり、未だ実用には至っていない。私はこれについては潔く匙を投げることにした。とはいえ、MathJax 等のサービスを利用するとか、SVG その他の画像として html ページに張り込むといった解決法と矛盾するようなことはしていないので、それらの方法で数式を書き入れたり、式に番号をつけたりすることはできるだろう。
ここで私がやろうとしたことは、もう一つのほう、つまり章節、図表、参考文献に対して連番を自動生成することと、ラベルを使ってそれらを本文中から参照することだ。LaTeX でいうと \label を \ref したり、\bibitem を \cite したりするのに当たる。これは、印刷を想定したウェブ・ページを作成する場合に特に有益である。というのは、「1.2.3で議論したように」とか「図1に示した通り」とか、あるいは「 [1]p.10 において…」というような表示ができれば、ハイパーリンクが表現できない媒体でも文書内での参照先が明らかになるからである。
このような欲求をできるだけ簡単な形で満たすために Javascript の関数をいくつか書き、これを集めて、article.js というファイルにまとめた。このページは実際にそれを読み込んで実行している。首尾はというと、html 記法の範囲内で、ある程度 LaTeX 的な要素を忍び込ませることができたのではないかと思う。
また、article.css というスタイルシート・ファイルを書き、ディスプレイ表示と印刷についての設定を書き込んだ。CSS は専らデザインの美的な面の改善に用いただけで、その連番生成機能は使っていない。したがって、まったく別のスタイルシートを読み込んで使っても差し支えない。
最低限なすべきことは、article.jsを読み込むことだけである。また、必須というわけではないが、article.css を読み込んむと、文書のデザインを LaTeX で出力したものにある程度似せることができる。
特別なことを何もしなくても、(h1),h2,h3... 要素中の先頭に自動的に番号付けした数字が書き込まれる(h1 がドキュメント中に 1 つしかない場合、これは文書のタイトルと判断され、章節番号の付加は h2 以下の要素に限られる)。章節番号の参照をするには、番号を挿入したい場所に <a href="#id"></a> と書く。ここで id というのは参照相手となる (h1,)h2,h3... 要素の id である。なお、a 要素がこのように特別な働きをするのは、その href 属性の値が # で始まっている場合にかぎられる。
figure 要素は図と解釈される(figure 要素内に置かれていない img 要素は図としては扱われない)。図には文書を通じた通し番号が割り当てられ、figcaption 要素に図の番号が入る。図番号を参照するには、参照先の figure 要素が持つ id を使って <a href="#the_id"></a> のように書く。参照相手要素のタイプが違うというだけで、見出しに対する参照と書き方はそっくりだ。
table 要素も figure 要素と同じだが、あらかじめ caption 要素を含む場合にだけ表と解釈されるという違いがある(figure 要素では figcaption 要素は必須ではなかった)。表番号を参照するには、参照対象である table 要素の id を用いて <a href="#the_id"></a> と書けばよい。
注釈は <span class="note">(内容)</span> のようにして本文に埋め込む。すると、その場所に参照番号を残して、本体は節の最後に移動し、他の注釈といっしょにまとめて表示される。
参考文献リストは、任意の場所に <ul class="biblio"><ul> を書き、その中に <li id="#the_id">書名等</li> を入れる。このとき、ul 要素の data-sort 属性を "byAppearaneOrder" にしておくと、参考文献リストの各項目が本文中で参照された順番に並び替えられる。また data-sort 属性を "byKey" にすると、各 li 要素中の data-key 属性の値によって並び替えが行われる。
目次を作成したい場合は、挿入したい場所に <ul class="tableOfContents"></ul> と書く。なお、article.css の設定は、印刷メディア利用時に目次の出力を抑制するよう設定されている。
html 文書のタイトルというのは、漠然として言い方である。というのは、それが head 要素内にある title 要素のを指しているのか、より抽象的に文書の「タイトル」を指しているのかはっきりしないからである。ここではカタカナでタイトルと表記した場合は、後者の意味で使うことにする。
タイトルを title 要素中に書くことはごく一般的なことであるが、それだけではせいぜいユーザーエージェントのタイトルバーに小さく表示されるに過ぎない。そこで、文書冒頭に大きな文字でそれを表示するために、別の要素を使うわけだが、ここで問題になるのは、h1 要素をこの用途に当てるべきかどうかである。これは、h1 要素に対して章節の番号付けを行うかどうか、また、目次に h1 要素を含めるかどうかという問題にかかわってくる。article.js は、この問題の中立の立場をとり、h1 要素が文書中にちょうど 1 回だけ出現する場合には、それをタイトルだと判断し、2 回以上現れる場合は見出しだと判断する。
article.js は、文書先頭から (h1,)h2,h3...要素を探していき、1, 1.2, 1.2.3 のように階層化された章節番号をふる。現在のところ、この算用数字を漢数字やアルファベットにする手段は用意していない。なお、番号づけはすべて Javascript によって行われていて、CSS の連番作成機能を用いていない。CSS で番号をふると、後でその番号にアクセスする手段がないからである。
しばしば、h2 要素の下にいきなり h4 要素が置かれるようなことがある。こうした場合、架空の h3 要素があるかのごとく扱う。この架空の要素には、番号 0 が割り振られる。
見出し要素(出現順) | 章節番号 | ||
---|---|---|---|
<h2> | 1 | ||
<h2> | 2 | ||
<h4> | 2.0.1 | ||
<h4> | 2.0.2 | ||
<h3> | 2.1 | ||
<h4> | 2.1.1 | ||
<h4> | 2.1.2 | ||
<h3> | 2.2 |
通常の文章中から見出しを参照するために、LaTeX は \label を用いるが、「なんちゃって LaTeX」では (h1,)h2,h3... 要素の id 属性を用いる。参照する側には、<a href="#the_id></a> と書くと、これが のようなリンクつきのテキストに置き代わる。このとき 「<a href="#link_to_index">本節</a>」のように a 要素の中身にあらかじめテキストが入っているなら、「本節」のように展開されるただし、<a href="#the_id>[link]</a> のように a 要素中のテキストが "[link]" という文字列だけの場合には、テキストが入っていないものとみなされる。これは、Javascript が機能しない環境で意味を持つ。この [link] というダミーテキストは、article.js の冒頭近くの dummyText を編集すれば変えられる)。。また、#the_id は # で始まっている必要があり、#the_id の代わりに、foo.html#the_id のように書くと、それが同じ要素を指す場合であっても、テキストの置き換えは起こらない。
html 中に図を入れる際には、一般に img 要素が使われる。しかしながら、img 要素はわれわれが「図」として把握する場合よりも、ずっと多くの機会に使われている。たとえば、印刷不可能な文字を p 要素中に埋め込むような場合、これらにすべて図として番号をふるのは現実的でない。こうした問題を避けるために、html の figure 要素を使うことにする。figure 要素の一般的な使い方は、次のようなものになる。
<figure id="cursive_t"> <img src="t2.png"> <figcaption>筆記体の t</figcaption> </figure>
図に対して割り振られる番号は document を通じた通し番号となり、(h1),h2,h3... 等の要素をまたいでもリセットされることはない。図番号は、figcaption 要素の先頭に挿入されるが、もし figure 要素に figcaption 要素がないならば、新たに作成される。
これに対して figure 要素の id 属性(ここでは "cursive_t")を用いて <a href="#cursive_t"></a> のように書けば、 「」のように展開される。もし、「<a href="#cursive_t">筆記体のt</a>」のように、a 要素の中にテキストがある場合は、「筆記体のt」のごとく展開される。
html で表を実現するときに一般的に用いられるのは table 要素である。しかし、table 要素をたんなるレイアウトのための方便として用いることも広く行われているので、すべての table 要素に表番号をふるのは現実的ではない。そこで、table 要素のうち、caption 要素を含むものだけを番号をふるべき表として扱うことにした。この点を除けば、図における figure 要素の扱いと変わるところはない。つまり、
あいうえお | かきくけこ |
さしすせそ | たちつてと |
<table id="mihon"> <caption>テーブル見本</caption> <tbody> <tr><td>あいうえお</td><td>かきくけこ</td></tr> <tr><td>さしすせそ</td><td>たちつてと</td></tr> </tbody> </table>
のような表の表番号を参照するために、<a href="#mihon"></a> のように書けば、「」のように展開される。
注釈の原稿は通常の文章中に、<span class="note">(内容)</span>のようにして埋め込む。原稿を埋め込んだ場所に上つきの数字が表示され、注釈本体は〈文書を h1〜h4 要素を区切として分割したときにできる各ブロック〉html の構造上は h1〜h4 要素は p 要素の兄弟に過ぎないの最後にまとめて置かれる。つまり、番号づけされた見出しをまたいで参照しないで済む限りにおいて、まとめて配置される。このブロックの単位は、article.js の冒頭の notePosition という変数を設定し直すことで変更できる。参照番号は、h1〜h4 要素を越したときに 1 にリセットされる。
クラス名が biblio の ul リストが参考文献リストとして扱われリストは文書中どこに置いてもかまわないが、複数ある場合には最初の一つだけを認識する。、その中の li 要素が 1 つひとつの参考文献と見倣される。次の html コードはその例である(もちろん、書目はダミーである)。
<ul class="biblio" data-sort="byKey"> <li id="u" data-key="う">「うちゅう的な著者名による文献リストのソート」,宇ウ一郎著</li> <li id="i" data-key="い">「いうに及ばぬ引用順文献リストのソート」,伊井意一郎著</li> <li id="a" data-key="あ">「あっと驚く文献リストの自動ソート」,亜愛一郎著</li> </ul>
文献リストは、ul 要素の data-sort 属性の値によってソートされたうえで、各アイテムの冒頭に番号がふられる。data-sort 属性の値が "byAppearanceOrder" であるならば、本文中で引用された順番に合わせて文献リストが並び替えられ、また、この値が "byKey" であるならば、文献リストを本文とは独立に並び替えられる。このとき並び替えの基準となるものは、各 li 要素が持つ data-key 属性の値である。
次は、キーによって並び替えが行われた文献リストである。
文献リスト中の項目を参照するには、a 要素を用い、その href 属性の値に、参照先にしたい li 要素の id を用いる。a 要素の中にテキストがない <a href="#u"></a> のような場合は のように展開され、a 要素の中にテキストがある、たとえば「<a href="#u">この本</a>」のような場合は この本 のように展開される。
文書がディスプレイを通して読まれる場合、同じ文書の長さであっても紙媒体で読まれるときに比べて目次の必要性が大きくなる。article.js では、任意の場所に書かれた
<ul class="tableOfContents"></ul>
に対して li 要素を挿入していき、目次を作成する。これは階層を持たないリストになるので、見出しの大きさによってインデンションを行うような場合は、スタイルシートで対応する必要がある。この目的のために、(h1,)h2,h3,h4 それぞれの見出しに対応した各 li 要素は、そのクラス名が ("h1",)"h2","h3","h4" にセットされる。
なお、この文書が用いている article.css は、印刷媒体用の設定として、こうして作成された目次の出力を省略するようになっている。したがって、ユーザーエージェントから紙に印刷したり、pdf に出力した場合は、目次がつかない。短かい文書の場合、これを印刷したときに目次がついている必要性が薄いと判断したからである。その他、印刷用の設定では、リンクの文字色を黒色にしてアンダーラインを引かない、フォントのウェイトが総じて細くなるなどの違いがあるが、これらは美的な問題に過ぎない。
ま、一応お行儀なので書いとくね。article.js, article.css は GPL です。自由に改変してご利用あれ。そして、この文書そのものは
article.html by Kabipanotoko is licensed under a Creative Commons Attribution 4.0 International License.
です。