読者です 読者をやめる 読者になる 読者になる

blechmusikの日記

キー・カスタマイズ・ソフトウェア "DvorakJ" の覚え書きをはじめとして様々なことを書いています。

Gaucheのhtml-liteを用いて作成するウェブページでjQuery.exTOC.jsを利用する際の注意点

問題の所在

Gaucheのhtml-liteを用いて作成するウェブページに、ウェブページのhr要素から目次を自動的に生成するjQuery.exTOC.js*1を使おうとした。ウェブページを生成するソースはつぎのとおりである。

(use www.cgi)
(use text.html-lite)

(cgi-main
 (lambda (params)
   (list
    (cgi-header)
    (format #f "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
    (html-doctype :type :xhtml-1.0-transitional)
    (html:html
     (html:head :xmlns "http://www.w3.org/1999/xhtml"
        :xml:lang "ja"
        :lang "ja"
        (html:script :type "text/javascript"
                 :src "./jquery-1.7.2.min.js")
        ;; http://cyokodog.web.fc2.com/cyokolab/lib/exjquery/extoc_1_0.js
        (html:script :type "text/javascript"
                 :src "./extoc_1_0.js")
        (html:script :type "text/javascript"
                 :src "./generate_toc.js")
        )
     (html:body
      (html:h1 "test")
      (html:h2 "hoge"))))))

generate_toc.jsの内容は以下のとおりだ。

jQuery(function($){
        $('h2:first').exTOC({
                headFrom : 2,
                headTo : 4,
                insertMethod : 'before',
                numberingHead : true,
                numberingFrom : 1,
                numberingTo : 3
        });
       });

上記のスクリプトを実行すると、意図した通りの結果が表示される。

問題はここからだ。Google Chrome では問題無いのだが、Firefox で上記のページのソースを表示しようとすると、ブラウザが100%の確率でクラッシュしてしまう。Firefox のアドオンをすべて無効化したうえでページを開こうとしても、クラッシュするのである。

検証

Google Chrome のソースの表示機能を使ってウェブページの内容を確認したところ、こういう内容が出力されていることがわかった。

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html><head xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"><script type="text/javascript" src="./jquery-1.7.2.min.js"></script
><script type="text/javascript" src="./extoc_1_0.js"></script
><script type="text/javascript" src="./generate_toc.js"></script
></head
><body><h1>test</h1
><h2>hoge</h2
></body
></html
>

これを見て気づくのは、script の閉じタグの終わりに改行が含まれていることである。ためしに、出力されたソースのうち script の部分の改行を取り除いてみよう。

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html><head xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"><script type="text/javascript" src="./jquery-1.7.2.min.js"></script><script type="text/javascript" src="./extoc_1_0.js"></script><script type="text/javascript" src="./generate_toc.js"></script></head
><body><h1>test</h1
><h2>hoge</h2
></body
></html
>

このように書くと正しく動作する。
さらに調べて分かったのは、改行を取り除かなければならないのが、extoc_1_0.js を読み込む箇所だけだということである。そういうわけでつぎのように出力すれば問題ない。

<?xml version="1.0" encoding="utf-8"?> 
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html><head xmlns="http://www.w3.org/1999/xhtml" xml:lang="ja" lang="ja"><script type="text/javascript" src="./jquery-1.7.2.min.js"></script><script type="text/javascript" src="./extoc_1_0.js"></script><script type="text/javascript" src="./generate_toc.js"></script></head
><body><h1>test</h1
><h2>hoge</h2
></body
></html
>

このように出力するよう元の処理を改変しよう。

解決方法

上記の検証を踏まえれば、問題に対処するにはつぎの二つの処理を行うことになるだろう。

  1. html:script の手続きが返すテキストを文字列に変換する
  2. 文字列中の改行を取り除く

一つ目については text.treeモジュールの tree->string を、二つ目については regexp-replace-all* を利用すればよい。

以上より、つぎの処理を追記することになる。

(use text.tree)
(define-syntax html:script-without-newline
  (syntax-rules ()
    ((html:script-without-newline elem ...)
     (regexp-replace-all* (tree->string (html:script elem ...)) #/\n/ ""))
    ))

最終的には元のソースを以下のように書きかえることとなった。

(use www.cgi)
(use text.html-lite)

(use text.tree)
(define-syntax html:script-without-newline
  (syntax-rules ()
    ((html:script-without-newline elem ...)
     (regexp-replace-all* (tree->string (html:script elem ...)) #/\n/ ""))
    ))

(cgi-main
 (lambda (params)
   (list
    (cgi-header)
    (format #f "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n")
    (html-doctype :type :xhtml-1.0-transitional)
    (html:html
     (html:head :xmlns "http://www.w3.org/1999/xhtml"
        :xml:lang "ja"
        :lang "ja"
        (html:script :type "text/javascript"
                 :src "./jquery-1.7.2.min.js")
        ;; http://cyokodog.web.fc2.com/cyokolab/lib/exjquery/extoc_1_0.js
        (html:script-without-newline :type "text/javascript"
                 :src "./extoc_1_0.js")
        (html:script :type "text/javascript"
                 :src "./generate_toc.js")
        )
     (html:body
      (html:h1 "test")
      (html:h2 "hoge"))))))

これで、生成されたページのソースを Firefox から閲覧できるようになった。

まとめ

Gaucheのhtml-liteを用いて作成するウェブページでjQuery.exTOC.jsを利用しようとするならば、html-lite の html:script をそのまま使用してはならない。html:script が返すテキストから改行を取り除く必要がある。