KDP(電子出版)のメモ 急急如律令

Amazon Kindleダイレクト・パブリッシングでの電子出版や電子書籍の作成販売について、文章やイラストの作成や編集方法について書いています。

最近のHTMLタグはrbタグが非推奨になったのでrubyタグのDOMパーサーを書き換えてみた

 HTMLのrubyタグをパースして青空文庫のルビ注記に変換する。ただし、rbタグがあることを前提に作られたHTMLパーサーだとおかしなことになる。AozoraEpub3のrubyタグのパーサー部分を見るとrbタグがあることが前提で書かれている。

 /** ルビを青空ルビにして出力 */
    private void printRuby(BufferedWriter bw, Element ruby) throws IOException
    {
        Elements rb = ruby.getElementsByTag("rb");
        Elements rt = ruby.getElementsByTag("rt");
        if (rb.size() > 0) {
            if (rt.size() > 0) {
                bw.append('|');
                printText(bw, rb.get(0).text());
                bw.append('《');
                printText(bw, rt.get(0).text());
                bw.append('》');
            } else {
                printText(bw, rb.get(0).text());
            }
        }
    }

どういう場合分けがいいのか、rubyタグ内にrbタグがなかったら、textエレメントがあるのかと思ったらnodeNameの#textを見る。ただし、Javaでも同じようには書けなかった。Javaではテキストはテキストノードで、エレメントと別に書かれていた。

ブラウザで可能なテスト要素に書き換えるとモノルビでは対応できてなさそう。ものルビを使っている小説投稿サイトがまずないのだが、rbタグを廃止している傾向がある。

// rubyタグ
let html = "<ruby><rb>漢</rb><rb>字</rb><rp>(</rp><rt>kan</rt><rt>ji</rt><rp>)</rp></ruby>"
let parser = new DOMParser();
let doc = parser.parseFromString(html, "text/html");
ruby=doc.getElementsByTagName("ruby")[0]
rb= ruby.getElementsByTagName("rb")
rt=ruby.getElementsByTagName("rt")
bw=""
if(rb.length){
if(rt.length){
bw=bw + '|' + rb[0].textContent+'《'+rt[0].textContent +'》'

}
else{bw=bw + rb[0].textContent
}
}

モノルビに対応するにはforループを使ってみる

let html = "<ruby><rb>漢</rb><rb>字</rb><rp>(</rp><rt>kan</rt><rt>ji</rt><rp>)</rp></ruby>"
let parser = new DOMParser();
let doc = parser.parseFromString(html, "text/html");
ruby=doc.getElementsByTagName("ruby")[0]
rb= ruby.getElementsByTagName("rb")
rt=ruby.getElementsByTagName("rt")
bw=""
if(rb.length){
if(rt.length){
    for(var i=0; i<rb.length; i++) {
bw=bw + '|' + rb[i].textContent+'《'+rt[i].textContent +'》'
    }
}
else{bw=bw + rb[0].textContent
}

}

次はrbタグがないときの処理

let html =
    "<ruby>漢<rp>(</rp><rt>kan</rt><rp>)</rp>字<rp>(</rp><rt>ji</rt><rp>)</rp></ruby>"
let parser = new DOMParser();
let doc = parser.parseFromString(html, "text/html");
ruby = doc.getElementsByTagName("ruby")[0]
rb = ruby.getElementsByTagName("rb")
rt = ruby.getElementsByTagName("rt")
bw = ""
if (rb.length) {
    if (rt.length) {
        for (let i = 0; i < rb.length; i++) {
            bw = bw + '|' + rb[i].textContent + '《' + rt[i].textContent + '》'
        }
    } else {
        bw = bw + rb[0].textContent
    }
} else {
    for (let i = 0; i < ruby.childNodes.length; i++) {

        switch (ruby.childNodes[i].nodeName) {
            case '#text':
                bw = bw + '|' + ruby.childNodes[i].textContent
                break;
            case 'RP':
                break;
            case 'RT':
                bw = bw + '《' + ruby.childNodes[i].textContent + '》'
                break;
            case 'RB':
                bw = bw + '|' + ruby.childNodes[i].textContent
                break;
            default:
                console.log("未定義");
        }


    }
}

switch caseだけで統一できるかなと思ったんだけど、rb,rb,rt,rtという順番の場合にパースができないので複雑になってしまった。モノルビではなかったらswitch caseだけでよさそう

github.com

モノルビなどrbタグがあったりなかったり、rpタグ内は見ない。

<ruby>漢<rp>(</rp><rt>kan</rt><rp>)</rp>字<rp>(</rp><rt>ji</rt><rp>)</rp> </ruby>
<ruby><rb>漢</rb><rp>(</rp><rt>kan</rt><rp>)</rp><rb>字 </rb><rp>(</rp><rt>ji</rt><rp>)</rp> </ruby>
<ruby>
  <rb>漢</rb><rb>字 </rb><rp>(</rp><rt>kan</rt><rt>ji</rt><rp>)</rp>
</ruby>

developer.mozilla.org

developer.mozilla.org

html2aozoraでrb,rb,rt,rtという順番の場合にパースができてない。パーサーを作るのが難しい。 github.com