Files
sphinx/tests/test_markup.py
T

213 lines
7.6 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""
test_markup
~~~~~~~~~~~
Test various Sphinx-specific markup extensions.
2016-01-14 22:54:04 +01:00
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import re
2016-05-25 12:06:49 +09:00
import pickle
from docutils import frontend, utils, nodes
from docutils.parsers import rst
from sphinx import addnodes
from sphinx.util import texescape
from sphinx.util.docutils import sphinx_domains
from sphinx.writers.html import HTMLWriter, SmartyPantsHTMLTranslator
from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator
2016-05-25 12:06:49 +09:00
from util import TestApp, with_app, assert_node
app = settings = parser = domain_context = None
2014-09-21 17:17:02 +02:00
def setup_module():
global app, settings, parser, domain_context
texescape.init() # otherwise done by the latex builder
2014-09-21 17:17:02 +02:00
app = TestApp()
optparser = frontend.OptionParser(
components=(rst.Parser, HTMLWriter, LaTeXWriter))
settings = optparser.get_default_values()
settings.env = app.builder.env
2010-01-18 00:41:34 +01:00
settings.env.temp_data['docname'] = 'dummy'
parser = rst.Parser()
domain_context = sphinx_domains(settings.env)
domain_context.enable()
2014-09-21 17:17:02 +02:00
def teardown_module():
app.cleanup()
domain_context.disable()
2016-06-12 00:00:52 +09:00
# since we're not resolving the markup afterwards, these nodes may remain
class ForgivingTranslator:
def visit_pending_xref(self, node):
pass
2014-09-21 17:17:02 +02:00
def depart_pending_xref(self, node):
pass
2014-09-21 17:17:02 +02:00
class ForgivingHTMLTranslator(SmartyPantsHTMLTranslator, ForgivingTranslator):
pass
2014-09-21 17:17:02 +02:00
class ForgivingLaTeXTranslator(LaTeXTranslator, ForgivingTranslator):
pass
def verify_re(rst, html_expected, latex_expected):
document = utils.new_document(b'test data', settings)
2009-03-16 11:24:19 +01:00
document['file'] = 'dummy'
parser.parse(rst, document)
for msg in document.traverse(nodes.system_message):
if msg['level'] == 1:
msg.replace_self([])
if html_expected:
html_translator = ForgivingHTMLTranslator(app.builder, document)
document.walkabout(html_translator)
html_translated = ''.join(html_translator.fragment).strip()
assert re.match(html_expected, html_translated), 'from ' + rst
if latex_expected:
latex_translator = ForgivingLaTeXTranslator(document, app.builder)
2016-06-12 00:00:52 +09:00
latex_translator.first_document = -1 # don't write \begin{document}
document.walkabout(latex_translator)
latex_translated = ''.join(latex_translator.body).strip()
assert re.match(latex_expected, latex_translated), 'from ' + repr(rst)
2016-06-12 00:00:52 +09:00
def verify(rst, html_expected, latex_expected):
if html_expected:
html_expected = re.escape(html_expected) + '$'
if latex_expected:
latex_expected = re.escape(latex_expected) + '$'
verify_re(rst, html_expected, latex_expected)
def test_inline():
# correct interpretation of code with whitespace
2014-08-12 12:12:10 +09:00
_html = ('<p><code class="(samp )?docutils literal"><span class="pre">'
2016-07-21 10:09:01 +09:00
'code</span>&#160;&#160; <span class="pre">sample</span></code></p>')
yield verify_re, '``code sample``', _html, r'\\sphinxcode{code sample}'
yield verify_re, ':samp:`code sample`', _html, r'\\sphinxcode{code sample}'
# interpolation of braces in samp and file roles (HTML only)
2009-02-21 17:16:56 +01:00
yield (verify, ':samp:`a{b}c`',
2014-08-12 12:12:10 +09:00
'<p><code class="samp docutils literal"><span class="pre">a</span>'
'<em><span class="pre">b</span></em>'
2014-08-12 12:12:10 +09:00
'<span class="pre">c</span></code></p>',
2016-06-17 19:32:16 +02:00
'\\sphinxcode{a\\sphinxstyleemphasis{b}c}')
# interpolation of arrows in menuselection
2009-02-21 17:16:56 +01:00
yield (verify, ':menuselection:`a --> b`',
u'<p><span class="menuselection">a \N{TRIANGULAR BULLET} b</span></p>',
'\\sphinxmenuselection{a \\(\\rightarrow\\) b}')
# interpolation of ampersands in guilabel/menuselection
yield (verify, ':guilabel:`&Foo -&&- &Bar`',
u'<p><span class="guilabel"><span class="accelerator">F</span>oo '
'-&amp;- <span class="accelerator">B</span>ar</span></p>',
r'\sphinxmenuselection{\sphinxaccelerator{F}oo -\&- \sphinxaccelerator{B}ar}')
# non-interpolation of dashes in option role
2009-02-21 17:16:56 +01:00
yield (verify_re, ':option:`--with-option`',
2014-09-20 20:54:23 +02:00
'<p><code( class="xref std std-option docutils literal")?>'
'<span class="pre">--with-option</span></code></p>$',
r'\\sphinxcode{-{-}with-option}$')
# verify smarty-pants quotes
2009-02-21 17:16:56 +01:00
yield verify, '"John"', '<p>&#8220;John&#8221;</p>', "``John''"
# ... but not in literal text
2009-02-21 17:16:56 +01:00
yield (verify, '``"John"``',
2014-08-12 12:12:10 +09:00
'<p><code class="docutils literal"><span class="pre">'
'&quot;John&quot;</span></code></p>',
'\\sphinxcode{"John"}')
# verify classes for inline roles
yield (verify, ':manpage:`mp(1)`',
'<p><em class="manpage">mp(1)</em></p>',
2016-06-17 19:32:16 +02:00
'\\sphinxstyleliteralemphasis{mp(1)}')
2016-06-12 00:00:52 +09:00
def test_latex_escaping():
# correct escaping in normal mode
2009-05-10 20:59:08 +02:00
yield (verify, u\\\\∞$', None,
r'\(\Gamma\)\textbackslash{}\(\infty\)\$')
# in verbatim code fragments
yield (verify, u'::\n\n\\∞${}', None,
u'\\begin{sphinxVerbatim}[commandchars=\\\\\\{\\}]\n'
u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n'
u'\\end{sphinxVerbatim}')
# in URIs
2010-02-20 19:51:37 +01:00
yield (verify_re, u'`test <http://example.com/~me/>`_', None,
r'\\href{http://example.com/~me/}{test}.*')
2016-05-25 12:06:49 +09:00
@with_app(buildername='dummy', testroot='prolog')
def test_rst_prolog(app, status, warning):
app.builder.build_all()
rst = pickle.loads((app.doctreedir / 'restructuredtext.doctree').bytes())
md = pickle.loads((app.doctreedir / 'markdown.doctree').bytes())
2016-05-25 12:06:49 +09:00
# rst_prolog
assert_node(rst[0], nodes.paragraph)
assert_node(rst[0][0], nodes.emphasis)
assert_node(rst[0][0][0], nodes.Text)
assert rst[0][0][0] == 'Hello world'
2016-05-25 12:06:49 +09:00
# rst_epilog
assert_node(rst[-1], nodes.section)
assert_node(rst[-1][-1], nodes.paragraph)
assert_node(rst[-1][-1][0], nodes.emphasis)
assert_node(rst[-1][-1][0][0], nodes.Text)
assert rst[-1][-1][0][0] == 'Good-bye world'
# rst_prolog & rst_epilog on exlucding reST parser
assert not md.rawsource.startswith('*Hello world*.')
assert not md.rawsource.endswith('*Good-bye world*.\n')
@with_app(buildername='dummy', testroot='keep_warnings')
def test_keep_warnings_is_True(app, status, warning):
app.builder.build_all()
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
assert_node(doctree[0], nodes.section)
assert len(doctree[0]) == 2
assert_node(doctree[0][1], nodes.system_message)
@with_app(buildername='dummy', testroot='keep_warnings',
confoverrides={'keep_warnings': False})
def test_keep_warnings_is_False(app, status, warning):
app.builder.build_all()
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
assert_node(doctree[0], nodes.section)
assert len(doctree[0]) == 1
@with_app(buildername='dummy', testroot='refonly_bullet_list')
def test_compact_refonly_bullet_list(app, status, warning):
app.builder.build_all()
doctree = pickle.loads((app.doctreedir / 'index.doctree').bytes())
assert_node(doctree[0], nodes.section)
assert len(doctree[0]) == 5
assert doctree[0][1].astext() == 'List A:'
assert_node(doctree[0][2], nodes.bullet_list)
assert_node(doctree[0][2][0][0], addnodes.compact_paragraph)
assert doctree[0][2][0][0].astext() == 'genindex'
assert doctree[0][3].astext() == 'List B:'
assert_node(doctree[0][4], nodes.bullet_list)
assert_node(doctree[0][4][0][0], nodes.paragraph)
assert doctree[0][4][0][0].astext() == 'Hello'