summaryrefslogtreecommitdiff
path: root/docutils
diff options
context:
space:
mode:
authormilde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2009-09-28 10:51:11 +0000
committermilde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2009-09-28 10:51:11 +0000
commitd1a332cc00a1b10df4c2b8fa6efdd3ca79dbf763 (patch)
tree8a63e8832be3b635058bf2f5313c8024f2ecb53e /docutils
parentf917adfda4d59206e27f5f7b7925a1b4610ca131 (diff)
downloaddocutils-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')
-rw-r--r--docutils/docutils/writers/latex2e/__init__.py69
-rw-r--r--docutils/test/functional/expected/standalone_rst_latex.tex77
-rw-r--r--docutils/test/functional/input/data/hyperlinking.txt23
-rw-r--r--docutils/test/functional/input/standalone_rst_latex.txt1
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