2008-11-30 12:58:29 -06:00
|
|
|
"""Test the Pygments highlighting bridge."""
|
|
|
|
|
2024-11-22 15:54:26 -06:00
|
|
|
from __future__ import annotations
|
|
|
|
|
2019-03-07 08:35:36 -06:00
|
|
|
from unittest import mock
|
|
|
|
|
2024-07-29 19:10:32 -05:00
|
|
|
import pygments
|
2024-08-12 16:34:03 -05:00
|
|
|
import pytest
|
2018-02-19 07:39:14 -06:00
|
|
|
from pygments.formatters.html import HtmlFormatter
|
2008-11-30 12:58:29 -06:00
|
|
|
from pygments.lexer import RegexLexer
|
2020-11-11 05:00:27 -06:00
|
|
|
from pygments.token import Name, Text
|
2008-11-30 12:58:29 -06:00
|
|
|
|
|
|
|
from sphinx.highlighting import PygmentsBridge
|
|
|
|
|
2025-01-06 00:56:10 -06:00
|
|
|
if tuple(map(int, pygments.__version__.split('.')[:2])) < (2, 18):
|
2024-07-29 19:10:32 -05:00
|
|
|
from pygments.formatter import Formatter
|
2024-08-11 08:58:56 -05:00
|
|
|
|
2024-07-29 19:51:27 -05:00
|
|
|
Formatter.__class_getitem__ = classmethod(lambda cls, name: cls) # type: ignore[attr-defined]
|
2024-07-29 19:10:32 -05:00
|
|
|
|
2008-11-30 12:58:29 -06:00
|
|
|
|
|
|
|
class MyLexer(RegexLexer):
|
|
|
|
name = 'testlexer'
|
|
|
|
|
|
|
|
tokens = {
|
|
|
|
'root': [
|
|
|
|
('a', Name),
|
|
|
|
('b', Text),
|
|
|
|
],
|
|
|
|
}
|
|
|
|
|
2009-01-01 10:33:41 -06:00
|
|
|
|
2024-07-20 13:54:49 -05:00
|
|
|
class MyFormatter(HtmlFormatter[str]):
|
2008-11-30 13:29:34 -06:00
|
|
|
def format(self, tokensource, outfile):
|
2009-06-16 14:53:53 -05:00
|
|
|
for tok in tokensource:
|
|
|
|
outfile.write(tok[1])
|
2008-11-30 13:29:34 -06:00
|
|
|
|
2008-11-30 12:58:29 -06:00
|
|
|
|
2009-02-06 15:18:16 -06:00
|
|
|
class ComplainOnUnhighlighted(PygmentsBridge):
|
|
|
|
def unhighlighted(self, source):
|
2024-08-11 08:58:56 -05:00
|
|
|
raise AssertionError('should highlight %r' % source)
|
2009-02-06 15:18:16 -06:00
|
|
|
|
|
|
|
|
2024-08-12 16:34:03 -05:00
|
|
|
@pytest.mark.sphinx('html', testroot='root')
|
2024-07-23 09:35:55 -05:00
|
|
|
def test_add_lexer(app):
|
2020-02-16 05:42:43 -06:00
|
|
|
app.add_lexer('test', MyLexer)
|
2008-11-30 12:58:29 -06:00
|
|
|
|
|
|
|
bridge = PygmentsBridge('html')
|
|
|
|
ret = bridge.highlight_block('ab', 'test')
|
|
|
|
assert '<span class="n">a</span>b' in ret
|
2008-11-30 13:29:34 -06:00
|
|
|
|
2014-09-21 10:17:02 -05:00
|
|
|
|
2009-01-01 10:33:41 -06:00
|
|
|
def test_detect_interactive():
|
|
|
|
bridge = ComplainOnUnhighlighted('html')
|
|
|
|
blocks = [
|
|
|
|
"""
|
|
|
|
>>> testing()
|
|
|
|
True
|
|
|
|
""",
|
2014-09-21 10:17:02 -05:00
|
|
|
]
|
2009-01-01 10:33:41 -06:00
|
|
|
for block in blocks:
|
|
|
|
ret = bridge.highlight_block(block.lstrip(), 'python')
|
2024-08-11 08:58:56 -05:00
|
|
|
assert ret.startswith('<div class="highlight">')
|
2009-01-01 10:33:41 -06:00
|
|
|
|
2014-09-21 10:17:02 -05:00
|
|
|
|
2015-01-05 11:49:06 -06:00
|
|
|
def test_lexer_options():
|
|
|
|
bridge = PygmentsBridge('html')
|
2016-06-11 10:00:52 -05:00
|
|
|
ret = bridge.highlight_block('//comment', 'php', opts={'startinline': True})
|
2015-01-05 11:49:06 -06:00
|
|
|
assert '<span class="c1">//comment</span>' in ret
|
|
|
|
|
|
|
|
|
2008-11-30 13:29:34 -06:00
|
|
|
def test_set_formatter():
|
|
|
|
PygmentsBridge.html_formatter = MyFormatter
|
|
|
|
try:
|
|
|
|
bridge = PygmentsBridge('html')
|
2009-06-16 14:53:53 -05:00
|
|
|
ret = bridge.highlight_block('foo\n', 'python')
|
|
|
|
assert ret == 'foo\n'
|
|
|
|
finally:
|
|
|
|
PygmentsBridge.html_formatter = HtmlFormatter
|
|
|
|
|
2014-09-21 10:17:02 -05:00
|
|
|
|
2016-12-20 08:21:30 -06:00
|
|
|
@mock.patch('sphinx.highlighting.logger')
|
|
|
|
def test_default_highlight(logger):
|
2016-02-18 18:36:43 -06:00
|
|
|
bridge = PygmentsBridge('html')
|
|
|
|
|
|
|
|
# default: highlights as python3
|
|
|
|
ret = bridge.highlight_block('print "Hello sphinx world"', 'default')
|
2024-08-11 08:58:56 -05:00
|
|
|
assert ret == (
|
|
|
|
'<div class="highlight"><pre><span></span><span class="nb">print</span> '
|
|
|
|
'<span class="s2">"Hello sphinx world"</span>\n</pre></div>\n'
|
|
|
|
)
|
2016-02-18 18:36:43 -06:00
|
|
|
|
|
|
|
# default: fallbacks to none if highlighting failed
|
|
|
|
ret = bridge.highlight_block('reST ``like`` text', 'default')
|
2024-08-11 08:58:56 -05:00
|
|
|
assert ret == (
|
|
|
|
'<div class="highlight"><pre><span></span>reST ``like`` text\n</pre></div>\n'
|
|
|
|
)
|
2016-02-18 18:36:43 -06:00
|
|
|
|
2022-09-24 18:10:59 -05:00
|
|
|
# python: highlights as python3
|
|
|
|
ret = bridge.highlight_block('print("Hello sphinx world")', 'python')
|
2024-08-11 08:58:56 -05:00
|
|
|
assert ret == (
|
|
|
|
'<div class="highlight"><pre><span></span><span class="nb">print</span>'
|
|
|
|
'<span class="p">(</span>'
|
|
|
|
'<span class="s2">"Hello sphinx world"</span>'
|
|
|
|
'<span class="p">)</span>\n</pre></div>\n'
|
|
|
|
)
|
2016-02-18 18:36:43 -06:00
|
|
|
|
2022-09-24 18:10:59 -05:00
|
|
|
# python3: highlights as python3
|
|
|
|
ret = bridge.highlight_block('print("Hello sphinx world")', 'python3')
|
2024-08-11 08:58:56 -05:00
|
|
|
assert ret == (
|
|
|
|
'<div class="highlight"><pre><span></span><span class="nb">print</span>'
|
|
|
|
'<span class="p">(</span>'
|
|
|
|
'<span class="s2">"Hello sphinx world"</span>'
|
|
|
|
'<span class="p">)</span>\n</pre></div>\n'
|
|
|
|
)
|
2022-09-24 18:10:59 -05:00
|
|
|
|
|
|
|
# python: raises error if highlighting failed
|
|
|
|
ret = bridge.highlight_block('reST ``like`` text', 'python')
|
2024-08-11 08:58:56 -05:00
|
|
|
logger.warning.assert_called_with(
|
|
|
|
'Lexing literal_block %r as "%s" resulted in an error at token: %r. '
|
|
|
|
'Retrying in relaxed mode.',
|
|
|
|
'reST ``like`` text',
|
|
|
|
'python',
|
|
|
|
'`',
|
|
|
|
type='misc',
|
|
|
|
subtype='highlighting_failure',
|
|
|
|
location=None,
|
|
|
|
)
|