mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Fix #6738: latex: literal_block does not support raw unicode characters
This commit is contained in:
parent
ef09ea23fe
commit
660e746cf8
@ -28,7 +28,7 @@ from sphinx.ext import doctest
|
|||||||
from sphinx.locale import __
|
from sphinx.locale import __
|
||||||
from sphinx.pygments_styles import SphinxStyle, NoneStyle
|
from sphinx.pygments_styles import SphinxStyle, NoneStyle
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.texescape import tex_hl_escape_map_new
|
from sphinx.util.texescape import get_hlescape_func, tex_hl_escape_map_new
|
||||||
|
|
||||||
if False:
|
if False:
|
||||||
# For type annotation
|
# For type annotation
|
||||||
@ -68,9 +68,11 @@ class PygmentsBridge:
|
|||||||
html_formatter = HtmlFormatter
|
html_formatter = HtmlFormatter
|
||||||
latex_formatter = LatexFormatter
|
latex_formatter = LatexFormatter
|
||||||
|
|
||||||
def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=None):
|
def __init__(self, dest='html', stylename='sphinx', trim_doctest_flags=None,
|
||||||
# type: (str, str, bool) -> None
|
latex_engine=None):
|
||||||
|
# type: (str, str, bool, str) -> None
|
||||||
self.dest = dest
|
self.dest = dest
|
||||||
|
self.latex_engine = latex_engine
|
||||||
|
|
||||||
style = self.get_style(stylename)
|
style = self.get_style(stylename)
|
||||||
self.formatter_args = {'style': style} # type: Dict[str, Any]
|
self.formatter_args = {'style': style} # type: Dict[str, Any]
|
||||||
@ -192,7 +194,8 @@ class PygmentsBridge:
|
|||||||
if self.dest == 'html':
|
if self.dest == 'html':
|
||||||
return hlsource
|
return hlsource
|
||||||
else:
|
else:
|
||||||
return hlsource.translate(tex_hl_escape_map_new)
|
escape = get_hlescape_func(self.latex_engine)
|
||||||
|
return escape(hlsource)
|
||||||
|
|
||||||
def get_stylesheet(self):
|
def get_stylesheet(self):
|
||||||
# type: () -> str
|
# type: () -> str
|
||||||
|
@ -32,7 +32,6 @@ tex_replacements = [
|
|||||||
('¶', r'\P{}'),
|
('¶', r'\P{}'),
|
||||||
('§', r'\S{}'),
|
('§', r'\S{}'),
|
||||||
('€', r'\texteuro{}'),
|
('€', r'\texteuro{}'),
|
||||||
('∞', r'\(\infty\)'),
|
|
||||||
('±', r'\(\pm\)'),
|
('±', r'\(\pm\)'),
|
||||||
('→', r'\(\rightarrow\)'),
|
('→', r'\(\rightarrow\)'),
|
||||||
('‣', r'\(\rightarrow\)'),
|
('‣', r'\(\rightarrow\)'),
|
||||||
@ -53,6 +52,8 @@ tex_replacements = [
|
|||||||
# A map Unicode characters to LaTeX representation
|
# A map Unicode characters to LaTeX representation
|
||||||
# (for LaTeX engines which don't support unicode)
|
# (for LaTeX engines which don't support unicode)
|
||||||
unicode_tex_replacements = [
|
unicode_tex_replacements = [
|
||||||
|
# map special Unicode characters to TeX commands
|
||||||
|
('∞', r'\(\infty\)'),
|
||||||
# superscript
|
# superscript
|
||||||
('⁰', r'\(\sp{\text{0}}\)'),
|
('⁰', r'\(\sp{\text{0}}\)'),
|
||||||
('¹', r'\(\sp{\text{1}}\)'),
|
('¹', r'\(\sp{\text{1}}\)'),
|
||||||
@ -80,7 +81,8 @@ unicode_tex_replacements = [
|
|||||||
tex_escape_map = {} # type: Dict[int, str]
|
tex_escape_map = {} # type: Dict[int, str]
|
||||||
tex_escape_map_without_unicode = {} # type: Dict[int, str]
|
tex_escape_map_without_unicode = {} # type: Dict[int, str]
|
||||||
tex_replace_map = {}
|
tex_replace_map = {}
|
||||||
tex_hl_escape_map_new = {}
|
tex_hl_escape_map_new = {} # type: Dict[int, str]
|
||||||
|
tex_hl_escape_map_new_without_unicode = {} # type: Dict[int, str]
|
||||||
|
|
||||||
|
|
||||||
def get_escape_func(latex_engine: str) -> Callable[[str], str]:
|
def get_escape_func(latex_engine: str) -> Callable[[str], str]:
|
||||||
@ -101,6 +103,24 @@ def escape_for_unicode_latex_engine(s: str) -> str:
|
|||||||
return s.translate(tex_escape_map_without_unicode)
|
return s.translate(tex_escape_map_without_unicode)
|
||||||
|
|
||||||
|
|
||||||
|
def get_hlescape_func(latex_engine: str) -> Callable[[str], str]:
|
||||||
|
"""Get hlescape() function for given latex_engine."""
|
||||||
|
if latex_engine in ('lualatex', 'xelatex'):
|
||||||
|
return hlescape_for_unicode_latex_engine
|
||||||
|
else:
|
||||||
|
return hlescape
|
||||||
|
|
||||||
|
|
||||||
|
def hlescape(s: str) -> str:
|
||||||
|
"""Escape text for LaTeX highlighter."""
|
||||||
|
return s.translate(tex_hl_escape_map_new)
|
||||||
|
|
||||||
|
|
||||||
|
def hlescape_for_unicode_latex_engine(s: str) -> str:
|
||||||
|
"""Escape text for unicode supporting LaTeX engine."""
|
||||||
|
return s.translate(tex_hl_escape_map_new_without_unicode)
|
||||||
|
|
||||||
|
|
||||||
def escape_abbr(text: str) -> str:
|
def escape_abbr(text: str) -> str:
|
||||||
"""Adjust spacing after abbreviations. Works with @ letter or other."""
|
"""Adjust spacing after abbreviations. Works with @ letter or other."""
|
||||||
return re.sub(r'\.(?=\s|$)', r'.\@{}', text)
|
return re.sub(r'\.(?=\s|$)', r'.\@{}', text)
|
||||||
@ -120,3 +140,7 @@ def init() -> None:
|
|||||||
if a in '[]{}\\':
|
if a in '[]{}\\':
|
||||||
continue
|
continue
|
||||||
tex_hl_escape_map_new[ord(a)] = b
|
tex_hl_escape_map_new[ord(a)] = b
|
||||||
|
tex_hl_escape_map_new_without_unicode[ord(a)] = b
|
||||||
|
|
||||||
|
for a, b in unicode_tex_replacements:
|
||||||
|
tex_hl_escape_map_new[ord(a)] = b
|
||||||
|
@ -653,7 +653,8 @@ class LaTeXTranslator(SphinxTranslator):
|
|||||||
self.elements['classoptions'] += ',' + \
|
self.elements['classoptions'] += ',' + \
|
||||||
self.elements['extraclassoptions']
|
self.elements['extraclassoptions']
|
||||||
|
|
||||||
self.highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style)
|
self.highlighter = highlighting.PygmentsBridge('latex', self.config.pygments_style,
|
||||||
|
latex_engine=self.config.latex_engine)
|
||||||
self.context = [] # type: List[Any]
|
self.context = [] # type: List[Any]
|
||||||
self.descstack = [] # type: List[str]
|
self.descstack = [] # type: List[str]
|
||||||
self.table = None # type: Table
|
self.table = None # type: Table
|
||||||
|
@ -312,6 +312,24 @@ def test_inline(get_verifier, type, rst, html_expected, latex_expected):
|
|||||||
verifier(rst, html_expected, latex_expected)
|
verifier(rst, html_expected, latex_expected)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.sphinx(confoverrides={'latex_engine': 'xelatex'})
|
||||||
|
@pytest.mark.parametrize('type,rst,html_expected,latex_expected', [
|
||||||
|
(
|
||||||
|
# in verbatim code fragments
|
||||||
|
'verify',
|
||||||
|
'::\n\n @Γ\\∞${}',
|
||||||
|
None,
|
||||||
|
('\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
|
||||||
|
'@Γ\\PYGZbs{}∞\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
|
||||||
|
'\\end{sphinxVerbatim}'),
|
||||||
|
),
|
||||||
|
])
|
||||||
|
def test_inline_for_unicode_latex_engine(get_verifier, type, rst,
|
||||||
|
html_expected, latex_expected):
|
||||||
|
verifier = get_verifier(type)
|
||||||
|
verifier(rst, html_expected, latex_expected)
|
||||||
|
|
||||||
|
|
||||||
def test_samp_role(parse):
|
def test_samp_role(parse):
|
||||||
# no braces
|
# no braces
|
||||||
text = ':samp:`a{b}c`'
|
text = ':samp:`a{b}c`'
|
||||||
|
Loading…
Reference in New Issue
Block a user