Sphinxで日本語文章の不自然な空白をなくしたい
Sphinx拡張機能を使って日本語文章の不自然な空白をなくす
sphinx(日本のユーザ会)で、htmlなどを作成する元ネタrestructuredtextファイルを作成するとき日本語の途中で改行を入れると、htmlなどへ変換したときにその改行箇所で空白文字が入ってしまい、ブラウザで見るときにちょっと見た目が悪くなったりします。
5年くらい前に以下の記事で対応策っぽいものを書いてましたが、数年振りにSphinxを使ってみたら、当時の記事の内容をすっかり忘れていたのでメモ。
msiz.hatenablog.jp
conf.pyの編集(1)
「sphinx-quickstart」を実行したりして作成されるSphinxの設定ファイル「conf.py」で、拡張機能(を実装したPythonモジュール・パッケージ)を探すpathを調整:
... import os import sys sys.path.insert(0, os.path.abspath('exts')) ...
sys.pathに追加しているだけですね。この例の場合、conf.pyのあるディレクトリに「exts」ディレクトリを作成し、そこに追加のPythonファイルを置けば探し出して読み込んでくれる。
なお、「sphinx-quickstart」で作成したconf.pyだと、それっぽい記述がコメントアウトされているので、そこを編集。
拡張機能を実装
今回は「japanese_trunc_whitespace.py」というファイル名にして、「exts」に置きました。
#!/usr/bin/python #from docutils.core import publish_doctree, publish_from_doctree #import sys, codecs, re, optparse from docutils.nodes import paragraph, Text import re def japanese_truncate_whitespace(app, doctree, docname): para_list = get_para_list(doctree) strip_spaces_between_uchars(para_list) strip_spaces_around_uchars_paragraph_children(para_list) # in order no to change literals, select only 'paragraph' nodes # def get_para_list(dtree): para_list = [] for node in dtree.traverse(): if isinstance(node, paragraph): para_list.append(node) return para_list def strip_spaces_between_uchars(para_list): # non-ascii [\n\r\t] non-ascii __RGX = re.compile(r'([^!-~])[\n\r\t]+([^!-~])') # modify text inside Text node # for para in para_list: for node in para.traverse(): if isinstance(node, Text): newtext = node.astext() newtext = __RGX.sub(r"\1\2", newtext) node.parent.replace(node, Text(newtext)) def strip_spaces_around_uchars_paragraph_children(para_list): # non-ascii [\s]* <End-of-TEXT> __RGX1 = re.compile(r'([^!-~])[\s]*$') # <Beginning-of-TEXT> [\s]* non-ascii __RGX2 = re.compile(r'^[\s]*([^!-~])') # modify texts over 2 nodes # (paragraph node can have children of Inline (reference, etc) nodes) # for para in para_list: prev_textnode = Text("") for node in para.traverse(): new_textnode = None if isinstance(node, Text): prevtext = prev_textnode.astext() newtext = node.astext() if __RGX1.search(prevtext) and __RGX2.search(newtext): new_prev_textnode = Text(prev_textnode.astext().rstrip()) new_textnode = Text(newtext.lstrip()) prev_textnode.parent.replace(prev_textnode, new_prev_textnode) node.parent.replace(node, new_textnode) new_prev_textnode.parent = prev_textnode.parent new_textnode.parent = node.parent prev_textnode = new_textnode if new_textnode else node def setup(app): app.add_config_value('japanese_trunc_whitespace', True, True) app.connect("doctree-resolved", japanese_truncate_whitespace)
最後の「setup(app)」で、今回の拡張機能を使用するかを「conf.py」から設定できるようにしています。
conf.pyの編集(2)
conf.pyの適当な場所で、以下の記述を追加
... extensions = [ 'japanese_trunc_whitespace', ... # 他にも使用する拡張機能がある場合は指定 ] japanese_trunc_whitespace = True ...
上手くいけば、「make html」とかで作成したhtmlで、改行箇所の余分な空白がなくなるはず