Close #7530: html: Support nested <kbd> elements

This commit is contained in:
Takeshi KOMIYA 2020-04-30 21:48:53 +09:00
parent 911a3b9809
commit a148a8e7cb
4 changed files with 101 additions and 0 deletions

View File

@ -49,6 +49,7 @@ Features added
to generate stub files recursively to generate stub files recursively
* #4030: autosummary: Add :confval:`autosummary_context` to add template * #4030: autosummary: Add :confval:`autosummary_context` to add template
variables for custom templates variables for custom templates
* #7530: html: Support nested <kbd> elements
* #7481: html theme: Add right margin to footnote/citation labels * #7481: html theme: Add right margin to footnote/citation labels
* #7482: html theme: CSS spacing for code blocks with captions and line numbers * #7482: html theme: CSS spacing for code blocks with captions and line numbers
* #7443: html theme: Add new options :confval:`globaltoc_collapse` and * #7443: html theme: Add new options :confval:`globaltoc_collapse` and

View File

@ -1243,6 +1243,9 @@ def setup(app: Sphinx) -> Dict[str, Any]:
# load default math renderer # load default math renderer
app.setup_extension('sphinx.ext.mathjax') app.setup_extension('sphinx.ext.mathjax')
# load transforms for HTML builder
app.setup_extension('sphinx.builders.html.transforms')
return { return {
'version': 'builtin', 'version': 'builtin',
'parallel_read_safe': True, 'parallel_read_safe': True,

View File

@ -0,0 +1,69 @@
"""
sphinx.builders.html.transforms
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Transforms for HTML builder.
:copyright: Copyright 2007-2020 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re
from typing import Any, Dict
from docutils import nodes
from sphinx.application import Sphinx
from sphinx.transforms.post_transforms import SphinxPostTransform
from sphinx.util.nodes import NodeMatcher
class KeyboardTransform(SphinxPostTransform):
"""Transform :kbd: role to more detailed form.
Before::
<literal class="kbd">
Control-x
After::
<literal class="kbd">
<literal class="kbd">
Control
-
<literal class="kbd">
x
"""
default_priority = 400
builders = ('html',)
pattern = re.compile(r'(-|\+|\^|\s+)')
def run(self, **kwargs: Any) -> None:
matcher = NodeMatcher(nodes.literal, classes=["kbd"])
for node in self.document.traverse(matcher): # type: nodes.literal
parts = self.pattern.split(node[-1].astext())
if len(parts) == 1:
continue
node.pop()
while parts:
key = parts.pop(0)
node += nodes.literal('', key, classes=["kbd"])
try:
# key separator (ex. -, +, ^)
sep = parts.pop(0)
node += nodes.Text(sep)
except IndexError:
pass
def setup(app: Sphinx) -> Dict[str, Any]:
app.add_post_transform(KeyboardTransform)
return {
'version': 'builtin',
'parallel_read_safe': True,
'parallel_write_safe': True,
}

View File

@ -16,6 +16,7 @@ from docutils.parsers.rst import Parser as RstParser
from docutils.transforms.universal import SmartQuotes from docutils.transforms.universal import SmartQuotes
from sphinx import addnodes from sphinx import addnodes
from sphinx.builders.html.transforms import KeyboardTransform
from sphinx.builders.latex import LaTeXBuilder from sphinx.builders.latex import LaTeXBuilder
from sphinx.roles import XRefRole from sphinx.roles import XRefRole
from sphinx.testing.util import Struct, assert_node from sphinx.testing.util import Struct, assert_node
@ -94,6 +95,7 @@ class ForgivingLaTeXTranslator(LaTeXTranslator, ForgivingTranslator):
def verify_re_html(app, parse): def verify_re_html(app, parse):
def verify(rst, html_expected): def verify(rst, html_expected):
document = parse(rst) document = parse(rst)
KeyboardTransform(document).apply()
html_translator = ForgivingHTMLTranslator(document, app.builder) html_translator = ForgivingHTMLTranslator(document, app.builder)
document.walkabout(html_translator) document.walkabout(html_translator)
html_translated = ''.join(html_translator.fragment).strip() html_translated = ''.join(html_translator.fragment).strip()
@ -237,6 +239,32 @@ def get_verifier(verify, verify_re):
'<p><kbd class="kbd docutils literal notranslate">space</kbd></p>', '<p><kbd class="kbd docutils literal notranslate">space</kbd></p>',
'\\sphinxkeyboard{\\sphinxupquote{space}}', '\\sphinxkeyboard{\\sphinxupquote{space}}',
), ),
(
# kbd role
'verify',
':kbd:`Control+X`',
('<p><kbd class="kbd docutils literal notranslate">'
'<kbd class="kbd docutils literal notranslate">Control</kbd>'
'+'
'<kbd class="kbd docutils literal notranslate">X</kbd>'
'</kbd></p>'),
'\\sphinxkeyboard{\\sphinxupquote{Control+X}}',
),
(
# kbd role
'verify',
':kbd:`M-x M-s`',
('<p><kbd class="kbd docutils literal notranslate">'
'<kbd class="kbd docutils literal notranslate">M</kbd>'
'-'
'<kbd class="kbd docutils literal notranslate">x</kbd>'
' '
'<kbd class="kbd docutils literal notranslate">M</kbd>'
'-'
'<kbd class="kbd docutils literal notranslate">s</kbd>'
'</kbd></p>'),
'\\sphinxkeyboard{\\sphinxupquote{M\\sphinxhyphen{}x M\\sphinxhyphen{}s}}',
),
( (
# non-interpolation of dashes in option role # non-interpolation of dashes in option role
'verify_re', 'verify_re',