diff --git a/CHANGES.rst b/CHANGES.rst index 64f94e14ec3..e1cc14bbe55 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -66,6 +66,8 @@ Features added Patch by Adam Turner. * #13805: LaTeX: add support for ``fontawesome7`` package. Patch by Jean-François B. +* #13876: Group nodes generated by :kbd: role and add class to separators + Patch by Brecht Machiels. Bugs fixed ---------- diff --git a/sphinx/roles.py b/sphinx/roles.py index cadfb5a027b..dc5c3b599b9 100644 --- a/sphinx/roles.py +++ b/sphinx/roles.py @@ -491,27 +491,24 @@ def run(self) -> tuple[list[Node], list[system_message]]: if 'classes' in self.options: classes.extend(self.options['classes']) + compound = nodes.inline(self.rawtext, classes=['kbdcompound']) parts = self._pattern.split(self.text) - if len(parts) == 1 or self._is_multi_word_key(parts): - return [nodes.literal(self.rawtext, self.text, classes=classes)], [] - - compound: list[Node] = [] while parts: if self._is_multi_word_key(parts): key = ''.join(parts[:3]) parts[:3] = [] else: key = parts.pop(0) - compound.append(nodes.literal(key, key, classes=classes)) + compound += nodes.literal(key, key, classes=['kbd']) try: sep = parts.pop(0) # key separator ('-', '+', '^', etc) except IndexError: break else: - compound.append(nodes.Text(sep)) + compound += nodes.inline(sep, sep, classes=['kbdsep']) - return compound, [] + return [compound], [] @staticmethod def _is_multi_word_key(parts: list[str]) -> bool: diff --git a/tests/test_builders/test_build_html_5_output.py b/tests/test_builders/test_build_html_5_output.py index db9dd8a749c..50d3ff297d9 100644 --- a/tests/test_builders/test_build_html_5_output.py +++ b/tests/test_builders/test_build_html_5_output.py @@ -127,7 +127,7 @@ def checker(nodes: Iterable[Element]) -> Literal[True]: ('markup.html', './/li/p/strong', r'^command\\n$'), ('markup.html', './/li/p/strong', r'^program\\n$'), ('markup.html', './/li/p/em', r'^dfn\\n$'), - ('markup.html', './/li/p/kbd', r'^kbd\\n$'), + ('markup.html', './/li/p/span/kbd', r'^kbd\\n$'), ('markup.html', './/li/p/span', 'File \N{TRIANGULAR BULLET} Close'), ('markup.html', ".//li/p/code/span[@class='pre']", '^a/$'), ('markup.html', ".//li/p/code/em/span[@class='pre']", '^varpart$'), diff --git a/tests/test_markup/test_markup.py b/tests/test_markup/test_markup.py index fb4df4c400b..03b0e12b5dd 100644 --- a/tests/test_markup/test_markup.py +++ b/tests/test_markup/test_markup.py @@ -332,8 +332,19 @@ def get_verifier(verify, verify_re): # kbd role 'verify', ':kbd:`space`', - '
space
', - '\\sphinxAtStartPar\n\\sphinxkeyboard{\\sphinxupquote{space}}', + ( + '' + '' + 'space' + '' + '
' + ), + ( + '\\sphinxAtStartPar\n' + '\\DUrole{kbdcompound}{' + '\\sphinxkeyboard{\\sphinxupquote{space}}' + '}' + ), ), ( # kbd role @@ -341,16 +352,20 @@ def get_verifier(verify, verify_re): ':kbd:`Control+X`', ( '' + '' 'Control' - '+' + '+' 'X' + '' '
' ), ( '\\sphinxAtStartPar\n' + '\\DUrole{kbdcompound}{' '\\sphinxkeyboard{\\sphinxupquote{Control}}' - '+' + '\\DUrole{kbdsep}{+}' '\\sphinxkeyboard{\\sphinxupquote{X}}' + '}' ), ), ( @@ -359,16 +374,20 @@ def get_verifier(verify, verify_re): ':kbd:`Alt+^`', ( '' + '' 'Alt' - '+' + '+' '^' + '' '
' ), ( '\\sphinxAtStartPar\n' + '\\DUrole{kbdcompound}{' '\\sphinxkeyboard{\\sphinxupquote{Alt}}' - '+' + '\\DUrole{kbdsep}{+}' '\\sphinxkeyboard{\\sphinxupquote{\\textasciicircum{}}}' + '}' ), ), ( @@ -377,46 +396,83 @@ def get_verifier(verify, verify_re): ':kbd:`M-x M-s`', ( '' + '' 'M' - '-' + '-' 'x' - ' ' + ' ' 'M' - '-' + '-' 's' + '' '
' ), ( '\\sphinxAtStartPar\n' + '\\DUrole{kbdcompound}{' '\\sphinxkeyboard{\\sphinxupquote{M}}' - '\\sphinxhyphen{}' + '\\DUrole{kbdsep}{\\sphinxhyphen{}}' '\\sphinxkeyboard{\\sphinxupquote{x}}' - ' ' + '\\DUrole{kbdsep}{ }' '\\sphinxkeyboard{\\sphinxupquote{M}}' - '\\sphinxhyphen{}' + '\\DUrole{kbdsep}{\\sphinxhyphen{}}' '\\sphinxkeyboard{\\sphinxupquote{s}}' + '}' ), ), ( # kbd role 'verify', ':kbd:`-`', - '-
', - '\\sphinxAtStartPar\n\\sphinxkeyboard{\\sphinxupquote{\\sphinxhyphen{}}}', + ( + '' + '' + '-' + '' + '
' + ), + ( + '\\sphinxAtStartPar\n' + '\\DUrole{kbdcompound}{' + '\\sphinxkeyboard{\\sphinxupquote{\\sphinxhyphen{}}}' + '}' + ), ), ( # kbd role 'verify', ':kbd:`Caps Lock`', - 'Caps Lock
', - '\\sphinxAtStartPar\n\\sphinxkeyboard{\\sphinxupquote{Caps Lock}}', + ( + '' + '' + 'Caps Lock' + '' + '
' + ), + ( + '\\sphinxAtStartPar\n' + '\\DUrole{kbdcompound}{' + '\\sphinxkeyboard{\\sphinxupquote{Caps Lock}}' + '}' + ), ), ( # kbd role 'verify', ':kbd:`sys rq`', - 'sys rq
', - '\\sphinxAtStartPar\n\\sphinxkeyboard{\\sphinxupquote{sys rq}}', + ( + '' + '' + 'sys rq' + '' + '
' + ), + ( + '\\sphinxAtStartPar\n' + '\\DUrole{kbdcompound}{' + '\\sphinxkeyboard{\\sphinxupquote{sys rq}}' + '}' + ), ), ( # kbd role @@ -424,20 +480,24 @@ def get_verifier(verify, verify_re): ':kbd:`⌘+⇧+M`', ( '' + '' '⌘' - '+' + '+' '⇧' - '+' + '+' 'M' + '' '
' ), ( '\\sphinxAtStartPar\n' + '\\DUrole{kbdcompound}{' '\\sphinxkeyboard{\\sphinxupquote{⌘}}' - '+' + '\\DUrole{kbdsep}{+}' '\\sphinxkeyboard{\\sphinxupquote{⇧}}' - '+' + '\\DUrole{kbdsep}{+}' '\\sphinxkeyboard{\\sphinxupquote{M}}' + '}' ), ), (