# -*- coding: utf-8 -*- """ test_markup ~~~~~~~~~~~ Test various Sphinx-specific markup extensions. :copyright: Copyright 2007-2014 by the Sphinx team, see AUTHORS. :license: BSD, see LICENSE for details. """ import re from docutils import frontend, utils, nodes from docutils.parsers import rst from sphinx.util import texescape from sphinx.writers.html import HTMLWriter, SmartyPantsHTMLTranslator from sphinx.writers.latex import LaTeXWriter, LaTeXTranslator from util import TestApp app = settings = parser = None def setup_module(): global app, settings, parser texescape.init() # otherwise done by the latex builder app = TestApp() optparser = frontend.OptionParser( components=(rst.Parser, HTMLWriter, LaTeXWriter)) settings = optparser.get_default_values() settings.env = app.builder.env settings.env.patch_lookup_functions() settings.env.temp_data['docname'] = 'dummy' parser = rst.Parser() def teardown_module(): app.cleanup() # since we're not resolving the markup afterwards, these nodes may remain class ForgivingTranslator: def visit_pending_xref(self, node): pass def depart_pending_xref(self, node): pass class ForgivingHTMLTranslator(SmartyPantsHTMLTranslator, ForgivingTranslator): pass class ForgivingLaTeXTranslator(LaTeXTranslator, ForgivingTranslator): pass def verify_re(rst, html_expected, latex_expected): document = utils.new_document(b'test data', settings) 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) 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) 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 _html = ('

' 'code   sample

') yield verify_re, '``code sample``', _html, r'\\code{code sample}' yield verify_re, ':samp:`code sample`', _html, r'\\code{code sample}' # interpolation of braces in samp and file roles (HTML only) yield (verify, ':samp:`a{b}c`', '

a' 'b' 'c

', '\\code{a\\emph{b}c}') # interpolation of arrows in menuselection yield (verify, ':menuselection:`a --> b`', u'

a \N{TRIANGULAR BULLET} b

', '\\emph{a \\(\\rightarrow\\) b}') # interpolation of ampersands in guilabel/menuselection yield (verify, ':guilabel:`&Foo -&&- &Bar`', u'

Foo ' '-&- Bar

', r'\emph{\DUspan{accelerator}{F}oo -\&- \DUspan{accelerator}{B}ar}') # non-interpolation of dashes in option role yield (verify_re, ':option:`--with-option`', '

' '--with-option

$', r'\\code{-{-}with-option}$') # verify smarty-pants quotes yield verify, '"John"', '

“John”

', "``John''" # ... but not in literal text yield (verify, '``"John"``', '

' '"John"

', '\\code{"John"}') # verify classes for inline roles yield (verify, ':manpage:`mp(1)`', '

mp(1)

', '\\emph{\\texttt{mp(1)}}') def test_latex_escaping(): # correct escaping in normal mode yield (verify, u'Γ\\\\∞$', None, r'\(\Gamma\)\textbackslash{}\(\infty\)\$') # in verbatim code fragments yield (verify, u'::\n\n @Γ\\∞${}', None, u'\\begin{Verbatim}[frame=single,commandchars=\\\\\\{\\}]\n' u'@\\(\\Gamma\\)\\PYGZbs{}\\(\\infty\\)\\PYGZdl{}\\PYGZob{}\\PYGZcb{}\n' u'\\end{Verbatim}') # in URIs yield (verify_re, u'`test `_', None, r'\\href{http://example.com/~me/}{test}.*')