無保証です。なんとなく動くことは確認しました。
Well known issue:
- セクション名などを使って hash 値を生成しているので、同名のセクション名がファイル内に複数回登場すると破綻します。
元ネタはこのあたり参照: https://twitter.com/kmuto/status/1029290347082338304
無保証です。なんとなく動くことは確認しました。
Well known issue:
元ネタはこのあたり参照: https://twitter.com/kmuto/status/1029290347082338304
def on_doctree_resolved(app, doctree, docname): | |
from hashlib import md5 | |
from docutils import nodes | |
# add hash-based node-ID to sections | |
mapping = {} | |
for node in doctree.traverse(nodes.section): | |
new_id = md5(node.children[0].astext().encode('utf-8')).hexdigest() | |
for node_id in node['ids']: | |
mapping[node_id] = new_id | |
node['ids'].insert(0, new_id) | |
# use hash-based node-IDs at local reference | |
for node in doctree.traverse(nodes.reference): | |
refid = node.get('refid') | |
if refid in mapping: | |
node['refid'] = mapping.get(refid) | |
# use hash-based node-IDs at toctrees | |
for _, toctree in app.env.tocs.items(): | |
for node in toctree.traverse(nodes.reference): | |
if node.get('internal') and node.get('anchorname'): | |
node['anchorname'] = '#' + md5(node.astext().encode('utf-8')).hexdigest() | |
def setup(app): | |
app.connect('doctree-resolved', on_doctree_resolved) |
コメントが付いていたのに気づいていませんでした。
ご指摘のとおりです。
なお、Sphinx 的には (正確には docutils 的には) node[0]
と node.children[0]
は同じ意味です。ですので、どちらで記述しても構いません。どちらかといえば、シンプルに記述できる前者がよく使われている印象があります。
蛇足ですが section ノードの最初の要素は必ず title ノードであるという暗黙のルールがあるので、 node[0].astext()
はセクション名のテキスト表現を取得しています。
セクション名にシーケンス番号降って、同名のセクション名がファイル内に複数回登場しても破綻しないようにしたバージョン
def on_doctree_resolved(app, doctree, docname):
from collections import defaultdict
from hashlib import md5
from docutils import nodes
# add hash-based node-ID to sections
mapping = {}
sequences = defaultdict(int)
for node in doctree.traverse(nodes.section):
text = node.children[0].astext()
sequences[text] += 1
new_id = md5("{}-{}".format(text, sequences[text]).encode('utf-8')).hexdigest()
for node_id in node['ids']:
mapping[node_id] = new_id
node['ids'].insert(0, new_id)
# use hash-based node-IDs at local reference
for node in doctree.traverse(nodes.reference):
refid = node.get('refid')
if refid in mapping:
node['refid'] = mapping.get(refid)
# use hash-based node-IDs at toctrees
for _, toctree in app.env.tocs.items():
sequences = defaultdict(int)
for node in toctree.traverse(nodes.reference):
if node.get('internal') and node.get('anchorname'):
text = node.astext()
sequences[text] += 1
node['anchorname'] = '#' + md5("{}-{}".format(text, sequences[text]).encode('utf-8')).hexdigest()
node.children[0]
のほうがいいのかな?