Gaucheのhtml-liteを用いて作成するウェブページに、ウェブページのhr要素から目次を自動的に生成するjQuery.exTOC.js (目次の自動生成を行う jQuery.exTOC.js - Cyokodog :: Diary)を使おうとした。ウェブページを生成するソースはつぎのとおりである。
(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 >
このように出力するよう元の処理を改変しよう。
上記の検証を踏まえれば、問題に対処するにはつぎの二つの処理を行うことになるだろう。 +html:script の手続きが返すテキストを文字列に変換する +文字列中の改行を取り除く 一つ目については 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 が返すテキストから改行を取り除く必要がある。