TEI古典籍ビューワをカスタマイズして判読不能箇所(gap)を表示する
はじめに
東アジアの古典籍をデジタル化する際、TEI(Text Encoding Initiative)ガイドラインに準拠したXMLでマークアップすることが一般的になっています。一般財団法人人文情報学研究所が開発した「TEI古典籍ビューワ」は、このようなTEI/XMLファイルをブラウザで簡単に表示できる便利なツールです。
今回、このビューワをカスタマイズして、判読不能箇所を示す<gap>タグの表示に対応しました。本記事では、そのカスタマイズ方法を紹介します。
課題:gapタグが表示されない
古典籍のデジタル化において、虫損や破損などにより判読できない箇所は<gap>タグでマークアップします。
<gap reason="illegible" quantity="2" unit="character"/>
しかし、標準のTEI古典籍ビューワでは、このタグが適切に表示されません。そこで、判読不能な文字数分の黒四角(■)を表示し、マウスホバーで理由を確認できるようにカスタマイズしました。
カスタマイズの方針
TEI古典籍ビューワは以下のファイル構成になっています。
├── index.html
├── app.min.js ← ビューワ本体(minify済み)
├── app.min.css
├── app_conf.js ← 設定ファイル
└── lib/ ← 依存ライブラリ
app.min.jsを直接編集すると、本体のアップデート時に変更が失われてしまいます。そこで、app_conf.jsのみを編集することで、本体との互換性を保ちながらカスタマイズを実現しました。
実装方法
1. MutationObserverによるDOM監視
TEI古典籍ビューワはXMLをパースしてDOMに変換します。この変換後のタイミングで<gap>タグを処理するため、MutationObserverを使用してDOM変更を監視します。
// MutationObserverでDOM変更を監視
const observer = new MutationObserver(mutations => {
mutations.forEach(mutation => {
mutation.addedNodes.forEach(node => {
if (node.nodeType === Node.ELEMENT_NODE) {
processGapElements(node);
}
});
});
});
// body_resultの監視を開始
document.addEventListener('DOMContentLoaded', () => {
const bodyResult = document.getElementById('body_result');
if (bodyResult) {
observer.observe(bodyResult, { childList: true, subtree: true });
}
});
2. gapタグの処理
<gap>タグを検出したら、quantity属性の値に応じて黒四角を表示し、reason属性をツールチップとして設定します。
function processGapElements(container) {
const gaps = container.querySelectorAll('gap, .gap, [data-original-tag-name="gap"]');
gaps.forEach(gap => {
// 既に処理済みの場合はスキップ
if (gap.dataset.gapProcessed) return;
gap.dataset.gapProcessed = 'true';
// 属性から値を取得
const quantity = parseInt(gap.getAttribute('quantity') || '1', 10);
const reason = gap.getAttribute('reason') || '';
// ■をquantity分だけ生成
const placeholder = '■'.repeat(quantity);
gap.textContent = placeholder;
// ツールチップの設定(日本語化)
const reasonMap = {
'illegible': '判読不能',
'damage': '破損',
'worm': '虫損',
'omitted': '省略',
'cancelled': '抹消',
'lost': '欠損'
};
const reasonText = reasonMap[reason] || reason;
if (reasonText) {
gap.setAttribute('title', reasonText);
}
gap.style.color = '#333';
gap.style.cursor = 'help';
});
}
ポイント:属性の取得方法
TEI古典籍ビューワがXMLをHTMLに変換する際、属性の扱いは要素によって異なります。<gap>タグの場合、XML属性がそのまま保持されるため、getAttribute()で直接取得できます。
// XMLの属性名がそのまま保持されている場合
const quantity = gap.getAttribute('quantity');
// data-*形式に変換される場合はdatasetを使用
const quantity = gap.dataset.quantity;
実際のDOM構造をブラウザの開発者ツールで確認することが重要です。
追加カスタマイズ
同様の手法で、以下の機能も追加しました。
GETパラメータによる高さ指定
テキスト表示部の高さをURLパラメータで指定できるようにしました。
index.html?height=800
const params = new URLSearchParams(window.location.search);
const height = params.get('height');
if (height) {
const heightValue = parseInt(height, 10);
if (!isNaN(heightValue) && heightValue > 0) {
document.getElementById('text_body').style.height = heightValue + 'px';
}
}
ページタイトルの設定
TEI/XMLに複数の<title>要素がある場合、1つ目のタイトルをページタイトルに設定します(デフォルトでは最後のタイトルが使用されます)。
<titleStmt>
<title>メインタイトル</title> <!-- これがページタイトルになる -->
<title type="sub">副題</title>
</titleStmt>
書誌情報(sourceDesc/bibl)の表示改善
<sourceDesc>内の<bibl>要素を見やすく整形するため、CSSで各要素にラベルを付けてブロック表示にしました。
.sourceDesc .bibl title,
.sourceDesc .bibl editor,
.sourceDesc .bibl publisher,
.sourceDesc .bibl date,
.sourceDesc .bibl idno,
.sourceDesc .bibl note {
display: block;
margin-bottom: 0.3em;
}
.sourceDesc .bibl title::before { content: "【書名】"; font-weight: bold; }
.sourceDesc .bibl editor::before { content: "【編者】"; font-weight: bold; }
.sourceDesc .bibl publisher::before { content: "【出版者】"; font-weight: bold; }
/* ... */
これにより、以下のような見やすい表示になります:
【書名】○○○○
【編者】△△△△
【出版者】□□堂
【年代】江戸時代
【請求記号】A100:123
【所蔵】○○図書館 △△文庫
まとめ
TEI古典籍ビューワは、設定ファイルapp_conf.jsを編集することで柔軟にカスタマイズできます。今回紹介したMutationObserverを使った手法は、他のTEIタグへの対応にも応用可能です。
カスタマイズしたコードは以下のリポジトリで公開しています。
参考リンク
- TEI古典籍ビューワ公式サイト: https://tei.dhii.jp/teiviewer4eaj
- TEIガイドライン - gap要素: https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-gap.html
- 日本語向けTEIガイドライン: https://tei.dhii.jp/
謝辞
TEI古典籍ビューワを開発・公開されている永崎研宣氏(一般財団法人人文情報学研究所)、本間淳氏(フェリックス・スタイル)に感謝いたします。
Discussion