"""
Originally adapted from: https://github.com/mcmtroffaes/sphinxcontrib-bibtex
"""
import docutils
import sphinx.util
from ipypublish.sphinx.gls.cache import Cache
from ipypublish.sphinx.gls.bibgloss import latex_to_docutils
logger = sphinx.util.logging.getLogger(__name__)
[docs]def init_bibgloss_cache(app):
"""Create ``app.env.bibgloss_cache`` if it does not exist yet.
:param app: The sphinx application.
:type app: :class:`sphinx.application.Sphinx`
"""
if not hasattr(app.env, "bibgloss_cache"):
app.env.bibgloss_cache = Cache()
[docs]def purge_bibgloss_cache(app, env, docname):
"""Remove all information related to *docname* from the cache.
:param app: The sphinx application.
:type app: :class:`sphinx.application.Sphinx`
:param env: The sphinx build environment.
:type env: :class:`sphinx.environment.BuildEnvironment`
"""
env.bibgloss_cache.purge(docname)
[docs]def process_citations(app, doctree, docname):
"""Replace labels of citation nodes by actual labels.
:param app: The sphinx application.
:type app: :class:`sphinx.application.Sphinx`
:param doctree: The document tree.
:type doctree: :class:`docutils.nodes.document`
:param docname: The document name.
:type docname: :class:`str`
"""
# citation(rawsource='', *children, **attributes)
for node in doctree.traverse(docutils.nodes.citation):
if "bibglossary" not in node.attributes.get("classes", []):
continue
key = node[0].astext()
try:
label_str = app.env.bibgloss_cache.get_label_from_key(key)
except KeyError:
logger.warning(
"could not relabel glossary item [%s]" % key,
type="bibgloss",
subtype="relabel",
)
else:
if app.config.bibgloss_convert_latex:
label = latex_to_docutils(label_str)
# label(rawsource='', text='', *children, **attributes)
node[0] = docutils.nodes.label("", "", *label.children[0])
else:
node[0] = docutils.nodes.label("", label_str)
if sphinx.version_info >= (2,):
# this creates a line break between the label and the definition
node.insert(1, docutils.nodes.line())
[docs]def process_citation_references(app, doctree, docname):
"""Replace text of citation reference nodes by actual labels.
:param app: The sphinx application.
:type app: :class:`sphinx.application.Sphinx`
:param doctree: The document tree.
:type doctree: :class:`docutils.nodes.document`
:param docname: The document name.
:type docname: :class:`str`
"""
# sphinx has already turned citation_reference nodes
# into reference nodes, so iterate over reference nodes
# reference(rawsource='', text='', *children, **attributes)
for node in doctree.traverse(docutils.nodes.reference):
if "bibglossary" not in node.attributes.get("classes", []):
continue
text = node[0].astext()
key = text[1:-1]
try:
if "bibgplural" in node.attributes.get("classes", []):
label = app.env.bibgloss_cache.get_plural_from_key(key)
else:
label = app.env.bibgloss_cache.get_label_from_key(key)
except KeyError:
pass
logger.warning(
"could not relabel glossary reference [%s]" % key,
type="bibgloss",
subtype="relabel",
)
else:
if "bibgcapital" in node.attributes.get("classes", []):
label = label.capitalize()
if app.config.bibgloss_convert_latex:
# note we use only the first child of the document
# TODO is this the best way to do this
label = latex_to_docutils(label)
if sphinx.version_info < (2,):
node[0] = label.children[0]
else:
# in sphinx v2 the child is a paragraph
node[0] = label.children[0].children[0]
else:
node[0] = docutils.nodes.Text(label)