|
|
@ -1,12 +1,18 @@ |
|
|
|
from sphinx.builders.html import StandaloneHTMLBuilder |
|
|
|
from sphinx.builders.gettext import MessageCatalogBuilder, I18nBuilder, timestamp, ltz, should_write, GettextRenderer |
|
|
|
from sphinx.locale import __ |
|
|
|
from sphinx.util import status_iterator |
|
|
|
from sphinx.util.osutil import ensuredir |
|
|
|
from sphinx.environment.adapters.indexentries import IndexEntries |
|
|
|
from sphinx.writers.html5 import HTML5Translator |
|
|
|
import datetime |
|
|
|
import os |
|
|
|
|
|
|
|
|
|
|
|
class DPYHTML5Translator(HTML5Translator): |
|
|
|
def visit_section(self, node): |
|
|
|
self.section_level += 1 |
|
|
|
self.body.append( |
|
|
|
self.starttag(node, 'section')) |
|
|
|
self.body.append(self.starttag(node, 'section')) |
|
|
|
|
|
|
|
def depart_section(self, node): |
|
|
|
self.section_level -= 1 |
|
|
@ -20,6 +26,7 @@ class DPYHTML5Translator(HTML5Translator): |
|
|
|
super().depart_table(node) |
|
|
|
self.body.append('</div>') |
|
|
|
|
|
|
|
|
|
|
|
class DPYStandaloneHTMLBuilder(StandaloneHTMLBuilder): |
|
|
|
# This is mostly copy pasted from Sphinx. |
|
|
|
def write_genindex(self) -> None: |
|
|
@ -28,8 +35,7 @@ class DPYStandaloneHTMLBuilder(StandaloneHTMLBuilder): |
|
|
|
genindex = IndexEntries(self.env).create_index(self, group_entries=False) |
|
|
|
indexcounts = [] |
|
|
|
for _k, entries in genindex: |
|
|
|
indexcounts.append(sum(1 + len(subitems) |
|
|
|
for _, (_, subitems, _) in entries)) |
|
|
|
indexcounts.append(sum(1 + len(subitems) for _, (_, subitems, _) in entries)) |
|
|
|
|
|
|
|
genindexcontext = { |
|
|
|
'genindexentries': genindex, |
|
|
@ -38,40 +44,79 @@ class DPYStandaloneHTMLBuilder(StandaloneHTMLBuilder): |
|
|
|
} |
|
|
|
|
|
|
|
if self.config.html_split_index: |
|
|
|
self.handle_page('genindex', genindexcontext, |
|
|
|
'genindex-split.html') |
|
|
|
self.handle_page('genindex-all', genindexcontext, |
|
|
|
'genindex.html') |
|
|
|
self.handle_page('genindex', genindexcontext, 'genindex-split.html') |
|
|
|
self.handle_page('genindex-all', genindexcontext, 'genindex.html') |
|
|
|
for (key, entries), count in zip(genindex, indexcounts): |
|
|
|
ctx = {'key': key, 'entries': entries, 'count': count, |
|
|
|
'genindexentries': genindex} |
|
|
|
self.handle_page('genindex-' + key, ctx, |
|
|
|
'genindex-single.html') |
|
|
|
ctx = {'key': key, 'entries': entries, 'count': count, 'genindexentries': genindex} |
|
|
|
self.handle_page('genindex-' + key, ctx, 'genindex-single.html') |
|
|
|
else: |
|
|
|
self.handle_page('genindex', genindexcontext, 'genindex.html') |
|
|
|
|
|
|
|
|
|
|
|
class DPYMessageCatalogBuilder(MessageCatalogBuilder): |
|
|
|
def finish(self) -> None: |
|
|
|
# Bypass MessageCatalogBuilder.finish |
|
|
|
I18nBuilder.finish(self) |
|
|
|
|
|
|
|
# This is mostly copy pasted from Sphinx |
|
|
|
# However, this allows |
|
|
|
context = { |
|
|
|
'version': self.config.version, |
|
|
|
'copyright': self.config.copyright, |
|
|
|
'project': self.config.project, |
|
|
|
'last_translator': self.config.gettext_last_translator, |
|
|
|
'language_team': self.config.gettext_language_team, |
|
|
|
'ctime': datetime.datetime.fromtimestamp(timestamp, ltz).strftime('%Y-%m-%d %H:%M%z'), |
|
|
|
'display_location': self.config.gettext_location, |
|
|
|
'display_uuid': self.config.gettext_uuid, |
|
|
|
} |
|
|
|
for textdomain, catalog in status_iterator( |
|
|
|
self.catalogs.items(), |
|
|
|
__("writing message catalogs... "), |
|
|
|
"darkgreen", |
|
|
|
len(self.catalogs), |
|
|
|
self.app.verbosity, |
|
|
|
lambda textdomain__: textdomain__[0], |
|
|
|
): |
|
|
|
# noop if config.gettext_compact is set |
|
|
|
ensuredir(os.path.join(self.outdir, os.path.dirname(textdomain))) |
|
|
|
|
|
|
|
context['messages'] = list(catalog) |
|
|
|
content = GettextRenderer(template_path='_templates/gettext', outdir=self.outdir).render( |
|
|
|
'message.pot_t', context |
|
|
|
) |
|
|
|
|
|
|
|
pofn = os.path.join(self.outdir, textdomain + '.pot') |
|
|
|
if should_write(pofn, content): |
|
|
|
with open(pofn, 'w', encoding='utf-8') as pofile: |
|
|
|
pofile.write(content) |
|
|
|
|
|
|
|
|
|
|
|
def add_custom_jinja2(app): |
|
|
|
env = app.builder.templates.environment |
|
|
|
env.tests['prefixedwith'] = str.startswith |
|
|
|
env.tests['suffixedwith'] = str.endswith |
|
|
|
|
|
|
|
|
|
|
|
def add_builders(app): |
|
|
|
"""This is necessary because RTD injects their own for some reason.""" |
|
|
|
app.set_translator('html', DPYHTML5Translator, override=True) |
|
|
|
app.add_builder(DPYStandaloneHTMLBuilder, override=True) |
|
|
|
app.add_builder(DPYMessageCatalogBuilder, override=True) |
|
|
|
|
|
|
|
try: |
|
|
|
original = app.registry.builders['readthedocs'] |
|
|
|
except KeyError: |
|
|
|
pass |
|
|
|
else: |
|
|
|
injected_mro = tuple(base if base is not StandaloneHTMLBuilder else DPYStandaloneHTMLBuilder |
|
|
|
for base in original.mro()[1:]) |
|
|
|
injected_mro = tuple( |
|
|
|
base if base is not StandaloneHTMLBuilder else DPYStandaloneHTMLBuilder for base in original.mro()[1:] |
|
|
|
) |
|
|
|
new_builder = type(original.__name__, injected_mro, {'name': 'readthedocs'}) |
|
|
|
app.set_translator('readthedocs', DPYHTML5Translator, override=True) |
|
|
|
app.add_builder(new_builder, override=True) |
|
|
|
|
|
|
|
|
|
|
|
def setup(app): |
|
|
|
add_builders(app) |
|
|
|
app.connect('builder-inited', add_custom_jinja2) |
|
|
|