Source

possumpalace_kit / _ext / possumpalace.py

Full commit
"""
Sphinx plugins for PossumPalace documentation.
"""

import docutils.nodes
import docutils.transforms
import sphinx
import sphinx.addnodes
try:
    from sphinx import builders
except ImportError:
    import sphinx.builder as builders
import sphinx.directives
import sphinx.environment
try:
    import sphinx.writers.html as sphinx_htmlwriter
except ImportError:
    import sphinx.htmlwriter as sphinx_htmlwriter
try:
    import sphinx.writers.latex as sphinx_latexwriter
except ImportError:
    import sphinx.latexwriter as sphinx_latexwriter
import sphinx.roles

def setup(app):
    app.add_crossref_type(
        directivename = "fieldlookup",
        rolename      = "lookup",
        indextemplate = "pair: %s, field lookup type",
    )
    app.add_config_value('flickr_key', None, '')
    app.add_transform(SuppressBlockquotes)

    #hack to make my inline references not be shit
    from sphinx.domains.std import StandardDomain
    from sphinx.roles import XRefRole
    
    StandardDomain.roles ['ref'] = XRefRole(
        lowercase=True, innernodeclass=nodes.literal,
        warn_dangling=True)

    # see http://sphinx.pocoo.org/ext/appapi.html#sphinx.application.Sphinx.add_object_type
    # this enables
    #app.add_object_type(directivename, rolename, indextemplate='', parse_node=None, ref_nodeclass=None, objname='')
    
    app.connect('builder-inited', inject_config)   

def inject_config(app):
    import resocializedtext
    from resocializedtext.flickr import FlickrImage
    from resocializedtext.citeulike import set_username
    FlickrImage.FLICKR_KEY = app.config.flickr_key
    set_username(app.config.cul_username)
                
class SuppressBlockquotes(docutils.transforms.Transform):
    """
    Remove the default blockquotes that encase indented list, tables, etc.
    """
    default_priority = 300
    
    suppress_blockquote_child_nodes = (
        docutils.nodes.bullet_list, 
        docutils.nodes.enumerated_list, 
        docutils.nodes.definition_list,
        docutils.nodes.literal_block, 
        docutils.nodes.doctest_block, 
        docutils.nodes.line_block, 
        docutils.nodes.table,
        docutils.nodes.citation
    )
    
    def apply(self):
        for node in self.document.traverse(docutils.nodes.block_quote):
            if len(node.children) == 1 and isinstance(node.children[0], self.suppress_blockquote_child_nodes):
                node.replace_self(node.children[0])

class ManualCite(docutils.nodes.General, docutils.nodes.Element):
   pass

class PossumPalaceHTMLTranslator(sphinx_htmlwriter.SmartyPantsHTMLTranslator):
    """
    PossumPalace-specific reST to HTML tweaks.
    """
    # Don't use border=1, which docutils does by default.
    def visit_table(self, node):
        self.body.append(self.starttag(node, 'table', CLASS='docutils'))
    
    # # <big>? Really?
    # def visit_desc_parameterlist(self, node):
    #     self.body.append('(')
    #     self.first_param = 1
    # 
    # def depart_desc_parameterlist(self, node):
    #     self.body.append(')')
    #     pass
    
    #
    # Don't apply smartypants to literal blocks
    #
    def visit_literal_block(self, node):
        self.no_smarty += 1
        sphinx_htmlwriter.SmartyPantsHTMLTranslator.visit_literal_block(self, node)

    def depart_literal_block(self, node):
        sphinx_htmlwriter.SmartyPantsHTMLTranslator.depart_literal_block(self, node)
        self.no_smarty -= 1
    
    # Give each section a unique ID -- nice for custom CSS hooks
    def visit_section(self, node):
        old_ids = node.get('ids', [])
        node['ids'] = ['s-' + i for i in old_ids]
        node['ids'].extend(old_ids)
        sphinx_htmlwriter.SmartyPantsHTMLTranslator.visit_section(self, node)
        node['ids'] = old_ids

    # # for reference, docutils' hideous default version
    # # def visit_citation(self, node):
    # #     self.body.append(self.starttag(node, 'table',
    # #                                    CLASS='docutils citation',
    # #                                    frame="void", rules="none"))
    # #     self.body.append('<colgroup><col class="label" /><col /></colgroup>\n'
    # #                      '<tbody valign="top">\n'
    # #                      '<tr>')
    # #     self.footnote_backrefs(node)
    # # 
    # # def depart_citation(self, node):
    # #     self.body.append('</td></tr>\n'
    # #                      '</tbody>\n</table>\n')
    # 
    # def visit_citation(self, node):
    #     import pdb; pdb.set_trace()
    #     # node label available as node['names'][0] or node.children[0]
    #     self.body.append(self.starttag(node, 'dl', CLASS='docutils'))
    #     self.body.append(self.starttag(node, 'dd', ''))
    #     self.body.append('</dd>\n')
    #     self.body.append(self.starttag(node, 'dt'))
    #     self.body.append(self.starttag(node, 'cite',
    #                                    CLASS='docutils citation',))
    #     self.footnote_backrefs(node)
    # 
    # def depart_citation(self, node):
    #     self.body.append('</cite>\n')
    #     self.body.append('</dt>\n')
    #     self.body.append('</dl>\n')
    # # but some kind of weird magic happens here that makes it work. fark.   
    # # def visit_label(self, node):
    # #     # Context added in footnote_backrefs.
    # #     self.body.append(self.starttag(node, 'td', '%s[' % self.context.pop(),
    # #                                    CLASS='label'))
    # # 
    # # def depart_label(self, node):
    # #     # Context added in footnote_backrefs.
    # #     self.body.append(']%s</td><td>%s' % (self.context.pop(), self.context.pop()))
    #
class PossumPalaceLaTeXWriter(sphinx_latexwriter.LaTeXWriter):
    pass
    
    #     def visit_citation(self, node):
    #         # TODO maybe use cite bibitems
    #         self.bibitems.append(['', '', ''])  # [citeid, citetext, docname]
    #         self.context.append(len(self.body))
    #     def depart_citation(self, node):
    #         size = self.context.pop()
    #         text = ''.join(self.body[size:])
    #         del self.body[size:]
    #         self.bibitems[-1][1] = text
    # 
    #     def visit_citation_reference(self, node):
    #         # This is currently never encountered, since citation_reference nodes
    #         # are already replaced by pending_xref nodes in the environment.
    #         self.body.append('\\cite{%s}' % self.idescape(node.astext()))
    #         raise nodes.SkipNode