2 # -*- coding: utf-8 -*-
5 # Author: engelbert gruber <grubert@users.sourceforge.net>
6 # Copyright: This module has been placed in the public domain.
9 Tests for latex2e writer.
11 from __future__
import absolute_import
15 if __name__
== '__main__':
17 from test_transforms
import DocutilsTestSupport
# before importing docutils!
21 settings
= {'use_latex_toc': False,
22 # avoid latex writer future warnings:
23 'use_latex_citations': False,
24 'legacy_column_widths': True,
26 s
= DocutilsTestSupport
.PublishTestSuite('latex', suite_settings
=settings
)
27 s
.generateTests(totest
)
28 settings
['use_latex_toc'] = True
29 s
.generateTests(totest_latex_toc
)
30 settings
['documentclass'] = 'book'
31 s
.generateTests(totest_latex_toc_book
)
32 del settings
['documentclass']
33 settings
['use_latex_toc'] = False
34 settings
['sectnum_xform'] = False
35 s
.generateTests(totest_latex_sectnum
)
36 settings
['sectnum_xform'] = True
37 settings
['use_latex_citations'] = True
38 s
.generateTests(totest_latex_citations
)
39 settings
['table_style'] = ['colwidths-auto']
40 s
.generateTests(totest_table_style_auto
)
41 settings
['table_style'] = ['booktabs']
42 s
.generateTests(totest_table_style_booktabs
)
43 settings
['stylesheet_path'] = 'data/spam,data/ham.tex'
44 s
.generateTests(totest_stylesheet
)
45 settings
['embed_stylesheet'] = True
46 settings
['warning_stream'] = ''
47 s
.generateTests(totest_stylesheet_embed
)
50 head_template
= string
.Template(
51 r
"""$head_prefix% generated by Docutils <http://docutils.sourceforge.net/>
52 \usepackage{cmap} % fix search and cut-and-paste in Acrobat
54 %%% Custom LaTeX preamble
56 %%% User specified packages and stylesheets
58 %%% Fallback definitions for Docutils-specific commands
65 head_prefix
= r
"""\documentclass[a4paper]{article}
67 requirements
= r
"""\usepackage{ifthen}
68 \usepackage[T1]{fontenc}
69 \usepackage[utf8]{inputenc}
71 latex_preamble
= r
"""% PDF Standard Fonts
72 \usepackage{mathptmx} % Times
73 \usepackage[scaled=.90]{helvet}
76 longtable
= r
"""\usepackage{longtable,ltcaption,array}
77 \setlength{\extrarowheight}{2pt}
78 \newlength{\DUtablewidth} % internal use in tables
82 fallbacks_highlight
= r
"""
83 % basic code highlight:
84 \providecommand*\DUrolecomment[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}
85 \providecommand*\DUroledeleted[1]{\textcolor[rgb]{0.40,0.40,0.40}{#1}}
86 \providecommand*\DUrolekeyword[1]{\textbf{#1}}
87 \providecommand*\DUrolestring[1]{\textit{#1}}
89 % custom inline roles: \DUrole{#1}{#2} tries \DUrole#1{#2}
90 \providecommand*{\DUrole}[2]{%
91 \ifcsname DUrole#1\endcsname%
92 \csname DUrole#1\endcsname{#2}%
100 \ifthenelse{\isundefined{\hypersetup}}{
101 \usepackage[colorlinks=true,linkcolor=blue,urlcolor=blue]{hyperref}
102 \usepackage{bookmark}
103 \urlstyle{same} % normal text font (alternatives: tt, rm, sf)
108 head
= head_template
.substitute(parts
)
110 head_table
= head_template
.substitute(
111 dict(parts
, requirements
= parts
['requirements'] + parts
['longtable']))
113 head_booktabs
= head_template
.substitute(
114 dict(parts
, requirements
=parts
['requirements']
115 + '\\usepackage{booktabs}\n' + parts
['longtable']))
117 head_textcomp
= head_template
.substitute(
118 dict(parts
, requirements
= parts
['requirements'] +
119 r
"""\usepackage{textcomp} % text symbol macros
122 head_alltt
= head_template
.substitute(
123 dict(parts
, requirements
= parts
['requirements'] +
124 r
"""\usepackage{alltt}
129 totest_latex_toc
= {}
130 totest_latex_toc_book
= {}
131 totest_latex_sectnum
= {}
132 totest_latex_citations
= {}
133 totest_stylesheet
= {}
134 totest_stylesheet_embed
= {}
135 totest_table_style_auto
= {}
136 totest_table_style_booktabs
= {}
138 totest
['url_chars'] = [
139 ["http://nowhere/url_with%28parens%29",
141 \url{http://nowhere/url_with\%28parens\%29}
147 totest
['textcomp'] = [
148 ["2 µm is just 2/1000000 m",
150 2 µm is just 2/1000000 m
156 totest
['spanish quote'] = [
157 [".. role:: language-es\n\nUnd damit :language-es:`basta`!",
158 head_template
.substitute(dict(parts
, requirements
=
159 r
"""\usepackage{ifthen}
160 \usepackage[T1]{fontenc}
161 \usepackage[utf8]{inputenc}
162 \usepackage[spanish,english]{babel}
163 \AtBeginDocument{\shorthandoff{.<>}}
165 Und damit \foreignlanguage{spanish}{basta}!
171 totest
['code role'] = [
173 head_template
.substitute(dict(parts
, requirements
= parts
['requirements']+
174 r
"""\usepackage{color}
175 """, fallbacks
= parts
['fallbacks_highlight'])) + r
"""
176 \texttt{\DUrole{code}{x=1}}
182 totest
['table_of_contents'] = [
185 .. contents:: Table of Contents
196 head_template
.substitute(dict(parts
,
197 requirements
=parts
['requirements'] + '\\setcounter{secnumdepth}{0}\n',
199 % class handling for environments (block-level elements)
200 % \begin{DUclass}{spam} tries \DUCLASSspam and
201 % \end{DUclass}{spam} tries \endDUCLASSspam
202 \ifx\DUclass\undefined % poor man's "provideenvironment"
203 \newenvironment{DUclass}[1]%
204 {% "#1" does not work in end-part of environment.
205 \def\DocutilsClassFunctionName{DUCLASS#1}
206 \csname \DocutilsClassFunctionName \endcsname}%
207 {\csname end\DocutilsClassFunctionName \endcsname}%
210 % title for topics, admonitions, unsupported section levels, and sidebar
211 \providecommand*{\DUtitle}[1]{%
212 \smallskip\noindent\textbf{#1}\smallskip}
214 \providecommand*{\DUCLASScontents}{%
215 \renewenvironment{itemize}%
216 {\begin{list}{}{\setlength{\partopsep}{0pt}
217 \setlength{\parsep}{0pt}}
222 \phantomsection\label{table-of-contents}
223 \pdfbookmark[1]{Table of Contents}{table-of-contents}
225 \begin{DUclass}{contents}
227 \DUtitle{Table of Contents}
230 \item \hyperref[title-1]{Title 1}
233 \item \hyperref[title-2]{Title 2}
256 totest
['footnote text'] = [
263 .. [3] 1. enumeration
266 head_template
.substitute(dict(parts
,
268 % numerical or symbol footnotes with hyperlinks and backlinks
269 \providecommand*{\DUfootnotemark}[3]{%
270 \raisebox{1em}{\hypertarget{#1}{}}%
271 \hyperlink{#2}{\textsuperscript{#3}}%
273 \providecommand{\DUfootnotetext}[4]{%
275 \renewcommand{\thefootnote}{%
276 \protect\raisebox{1em}{\protect\hypertarget{#1}{}}%
277 \protect\hyperlink{#2}{#3}}%
282 \DUfootnotetext{footnote-1}{footnote-1}{1}{%
286 \DUfootnotetext{footnote-2}{footnote-2}{2}{}
288 \DUfootnotetext{footnote-3}{footnote-3}{3}{
298 totest_latex_toc
['no_sectnum'] = [
307 head_template
.substitute(dict(parts
,
308 requirements
=parts
['requirements'] + '\\setcounter{secnumdepth}{0}\n'
310 \phantomsection\label{contents}
311 \pdfbookmark[1]{Contents}{contents}
315 \section{first section%
316 \label{first-section}%
323 totest_latex_toc
['sectnum'] = [
333 head_template
.substitute(dict(parts
,
334 requirements
=parts
['requirements'] + '\\setcounter{secnumdepth}{0}\n'
336 \phantomsection\label{contents}
337 \pdfbookmark[1]{Contents}{contents}
341 \section{1 first section%
342 \label{first-section}%
349 totest_latex_toc
['depth'] = [
359 head_template
.substitute(dict(parts
,
360 requirements
=parts
['requirements'] + '\\setcounter{secnumdepth}{0}\n'
362 \phantomsection\label{contents}
363 \pdfbookmark[1]{Contents}{contents}
364 \setcounter{tocdepth}{1}
368 \section{first section%
369 \label{first-section}%
376 totest_latex_toc_book
['depth'] = [
386 head_template
.substitute(dict(parts
,
387 head_prefix
=r
"""\documentclass[a4paper]{book}
389 requirements
=parts
['requirements'] + '\\setcounter{secnumdepth}{0}\n'
391 \phantomsection\label{contents}
392 \pdfbookmark[1]{Contents}{contents}
393 \setcounter{tocdepth}{0}
397 \chapter{first chapter%
398 \label{first-chapter}%
406 totest_latex_sectnum
['no_sectnum'] = [
415 head_template
.substitute(dict(parts
, requirements
= parts
['requirements'] +
416 r
"""\setcounter{secnumdepth}{0}
421 \section{first section%
422 \label{first-section}%
429 totest_latex_sectnum
['sectnum'] = [
440 head_template
.substitute(dict(parts
,
441 requirements
=parts
['requirements'] + '\\setcounter{secnumdepth}{0}\n'
446 \section{first section%
447 \label{first-section}%
454 totest_latex_citations
['citations_with_underscore'] = [
457 Just a test citation [my_cite2006]_.
460 The underscore is mishandled.
464 Just a test citation \cite{my_cite2006}.
466 \begin{thebibliography}{my\_cite2006}
467 \bibitem[my\_cite2006]{my_cite2006}{
468 The underscore is mishandled.
470 \end{thebibliography}
477 totest_latex_citations
['adjacent_citations'] = [
480 Two non-citations: [MeYou2007]_[YouMe2007]_.
482 Need to be separated for grouping: [MeYou2007]_ [YouMe2007]_.
484 Two spaces (or anything else) for no grouping: [MeYou2007]_ [YouMe2007]_.
486 But a line break should work: [MeYou2007]_
490 .. [YouMe2007] important.
494 Two non-citations: {[}MeYou2007{]}\_{[}YouMe2007{]}\_.
496 Need to be separated for grouping: \cite{MeYou2007,YouMe2007}.
498 Two spaces (or anything else) for no grouping: \cite{MeYou2007} \cite{YouMe2007}.
500 But a line break should work: \cite{MeYou2007,YouMe2007}.
502 \begin{thebibliography}{MeYou2007}
503 \bibitem[MeYou2007]{MeYou2007}{
506 \bibitem[YouMe2007]{YouMe2007}{
509 \end{thebibliography}
516 totest
['enumerated_lists'] = [
520 2. Second to the previous item this one will explain
527 (I) having pre and postfixes
528 (II) in roman numerals.
535 \item Second to the previous item this one will explain
540 \renewcommand{\labelenumi}{\alph{enumi})}
548 \setcounter{enumi}{2}
554 \renewcommand{\labelenumi}{(\Roman{enumi})}
555 \item having pre and postfixes
557 \item in roman numerals.
565 # TODO: need to test for quote replacing if the language uses "ASCII-quotes"
566 # as active character (e.g. de (ngerman)).
569 totest
['table_caption'] = [
581 \setlength{\DUtablewidth}{\linewidth}%
582 \begin{longtable}{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
595 totest
['table_styles'] = [
607 \setlength{\DUtablewidth}{\linewidth}%
608 \begin{longtable*}{p{0.075\DUtablewidth}p{0.075\DUtablewidth}}
632 \setlength{\DUtablewidth}{\linewidth}%
633 \begin{longtable*}{p{0.075\DUtablewidth}p{0.028\DUtablewidth}}
647 :class: colwidths-auto
654 \begin{longtable*}{|l|l|}
671 \begin{longtable*}{|l|l|}
688 \setlength{\DUtablewidth}{\linewidth}%
689 \begin{longtable*}{|p{0.191\DUtablewidth}|p{0.365\DUtablewidth}|}
703 totest_table_style_booktabs
['table_styles'] = [
704 # borderless overrides "booktabs" table_style
716 \setlength{\DUtablewidth}{\linewidth}%
717 \begin{longtable*}{p{0.075\DUtablewidth}p{0.075\DUtablewidth}}
741 \begin{longtable*}{ll}
758 \setlength{\DUtablewidth}{\linewidth}%
759 \begin{longtable*}{p{0.191\DUtablewidth}p{0.365\DUtablewidth}}
772 totest_table_style_auto
['table_styles'] = [
784 \begin{longtable*}{ll}
800 \begin{longtable*}{ll}
808 # given width overrides "colwidth-auto"
818 \setlength{\DUtablewidth}{\linewidth}%
819 \begin{longtable*}{|p{0.191\DUtablewidth}|p{0.365\DUtablewidth}|}
833 totest
['table_align'] = [
844 \setlength{\DUtablewidth}{\linewidth}%
845 \begin{longtable*}[r]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
859 totest
['table_empty_cells'] = [
868 \setlength{\DUtablewidth}{\linewidth}%
869 \begin{longtable*}{|p{0.075\DUtablewidth}|p{0.086\DUtablewidth}|}
882 \multicolumn{2}{p{0.16\DUtablewidth}}{\raggedleft\ldots continued on next page}\\
903 \setlength{\DUtablewidth}{\linewidth}%
904 \begin{longtable*}{|p{0.063\DUtablewidth}|p{0.063\DUtablewidth}|}
912 \multicolumn{2}{|p{0.13\DUtablewidth}|}{} \\
920 totest
['table_nonstandard_class'] = [
931 head_template
.substitute(
934 requirements
= parts
['requirements'] + parts
['longtable'],
936 % class handling for environments (block-level elements)
937 % \begin{DUclass}{spam} tries \DUCLASSspam and
938 % \end{DUclass}{spam} tries \endDUCLASSspam
939 \ifx\DUclass\undefined % poor man's "provideenvironment"
940 \newenvironment{DUclass}[1]%
941 {% "#1" does not work in end-part of environment.
942 \def\DocutilsClassFunctionName{DUCLASS#1}
943 \csname \DocutilsClassFunctionName \endcsname}%
944 {\csname end\DocutilsClassFunctionName \endcsname}%
949 \begin{DUclass}{my-class}
950 \setlength{\DUtablewidth}{\linewidth}%
951 \begin{longtable*}{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|}
972 # The "[" needs to be protected (otherwise it will be seen as an
973 # option to "\\", "\item", etc. ).
975 totest
['bracket_protection'] = [
978 * [no option] to this item
982 \item {[}no option{]} to this item
989 totest
['literal_block'] = [
992 Test special characters { [ \\\\ ] } in literal block::
999 Test special characters \{ {[} \textbackslash{} {]} \} in literal block:
1003 \{ [ ( \textbackslash{}macro
1020 .. |sub| raw:: latex
1045 compound paragraph continuation.
1047 head_template
.substitute(
1050 % class handling for environments (block-level elements)
1051 % \begin{DUclass}{spam} tries \DUCLASSspam and
1052 % \end{DUclass}{spam} tries \endDUCLASSspam
1053 \ifx\DUclass\undefined % poor man's "provideenvironment"
1054 \newenvironment{DUclass}[1]%
1055 {% "#1" does not work in end-part of environment.
1056 \def\DocutilsClassFunctionName{DUCLASS#1}
1057 \csname \DocutilsClassFunctionName \endcsname}%
1058 {\csname end\DocutilsClassFunctionName \endcsname}%
1063 \begin{DUclass}{compound}
1066 compound paragraph continuation.
1073 totest
['title_with_inline_markup'] = [
1078 This is the *Subtitle*
1079 ----------------------
1081 This is a *section title*
1082 ~~~~~~~~~~~~~~~~~~~~~~~~~
1084 This is the *document*.
1086 head_template
.substitute(dict(parts
,
1087 requirements
=parts
['requirements'] + '\\setcounter{secnumdepth}{0}\n',
1089 % subtitle (in document title)
1090 \providecommand*{\DUdocumentsubtitle}[1]{{\large #1}}
1092 pdfsetup
=parts
['pdfsetup'] + r
"""\hypersetup{
1093 pdftitle={This is the Title},
1095 """, titledata
=r
"""\title{This is the \emph{Title}%
1096 \label{this-is-the-title}%
1098 \DUdocumentsubtitle{This is the \emph{Subtitle}}%
1099 \label{this-is-the-subtitle}}
1102 """)) + r
"""\maketitle
1105 \section{This is a \emph{section title}%
1106 \label{this-is-a-section-title}%
1109 This is the \emph{document}.
1115 totest_stylesheet
['two-styles'] = [
1117 ["""two stylesheet links in the header""",
1118 head_template
.substitute(dict(parts
, stylesheet
=
1119 r
"""\usepackage{data/spam}
1120 \input{data/ham.tex}
1122 two stylesheet links in the header
1128 totest_stylesheet_embed
['two-styles'] = [
1130 ["""two stylesheets embedded in the header""",
1131 head_template
.substitute(dict(parts
, stylesheet
=
1132 r
"""% Cannot embed stylesheet 'data/spam.sty':
1133 % No such file or directory.
1134 % embedded stylesheet: data/ham.tex
1135 \newcommand{\ham}{wonderful ham}
1138 two stylesheets embedded in the header
1144 if __name__
== '__main__':
1146 unittest
.main(defaultTest
='suite')