Source code for sphinxcontrib.bibtex.transforms

"""
    New Doctree Transforms
    ~~~~~~~~~~~~~~~~~~~~~~

    .. autoclass:: BibliographyTransform

        .. autoattribute:: default_priority
        .. automethod:: apply
"""

import copy
import docutils.nodes
import docutils.transforms

from pybtex.backends.doctree import Backend as output_backend
from pybtex.plugin import find_plugin

from sphinxcontrib.bibtex.nodes import bibliography

def node_text_transform(node, transform):
    """Apply transformation to all Text nodes within node."""
    for child in node.children:
        if isinstance(child, docutils.nodes.Text):
            node.replace(child, transform(child))
        else:
            node_text_transform(child, transform)

def transform_curly_bracket_strip(textnode):
    """Strip curly brackets from text."""
    text = textnode.astext()
    if '{' in text or '}' in text:
        text = text.replace('{', '').replace('}', '')
        return docutils.nodes.Text(text)
    else:
        return textnode

def transform_url_command(textnode):
    """Convert '\url{...}' into a proper docutils hyperlink."""
    text = textnode.astext()
    if '\url' in text:
        text1, _, text = text.partition('\url')
        text2, _, text3 = text.partition('}')
        text2 = text2.lstrip(' {')
        ref = docutils.nodes.reference(refuri=text2)
        ref += docutils.nodes.Text(text2)
        node = docutils.nodes.inline()
        node += transform_url_command(docutils.nodes.Text(text1))
        node += ref
        node += transform_url_command(docutils.nodes.Text(text3))
        return node
    else:
        return textnode

[docs]class BibliographyTransform(docutils.transforms.Transform): # transform must be applied before references are resolved default_priority = 10 """Priority of the transform. See http://docutils.sourceforge.net/docs/ref/transforms.html """
[docs] def apply(self): """Transform each :class:`~sphinxcontrib.bibtex.nodes.bibliography` node into a list of citations. """ env = self.document.settings.env for bibnode in self.document.traverse(bibliography): # get the information of this bibliography node # by looking up its id in the bibliography cache id_ = bibnode['ids'][0] info = [info for other_id, info in env.bibtex_cache.bibliographies.iteritems() if other_id == id_][0] # generate entries entries = [] for bibfile in info.bibfiles: # XXX entries are modified below in an unpickable way # XXX so fetch a deep copy data = env.bibtex_cache.bibfiles[bibfile].data if info.cite == "all": bibfile_entries = data.entries.itervalues() elif info.cite == "cited": bibfile_entries = ( entry for entry in data.entries.itervalues() if entry.key in env.bibtex_cited) elif info.cite == "notcited": bibfile_entries = ( entry for entry in data.entries.itervalues() if entry.key not in env.bibtex_cited) else: raise RuntimeError("invalid cite option (%s)" % info.cite) entries += copy.deepcopy(list(bibfile_entries)) # locate and instantiate style plugin style_cls = find_plugin( 'pybtex.style.formatting', info.style) style = style_cls() # create citation nodes for all references nodes = docutils.nodes.paragraph() backend = output_backend() # XXX style.format_entries modifies entries in unpickable way for entry in style.format_entries(entries): citation = backend.citation(entry, self.document) node_text_transform(citation, transform_url_command) if info.curly_bracket_strip: node_text_transform(citation, transform_curly_bracket_strip) nodes += citation bibnode.replace_self(nodes)

Project Versions