Do not use ``\\\\section*``-macros to suppress LaTeX section numbering.
[docutils.git] / test / test_writers / test_latex2e.py
blobbad705c5f0ace06d9a902650e3eb7279f9cf1b19
1 # -*- coding: utf8 -*-
2 #! /usr/bin/env python
4 # $Id$
5 # Author: engelbert gruber <grubert@users.sourceforge.net>
6 # Copyright: This module has been placed in the public domain.
8 """
9 Tests for latex2e writer.
10 """
12 import string
13 # compatibility module for Python 2.3
14 if not hasattr(string, 'Template'):
15 import docutils._string_template_compat
16 string.Template = docutils._string_template_compat.Template
18 from __init__ import DocutilsTestSupport
20 def suite():
21 settings = {'use_latex_toc': False}
22 s = DocutilsTestSupport.PublishTestSuite('latex', suite_settings=settings)
23 s.generateTests(totest)
24 settings['use_latex_toc'] = True
25 s.generateTests(totest_latex_toc)
26 settings['use_latex_toc'] = False
27 settings['sectnum_xform'] = False
28 s.generateTests(totest_latex_sectnum)
29 settings['sectnum_xform'] = True
30 settings['use_latex_citations'] = True
31 s.generateTests(totest_latex_citations)
32 settings['stylesheet_path'] = 'data/spam,data/ham.tex'
33 s.generateTests(totest_stylesheet)
34 settings['embed_stylesheet'] = True
35 settings['warning_stream'] = ''
36 s.generateTests(totest_stylesheet_embed)
37 return s
39 head_template = string.Template(
40 r"""$head_prefix% generated by Docutils <http://docutils.sourceforge.net/>
41 \usepackage{fixltx2e} % LaTeX patches, \textsubscript
42 \usepackage{cmap} % fix search and cut-and-paste in Acrobat
43 $requirements
44 %%% Custom LaTeX preamble
45 $latex_preamble
46 %%% User specified packages and stylesheets
47 $stylesheet
48 %%% Fallback definitions for Docutils-specific commands
49 $fallbacks$pdfsetup
50 $titledata
51 %%% Body
52 \begin{document}
53 """)
55 parts = dict(
56 head_prefix = r"""\documentclass[a4paper]{article}
57 """,
58 requirements = r"""\usepackage{ifthen}
59 \usepackage[T1]{fontenc}
60 \usepackage[utf8]{inputenc}
61 """,
62 latex_preamble = r"""% PDF Standard Fonts
63 \usepackage{mathptmx} % Times
64 \usepackage[scaled=.90]{helvet}
65 \usepackage{courier}
66 """,
67 stylesheet = '',
68 fallbacks = '',
69 pdfsetup = r"""
70 % hyperlinks:
71 \ifthenelse{\isundefined{\hypersetup}}{
72 \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
73 \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
74 }{}
75 """,
76 titledata = '')
78 head = head_template.substitute(parts)
80 head_table = head_template.substitute(
81 dict(parts, requirements = parts['requirements'] +
82 r"""\usepackage{longtable,ltcaption,array}
83 \setlength{\extrarowheight}{2pt}
84 \newlength{\DUtablewidth} % internal use in tables
85 """))
87 head_textcomp = head_template.substitute(
88 dict(parts, requirements = parts['requirements'] +
89 r"""\usepackage{textcomp} % text symbol macros
90 """))
92 totest = {}
93 totest_latex_toc = {}
94 totest_latex_sectnum = {}
95 totest_latex_citations = {}
96 totest_stylesheet = {}
97 totest_stylesheet_embed = {}
99 totest['url_chars'] = [
100 ["http://nowhere/url_with%28parens%29",
101 head + r"""
102 \url{http://nowhere/url_with\%28parens\%29}
104 \end{document}
105 """],
108 totest['textcomp'] = [
109 ["2 µm is just 2/1000000 m",
110 head_textcomp + r"""
111 2 µm is just 2/1000000 m
113 \end{document}
114 """],
117 totest['spanish quote'] = [
118 [".. role:: language-es\n\nUnd damit :language-es:`basta`!",
119 head_template.substitute(dict(parts, requirements =
120 r"""\usepackage{ifthen}
121 \usepackage[T1]{fontenc}
122 \usepackage[utf8]{inputenc}
123 \usepackage[spanish,english]{babel}
124 \addto\shorthandsspanish{\spanishdeactivate{."~<>}}
125 """)) + r"""
126 Und damit \otherlanguage{spanish}{basta}!
128 \end{document}
129 """],
132 totest['table_of_contents'] = [
133 # input
134 ["""\
135 .. contents:: Table of Contents
137 Title 1
138 =======
139 Paragraph 1.
141 Title 2
142 -------
143 Paragraph 2.
144 """,
145 ## # expected output
146 head_template.substitute(dict(parts,
147 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n',
148 fallbacks=r"""
149 % title for topics, admonitions, unsupported section levels, and sidebar
150 \providecommand*{\DUtitle}[2][class-arg]{%
151 % call \DUtitle#1{#2} if it exists:
152 \ifcsname DUtitle#1\endcsname%
153 \csname DUtitle#1\endcsname{#2}%
154 \else
155 \smallskip\noindent\textbf{#2}\smallskip%
158 """)) + r"""
159 \phantomsection\label{table-of-contents}
160 \pdfbookmark[1]{Table of Contents}{table-of-contents}
161 \DUtitle[contents]{Table of Contents}
163 \begin{list}{}{}
165 \item \hyperref[title-1]{Title 1}
167 \begin{list}{}{}
169 \item \hyperref[title-2]{Title 2}
171 \end{list}
173 \end{list}
176 \section{Title 1%
177 \label{title-1}%
180 Paragraph 1.
183 \subsection{Title 2%
184 \label{title-2}%
187 Paragraph 2.
189 \end{document}
190 """],
194 totest_latex_toc['no_sectnum'] = [
195 # input
196 ["""\
197 .. contents::
199 first section
200 -------------
201 """,
202 ## # expected output
203 head_template.substitute(dict(parts,
204 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
205 )) + r"""
206 \phantomsection\label{contents}
207 \pdfbookmark[1]{Contents}{contents}
208 \tableofcontents
212 \section{first section%
213 \label{first-section}%
216 \end{document}
217 """],
220 totest_latex_toc['sectnum'] = [
221 # input
222 ["""\
223 .. contents::
224 .. sectnum::
226 first section
227 -------------
228 """,
229 ## # expected output
230 head_template.substitute(dict(parts,
231 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
232 )) + r"""
233 \phantomsection\label{contents}
234 \pdfbookmark[1]{Contents}{contents}
235 \tableofcontents
239 \section{1~~~first section%
240 \label{first-section}%
243 \end{document}
244 """],
248 totest_latex_sectnum['no_sectnum'] = [
249 # input
250 ["""\
251 some text
253 first section
254 -------------
255 """,
256 ## # expected output
257 head_template.substitute(dict(parts, requirements = parts['requirements'] +
258 r"""\setcounter{secnumdepth}{0}
259 """)) + r"""
260 some text
263 \section{first section%
264 \label{first-section}%
267 \end{document}
268 """],
271 totest_latex_sectnum['sectnum'] = [
272 # input
273 ["""\
274 .. sectnum::
276 some text
278 first section
279 -------------
280 """,
281 ## # expected output
282 head_template.substitute(dict(parts,
283 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n'
284 )) + r"""
285 some text
288 \section{first section%
289 \label{first-section}%
292 \end{document}
293 """],
296 totest_latex_citations['citations_with_underscore'] = [
297 # input
298 ["""\
299 Just a test citation [my_cite2006]_.
301 .. [my_cite2006]
302 The underscore is mishandled.
303 """,
304 ## # expected output
305 head + r"""
306 Just a test citation \cite{my_cite2006}.
308 \begin{thebibliography}{my\_cite2006}
309 \bibitem[my\_cite2006]{my_cite2006}{
310 The underscore is mishandled.
312 \end{thebibliography}
314 \end{document}
315 """],
319 totest_latex_citations['adjacent_citations'] = [
320 # input
321 ["""\
322 Two non-citations: [MeYou2007]_[YouMe2007]_.
324 Need to be separated for grouping: [MeYou2007]_ [YouMe2007]_.
326 Two spaces (or anything else) for no grouping: [MeYou2007]_ [YouMe2007]_.
328 But a line break should work: [MeYou2007]_
329 [YouMe2007]_.
331 .. [MeYou2007] not.
332 .. [YouMe2007] important.
333 """,
334 # expected output
335 head + r"""
336 Two non-citations: {[}MeYou2007{]}\_{[}YouMe2007{]}\_.
338 Need to be separated for grouping: \cite{MeYou2007,YouMe2007}.
340 Two spaces (or anything else) for no grouping: \cite{MeYou2007} \cite{YouMe2007}.
342 But a line break should work: \cite{MeYou2007,YouMe2007}.
344 \begin{thebibliography}{MeYou2007}
345 \bibitem[MeYou2007]{MeYou2007}{
346 not.
348 \bibitem[YouMe2007]{YouMe2007}{
349 important.
351 \end{thebibliography}
353 \end{document}
354 """],
358 totest['enumerated_lists'] = [
359 # input
360 ["""\
361 1. Item 1.
362 2. Second to the previous item this one will explain
364 a) nothing.
365 b) or some other.
367 3. Third is
369 (I) having pre and postfixes
370 (II) in roman numerals.
371 """,
372 # expected output
373 head + r"""\newcounter{listcnt0}
374 \begin{list}{\arabic{listcnt0}.}
376 \usecounter{listcnt0}
377 \setlength{\rightmargin}{\leftmargin}
380 \item Item 1.
382 \item Second to the previous item this one will explain
383 \end{list}
385 \begin{quote}
386 \setcounter{listcnt0}{0}
387 \begin{list}{\alph{listcnt0})}
389 \usecounter{listcnt0}
390 \setlength{\rightmargin}{\leftmargin}
393 \item nothing.
395 \item or some other.
396 \end{list}
398 \end{quote}
399 \setcounter{listcnt0}{0}
400 \begin{list}{\arabic{listcnt0}.}
402 \usecounter{listcnt0}
403 \addtocounter{listcnt0}{2}
404 \setlength{\rightmargin}{\leftmargin}
407 \item Third is
408 \end{list}
410 \begin{quote}
411 \setcounter{listcnt0}{0}
412 \begin{list}{(\Roman{listcnt0})}
414 \usecounter{listcnt0}
415 \setlength{\rightmargin}{\leftmargin}
418 \item having pre and postfixes
420 \item in roman numerals.
421 \end{list}
423 \end{quote}
425 \end{document}
426 """],
429 # BUG: need to test for quote replacing if language is de (ngerman).
431 totest['quote_mangling'] = [
432 # input
433 ["""
434 Depending on language quotes are converted for latex.
435 Expecting "en" here.
437 Inside literal blocks quotes should be left untouched
438 (use only two quotes in test code makes life easier for
439 the python interpreter running the test)::
442 This is left "untouched" also *this*.
445 .. parsed-literal::
447 should get "quotes" and *italics*.
450 Inline ``literal "quotes"`` should be kept.
451 """,
452 head + r"""
453 Depending on language quotes are converted for latex.
454 Expecting ``en'' here.
456 Inside literal blocks quotes should be left untouched
457 (use only two quotes in test code makes life easier for
458 the python interpreter running the test):
460 \begin{quote}{\ttfamily \raggedright \noindent
461 "{}"\\
462 This~is~left~"untouched"~also~*this*.\\
463 "{}"
465 \end{quote}
467 \begin{quote}{\ttfamily \raggedright \noindent
468 should~get~"quotes"~and~\emph{italics}.
470 \end{quote}
472 Inline \texttt{literal "quotes"} should be kept.
474 \end{document}
475 """],
478 totest['table_caption'] = [
479 # input
480 ["""\
481 .. table:: Foo
483 +-----+-----+
484 | | |
485 +-----+-----+
486 | | |
487 +-----+-----+
488 """,
489 head_table + r"""
490 \setlength{\DUtablewidth}{\linewidth}
491 \begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
492 \caption{Foo}\\
493 \hline
494 & \\
495 \hline
496 & \\
497 \hline
498 \end{longtable}
500 \end{document}
501 """],
504 totest['table_class'] = [
505 # input
506 ["""\
507 .. table::
508 :class: borderless
510 +-----+-----+
511 | 1 | 2 |
512 +-----+-----+
513 | 3 | 4 |
514 +-----+-----+
515 """,
516 head_table + r"""
517 \setlength{\DUtablewidth}{\linewidth}
518 \begin{longtable*}[c]{p{0.075\DUtablewidth}p{0.075\DUtablewidth}}
529 \end{longtable*}
531 \end{document}
532 """],
535 # The "[" needs to be protected (otherwise it will be seen as an
536 # option to "\\", "\item", etc. ).
538 totest['brackett_protection'] = [
539 # input
540 ["""\
543 something before to get a end of line.
546 the empty line gets tested too
548 """,
549 head + r"""%
550 \begin{quote}{\ttfamily \raggedright \noindent
551 something~before~to~get~a~end~of~line.\\
552 {[}\\
554 the~empty~line~gets~tested~too\\
557 \end{quote}
559 \end{document}
560 """],
563 totest['raw'] = [
564 [r""".. raw:: latex
566 $E=mc^2$
568 A paragraph.
570 .. |sub| raw:: latex
572 (some raw text)
574 Foo |sub|
575 same paragraph.
576 """,
577 head + r"""
578 $E=mc^2$
580 A paragraph.
582 Foo (some raw text)
583 same paragraph.
585 \end{document}
586 """],
589 totest['title_with_inline_markup'] = [
590 ["""\
591 This is the *Title*
592 ===================
594 This is the *Subtitle*
595 ----------------------
597 This is a *section title*
598 ~~~~~~~~~~~~~~~~~~~~~~~~~
600 This is the *document*.
601 """,
602 head_template.substitute(dict(parts,
603 requirements=parts['requirements'] + '\\setcounter{secnumdepth}{0}\n',
604 pdfsetup=parts['pdfsetup'] + r"""\hypersetup{
605 pdftitle={This is the Title},
607 """, titledata=r"""%%% Title Data
608 \title{\phantomsection%
609 This is the \emph{Title}%
610 \label{this-is-the-title}%
611 \\ % subtitle%
612 \large{This is the \emph{Subtitle}}%
613 \label{this-is-the-subtitle}}
614 \author{}
615 \date{}
616 """)) + r"""\maketitle
619 \section{This is a \emph{section title}%
620 \label{this-is-a-section-title}%
623 This is the \emph{document}.
625 \end{document}
626 """],
629 totest_stylesheet['two-styles'] = [
630 # input
631 ["""two stylesheet links in the header""",
632 head_template.substitute(dict(parts, stylesheet =
633 r"""\usepackage{data/spam}
634 \input{data/ham.tex}
635 """)) + r"""
636 two stylesheet links in the header
638 \end{document}
639 """],
642 totest_stylesheet_embed['two-styles'] = [
643 # input
644 ["""two stylesheets embedded in the header""",
645 head_template.substitute(dict(parts, stylesheet =
646 r"""% Cannot embed stylesheet 'data/spam.sty':
647 % No such file or directory.
648 % embedded stylesheet: data/ham.tex
649 \newcommand{\ham}{wonderful ham}
651 """)) + r"""
652 two stylesheets embedded in the header
654 \end{document}
655 """],
659 if __name__ == '__main__':
660 import unittest
661 unittest.main(defaultTest='suite')