diff options
| author | milde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2009-09-28 10:51:11 +0000 |
|---|---|---|
| committer | milde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04> | 2009-09-28 10:51:11 +0000 |
| commit | d1a332cc00a1b10df4c2b8fa6efdd3ca79dbf763 (patch) | |
| tree | 8a63e8832be3b635058bf2f5313c8024f2ecb53e /docutils | |
| parent | f917adfda4d59206e27f5f7b7925a1b4610ca131 (diff) | |
| download | docutils-d1a332cc00a1b10df4c2b8fa6efdd3ca79dbf763.tar.gz | |
Fix hyper-targets in captions, support custom roles based on "raw".
git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk@6145 929543f6-e4f2-0310-98a6-ba3bd3dd1d04
Diffstat (limited to 'docutils')
4 files changed, 131 insertions, 39 deletions
diff --git a/docutils/docutils/writers/latex2e/__init__.py b/docutils/docutils/writers/latex2e/__init__.py index 915ee78fa..3930581b6 100644 --- a/docutils/docutils/writers/latex2e/__init__.py +++ b/docutils/docutils/writers/latex2e/__init__.py @@ -619,13 +619,13 @@ class Table(object): def open(self): self._open = 1 self._col_specs = [] - self.caption = None + self.caption = [] self._attrs = {} self._in_head = 0 # maybe context with search def close(self): self._open = 0 self._col_specs = None - self.caption = None + self.caption = [] self._attrs = {} self.stubs = [] def is_open(self): @@ -715,9 +715,10 @@ class Table(object): def get_caption(self): if not self.caption: return '' + caption = ''.join(self.caption) if 1 == self._translator.thead_depth(): - return r'\caption{%s}\\' '\n' % self.caption - return r'\caption[]{%s (... continued)}\\' '\n' % self.caption + return r'\caption{%s}\\' '\n' % caption + return r'\caption[]{%s (... continued)}\\' '\n' % caption def need_recurse(self): if self._latex_type == 'longtable': @@ -953,6 +954,7 @@ class LaTeXTranslator(nodes.NodeVisitor): # Where to collect the output of visitor methods (default: body) self.out = self.body + self.out_stack = [] # stack of output collectors # Process settings # ~~~~~~~~~~~~~~~~ @@ -1257,6 +1259,12 @@ class LaTeXTranslator(nodes.NodeVisitor): labels.insert(0, '\\phantomsection') return labels + def push_output_collector(self, new_out): + self.out_stack.append(self.out) + self.out = new_out + + def pop_output_collector(self): + self.out = self.out_stack.pop() # Visitor methods # --------------- @@ -1511,10 +1519,10 @@ class LaTeXTranslator(nodes.NodeVisitor): pass def visit_docinfo(self, node): - self.out = self.docinfo + self.push_output_collector(self.docinfo) def depart_docinfo(self, node): - self.out = self.body + self.pop_output_collector() # Some itmes (e.g. author) end up at other places if self.docinfo: # tabularx: automatic width of columns, no page breaks allowed. @@ -1841,13 +1849,13 @@ class LaTeXTranslator(nodes.NodeVisitor): self.out.append(self.context.pop()) def visit_footer(self, node): - self.out = [] + self.push_output_collector([]) self.out.append(r'\newcommand{\DUfooter}{') def depart_footer(self, node): self.out.append('}') self.requirements['~footer'] = ''.join(self.out) - self.out = self.body + self.pop_output_collector() def visit_footnote(self, node): try: @@ -1901,7 +1909,7 @@ class LaTeXTranslator(nodes.NodeVisitor): else: self.fallbacks['footnotes'] = PreambleCmds.footnotes # TODO: second argument = backlink id - self.out.append(r'\DUfootnotemark{%s}{%s}{' % + self.out.append(r'\DUfootnotemark{%s}{%s}{' % (node['ids'][0], href)) self.context.append('}') @@ -1937,13 +1945,13 @@ class LaTeXTranslator(nodes.NodeVisitor): pass def visit_header(self, node): - self.out = [] + self.push_output_collector([]) self.out.append(r'\newcommand{\DUheader}{') def depart_header(self, node): self.out.append('}') self.requirements['~header'] = ''.join(self.out) - self.out = self.body + self.pop_output_collector() def visit_hint(self, node): self.visit_admonition(node) @@ -2125,7 +2133,7 @@ class LaTeXTranslator(nodes.NodeVisitor): if self.literal_block_env != '' and self.is_plaintext(node): self.requirements['literal_block'] = packages.get( self.literal_block_env, '') - self.verbatim = 1 + self.verbatim = True self.out.append('\\begin{%s}%s\n' % (self.literal_block_env, self.literal_block_options)) else: @@ -2247,9 +2255,17 @@ class LaTeXTranslator(nodes.NodeVisitor): self.out.append('}}') def visit_raw(self, node): - if 'latex' in node.get('format', '').split(): - self.out.append(node.astext()) - raise nodes.SkipNode + if not 'latex' in node.get('format', '').split(): + raise nodes.SkipNode + if node['classes']: + self.visit_inline(node) + # append "as-is" skipping any LaTeX-encoding + self.verbatim = True + + def depart_raw(self, node): + self.verbatim = False + if node['classes']: + self.depart_inline(node) def visit_reference(self, node): # BUG: hash_char '#' is troublesome in LaTeX. @@ -2413,7 +2429,11 @@ class LaTeXTranslator(nodes.NodeVisitor): ## self.out.append('%% %s\n' % node) # for debugging return self.out.append('%\n') - self.out += self.ids_to_labels(node) + # do we need an anchor (\phantomsection)? + set_anchor = not(isinstance(node.parent, nodes.caption) or + isinstance(node.parent, nodes.title)) + # TODO: where else can/must we omit the \phantomsection? + self.out += self.ids_to_labels(node, set_anchor) def depart_target(self, node): pass @@ -2505,9 +2525,8 @@ class LaTeXTranslator(nodes.NodeVisitor): self.context.append('}\n') # Table caption elif isinstance(node.parent, nodes.table): - # caption must be written after column spec - self.active_table.caption = self.encode(node.astext()) - raise nodes.SkipNode + self.push_output_collector(self.active_table.caption) + self.context.append('') # Section title else: self.out.append('\n\n') @@ -2533,6 +2552,8 @@ class LaTeXTranslator(nodes.NodeVisitor): def depart_title(self, node): self.out.append(self.context.pop()) + if isinstance(node.parent, nodes.table): + self.pop_output_collector() def minitoc(self, title, depth): """Generate a local table of contents with LaTeX package minitoc""" @@ -2604,7 +2625,7 @@ class LaTeXTranslator(nodes.NodeVisitor): self.context.append('') elif ('abstract' in node['classes'] and self.settings.use_latex_abstract): - self.out = self.abstract + self.push_output_collector(self.abstract) self.out.append('\\begin{abstract}') self.context.append('\\end{abstract}\n') if isinstance(node.next_node(), nodes.title): @@ -2614,17 +2635,19 @@ class LaTeXTranslator(nodes.NodeVisitor): # special topics: if 'abstract' in node['classes']: self.fallbacks['abstract'] = PreambleCmds.abstract - self.out = self.abstract + self.push_output_collector(self.abstract) if 'dedication' in node['classes']: self.fallbacks['dedication'] = PreambleCmds.dedication - self.out = self.dedication + self.push_output_collector(self.dedication) self.out.append('\n\\DUtopic[%s]{\n' % ','.join(node['classes'])) self.context.append('}\n') def depart_topic(self, node): self.out.append(self.context.pop()) self.is_toc_list = False - self.out = self.body + if ('abstract' in node['classes'] or + 'dedication' in node['classes']): + self.pop_output_collector() def visit_inline(self, node): # <span>, i.e. custom roles # insert fallback definition diff --git a/docutils/test/functional/expected/standalone_rst_latex.tex b/docutils/test/functional/expected/standalone_rst_latex.tex index e87402ce6..41388901d 100644 --- a/docutils/test/functional/expected/standalone_rst_latex.tex +++ b/docutils/test/functional/expected/standalone_rst_latex.tex @@ -375,6 +375,8 @@ reStructuredText construct. \item \hyperref[encoding-special-chars]{3.5~~~Encoding special chars} +\item \hyperref[hyperlinks-and-targets]{3.6~~~Hyperlinks and -targets} + \end{list} \item \hyperref[error-handling]{4~~~Error Handling} @@ -926,8 +928,8 @@ This footnote shows the next symbol in the sequence. \begin{figure}[b]\raisebox{1em}{\hypertarget{id16}{}}\phantomsection\label{id16}\textsuperscript{4} Here's an unreferenced footnote, with a reference to a nonexistent footnote:% -\raisebox{1em}{\hypertarget{id86}{}}% -\raisebox{1em}{\hypertarget{id17}{}}\hyperlink{id85}{\textbf{\color{red}{[}5{]}\_}}. +\raisebox{1em}{\hypertarget{id87}{}}% +\raisebox{1em}{\hypertarget{id17}{}}\hyperlink{id86}{\textbf{\color{red}{[}5{]}\_}}. \end{figure} @@ -944,8 +946,8 @@ rendered separately and differently from footnotes. \end{figure} Here's a reference to the above, [\hyperlink{cit2002}{CIT2002}], and a % -\raisebox{1em}{\hypertarget{id88}{}}% -\raisebox{1em}{\hypertarget{id19}{}}\hyperlink{id87}{\textbf{\color{red}{[}nonexistent{]}\_}} +\raisebox{1em}{\hypertarget{id89}{}}% +\raisebox{1em}{\hypertarget{id19}{}}\hyperlink{id88}{\textbf{\color{red}{[}nonexistent{]}\_}} citation. @@ -973,7 +975,7 @@ Targets may be indirect and anonymous. Thus \hyperref[targets]{this phrase} may refer to the \hyperref[targets]{Targets} section. Here's a % -\raisebox{1em}{\hypertarget{id90}{}}\hyperlink{id89}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an +\raisebox{1em}{\hypertarget{id91}{}}\hyperlink{id90}{\textbf{\color{red}`hyperlink reference without a target`\_}}, which generates an error. @@ -1001,7 +1003,7 @@ explicit targets will generate ``warning'' (level-2) system messages. Since there are two ``Duplicate Target Names'' section headers, we cannot uniquely refer to either of them by name. If we try to (like this: % -\raisebox{1em}{\hypertarget{id92}{}}\hyperlink{id91}{\textbf{\color{red}`Duplicate Target Names`\_}}), an error is generated. +\raisebox{1em}{\hypertarget{id93}{}}\hyperlink{id92}{\textbf{\color{red}`Duplicate Target Names`\_}}), an error is generated. %___________________________________________________________________________ @@ -1481,8 +1483,8 @@ Here's one: This does not necessarily look nice, because there may be missing white space. It's just there to freeze the behavior. -A test.Second test.Another test with myclass set. -This is the fourth test with myrawroleclass set. +A test.Second test.\DUrole{myclass}{Another test with myclass set.} +This is the \DUrole{myrawroleclass}{fourth test} with myrawroleclass set. Fifth test in LaTeX.\\Line two. %___________________________________________________________________________ @@ -1990,6 +1992,49 @@ greater-than and bar, \textless{} \textbar{} \textgreater{}, except for typewrit } \end{quote} + +%___________________________________________________________________________ + +\subsection*{3.6~~~Hyperlinks and -targets% + \phantomsection% + \addcontentsline{toc}{subsection}{3.6~~~Hyperlinks and -targets}% + \label{hyperlinks-and-targets}% +} + +In LaTeX, we must set an explicit anchor (\texttt{\reflectbox{/}phantomsection}) for a +% +\phantomsection\label{hypertarget-in-plain-text}hypertarget in plain text but not in a table or figure caption: + +\leavevmode +\setlength{\DUtablewidth}{\linewidth} +\begin{longtable}[c]{|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|p{0.075\DUtablewidth}|} +\caption{Table with % +\label{hypertarget-in-table-title}hypertarget in table title.}\\ +\hline + +False + & +True + & +None + \\ +\hline +\end{longtable} +\begin{figure} +\noindent\makebox[\textwidth][c]{\includegraphics{../../../docs/user/rst/images/biohazard.png}} +\caption{Figure with % +\label{hypertarget-in-figure-caption}hypertarget in figure caption.} +\begin{DUlegend} +Legend with % +\phantomsection\label{hypertarget-in-figure-legend}hypertarget in figure legend. +\end{DUlegend} +\end{figure} + +See \hyperref[hypertarget-in-plain-text]{hypertarget in plain text}, +\hyperref[hypertarget-in-table-title]{hypertarget in table title}, +\hyperref[hypertarget-in-figure-caption]{hypertarget in figure caption}, and +\hyperref[hypertarget-in-figure-legend]{hypertarget in figure legend}, + % unusual combinations (from newlatex, for interactive testing) % .. include:: data/latex.txt @@ -2031,41 +2076,41 @@ Undefined substitution referenced: ``problematic''. \DUadmonition[system-message]{ \DUtitle[system-message]{system-message} -\raisebox{1em}{\hypertarget{id85}{}} +\raisebox{1em}{\hypertarget{id86}{}} {\color{red}ERROR/3} in \texttt{functional/input/standalone\_rst\_latex.txt}, line~359 -\hyperlink{id86}{ +\hyperlink{id87}{ Unknown target name: ``5''. }} \DUadmonition[system-message]{ \DUtitle[system-message]{system-message} -\raisebox{1em}{\hypertarget{id87}{}} +\raisebox{1em}{\hypertarget{id88}{}} {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~368 -\hyperlink{id88}{ +\hyperlink{id89}{ Unknown target name: ``nonexistent''. }} \DUadmonition[system-message]{ \DUtitle[system-message]{system-message} -\raisebox{1em}{\hypertarget{id89}{}} +\raisebox{1em}{\hypertarget{id90}{}} {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~395 -\hyperlink{id90}{ +\hyperlink{id91}{ Unknown target name: ``hyperlink reference without a target''. }} \DUadmonition[system-message]{ \DUtitle[system-message]{system-message} -\raisebox{1em}{\hypertarget{id91}{}} +\raisebox{1em}{\hypertarget{id92}{}} {\color{red}ERROR/3} in \texttt{functional/input/data/standard.txt}, line~408 -\hyperlink{id92}{ +\hyperlink{id93}{ Duplicate target name, cannot be used as a unique reference: ``duplicate target names''. }} diff --git a/docutils/test/functional/input/data/hyperlinking.txt b/docutils/test/functional/input/data/hyperlinking.txt new file mode 100644 index 000000000..495f4b34f --- /dev/null +++ b/docutils/test/functional/input/data/hyperlinking.txt @@ -0,0 +1,23 @@ +Hyperlinks and -targets +----------------------- + +In LaTeX, we must set an explicit anchor (``\phantomsection``) for a +_`hypertarget in plain text` but not in a table or figure caption: + +.. table:: Table with _`hypertarget in table title`. + + ===== ===== ===== + False True None + ===== ===== ===== + +.. figure:: ../../../docs/user/rst/images/biohazard.png + + Figure with _`hypertarget in figure caption`. + + Legend with _`hypertarget in figure legend`. + +See `hypertarget in plain text`_, +`hypertarget in table title`_, +`hypertarget in figure caption`_, and +`hypertarget in figure legend`_, + diff --git a/docutils/test/functional/input/standalone_rst_latex.txt b/docutils/test/functional/input/standalone_rst_latex.txt index 2b1331394..3fb55ed8c 100644 --- a/docutils/test/functional/input/standalone_rst_latex.txt +++ b/docutils/test/functional/input/standalone_rst_latex.txt @@ -16,6 +16,7 @@ not need to be tested with other writers (e.g. the HTML writer). .. include:: data/nonalphanumeric.txt .. include:: data/unicode.txt .. include:: data/latex_encoding.txt +.. include:: data/hyperlinking.txt .. unusual combinations (from newlatex, for interactive testing) .. include:: data/latex.txt |
