From: Yaroslav Halchenko Date: Thu, 21 Oct 2010 20:42:19 +0000 (-0400) Subject: initial support for quotes -- just renders :quote: directives atm X-Git-Url: https://git.donarmstrong.com/?a=commitdiff_plain;h=a59844a6df5e0b9a2986d8c1c39de52f69375c60;p=neurodebian.git initial support for quotes -- just renders :quote: directives atm --- diff --git a/sphinx/_static/neurodebian.css b/sphinx/_static/neurodebian.css index 69086be..e1cebba 100644 --- a/sphinx/_static/neurodebian.css +++ b/sphinx/_static/neurodebian.css @@ -660,6 +660,42 @@ img.logo { border: 0; } + +/* Epigraphs */ + +blockquote.epigraph { + padding: 0 1em 0 1em; + background-color: #f2f2f2; + border-top: 1px solid #ccc; + border-bottom: 1px solid #ccc; + font-style: italic; +} + +blockquote.epigraph p { + margin: 0.2em 0 0.2em 0; +} + +p.attribution { + padding: 0.2em 0 0 1em; + font-size: 80%; + font-style: normal; +} + +p.attribution span.author { + margin: 0; + font-weight: bold; +} + +p.attribution span.date { + font-size: 90%; +} + +p.attribution span.affiliation, span.source { + font-size: 90%; + padding: 0 0 0 25px; + display: block; +} + /* :::: PRINT :::: */ @media print { div.document, diff --git a/sphinx/conf.py b/sphinx/conf.py index 698c32d..f7d0378 100644 --- a/sphinx/conf.py +++ b/sphinx/conf.py @@ -41,7 +41,9 @@ def artworkdir(): # Add any Sphinx extension module names here, as strings. They can be extensions # coming with Sphinx (named 'sphinx.ext.*') or your custom ones. -extensions = [] +#extensions = [] +sys.path.append(os.path.abspath('.')) +extensions = ['ext.quote'] # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates'] diff --git a/sphinx/ext/__init__.py b/sphinx/ext/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/sphinx/ext/quote.py b/sphinx/ext/quote.py new file mode 100644 index 0000000..1b1ae8e --- /dev/null +++ b/sphinx/ext/quote.py @@ -0,0 +1,193 @@ +#emacs: -*- coding: utf-8; mode: python-mode; py-indent-offset: 4; tab-width: 4; indent-tabs-mode: t -*- +#ex: set sts=4 ts=4 sw=4 et: +""" + ext.quote + ~~~~~~~~~ + + Compile the quotes + + :copyright: Copyright 2010 Yaroslav O. Halchenko + :license: BSD +""" + +from docutils import nodes +from docutils.parsers.rst import directives, Directive +from docutils.parsers.rst.directives import body + +from sphinx.locale import _ +from sphinx.environment import NoUri +from sphinx.util.compat import Directive, make_admonition + + +class quote_node(nodes.Admonition, nodes.Element): pass +class quotelist(nodes.General, nodes.Element): pass + +class Quote(Directive): + """ + A quote entry, displayed (if configured) in the form of an admonition. + """ + + has_content = True + required_arguments = 0 + optional_arguments = 0 + final_argument_whitespace = False + option_spec = { + 'author': directives.unchanged, + 'affiliation': directives.unchanged, + 'date': directives.unchanged, + 'group': directives.unchanged, + 'source': directives.unchanged} + + def run(self): + state = self.state + env = self.state.document.settings.env + options = self.options + + targetid = 'index-%s' % env.new_serialno('index') + targetnode = nodes.target('', '', ids=[targetid]) + targetnode['classes'] = ['epigraph'] + + node = state.block_quote(self.content, self.content_offset) + for element in node: + if isinstance(element, nodes.block_quote): + element['classes'] += ['epigraph'] + + signode = [nodes.attribution('--', '--')] + # Embed all components within attributions + siglb = nodes.line_block('') + # Pre-format some + if 'date' in options: + options['date'] = '[%(date)s]' % options + if 'source' in options: + options['source'] = 'Source: %(source)s' % options + for el in ['author', 'date', 'affiliation', 'source']: + if el in options: + siglb += [nodes.inline('', ' '+options[el], classes=[el])] + signode[0].extend(siglb) + node[0].extend(signode) + return [targetnode] + node; + + + +def process_quotes(app, doctree): + # collect all quotes in the environment + # this is not done in the directive itself because it some transformations + # must have already been run, e.g. substitutions + env = app.builder.env + if not hasattr(env, 'quote_all_quotes'): + env.quote_all_quotes = [] + ## for node in doctree.traverse(quote_node): + ## try: + ## targetnode = node.parent[node.parent.index(node) - 1] + ## if not isinstance(targetnode, nodes.target): + ## raise IndexError + ## except IndexError: + ## targetnode = None + ## env.quote_all_quotes.append({ + ## 'docname': env.docname, + ## 'lineno': node.line, + ## 'quote': node.deepcopy(), + ## 'target': targetnode, + ## }) + + +class QuoteList(Directive): + """ + A list of all quote entries. + """ + + has_content = False + required_arguments = 0 + optional_arguments = 0 + final_argument_whitespace = False + option_spec = { + 'entries': lambda a: directives.choice(a, ('all', 'random')), + 'grouping': lambda a: directives.choice(a, ('month', 'group', None))} + + def run(self): + # Simply insert an empty quotelist node which will be replaced later + # when process_quote_nodes is called + return [quotelist('')] + + + +def process_quote_nodes(app, doctree, fromdocname): + ## if not app.config['quote_include_quotes']: + ## for node in doctree.traverse(quote_node): + ## node.parent.remove(node) + + # Replace all quotelist nodes with a list of the collected quotes. + # Augment each quote with a backlink to the original location. + env = app.builder.env + + if not hasattr(env, 'quote_all_quotes'): + env.quote_all_quotes = [] + + for node in doctree.traverse(quotelist): + ## if not app.config['quote_include_quotes']: + ## node.replace_self([]) + ## continue + + content = [] + + for quote_info in env.quote_all_quotes: + para = nodes.paragraph(classes=['quote-source']) + filename = env.doc2path(quote_info['docname'], base=None) + description = _('(The <> is located in ' + ' %s, line %d.)') % (filename, quote_info['lineno']) + desc1 = description[:description.find('<<')] + desc2 = description[description.find('>>')+2:] + para += nodes.Text(desc1, desc1) + + # Create a reference + newnode = nodes.reference('', '', internal=True) + innernode = nodes.emphasis(_('original entry'), _('original entry')) + try: + newnode['refuri'] = app.builder.get_relative_uri( + fromdocname, quote_info['docname']) + newnode['refuri'] += '#' + quote_info['target']['refid'] + except NoUri: + # ignore if no URI can be determined, e.g. for LaTeX output + pass + newnode.append(innernode) + para += newnode + para += nodes.Text(desc2, desc2) + #para += nodes.Text("XXX", "YYY") + + # (Recursively) resolve references in the quote content + quote_entry = quote_info['quote'] + env.resolve_references(quote_entry, quote_info['docname'], + app.builder) + + # Insert into the quotelist + content.append(quote_entry) + content.append(para) + + node.replace_self(content) + + +def purge_quotes(app, env, docname): + if not hasattr(env, 'quote_all_quotes'): + return + env.quote_all_quotes = [quote for quote in env.quote_all_quotes + if quote['docname'] != docname] + + +def quotes_noop(self, node): + pass + +def setup(app): + ## app.add_config_value('quotes_include_quotes', False, False) + #import pydb + #pydb.debugger() + app.add_node(quotelist) + app.add_node(quote_node, + html=(quotes_noop, quotes_noop), + latex=(quotes_noop, quotes_noop), + text=(quotes_noop, quotes_noop)) + + app.add_directive('quote', Quote) + app.add_directive('quotelist', QuoteList) + app.connect('doctree-read', process_quotes) + app.connect('doctree-resolved', process_quote_nodes) + app.connect('env-purge-doc', purge_quotes)