diff --git a/AUTHORS.rst b/AUTHORS.rst
index 43a8da3469d..dc1f87b6529 100644
--- a/AUTHORS.rst
+++ b/AUTHORS.rst
@@ -58,6 +58,7 @@ Contributors
* Filip Vavera -- napoleon todo directive
* Glenn Matthews -- python domain signature improvements
* Gregory Szorc -- performance improvements
+* Héctor Medina Abarca -- per-code-block highlighting style overrides
* Henrique Bastos -- SVG support for graphviz extension
* Hernan Grecco -- search improvements
* Hong Xu -- svg support in imgmath extension and various bug fixes
diff --git a/CHANGES.rst b/CHANGES.rst
index 476b5da0178..f866e3b27df 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -54,6 +54,11 @@ Features added
Patch by Adam Turner.
* #13647: LaTeX: allow more cases of table nesting.
Patch by Jean-François B.
+* #13611: Allow `Pygments style `_ overriding on a
+ per-block basis via new options (:rst:dir:`code-block:style-light` and
+ :rst:dir:`code-block:style-dark`) for the :rst:dir:`code-block`,
+ :rst:dir:`sourcecode`, :rst:dir:`literalinclude` and :rst:dir:`code`.
+ Patch by Héctor Medina Abarca.
Bugs fixed
----------
diff --git a/doc/usage/restructuredtext/directives.rst b/doc/usage/restructuredtext/directives.rst
index 5845a6ab717..de5da6659a8 100644
--- a/doc/usage/restructuredtext/directives.rst
+++ b/doc/usage/restructuredtext/directives.rst
@@ -728,13 +728,15 @@ values are supported:
* ... and any other `lexer alias that Pygments supports`__
If highlighting with the selected language fails (i.e. Pygments emits an
-"Error" token), the block is not highlighted in any way.
+"Error" token), the block is not highlighted in any way. Per-block highlighting
+styles can be specified for directives :rst:dir:`code-block`,
+:rst:dir:`sourcecode`, :rst:dir:`literalinclude`, and :rst:dir:`code`.
.. important::
- The list of lexer aliases supported is tied to the Pygment version. If you
- want to ensure consistent highlighting, you should fix your version of
- Pygments.
+ The list of lexer and style aliases supported is tied to the Pygment
+ version. If you want to ensure consistent highlighting, you should fix your
+ version of Pygments.
__ https://pygments.org/docs/lexers
@@ -903,6 +905,51 @@ __ https://pygments.org/docs/lexers
.. versionchanged:: 3.5
Support automatic dedent.
+ .. rst:directive:option:: style-light: style name
+ style-dark: style name
+ :type: the name of a style to use
+
+ Pygments includes `various highlighting styles
+ `_, and supports `custom ones
+ `_ installed as
+ plugins. This option accepts any valid style name and will apply it to
+ this code block, overriding any default in :confval:`pygments_style`
+ config value. Some builder and theme configurations (e.g.
+ :ref:`HTML ` & `Python Docs Theme `_) will
+ accept both `light` and `dark` options, and switch appropriately; others
+ may support only one style (e.g. PDF), in which case `style-light` takes
+ precedence. For example::
+
+ .. code-block:: python
+
+ print('Code with default styling')
+
+
+ Renders as:
+
+ .. code-block:: python
+
+ print('Code with default styling')
+
+
+ While this code::
+
+ .. code-block:: python
+ :style-light: tango
+
+ print('Code with a style override')
+
+
+ Renders as:
+
+ .. code-block:: python
+ :style-light: tango
+
+ print('Code with a style override')
+
+ .. versionadded:: 8.3
+
+
.. rst:directive:: .. literalinclude:: filename
Longer displays of verbatim text may be included by storing the example text
diff --git a/sphinx/builders/html/__init__.py b/sphinx/builders/html/__init__.py
index e72dffc2b33..e4473a9c533 100644
--- a/sphinx/builders/html/__init__.py
+++ b/sphinx/builders/html/__init__.py
@@ -66,7 +66,7 @@
if TYPE_CHECKING:
from collections.abc import Iterator, Set
- from typing import Any, TypeAlias
+ from typing import Any, TypeAlias, TypedDict
from docutils.nodes import Node
from docutils.readers import Reader
@@ -262,6 +262,19 @@ def init_highlighter(self) -> None:
else:
self.dark_highlighter = None
+ # Maps a code block's identifier to requested light and dark styles.
+ # This is populated by the writer / translator as it invokes
+ # the visit_literal_block method.
+ # The information is also used in the selectors of the CSS file(s).
+ if TYPE_CHECKING:
+
+ class spec_highlighter(TypedDict):
+ bridge: PygmentsBridge
+ ids: list[int]
+
+ self.specialized_dark_lighters: dict[str, spec_highlighter] = {}
+ self.specialized_light_lighters: dict[str, spec_highlighter] = {}
+
@property
def css_files(self) -> list[_CascadingStyleSheet]:
_deprecation_warning(
@@ -691,6 +704,7 @@ def write_doc_serialized(self, docname: str, doctree: nodes.document) -> None:
self.index_page(docname, doctree, title)
def finish(self) -> None:
+ self.finish_tasks.add_task(self.create_pygments_style_file)
self.finish_tasks.add_task(self.gen_indices)
self.finish_tasks.add_task(self.gen_pages_from_extensions)
self.finish_tasks.add_task(self.gen_additional_pages)
@@ -827,16 +841,68 @@ def to_relpath(f: str) -> str:
err,
)
+ def update_override_styles_dark(self, style: str, id: int) -> PygmentsBridge:
+ """Update the tracker of highlighting styles with a possibly new dark-mode style;
+ return the PygmentsBridge object associated with said style.
+ """
+ if style in self.specialized_dark_lighters:
+ self.specialized_dark_lighters[style]['ids'].append(id)
+ else:
+ pb = PygmentsBridge(dest='html', stylename=style)
+ self.specialized_dark_lighters[style] = {'bridge': pb, 'ids': [id]}
+ return self.specialized_dark_lighters[style]['bridge']
+
+ def update_override_styles_light(self, style: str, id: int) -> PygmentsBridge:
+ """Update the tracker of highlighting styles with a possibly new light-mode style;
+ return the PygmentsBridge object associated with said style.
+ """
+ if style in self.specialized_light_lighters:
+ self.specialized_light_lighters[style]['ids'].append(id)
+ else:
+ pb = PygmentsBridge(dest='html', stylename=style)
+ self.specialized_light_lighters[style] = {'bridge': pb, 'ids': [id]}
+ return self.specialized_light_lighters[style]['bridge']
+
def create_pygments_style_file(self) -> None:
- """Create a style file for pygments."""
+ """Create style file(s) for Pygments."""
pyg_path = self._static_dir / 'pygments.css'
- with open(pyg_path, 'w', encoding='utf-8') as f:
- f.write(self.highlighter.get_stylesheet())
+ light_style = self.highlighter.formatter_args.get('style')
+ if light_style is None:
+ logger.warning(__('Default highlighter has no set style'))
+ else:
+ with open(pyg_path, 'w', encoding='utf-8') as f:
+ light_style_name = light_style.name
+ light_style_sheet = '/* CSS for style: {} */\n'.format(light_style_name)
+ light_style_sheet += self.highlighter.get_stylesheet()
+ if self.specialized_light_lighters:
+ for s_name, item in self.specialized_light_lighters.items():
+ light_style_sheet += '\n\n/* CSS for style: {} */\n'.format(
+ s_name
+ )
+ light_style_sheet += item['bridge'].get_stylesheet(item['ids'])
+ f.write(light_style_sheet)
if self.dark_highlighter:
- dark_path = self._static_dir / 'pygments_dark.css'
- with open(dark_path, 'w', encoding='utf-8') as f:
- f.write(self.dark_highlighter.get_stylesheet())
+ dark_style = self.dark_highlighter.formatter_args.get('style')
+ if dark_style is None:
+ logger.warning(__('Default dark highlighter has no set style'))
+ else:
+ dark_path = self._static_dir / 'pygments_dark.css'
+ with open(dark_path, 'w', encoding='utf-8') as f:
+ dark_style_name = dark_style.name
+ dark_style_sheet = '/* CSS for style: {} */\n'.format(
+ dark_style_name
+ )
+ dark_style_sheet += self.dark_highlighter.get_stylesheet()
+ if self.specialized_dark_lighters:
+ for s_name, item in self.specialized_dark_lighters.items():
+ dark_style_sheet += '\n\n/* CSS for style: {} */\n'.format(
+ s_name
+ )
+ dark_style_sheet += item['bridge'].get_stylesheet(
+ item['ids']
+ )
+ f.write(dark_style_sheet)
def copy_translation_js(self) -> None:
"""Copy a JavaScript file for translations."""
@@ -930,7 +996,6 @@ def copy_static_files(self) -> None:
if self.indexer is not None:
context.update(self.indexer.context_for_searchtool())
- self.create_pygments_style_file()
self.copy_translation_js()
self.copy_stemmer_js()
self.copy_theme_static_files(context)
diff --git a/sphinx/builders/latex/__init__.py b/sphinx/builders/latex/__init__.py
index feaa8e021cb..3af185304ec 100644
--- a/sphinx/builders/latex/__init__.py
+++ b/sphinx/builders/latex/__init__.py
@@ -130,6 +130,7 @@ def init(self) -> None:
self.docnames: Iterable[str] = {}
self.document_data: list[tuple[str, str, str, str, str, bool]] = []
self.themes = ThemeFactory(srcdir=self.srcdir, config=self.config)
+ self.specialized_highlighters: dict[str, highlighting.PygmentsBridge] = {}
texescape.init()
self.init_context()
@@ -272,6 +273,17 @@ def init_multilingual(self) -> None:
self.context['multilingual'] = f'{self.context["polyglossia"]}\n{language}'
+ def update_override_styles(self, style: str) -> highlighting.PygmentsBridge:
+ """Update the tracker of highlighting styles with a possibly new style;
+ return the PygmentsBridge object associated with said style.
+ """
+ if style in self.specialized_highlighters:
+ return self.specialized_highlighters[style]
+ else:
+ pb = highlighting.PygmentsBridge(dest='latex', stylename=style)
+ self.specialized_highlighters[style] = pb
+ return pb
+
def write_stylesheet(self) -> None:
highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
stylesheet = self.outdir / 'sphinxhighlight.sty'
@@ -279,16 +291,23 @@ def write_stylesheet(self) -> None:
f.write('\\NeedsTeXFormat{LaTeX2e}[1995/12/01]\n')
f.write(
'\\ProvidesPackage{sphinxhighlight}'
- '[2022/06/30 stylesheet for highlighting with pygments]\n'
+ '[2025/06/15 stylesheet for highlighting with pygments]\n'
)
f.write(
- '% Its contents depend on pygments_style configuration variable.\n\n'
+ '% Its contents depend on pygments_style configuration variable.\n'
+ '% And also on encountered code-blocks :style-light: options.\n\n'
)
f.write(highlighter.get_stylesheet())
+ if self.specialized_highlighters:
+ specialized_styles = []
+ for style_name, pyg_bridge in self.specialized_highlighters.items():
+ specialized_style = '\n% Stylesheet for style {}'.format(style_name)
+ specialized_style += pyg_bridge.get_stylesheet(style_name)
+ specialized_styles.append(specialized_style)
+ f.write('\n'.join(specialized_styles))
def prepare_writing(self, docnames: Set[str]) -> None:
self.init_document_data()
- self.write_stylesheet()
def copy_assets(self) -> None:
self.copy_support_files()
@@ -413,6 +432,7 @@ def assemble_doctree(
return largetree
def finish(self) -> None:
+ self.write_stylesheet()
self.copy_image_files()
self.write_message_catalog()
diff --git a/sphinx/builders/singlehtml.py b/sphinx/builders/singlehtml.py
index 1888f6679d1..46b86b92010 100644
--- a/sphinx/builders/singlehtml.py
+++ b/sphinx/builders/singlehtml.py
@@ -182,6 +182,7 @@ def finish(self) -> None:
self.copy_image_files()
self.copy_download_files()
self.copy_static_files()
+ self.create_pygments_style_file()
self.copy_extra_files()
self.write_buildinfo()
self.dump_inventory()
diff --git a/sphinx/directives/code.py b/sphinx/directives/code.py
index e94b18a18f0..cd99d3877df 100644
--- a/sphinx/directives/code.py
+++ b/sphinx/directives/code.py
@@ -114,6 +114,8 @@ class CodeBlock(SphinxDirective):
'caption': directives.unchanged_required,
'class': directives.class_option,
'name': directives.unchanged,
+ 'style-light': directives.unchanged,
+ 'style-dark': directives.unchanged,
}
def run(self) -> list[Node]:
@@ -162,6 +164,8 @@ def run(self) -> list[Node]:
self.env.current_document.highlight_language
or self.config.highlight_language
)
+ literal['style-light'] = self.options.get('style-light')
+ literal['style-dark'] = self.options.get('style-dark')
extra_args = literal['highlight_args'] = {}
if hl_lines is not None:
extra_args['hl_lines'] = hl_lines
@@ -425,6 +429,8 @@ class LiteralInclude(SphinxDirective):
'lineno-match': directives.flag,
'tab-width': int,
'language': directives.unchanged_required,
+ 'style-light': directives.unchanged,
+ 'style-dark': directives.unchanged,
'force': directives.flag,
'encoding': directives.encoding,
'pyobject': directives.unchanged_required,
@@ -468,6 +474,8 @@ def run(self) -> list[Node]:
retnode['language'] = 'udiff'
elif 'language' in self.options:
retnode['language'] = self.options['language']
+ retnode['style-light'] = self.options.get('style-light')
+ retnode['style-dark'] = self.options.get('style-dark')
if (
'linenos' in self.options
or 'lineno-start' in self.options
diff --git a/sphinx/directives/patches.py b/sphinx/directives/patches.py
index 0a7419ed563..4a840ec782b 100644
--- a/sphinx/directives/patches.py
+++ b/sphinx/directives/patches.py
@@ -93,6 +93,8 @@ class Code(SphinxDirective):
'class': directives.class_option,
'force': directives.flag,
'name': directives.unchanged,
+ 'style-light': directives.unchanged,
+ 'style-dark': directives.unchanged,
'number-lines': optional_int,
}
has_content = True
@@ -124,6 +126,9 @@ def run(self) -> list[Node]:
or self.config.highlight_language
)
+ node['style-light'] = self.options.get('style-light')
+ node['style-dark'] = self.options.get('style-dark')
+
if 'number-lines' in self.options:
node['linenos'] = True
diff --git a/sphinx/highlighting.py b/sphinx/highlighting.py
index 29cf9d26e8c..2d39b678cc2 100644
--- a/sphinx/highlighting.py
+++ b/sphinx/highlighting.py
@@ -2,7 +2,9 @@
from __future__ import annotations
+import re
from functools import partial
+from hashlib import md5
from importlib import import_module
from typing import TYPE_CHECKING
@@ -20,6 +22,7 @@
guess_lexer,
)
from pygments.styles import get_style_by_name
+from pygments.token import Token
from pygments.util import ClassNotFound
from sphinx.locale import __
@@ -90,7 +93,9 @@
\def\PYGZti{\text\textasciitilde}
\makeatletter
% use \protected to allow syntax highlighting in captions
-\protected\def\PYG#1#2{\PYG@reset\PYG@toks#1+\relax+{\PYG@do{#2}}}
+\def\PYG@#1#2{{\PYG@reset\PYG@toks#1+\relax+{{\PYG@do{{#2}}}}}}
+\protected\def\PYG{\csname PYG\ifdefined\sphinxpygmentsstylename
+ \sphinxpygmentsstylename\else @\fi\endcsname}
\makeatother
"""
@@ -229,9 +234,95 @@ def highlight_block(
# MEMO: this is done to escape Unicode chars with non-Unicode engines
return texescape.hlescape(hlsource, self.latex_engine)
- def get_stylesheet(self) -> str:
+ def get_stylesheet(self, selectors: list[int] | str | None = None) -> str:
+ """Return a string with the specification for the tokens yielded by the language
+ lexer, appropriate for the output formatter, using the style defined at
+ initialization. In an HTML context, `selectors` is a list of CSS class selectors. In a
+ LaTeX context, it modifies the command prefix used for macro definitions; see also
+ LaTeXBuilder.add_block_style()
+ """
formatter = self.get_formatter()
- if self.dest == 'html':
- return formatter.get_style_defs('.highlight')
+ if isinstance(formatter, HtmlFormatter):
+ if selectors:
+ return formatter.get_style_defs(['.c{}'.format(s) for s in selectors]) # type: ignore [no-untyped-call]
+ else:
+ return formatter.get_style_defs('.highlight') # type: ignore [no-untyped-call]
else:
- return formatter.get_style_defs() + _LATEX_ADD_STYLES
+ if selectors:
+ if not isinstance(selectors, str):
+ logger.error(
+ __(
+ 'Encountered %s in selectors field; expected a string '
+ 'for the LaTeX formatter. Please report this error.'
+ ),
+ type(selectors),
+ type='misc',
+ subtype='highlighting_failure',
+ )
+ # not using '' as we don't want \PYG being overwritten.
+ _tex_name = 'INVALID'
+ selectors = 'default' # TODO: make more informed choice?
+ _tex_name = md5(selectors.encode()).hexdigest()[:6] # noqa: S324
+ for d, l in [
+ ('0', 'G'),
+ ('1', 'H'),
+ ('2', 'I'),
+ ('3', 'J'),
+ ('4', 'K'),
+ ('5', 'L'),
+ ('6', 'M'),
+ ('7', 'N'),
+ ('8', 'O'),
+ ('9', 'P'),
+ ]:
+ _tex_name = _tex_name.replace(d, l)
+ stylesheet = self.formatter(
+ style=selectors, commandprefix='PYG' + _tex_name
+ ).get_style_defs()
+ sphinx_redefs = ''
+ bc = self.get_style(selectors).background_color
+ if bc is not None:
+ bc = bc.lstrip('#').lower()
+ # The xcolor LaTeX package requires 6 hexadecimal digits
+ if len(bc) == 3:
+ bc = bc[0] * 2 + bc[1] * 2 + bc[2] * 2
+ # We intercept a purely white background, so that PDF will use Sphinx
+ # light gray default, rather, or the user VerbatimColor global choice.
+ # TODO: argue pros and cons.
+ if bc != 'ffffff':
+ sphinx_redefs = (
+ '% background color for above style, "HTML" syntax\n'
+ f'\\def\\sphinxPYG{_tex_name}bc{{{bc}}}\n'
+ )
+ # TODO: THIS MAY NOT BE THE RIGHT THING TO DO.
+ # TODO: REMOVE NEXT COMMENTS.
+ # I wanted to try with
+ # solarized-light which will use #657b83 but my sample code-block
+ # has no token not using a color so I could not confirm it does work.
+ # (indeed solarized-light uses \textcolor everywhere in its stylesheet,
+ # so I modified manually LaTeX output to confirm the whole thing
+ # actually worked as expected).
+ # I have not for lack of time searched for a pygments style defining
+ # such a color and not using \textcolor everywhere.
+ # The idea is to avoid invisible text on dark background which I believe
+ # I have experienced in the past when using dark background via injection
+ # of \sphinxsetup using raw:: latex directive.
+ base_style = self.get_style(selectors).styles[Token]
+ if base_style: # could look like 'italic #000 bg:#ffffff'
+ match = re.match(
+ r'#([0-9a-fA-F]{3,6})(?:\s+bg:#([0-9a-fA-F]{3,6}))?', base_style
+ )
+ if match is not None:
+ tc = match.group(1)
+ if len(tc) == 3:
+ tc = tc[0] * 2 + tc[1] * 2 + tc[2] * 2
+ sphinx_redefs += (
+ '% text default color for above style, "HTML" syntax\n'
+ f'\\def\\sphinxPYG{_tex_name}tc{{{tc}}}\n'
+ )
+ # TODO: what should we do for the color used to emphasize lines?
+ # It is VerbatimHightlightColor.
+ else:
+ stylesheet = formatter.get_style_defs()
+ sphinx_redefs = _LATEX_ADD_STYLES
+ return stylesheet + sphinx_redefs
diff --git a/sphinx/writers/html5.py b/sphinx/writers/html5.py
index 39d7ecea680..0f23af5b006 100644
--- a/sphinx/writers/html5.py
+++ b/sphinx/writers/html5.py
@@ -600,14 +600,43 @@ def visit_literal_block(self, node: nodes.literal_block) -> None:
if linenos and self.config.html_codeblock_linenos_style:
linenos = self.config.html_codeblock_linenos_style
- highlighted = self.highlighter.highlight_block(
- node.rawsource,
- lang,
- opts=opts,
- linenos=linenos,
- location=node,
- **highlight_args,
- )
+ # As blocks are processed, we discover specified styles.
+ # If either dark or style were requested, use their specialized
+ # highlighter. If neither, use the default highlighter.
+ block_id = hash(node)
+ dark_style = node.get('style-dark', None)
+ light_style = node.get('style-light', None)
+ if dark_style:
+ pb = self.builder.update_override_styles_dark(dark_style, block_id)
+ highlighted = pb.highlight_block(
+ node.rawsource,
+ lang,
+ opts=opts,
+ linenos=linenos,
+ location=node,
+ cssclass='highlight c{}'.format(block_id),
+ **highlight_args,
+ )
+ if light_style:
+ pb = self.builder.update_override_styles_light(light_style, block_id)
+ highlighted = pb.highlight_block(
+ node.rawsource,
+ lang,
+ opts=opts,
+ linenos=linenos,
+ location=node,
+ cssclass='highlight c{}'.format(block_id),
+ **highlight_args,
+ )
+ if not (dark_style or light_style):
+ highlighted = self.highlighter.highlight_block(
+ node.rawsource,
+ lang,
+ opts=opts,
+ linenos=linenos,
+ location=node,
+ **highlight_args,
+ )
starttag = self.starttag(
node, 'div', suffix='', CLASS='highlight-%s notranslate' % lang
)
diff --git a/sphinx/writers/latex.py b/sphinx/writers/latex.py
index 39aef55ddfe..5bf521faa0d 100644
--- a/sphinx/writers/latex.py
+++ b/sphinx/writers/latex.py
@@ -8,6 +8,7 @@
import re
from collections import defaultdict
+from hashlib import md5
from pathlib import Path
from typing import TYPE_CHECKING, cast
@@ -2257,14 +2258,57 @@ def visit_literal_block(self, node: Element) -> None:
highlight_args['force'] = node.get('force', False)
opts = self.config.highlight_options.get(lang, {})
- hlcode = self.highlighter.highlight_block(
- node.rawsource,
- lang,
- opts=opts,
- linenos=linenos,
- location=node,
- **highlight_args,
- )
+ # As blocks are processed, we discover specified styles.
+ _texstylename = ''
+ if node.get('style-light'):
+ code_style = node.get('style-light')
+ pb = self.builder.update_override_styles(style=code_style)
+ hlcode = pb.highlight_block(
+ node.rawsource,
+ lang,
+ opts=opts,
+ linenos=linenos,
+ location=node,
+ **highlight_args,
+ )
+ _texstylename = md5(code_style.encode()).hexdigest()[:6] # noqa: S324
+ for d, l in [
+ ('0', 'G'),
+ ('1', 'H'),
+ ('2', 'I'),
+ ('3', 'J'),
+ ('4', 'K'),
+ ('5', 'L'),
+ ('6', 'M'),
+ ('7', 'N'),
+ ('8', 'O'),
+ ('9', 'P'),
+ ]:
+ _texstylename = _texstylename.replace(d, l)
+ else:
+ hlcode = self.highlighter.highlight_block(
+ node.rawsource,
+ lang,
+ opts=opts,
+ linenos=linenos,
+ location=node,
+ **highlight_args,
+ )
+ if _texstylename:
+ # There is no a priori "VerbatimTextColor" set, except is user employed
+ # the sphinxsetup with pre_TeXcolor. We could query the TeX boolean
+ # ifspx@opt@pre@withtextcolor but the @ letter is annoying here. So
+ # let's simply add a group level and not worry about testing if this
+ # or other things pre-exist so we don't have to reset.
+ self.body.append(
+ f'{CR}\\begingroup\\def\\sphinxpygmentsstylename{{{_texstylename}}}%'
+ f'{CR}\\ifdefined\\sphinxPYG{_texstylename}bc'
+ f'{CR} \\sphinxsetup{{VerbatimColor={{HTML}}'
+ f'{{\\sphinxPYG{_texstylename}bc}}}}%{CR}\\fi'
+ f'{CR}\\ifdefined\\sphinxPYG{_texstylename}tc'
+ f'{CR} \\sphinxsetup{{pre_TeXcolor={{HTML}}'
+ f'{{\\sphinxPYG{_texstylename}tc}}}}%{CR}\\fi'
+ )
if self.in_footnote:
self.body.append(CR + r'\sphinxSetupCodeBlockInFootnote')
hlcode = hlcode.replace(r'\begin{Verbatim}', r'\begin{sphinxVerbatim}')
@@ -2291,6 +2335,8 @@ def visit_literal_block(self, node: Element) -> None:
self.body.append(CR + hlcode + CR)
if hllines:
self.body.append(r'\sphinxresetverbatimhllines' + CR)
+ if _texstylename:
+ self.body.append(r'\endgroup' + CR)
raise nodes.SkipNode
def depart_literal_block(self, node: Element) -> None: