HTML のドキュメントを Sphinx に移行する
CodeIgniter の HTML で書かれたユーザガイドを Sphinx の RST へ変換したときの作業記録です。
最終的なソースコードは、以下に置いてあります。
html2rest を用意する
BeautifulSoup が必要なのでインストールします。
$ sudo apt-get install python-beautifulsoup
html2rest.py を bitbucket から取得します。
$ hg clone https://bitbucket.org/djerdo/musette
musette/musette/html/html2rest.py にあります。
textwrap でマルチバイト文字列を fold するため、textwrap でマルチバイト文字列を fold する - daily dayflower にある mbtextwrap.py を html2rest.py と同じフォルダに置きます。Gist にコピーを置いておきました。
MBTextWrapper を使うように、リダイレクトしてもエラーにならないように、出力フォーマットの調整のために html2rest.py を変更します。
diff -r ec24787e957b musette/html/html2rest.py --- a/musette/html/html2rest.py Mon Feb 01 16:54:15 2010 +0000 +++ b/musette/html/html2rest.py Thu Oct 06 22:27:14 2011 +0900 @@ -27,12 +27,12 @@ import codecs from sgmllib import SGMLParser from StringIO import StringIO -from textwrap import TextWrapper +from mbtextwrap import MBTextWrapper CODEBLOCK = '.. sourcecode:: python' BLOCKTAGS = ['div', 'blockquote'] IGNORETAGS = ['title', 'style', 'script'] -UNDERLINES = list('=-~`+;') +UNDERLINES = list('#=~`+;') # Fredrik Lundh, http://effbot.org/zone/re-sub.html def unescape(text): @@ -61,7 +61,7 @@ def __init__(self): self._lines = [] - self._wrapper = TextWrapper() + self._wrapper = MBTextWrapper(encoding='utf-8') def __len__(self): return len(self._lines) @@ -122,7 +122,7 @@ if self.inblock > 1: indent = 4 * (self.inblock - 1) self.linebuffer.indent(indent) - self.writer.write(unescape(self.linebuffer.read())) + self.writer.write(unescape(self.linebuffer.read()).encode(sys.getfilesystemencoding())) self.linebuffer.clear() def flush_stringbuffer(self): @@ -218,7 +218,7 @@ def end_a(self): if self.link: - self.data(' <%s>`__' % self.link) + self.data(' <%s>`' % self.link) self.link = None def start_pre(self, attrs): @@ -245,7 +245,7 @@ self.writeline() else: self.writeline() - self.lists.append('+ ') + self.lists.append('- ') self.inblock += 1 def end_ul(self): @@ -299,7 +299,7 @@ def end_li(self): self.flush_stringbuffer() linebuf = self.linebuffer - if linebuf and linebuf[0] and linebuf[0].lstrip()[:2] in ['+ ', '#.']: + if linebuf and linebuf[0] and linebuf[0].lstrip()[:2] in ['- ', '#.']: start=1 else: # the start of the <li> has already been written, perhaps because
これで、以下のようにすると RSTファイルを生成できます。
$ python html2rest.py HTMLファイル > RSTファイル
変換処理
本家リポジトリの最新の user_guide_src を user_guide_ja_src として ci-ja リポジトリにコピーします。
作成が必要なファイルのリストを生成します。
$ cd user_guide_ja_src/source $ find . -name '*.rst' > FILES
変換処理の shell script を作成します。
convert.sh
for i in `cat FILES`; do file=`echo $i | sed -e "s/\.rst$//"` file="../../user_guide_ja/$file.html" if [ ! -f $file ]; then continue fi ls $file python $HOME/html2rest.py $file > $i php filter.php $i done cat << EOD >> index.rst .. toctree:: :glob: :titlesonly: :hidden: * overview/index installation/index general/index libraries/index database/index helpers/index documentation/index EOD
後処理の filter.php を作成します。
filter.php
<?php $file = $argv[1]; if (file_exists($file)) { $lines = file($file); } else { exit("No such file: $file\n"); } $remove_before = 'ユーザガイドを検索'; $remove_after = '前のトピック|ページの先頭'; $new_doc = ''; $state = 'head'; foreach ($lines as $line) { if ($state === 'head') { if (preg_match('/' . $remove_before . '/', $line, $matches)) { //var_dump($matches); $state = 'after_head'; } } else if ($state === 'after_head') { if ($line != "\n") { $state = 'content'; $new_doc .= $line; } } else { if (preg_match('/' . $remove_after . '/', $line, $matches)) { break; } else { $new_doc .= $line; } } } file_put_contents($file, $new_doc);
これで準備完了しました。
$ sh convret.sh
で変換処理が走ります。