# Copyright © 2021 Lee Yingtong Li # # This Source Code Form is subject to the terms of the Mozilla Public # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/.https://mozilla.org/MPL/2.0/. def setup(app): app.add_builder(POStandaloneHTMLBuilder, override=True) app.add_builder(POLaTeXBuilder, override=True) app.add_role('subref', SubRefRole()) #app.add_source_parser(PORSTParser, override=True) # HTML Builder from sphinx.builders.html import StandaloneHTMLBuilder from sphinx.environment.adapters.toctree import TocTree from sphinx.writers.html5 import HTML5Translator import docutils.nodes import sphinx.addnodes from sphinx.util import logging logger = logging.getLogger(__name__) class POHTML5Translator(HTML5Translator): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.paragraph_num = 0 self.footnote_order = [] def visit_paragraph(self, node): super().visit_paragraph(node) if node.parent.tagname == 'section': # Add paragraph numbers self.paragraph_num += 1 self.body.append('{0}'.format(self.paragraph_num)) def visit_footnote_reference(self, node): super().visit_footnote_reference(node) # Verify order if node['refid'] not in self.footnote_order: self.footnote_order.append(node['refid']) def visit_footnote(self, node): super().visit_footnote(node) # Verify order if not self.footnote_order: pass elif node['ids'][0] == self.footnote_order[0]: del self.footnote_order[0] else: logger.warning('footnote defined out of sequence: expecting {}'.format(self.footnote_order[0]), location=node) self.footnote_order = None # Ignore future errors class POStandaloneHTMLBuilder(StandaloneHTMLBuilder): default_translator_class = POHTML5Translator __TocTree_resolve = TocTree.resolve def _TocTree_resolve(self, *args, **kwargs): result = __TocTree_resolve(self, *args, **kwargs) if self.env.app.builder.name == 'html': # Add Index TOC entry bullet_list = result[1] reference = docutils.nodes.reference('', '', internal=True, refuri='genindex.html', anchorname='', *[docutils.nodes.Text('Index')]) compact_paragraph = sphinx.addnodes.compact_paragraph('', '', reference) list_item = docutils.nodes.list_item('', classes=['toctree-l1'], *[compact_paragraph]) bullet_list.append(list_item) return result TocTree.resolve = _TocTree_resolve # LaTeX Builder from sphinx.builders.latex import LaTeXBuilder from sphinx.writers.latex import LaTeXTranslator class POLaTeXTranslator(LaTeXTranslator): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.paragraph_num = 0 def visit_title(self, node): super().visit_title(node) if self.sectionlevel == 1: # Reset paragraph numbers self.paragraph_num = 0 def visit_paragraph(self, node): super().visit_paragraph(node) if node.parent.tagname == 'section': # Add paragraph numbers self.paragraph_num += 1 #self.body.append(r'\makebox[0pt][r]{{\small\textcolor[HTML]{{AAAAAA}}{{¶{0}}}\hspace{{0.8em}}}}'.format(self.paragraph_num)) #self.body.append(r'{{\small\textcolor[HTML]{{AAAAAA}}{{[¶{0}]}}}} '.format(self.paragraph_num)) self.body.append(r'{{\small\bfseries\sffamily[{0}]}} '.format(self.paragraph_num)) class POLaTeXBuilder(LaTeXBuilder): default_translator_class = POLaTeXTranslator # :subref: Role from sphinx.roles import XRefRole class SubRefRole(XRefRole): def __init__(self, *args, **kwargs): super().__init__(lowercase=True, innernodeclass=docutils.nodes.inline, warn_dangling=True, *args, **kwargs) def run(self): self.name = 'std:ref' return super().run() def result_nodes(self, document, env, node, is_ref): result = super().result_nodes(document, env, node, is_ref) pending_xref = result[0][0] inline = pending_xref[0] substitution_reference = docutils.nodes.substitution_reference('', '', refname=docutils.nodes.fully_normalize_name(self.title)) inline.clear() # Remove raw "title" text node inline.append(substitution_reference) # Replace with substitution_reference pending_xref['po_subref'] = True # Flag for StandardDomain._resolve_ref_xref return result from sphinx.domains.std import StandardDomain __StandardDomain_resolve_ref_xref = StandardDomain._resolve_ref_xref def _StandardDomain_resolve_ref_xref(self, env, fromdocname, builder, typ, target, node, contnode): if 'po_subref' in node: # Build reference node, preserving substitution docname, labelid = self.anonlabels.get(target, ('', '')) # Based on StandardDomain.build_reference_node newnode = docutils.nodes.reference('', '', internal=True) if docname == fromdocname: newnode['refid'] = labelid else: contnode = sphinx.addnodes.pending_xref('') contnode['refdocname'] = docname contnode['refsectname'] = node.astext() newnode['refuri'] = builder.get_relative_uri(fromdocname, docname) if labelid: newnode['refuri'] += '#' + labelid # Copy across substitution newnode.children.extend(node.children) return newnode return __StandardDomain_resolve_ref_xref(self, env, fromdocname, builder, typ, target, node, contnode) StandardDomain._resolve_ref_xref = _StandardDomain_resolve_ref_xref # RST Parser from sphinx.parsers import RSTParser class PORSTParser(RSTParser): def parse(self, inputstring, document): super().parse(inputstring, document) # Verify footnotes print(document)