documentation/extensions/html_domain/__init__.py
Victor Feyens 2ddac026f1 [FIX] extensions: support parallel read
Now that patchqueue was removed, we can consider supporting the parallel 
read with our local extensions.

Since we only have basic extensions, not storing any data on the build 
environment, the change mainly consists of specifying the extensions as 
parallelizable.

The only specific case is the html domain, since the base html domain 
requires the support of the method merge_domaindata in parallel read 
mode.  Since we do not need to share anything between the envs for this 
extension, we can simply ignore the method.
2021-05-19 15:03:39 +02:00

194 lines
5.1 KiB
Python
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# -*- coding: utf-8 -*-
"""
Defines a "raw HTML" domain with a ``div[classes]`` and a number of roles
rendered more or less directly to HTML.
.. warning::
the purpose of this domain is *not* to document HTML or components
NOTE: this extension is only used by special accounting pages (memento, valuation, ...)
for directives likes .. h:div::
TO REMOVE AS SOON AS WE DROP MEMENTOES
"""
from docutils import nodes, utils
from docutils.parsers.rst import Directive, directives
from docutils.parsers.rst.directives.body import LineBlock
import sphinx
import sphinx.roles
from sphinx.domains import Domain
def setup(app):
app.add_domain(HtmlDomain)
app.add_node(div, html=(
lambda self, node: self.body.append(self.starttag(node, 'div')),
lambda self, node: self.body.append('</div>\n')))
# override parameter was added for version sphinx >= 1.4, TypeError before
kw = {'override': True} if sphinx.version_info >= (1, 4) else {}
app.add_node(address, html=(
lambda self, node: self.body.append(self.starttag(node, 'address')),
lambda self, node: self.body.append('</address>\n')
), **kw) # docutils.nodes.address exists and is a bibliographic element
app.add_node(cite, html=(visit_cite, depart_cite))
for name, node in [('mark', mark), ('ins', insert), ('del', delete),
('s', strikethrough), ('u', underline), ('small', small),
('kbd', kbd), ('var', var), ('samp', samp)]:
addnode(app, node, name)
return {
'parallel_read_safe': True,
'parallel_write_safe': True
}
class div(nodes.General, nodes.Element):
pass
class Div(Directive):
optional_arguments = 1
final_argument_whitespace = 1
has_content = True
def run(self):
self.assert_has_content()
text = '\n'.join(self.content)
try:
if self.arguments:
classes = directives.class_option(self.arguments[0])
else:
classes = []
except ValueError:
raise self.error(
'Invalid class attribute value for "%s" directive: "%s".'
% (self.name, self.arguments[0]))
node = div(text)
node['classes'].extend(classes)
self.add_name(node)
self.state.nested_parse(self.content, self.content_offset, node)
return [node]
class address(nodes.General, nodes.Element):
pass
class Address(LineBlock):
def run(self):
[node] = super(Address, self).run()
ad = address(node.rawsource, *node.children)
return [ad]
class mark(nodes.Inline, nodes.TextElement):
pass
class insert(nodes.Inline, nodes.TextElement):
pass
class delete(nodes.Inline, nodes.TextElement):
pass
class strikethrough(nodes.Inline, nodes.TextElement):
pass
class underline(nodes.Inline, nodes.TextElement):
pass
class small(nodes.Inline, nodes.TextElement):
pass
class kbd(nodes.Inline, nodes.FixedTextElement):
pass
class var(nodes.Inline, nodes.FixedTextElement):
pass
class samp(nodes.Inline, nodes.FixedTextElement):
pass
def makerole(node):
return lambda name, rawtext, text, lineno, inliner, options=None, content=None:\
([node(rawtext.strip(), text.strip())], [])
def addnode(app, node, nodename):
app.add_node(node, html=(
lambda self, n: self.body.append(self.starttag(n, nodename)),
lambda self, n: self.body.append('</%s>' % nodename)
))
def initialism(*args, **kwargs):
nodes, _ = sphinx.roles.abbr_role(*args, **kwargs)
[abbr] = nodes
abbr.attributes.setdefault('classes', []).append('initialism')
return [abbr], []
def cite_role(typ, rawtext, text, lineno, inliner, options=None, content=None):
text = utils.unescape(text)
m = sphinx.roles._abbr_re.search(text)
if m is None:
return [cite(text, text, **(options or {}))], []
content = text[:m.start()].strip()
source = m.group(1)
return [cite(content, content, source=source)], []
class cite(nodes.Inline, nodes.TextElement):
pass
def visit_cite(self, node):
attrs = {}
if node.hasattr('source'):
attrs['title'] = node['source']
self.body.append(self.starttag(node, 'cite', '', **attrs))
def depart_cite(self, node):
self.body.append('</abbr>')
class HtmlDomain(Domain):
name = 'h'
label = 'HTML'
directives = {
'div': Div,
'address': Address,
}
roles = {
'mark': makerole(mark),
'ins': makerole(insert),
'del': makerole(delete),
's': makerole(strikethrough),
'u': makerole(underline),
'small': makerole(small),
'initialism': initialism,
'cite': cite_role,
'kbd': makerole(kbd),
'var': makerole(var),
'samp': makerole(samp),
}
def merge_domaindata(self, docnames, otherdata) -> None:
"""Merge in data regarding *docnames* from a different domaindata
inventory (coming from a subprocess in parallel builds).
"""
# This extension doesn't store any data on the env
# and therefore doesn't need to support this method.
pass