This repository provides User Manual for setting up a Docker environment tailored for testing DGTD code.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

281 lines
8.7 KiB

"""
.. autofunction:: sphinxcontrib.bibtex.style.template.join(\
sep='', sep2=None, last_sep=None, other=None)
.. autofunction:: sphinxcontrib.bibtex.style.template.sentence(\
capfirst=False, capitalize=False, add_period=True, \
sep=', ', sep2=None, last_sep=None, other=None)
.. autofunction:: sphinxcontrib.bibtex.style.template.names(\
role, sep='', sep2=None, last_sep=None, other=None)
.. autofunction:: sphinxcontrib.bibtex.style.template.entry_label()
.. autofunction:: sphinxcontrib.bibtex.style.template.reference()
.. autofunction:: sphinxcontrib.bibtex.style.template.footnote_reference()
"""
from typing import TYPE_CHECKING, Any, Dict, List, NamedTuple, cast
import docutils.nodes
import pybtex_docutils
from pybtex.richtext import Text
from pybtex.style.template import (
FieldIsMissing,
Node,
_format_list,
field,
first_of,
optional,
tag,
)
from sphinx.util.nodes import make_refnode
from sphinxcontrib.bibtex.nodes import raw_latex
from sphinxcontrib.bibtex.richtext import BaseReferenceText
if TYPE_CHECKING:
from pybtex.backends import BaseBackend
from pybtex.richtext import BaseText
from pybtex.style import FormattedEntry
from sphinx.builders import Builder
# extended from pybtex: also copies the docstring into the wrapped object
def node(f):
n = Node(f.__name__, f)
n.__doc__ = f.__doc__
return n
# copied from pybtex join but extended to allow "et al" formatting
@node
def join(children, data, sep="", sep2=None, last_sep=None, other=None):
"""Join text fragments together."""
if sep2 is None:
sep2 = sep
if last_sep is None:
last_sep = sep
parts = [part for part in _format_list(children, data) if part]
if len(parts) <= 1:
return Text(*parts)
elif len(parts) == 2:
return Text(sep2).join(parts)
elif other is None:
return Text(last_sep).join([Text(sep).join(parts[:-1]), parts[-1]])
else:
return Text(parts[0], other)
@node
def join2(children, data, sep1="", sep2=""):
"""Join text fragments together."""
if not children:
return Text()
else:
return join(sep=sep1)[children[0], join(sep=sep2)[children[1:]]].format_data(
data
)
# copied from pybtex names but using the new join
@node
def sentence(
children,
data,
capfirst=False,
capitalize=False,
add_period=True,
sep=", ",
sep2=None,
last_sep=None,
other=None,
):
"""Join text fragments, capitalize the first letter,
and add a period to the end.
"""
text = join(sep=sep, sep2=sep2, last_sep=last_sep, other=other)[
children
].format_data(data)
if capfirst:
text = text.capfirst()
if capitalize:
text = text.capitalize()
if add_period:
text = text.add_period()
return text
# copied from pybtex names but using the new join allowing "et al" formatting
@node
def names(children, data, role, **kwargs):
"""Return formatted names."""
assert not children
try:
persons = data["entry"].persons[role]
except KeyError:
raise FieldIsMissing(role, data["entry"])
style = data["style"]
formatted_names = [
style.person.style_plugin.format(person, style.person.abbreviate)
for person in persons
]
return join(**kwargs)[formatted_names].format_data(data)
@node
def entry_label(children, data) -> "BaseText":
"""Node for inserting the label of a formatted entry."""
assert not children
entry = cast("FormattedEntry", data["formatted_entry"])
return Text(entry.label)
class SphinxReferenceInfo(NamedTuple):
"""Tuple containing reference info to enable sphinx to resolve a reference
to a citation.
"""
builder: "Builder" #: The Sphinx builder.
fromdocname: str #: Document name of the citation reference.
todocname: str #: Document name of the bibliography.
citation_id: str #: Unique id of the citation within the bibliography.
title: str #: Title attribute for reference node.
pre_text: str #: Text to come before citation.
post_text: str #: Text to come after citation.
class SphinxReferenceText(BaseReferenceText[SphinxReferenceInfo]):
"""Pybtex rich text class generating
a docutils reference node to a citation
for use with :class:`SphinxReferenceInfo`.
"""
def render(self, backend: "BaseBackend") -> List[docutils.nodes.Element]:
assert isinstance(
backend, pybtex_docutils.Backend
), "SphinxReferenceText only supports the docutils backend"
info = self.info[0]
if info.builder.name == "latex":
key = f"cite.{info.todocname}:{info.citation_id}"
return (
[raw_latex(f"\\hyperlink{{{key}}}{{")]
+ super().render(backend)
+ [raw_latex("}")]
)
elif info.builder.name == "rinoh":
children = super().render(backend)
refid = f"%{info.todocname}#{info.citation_id}"
refnode = docutils.nodes.citation_reference(
text=children[0], refid=refid, reftitle=info.title
)
refnode.extend(children[1:])
return [refnode]
else:
children = super().render(backend)
# make_refnode only takes a single child
refnode2 = make_refnode(
builder=info.builder,
fromdocname=info.fromdocname,
todocname=info.todocname,
targetid=info.citation_id,
child=children[0],
title=info.title,
)
refnode2.extend(children[1:]) # type: ignore
return [refnode2]
@node
def reference(children, data: Dict[str, Any]):
"""Pybtex node for inserting a docutils reference node to a citation.
The children of the node
comprise the content of the reference, and any referencing information
is stored in the *reference_info* key of the *data*.
The data must also contain a *style* key pointing to the corresponding
:class:`~sphinxcontrib.bibtex.style.referencing.BaseReferenceStyle`.
"""
parts = _format_list(children, data)
info = data["reference_info"]
assert isinstance(info, SphinxReferenceInfo)
return SphinxReferenceText(info, *parts)
@node
def pre_text(children, data: Dict[str, Any]):
assert not children
info = data["reference_info"]
assert isinstance(info, SphinxReferenceInfo)
return Text(info.pre_text)
@node
def post_text(children, data: Dict[str, Any]):
assert not children
info = data["reference_info"]
assert isinstance(info, SphinxReferenceInfo)
return Text(info.post_text)
class FootReferenceInfo(NamedTuple):
"""Tuple containing reference info to enable sphinx to resolve a footnote
reference.
"""
key: str #: Citation key.
document: "docutils.nodes.document" #: Current docutils document.
refname: str #: Citation reference name.
class FootReferenceText(BaseReferenceText[FootReferenceInfo]):
"""Pybtex rich text class generating
a docutils footnote_reference node to a citation
for use with :class:`FootReferenceInfo`.
"""
def render(self, backend: "BaseBackend"):
assert isinstance(
backend, pybtex_docutils.Backend
), "FootReferenceText only supports the docutils backend"
info = self.info[0]
# see docutils.parsers.rst.states.Body.footnote_reference()
refnode = docutils.nodes.footnote_reference(
"[#%s]_" % info.key, refname=info.refname, auto=1
)
info.document.note_autofootnote_ref(refnode)
info.document.note_footnote_ref(refnode)
return [refnode]
@node
def footnote_reference(children, data: Dict[str, Any]):
"""Pybtex node for inserting a footnote_reference docutils node.
Any referencing information
is stored in the *reference_info* key of the *data*.
The data must also contain a *style* key pointing to the corresponding
:class:`~sphinxcontrib.bibtex.style.referencing.BaseReferenceStyle`.
"""
assert not children
info = data["reference_info"]
assert isinstance(info, FootReferenceInfo)
# we need to give the footnote text some fake content
# otherwise pybtex richtext engine will mess things up
return FootReferenceText(info, "#")
@node
def year(children, data: Dict[str, Any]) -> "BaseText":
assert not children
return first_of[optional[field("year")], "n.d."].format_data(data)
@node
def author_or_editor_or_title(children, data, **kwargs):
assert not children
return first_of[
optional[names("author", **kwargs)],
optional[names("editor", **kwargs)],
tag("em")[field("title")],
].format_data(data)