# Source code for sphinxcontrib.bibtex.transforms

    """
    .. autoclass:: BibliographyTransform
        :show-inheritance:

        .. autoattribute:: default_priority
        .. automethod:: run
    """

    from itertools import zip_longest
    from typing import TYPE_CHECKING, cast

    import docutils.nodes
    from pybtex.plugin import find_plugin
    from sphinx.transforms.post_transforms import SphinxPostTransform
    from sphinx.util.logging import getLogger

    from .directives import BibliographyKey
    from .nodes import bibliography as bibliography_node

    if TYPE_CHECKING:
        from sphinx.environment import BuildEnvironment

        from .domain import BibtexDomain

    logger = getLogger(__name__)

    def node_text_transform(node: docutils.nodes.Element) -> None:
        """Apply extra text transformations to a node."""
        for child, next_child in zip_longest(node.children[:], node.children[1:]):
            if isinstance(child, docutils.nodes.Text):
                if child.endswith(r"\url ") and isinstance(next_child, docutils.nodes.Text):
                    node.replace(child, docutils.nodes.Text(child[:-5]))
                    ref_node = docutils.nodes.reference(refuri=next_child.astext())
                    ref_node += next_child
                    node.replace(next_child, ref_node)
            elif isinstance(child, docutils.nodes.Element):  # pragma: no branch
                node_text_transform(child)

    class BibliographyTransform(SphinxPostTransform):
        """A docutils transform to generate citation entries for
        bibliography nodes.
        """

        # transform must be applied before sphinx runs its ReferencesResolver
        # which has priority 10, so when ReferencesResolver calls the cite domain
        # resolve_xref, the target is present and all will work fine
        default_priority = 5
        backend = find_plugin("pybtex.backends", "docutils")()

        def run(self, **kwargs):
            """Transform each
            :class:`~sphinxcontrib.bibtex.nodes.bibliography` node into a
            list of citations.
            """
            env = cast("BuildEnvironment", self.document.settings.env)
            domain = cast("BibtexDomain", env.get_domain("cite"))
            # Can just use "findall" once docutils 0.18+ is required
            meth = "findall" if hasattr(self.document, "findall") else "traverse"
            for bibnode in getattr(self.document, meth)(bibliography_node):
                # reminder: env.docname may be equal to 'index' instead of
                # bibnode['docname'] in post-transform phase (e.g. latex builder)
                bib_key = BibliographyKey(docname=bibnode["docname"], id_=bibnode["ids"][0])
                bibliography = domain.bibliographies[bib_key]
                citations = [
                    citation
                    for citation in domain.citations
                    if citation.bibliography_key == bib_key
                ]
                # create citation nodes for all references
                if bibliography.list_ == "enumerated":
                    nodes = docutils.nodes.enumerated_list()
                    nodes["enumtype"] = bibliography.enumtype
                    if bibliography.start >= 1:
                        nodes["start"] = bibliography.start
                        env.temp_data["bibtex_enum_count"] = bibliography.start
                    else:
                        nodes["start"] = env.temp_data.setdefault("bibtex_enum_count", 1)
                elif bibliography.list_ == "bullet":
                    nodes = docutils.nodes.bullet_list()
                else:  # "citation"
                    nodes = []
                for citation in citations:
                    citation_node = bibliography.citation_nodes[citation.key]
                    if bibliography.list_ in {"enumerated", "bullet"}:
                        citation_node += self.backend.paragraph(citation.formatted_entry)
                    else:  # "citation"
                        # backrefs only supported in same document
                        backrefs = [
                            citation_ref.citation_ref_id
                            for citation_ref in domain.citation_refs
                            if bib_key.docname == citation_ref.docname
                            and citation.key
                            in {target.key for target in citation_ref.targets}
                        ]
                        if backrefs:
                            citation_node["backrefs"] = backrefs
                        citation_node += docutils.nodes.label(
                            "", citation.formatted_entry.label, support_smartquotes=False
                        )
                        citation_node += self.backend.paragraph(citation.formatted_entry)
                    citation_node["docname"] = bib_key.docname
                    node_text_transform(citation_node)
                    nodes.append(citation_node)
                    if bibliography.list_ == "enumerated":
                        env.temp_data["bibtex_enum_count"] += 1
                if citations:
                    final_node = domain.bibliography_header.deepcopy()
                    final_node += nodes
                    bibnode.replace_self(final_node)
                else:
                    bibnode.replace_self(docutils.nodes.target())