Skip to content

Commit

Permalink
Handle markup in term tooltips (#309)
Browse files Browse the repository at this point in the history
By extending Sphinx's TextWriter and dependencies, we can handle the
docutils nodes as we wish.

Now, the tables are displayed as clipped text with only they label as a
caption, xref and term references are surrounded by square brackets, to
see in advance if the definition contains references to other terms.

Some behaviour has been directly inherited from Sphinx's TextWriter,
mainly the indentation for some blocks (e.g. the admonitions), the lists
should now be displayed properly and the inline code literals are
surrounded by straight double quotes.

Also added indentation for literal blocks.
  • Loading branch information
n-peugnet authored Jul 29, 2024
1 parent 2343854 commit 2045944
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 8 deletions.
56 changes: 49 additions & 7 deletions _ext/term_tooltips.py
Original file line number Diff line number Diff line change
@@ -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):
Expand All @@ -16,9 +53,12 @@ class TermTooltips(SphinxPostTransform):
logger = logging.getLogger('term_tooltips')
start_after: Optional[str]
end_before: Optional[str]
single_newlines = re.compile('(?<!\n)\n(?!\n)')
too_much_newlines = re.compile('\n{3,}')
stddomain: StandardDomain
writer: writers.Writer

def __init__(self, document: nodes.document, startnode: nodes.Node | None = None):
super().__init__(document, startnode)
self.writer = TextWriter(TooltipBuilder(self.app, self.env)) # type: ignore

def run(self) -> None:
if self.app.builder.format != 'html':
Expand Down Expand Up @@ -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:
Expand Down
2 changes: 1 addition & 1 deletion conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -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']
Expand Down

0 comments on commit 2045944

Please sign in to comment.