Theming¶
This collection of pages uses a modified version of the Sphinx haiku theme. Thankfully, it was relatively easy to modify and does not involve copying the whole theme.
The config file:
[theme] inherit = haiku stylesheet = haikuish.css
The CSS overrides:
@import url("haiku.css"); body { max-width: 95vw; } div.relbar1 { float: right; padding-top: 15px; font-size: 0.8em; position: relative; z-index: 1; } div.header h2 { text-transform: none; color: #444; } /* Try to wrap bounding boxes around floats */ div.section * { overflow: hidden; } /* Code blocks */ div.highlight pre { display: inline-block; min-width: 50%; margin-inline-start: 5pt; } /* Override pygments' default */ .highlight { background: transparent !important; } /* * For marked inactive nodes that are not the first child or section headings, * set the text transparent and render a grey background, making it look like a * redaction */ .html-toggle:not(:active) :not(:first-child, section, .toc-backref, .headerlink) { background: grey; color: transparent; } /* * A "more specific" selector than :not is required, apparently, to prevent * links from showing through */ .html-toggle:not(:active) a :not(.toc-backref, .headerlink) { background: grey; color: transparent; }
The HTML overrides:
{%- extends "haiku/layout.html" %} {% block relbar1 %} <div class="relbar1"> {%- if show_source and has_source and sourcename %} <a href="{{ pathto('_sources/' + sourcename, true)|e }}" rel="nofollow">{{ _('Show Source') }}</a> {%- endif %} </div> {% endblock %}
Extensions¶
Disabling Searching for Particular Directories¶
Sometimes we don’t want to leak data via search pages. This is a very hackish extension that directly modifies the HTML builder object, since there does not appear to be a better way.
import sphinx
import types
def modBuilder(app):
try:
old_index_page = app.builder.index_page
def new_index_page(self, pagename, doctree, title):
if (not pagename.startswith("secret/")) :
old_index_page(pagename, doctree, title)
app.builder.index_page = types.MethodType(new_index_page, app.builder)
except Exception:
# Alternatively, don't do that and do this instead to disable
# search functionality altogether.
app.builder.search = False
def setup(app):
app.connect('builder-inited', modBuilder)
return {'version': "1", 'parallel_read_safe': True}
Separately, the secret/
path and _source/secret/
paths are protected
by the web server itself so that unauthenticated clients may not read them;
otherwise, there’d be little point!
Removing Document Title From Markup¶
The theme I am using places the title up top specially, but it also remains in the document tree and so gets rendered first thing. That looks bad. This extension surgically removes the document title from pages without altering the sphinx metadata and then promotes the title’s sibling nodes to take the place of the former page container.
import sphinx
from docutils import nodes
def munge_doc_tree(app, doctree, docname):
sec1i = doctree.first_child_matching_class(nodes.section)
if sec1i is None: return
sec1n = doctree[sec1i]
if sec1n is None: return
ts1i = sec1n.first_child_matching_class(nodes.title)
if ts1i is None: return
sec1n.pop(ts1i)
sec1n.replace_self(sec1n.children)
def setup(app):
app.connect('doctree-resolved', munge_doc_tree)
return {'version': "1", 'parallel_read_safe': True}
Hacking Generality Into Toctrees¶
Despite it being a long-standing feature request (https://github.com/sphinx-doc/sphinx/issues/701) with a few PRs taking a stab at it (some from yours truly), sphinx core is hesitant to extend the semantics of toctrees or muck about in their core. So, instead, I present the following truly terrible workaround.
This is an extension which adds a toctreeish
directive that manually
parses the toctree entries and fakes the references that sphinx would
otherwise generate. (It then causes Sphinx to perceive a hidden toctree so
that the rest of the deep, internal document cluster and toctree resolution
magic happens.) The key feature is that entries that begin with an underscore
followed by space will have the rest of their literal text parsed by
docutils
and then inserted into the list. It is in use on this site in
Formal Writings, which contains (roughly)
.. toctreeish::
foo
bar
_ :ref:`baz title <baz#ref>`
It’s gross, it’s terrible, but it means I don’t have to carry around a patched Sphinx or link to the wrong place in my list of publications. Hooray?
import re
from typing import List
from docutils import nodes
from docutils.nodes import Node
from docutils.statemachine import StringList, ViewList
import sphinx
from sphinx import addnodes
from sphinx.directives.other import TocTree
class TocTreeish(TocTree) :
def run(self) -> List[Node]:
assert self.options.get("hidden",False) == False
assert self.options.get("maxdepth",1) == 1
rootln = nodes.bullet_list()
delme = []
for entry in self.content:
node = addnodes.compact_paragraph()
if re.search(r"\s", entry):
if entry.startswith("_ "):
# Raw syntax: parse...
tmp = nodes.paragraph()
self.state.nested_parse(ViewList([entry[2:]]), 0, tmp)
# ... rip out the parsed thing into a compact paragraph...
node += tmp.children[0].children
# ... and prevent the real toctree from seeing it
delme += [ entry ]
else:
assert False, "TocTreeish doesn't understand spaced things"
elif entry == "self":
assert False, "TocTreeish doesn't do 'self'"
else:
# Single word, must be a doc xref. Fake one up!
pxr = addnodes.pending_xref(entry, reftype='doc',
refdomain='std', refexplicit=False, reftarget=entry)
pxr += nodes.inline('', entry, classes="xref std std-doc")
node += pxr
rootln.children += nodes.bullet_list('', nodes.list_item('', node))
for d in delme:
self.content.remove(d)
self.options["hidden"] = True
res = super().run()
# Push our list into the wrapper that still gets generated despite
# setting the toctree to hidden.
wrappernode = res[-1]
wrappernode.append(rootln)
return res
def setup(app):
app.add_directive("toctreeish", TocTreeish)
return {'version': "1", 'parallel_read_safe': True}
Bibliographic Management¶
The entire Formal Writings section of this site is
generated from a bib file, a series of small ReStructredText inputs, and the
downloads themselves. The bulk of the work is done by this TCL
script
. The two parameter files
for bibtool
are: