Skip to content

Instantly share code, notes, and snippets.

@tk0miya
Created June 11, 2017 05:40
Show Gist options
  • Save tk0miya/83259d3cda6a9d5d1d7488f40a8d8396 to your computer and use it in GitHub Desktop.
Save tk0miya/83259d3cda6a9d5d1d7488f40a8d8396 to your computer and use it in GitHub Desktop.
# -*- coding: utf-8 -*-
"""
renumber_footnotes.py
=====================
An extension for Sphinx to renumber footnotes to sequential in whole of
project.
:copyright: Copyright 2018 by Takeshi KOMIYA
:license: BSD
"""
from docutils import nodes
from sphinx import addnodes
from sphinx.util import url_re
def traverse_doc(app, docname=None, parents=None):
if docname is None:
master_doc = app.config.master_doc
yield master_doc
for docname in traverse_doc(app, master_doc, [master_doc]):
yield docname
else:
doctree = app.env.get_doctree(docname)
for toctree in doctree.traverse(addnodes.toctree):
for entry in toctree['entries']:
title, ref = entry
if url_re.match(ref) or ref == 'self' or ref in parents:
pass
else:
yield ref
parents.append(ref)
for subdocname in traverse_doc(app, ref, parents):
yield subdocname
def note_footnotes(env, docname):
if not getattr(env, 'footnote_numbers', None):
env.current_footnote_number = 1
env.footnote_numbers = {} # (docname, id) -> new number
doctree = env.get_doctree(docname)
for footnote in doctree.traverse(nodes.footnote):
key = (docname, footnote['ids'][0])
env.footnote_numbers[key] = env.current_footnote_number
env.current_footnote_number += 1
def renumber_footnote(env, docname, footnote):
old_number = footnote.pop(0)
if old_number.astext() in footnote['names']:
footnote['names'].remove(old_number.astext())
key = (docname, footnote['ids'][0])
new_number = env.footnote_numbers[key]
footnote.insert(0, nodes.label('', str(new_number)))
footnote['names'].append(str(new_number))
def renumber_footnote_reference(env, docname, footnote_ref):
key = (docname, footnote_ref['refid'])
new_number = env.footnote_numbers[key]
footnote_ref.remove(footnote_ref[0])
footnote_ref += nodes.Text(str(new_number))
def on_env_check_consistency(app, env):
for docname in traverse_doc(app):
note_footnotes(env, docname)
def on_doctree_resolved(app, doctree, docname):
for footnote in doctree.traverse(nodes.footnote):
renumber_footnote(app.env, docname, footnote)
for footnote_ref in doctree.traverse(nodes.footnote_reference):
renumber_footnote_reference(app.env, docname, footnote_ref)
def setup(app):
app.connect('env-check-consistency', on_env_check_consistency)
app.connect('doctree-resolved', on_doctree_resolved)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment