diff --git a/_ext/term_tooltips.py b/_ext/term_tooltips.py index d2ffeddf..0855719b 100644 --- a/_ext/term_tooltips.py +++ b/_ext/term_tooltips.py @@ -1,13 +1,50 @@ import re +from docutils import nodes, writers +from docutils.io import StringOutput from sphinx import addnodes from sphinx.application import Sphinx +from sphinx.builders.dummy import DummyBuilder from sphinx.domains.std import StandardDomain +from sphinx.util.docutils import new_document from sphinx.writers.html5 import HTML5Translator +from sphinx.writers.text import TextTranslator, TextWriter from sphinx.transforms.post_transforms import SphinxPostTransform +from sphinx.locale import _ from sphinx.util import logging -from docutils import nodes -from typing import Callable, Optional, Tuple +from typing import Optional, Tuple + +class TooltipTranslator(TextTranslator): + def visit_table(self, node: nodes.Element) -> None: + title = next(node.findall(nodes.title), None) + caption = _('Table: %s') % title.astext() if title else _('Table') + self.add_text('[%s]' % caption) + raise nodes.SkipNode + + def new_state(self, indent: int = 0) -> None: + """Override new_state() to disable indentation by default.""" + super().new_state(indent) + + def visit_emphasis(self, node: nodes.Element) -> None: + pass + + def depart_emphasis(self, node: nodes.Element) -> None: + pass + + def visit_inline(self, node: nodes.Element) -> None: + if 'xref' in node['classes'] or 'term' in node['classes']: + self.add_text('[') + + def depart_inline(self, node: nodes.Element) -> None: + if 'xref' in node['classes'] or 'term' in node['classes']: + self.add_text(']') + + def visit_literal_block(self, node: nodes.Element) -> None: + self.new_state(indent=3) + + +class TooltipBuilder(DummyBuilder): + default_translator_class = TooltipTranslator class TermTooltips(SphinxPostTransform): @@ -16,9 +53,12 @@ class TermTooltips(SphinxPostTransform): logger = logging.getLogger('term_tooltips') start_after: Optional[str] end_before: Optional[str] - single_newlines = re.compile('(? None: if self.app.builder.format != 'html': @@ -95,9 +135,11 @@ def build_definition_text(self, target: Tuple[str,str], definition_node_type: ty assert isinstance(parent, nodes.Element), f'parent {parent} is not an Element !?' index = parent.first_child_matching_class(definition_node_type) assert index is not None, f'element {targetnode} has no definition !?' - deftext = parent[index].astext() - deftext = self.single_newlines.sub(' ', deftext) - deftext = self.too_much_newlines.sub('\n\n', deftext) + tmpdoc = new_document(document.settings) + tmpdoc += parent[index] + destination = StringOutput(encoding='unicode') + self.writer.write(tmpdoc, destination) + deftext: str = destination.destination.strip() # type: ignore if self.start_after != None: deftext = deftext.split(self.start_after, 1)[-1].lstrip() if self.end_before != None: diff --git a/conf.py b/conf.py index ce180283..d37f7975 100644 --- a/conf.py +++ b/conf.py @@ -94,7 +94,7 @@ myst_url_schemes = ['http', 'https', 'mailto', 'matrix'] # Strip everything after the first emdash in term's tooltips. -term_tooltips_end_before = '— ' +term_tooltips_end_before = '—' # Add any paths that contain templates here, relative to this directory. templates_path = ['_templates']