From fe4311d5a1482ab2e0edfe78c556bf28fc50adf7 Mon Sep 17 00:00:00 2001 From: John MacFarlane Date: Wed, 1 Mar 2017 21:38:28 +0100 Subject: LaTeX writer: always add hypertarget when there's a non-empty identifier. Previously the hypertargets were only added when there was actually a link to that identifier. Closes #2719. --- src/Text/Pandoc/Writers/LaTeX.hs | 48 ++++++++------------- test/Tests/Writers/LaTeX.hs | 2 +- test/lhs-test.latex | 3 +- test/lhs-test.latex+lhs | 3 +- test/writer.latex | 93 ++++++++++++++++++++++++++-------------- test/writers-lang-and-dir.latex | 12 ++++-- 6 files changed, 94 insertions(+), 67 deletions(-) diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index 07cd6bc8b..054a16259 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -418,11 +418,7 @@ blockToLaTeX :: PandocMonad m blockToLaTeX Null = return empty blockToLaTeX (Div (identifier,classes,kvs) bs) = do beamer <- gets stBeamer - ref <- toLabel identifier - let linkAnchor = if null identifier - then empty - else "\\hypertarget" <> braces (text ref) <> - braces empty + linkAnchor <- hypertarget True identifier empty let align dir txt = inCmd "begin" dir $$ txt $$ inCmd "end" dir let wrapDir = case lookup "dir" kvs of Just "rtl" -> align "RTL" @@ -459,13 +455,13 @@ blockToLaTeX (Para [Image attr@(ident, _, _) txt (src,'f':'i':'g':':':tit)]) = d let footnotes = notesToLaTeX notes lab <- labelFor ident let caption = "\\caption" <> captForLof <> braces capt <> lab - figure <- hypertarget ident (cr <> - "\\begin{figure}" $$ "\\centering" $$ img $$ - caption $$ "\\end{figure}" <> cr) + let figure = cr <> "\\begin{figure}" $$ "\\centering" $$ img $$ + caption $$ "\\end{figure}" <> cr + figure' <- hypertarget True ident figure return $ if inNote -- can't have figures in notes then "\\begin{center}" $$ img $+$ capt $$ "\\end{center}" - else figure $$ footnotes + else figure' $$ footnotes -- . . . indicates pause in beamer slides blockToLaTeX (Para [Str ".",Space,Str ".",Space,Str "."]) = do beamer <- gets stBeamer @@ -493,11 +489,8 @@ blockToLaTeX (BlockQuote lst) = do return $ "\\begin{quote}" $$ contents $$ "\\end{quote}" blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do opts <- gets stOptions - ref <- toLabel identifier - let linkAnchor = if null identifier - then empty - else "\\hypertarget" <> braces (text ref) <> - braces ("\\label" <> braces (text ref)) + lab <- labelFor identifier + linkAnchor <- hypertarget True identifier lab let lhsCodeBlock = do modify $ \s -> s{ stLHS = True } return $ flush (linkAnchor $$ "\\begin{code}" $$ text str $$ @@ -512,6 +505,7 @@ blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do text str $$ text ("\\end{" ++ env ++ "}")) <> cr let listingsCodeBlock = do st <- get + ref <- toLabel identifier let params = if writerListings (stOptions st) then (case getListingsLanguage classes of Just l -> [ "language=" ++ mbBraced l ] @@ -830,7 +824,8 @@ sectionHeader unnumbered ident level lst = do lab <- labelFor ident let star = if unnumbered && level' < 4 then text "*" else empty let stuffing = star <> optional <> contents - stuffing' <- hypertarget ident $ text ('\\':sectionType) <> stuffing <> lab + stuffing' <- hypertarget True ident $ + text ('\\':sectionType) <> stuffing <> lab return $ if level' > 5 then txt else prefix $$ stuffing' @@ -840,16 +835,13 @@ sectionHeader unnumbered ident level lst = do braces txtNoNotes else empty -hypertarget :: PandocMonad m => String -> Doc -> LW m Doc -hypertarget ident x = do +hypertarget :: PandocMonad m => Bool -> String -> Doc -> LW m Doc +hypertarget _ "" x = return x +hypertarget addnewline ident x = do ref <- text `fmap` toLabel ident - internalLinks <- gets stInternalLinks - return $ - if ident `elem` internalLinks - then text "\\hypertarget" + return $ text "\\hypertarget" <> braces ref - <> braces x - else x + <> braces ((if addnewline then ("%" <> cr) else empty) <> x) labelFor :: PandocMonad m => String -> LW m Doc labelFor "" = return empty @@ -892,11 +884,7 @@ inlineToLaTeX :: PandocMonad m => Inline -- ^ Inline to convert -> LW m Doc inlineToLaTeX (Span (id',classes,kvs) ils) = do - ref <- toLabel id' - let linkAnchor = if null id' - then empty - else "\\protect\\hypertarget" <> braces (text ref) <> - braces empty + linkAnchor <- hypertarget False id' empty let cmds = ["textup" | "csl-no-emph" `elem` classes] ++ ["textnormal" | "csl-no-strong" `elem` classes || "csl-no-smallcaps" `elem` classes] ++ @@ -908,7 +896,9 @@ inlineToLaTeX (Span (id',classes,kvs) ils) = do in ["text" ++ l ++ ops] Nothing -> []) contents <- inlineListToLaTeX ils - return $ linkAnchor <> + return $ (if null id' + then empty + else "\\protect" <> linkAnchor) <> if null cmds then braces contents else foldr inCmd contents cmds diff --git a/test/Tests/Writers/LaTeX.hs b/test/Tests/Writers/LaTeX.hs index f54aef4dc..fc4212aed 100644 --- a/test/Tests/Writers/LaTeX.hs +++ b/test/Tests/Writers/LaTeX.hs @@ -58,7 +58,7 @@ tests = [ testGroup "code blocks" [ "unnumbered header" =: headerWith ("foo",["unnumbered"],[]) 1 (text "Header 1" <> note (plain $ text "note")) =?> - "\\section*{\\texorpdfstring{Header 1\\footnote{note}}{Header 1}}\\label{foo}\n\\addcontentsline{toc}{section}{Header 1}\n" + "\\hypertarget{foo}{%\n\\section*{\\texorpdfstring{Header 1\\footnote{note}}{Header 1}}\\label{foo}}\n\\addcontentsline{toc}{section}{Header 1}\n" , "in list item" =: bulletList [header 2 (text "foo")] =?> "\\begin{itemize}\n\\item ~\n \\subsection{foo}\n\\end{itemize}" diff --git a/test/lhs-test.latex b/test/lhs-test.latex index bc02b6ae5..3ca8f97c8 100644 --- a/test/lhs-test.latex +++ b/test/lhs-test.latex @@ -91,7 +91,8 @@ \begin{document} -\section{lhs test}\label{lhs-test} +\hypertarget{lhs-test}{% +\section{lhs test}\label{lhs-test}} \texttt{unsplit} is an arrow that takes a pair of values and combines them to return a single value: diff --git a/test/lhs-test.latex+lhs b/test/lhs-test.latex+lhs index 64271b415..3509cb4a6 100644 --- a/test/lhs-test.latex+lhs +++ b/test/lhs-test.latex+lhs @@ -55,7 +55,8 @@ \begin{document} -\section{lhs test}\label{lhs-test} +\hypertarget{lhs-test}{% +\section{lhs test}\label{lhs-test}} \texttt{unsplit} is an arrow that takes a pair of values and combines them to return a single value: diff --git a/test/writer.latex b/test/writer.latex index 8f834df8f..f88621a28 100644 --- a/test/writer.latex +++ b/test/writer.latex @@ -77,34 +77,44 @@ markdown test suite. \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Headers}\label{headers} +\hypertarget{headers}{% +\section{Headers}\label{headers}} +\hypertarget{level-2-with-an-embedded-link}{% \subsection{\texorpdfstring{Level 2 with an \href{/url}{embedded -link}}{Level 2 with an embedded link}}\label{level-2-with-an-embedded-link} +link}}{Level 2 with an embedded link}}\label{level-2-with-an-embedded-link}} +\hypertarget{level-3-with-emphasis}{% \subsubsection{\texorpdfstring{Level 3 with -\emph{emphasis}}{Level 3 with emphasis}}\label{level-3-with-emphasis} +\emph{emphasis}}{Level 3 with emphasis}}\label{level-3-with-emphasis}} -\paragraph{Level 4}\label{level-4} +\hypertarget{level-4}{% +\paragraph{Level 4}\label{level-4}} -\subparagraph{Level 5}\label{level-5} +\hypertarget{level-5}{% +\subparagraph{Level 5}\label{level-5}} -\section{Level 1}\label{level-1} +\hypertarget{level-1}{% +\section{Level 1}\label{level-1}} +\hypertarget{level-2-with-emphasis}{% \subsection{\texorpdfstring{Level 2 with -\emph{emphasis}}{Level 2 with emphasis}}\label{level-2-with-emphasis} +\emph{emphasis}}{Level 2 with emphasis}}\label{level-2-with-emphasis}} -\subsubsection{Level 3}\label{level-3} +\hypertarget{level-3}{% +\subsubsection{Level 3}\label{level-3}} with no blank line -\subsection{Level 2}\label{level-2} +\hypertarget{level-2}{% +\subsection{Level 2}\label{level-2}} with no blank line \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Paragraphs}\label{paragraphs} +\hypertarget{paragraphs}{% +\section{Paragraphs}\label{paragraphs}} Here's a regular paragraph. @@ -119,7 +129,8 @@ here. \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Block Quotes}\label{block-quotes} +\hypertarget{block-quotes}{% +\section{Block Quotes}\label{block-quotes}} E-mail style: @@ -164,7 +175,8 @@ And a following paragraph. \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Code Blocks}\label{code-blocks} +\hypertarget{code-blocks}{% +\section{Code Blocks}\label{code-blocks}} Code: @@ -188,9 +200,11 @@ These should not be escaped: \$ \\ \> \[ \{ \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Lists}\label{lists} +\hypertarget{lists}{% +\section{Lists}\label{lists}} -\subsection{Unordered}\label{unordered} +\hypertarget{unordered}{% +\subsection{Unordered}\label{unordered}} Asterisks tight: @@ -261,7 +275,8 @@ Minuses loose: Minus 3 \end{itemize} -\subsection{Ordered}\label{ordered} +\hypertarget{ordered}{% +\subsection{Ordered}\label{ordered}} Tight: @@ -327,7 +342,8 @@ Multiple paragraphs: Item 3. \end{enumerate} -\subsection{Nested}\label{nested} +\hypertarget{nested}{% +\subsection{Nested}\label{nested}} \begin{itemize} \tightlist @@ -392,7 +408,8 @@ Same thing but with paragraphs: Third \end{enumerate} -\subsection{Tabs and spaces}\label{tabs-and-spaces} +\hypertarget{tabs-and-spaces}{% +\subsection{Tabs and spaces}\label{tabs-and-spaces}} \begin{itemize} \item @@ -408,7 +425,8 @@ Same thing but with paragraphs: \end{itemize} \end{itemize} -\subsection{Fancy list markers}\label{fancy-list-markers} +\hypertarget{fancy-list-markers}{% +\subsection{Fancy list markers}\label{fancy-list-markers}} \begin{enumerate} \def\labelenumi{(\arabic{enumi})} @@ -496,7 +514,8 @@ B. Williams \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Definition Lists}\label{definition-lists} +\hypertarget{definition-lists}{% +\section{Definition Lists}\label{definition-lists}} Tight using spaces: @@ -599,7 +618,8 @@ orange fruit \end{enumerate} \end{description} -\section{HTML Blocks}\label{html-blocks} +\hypertarget{html-blocks}{% +\section{HTML Blocks}\label{html-blocks}} Simple block on one line: @@ -661,7 +681,8 @@ Hr's: \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Inline Markup}\label{inline-markup} +\hypertarget{inline-markup}{% +\section{Inline Markup}\label{inline-markup}} This is \emph{emphasized}, and so \emph{is this}. @@ -693,7 +714,8 @@ spaces: a\^{}b c\^{}d, a\textasciitilde{}b c\textasciitilde{}d. \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Smart quotes, ellipses, dashes}\label{smart-quotes-ellipses-dashes} +\hypertarget{smart-quotes-ellipses-dashes}{% +\section{Smart quotes, ellipses, dashes}\label{smart-quotes-ellipses-dashes}} ``Hello,'' said the spider. ``\,`Shelob' is my name.'' @@ -714,7 +736,8 @@ Ellipses\ldots{}and\ldots{}and\ldots{}. \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{LaTeX}\label{latex} +\hypertarget{latex}{% +\section{LaTeX}\label{latex}} \begin{itemize} \tightlist @@ -762,7 +785,8 @@ Cat & 1 \\ \hline \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Special Characters}\label{special-characters} +\hypertarget{special-characters}{% +\section{Special Characters}\label{special-characters}} Here is some unicode: @@ -824,9 +848,11 @@ Minus: - \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Links}\label{links} +\hypertarget{links}{% +\section{Links}\label{links}} -\subsection{Explicit}\label{explicit} +\hypertarget{explicit}{% +\subsection{Explicit}\label{explicit}} Just a \href{/url/}{URL}. @@ -846,7 +872,8 @@ Just a \href{/url/}{URL}. \href{}{Empty}. -\subsection{Reference}\label{reference} +\hypertarget{reference}{% +\subsection{Reference}\label{reference}} Foo \href{/url/}{bar}. @@ -874,7 +901,8 @@ Foo \href{/url/}{bar}. Foo \href{/url/}{biz}. -\subsection{With ampersands}\label{with-ampersands} +\hypertarget{with-ampersands}{% +\subsection{With ampersands}\label{with-ampersands}} Here's a \href{http://example.com/?foo=1\&bar=2}{link with an ampersand in the URL}. @@ -886,7 +914,8 @@ Here's an \href{/script?foo=1\&bar=2}{inline link}. Here's an \href{/script?foo=1\&bar=2}{inline link in pointy braces}. -\subsection{Autolinks}\label{autolinks} +\hypertarget{autolinks}{% +\subsection{Autolinks}\label{autolinks}} With an ampersand: \url{http://example.com/?foo=1\&bar=2} @@ -916,7 +945,8 @@ or here: \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Images}\label{images} +\hypertarget{images}{% +\section{Images}\label{images}} From ``Voyage dans la Lune'' by Georges Melies (1902): @@ -930,7 +960,8 @@ Here is a movie \includegraphics{movie.jpg} icon. \begin{center}\rule{0.5\linewidth}{\linethickness}\end{center} -\section{Footnotes}\label{footnotes} +\hypertarget{footnotes}{% +\section{Footnotes}\label{footnotes}} Here is a footnote reference,\footnote{Here is the footnote. It can go anywhere after the footnote reference. It need not be placed at the end of diff --git a/test/writers-lang-and-dir.latex b/test/writers-lang-and-dir.latex index 1c705399b..cba3dd96b 100644 --- a/test/writers-lang-and-dir.latex +++ b/test/writers-lang-and-dir.latex @@ -84,7 +84,8 @@ \begin{document} -\section{Empty Divs and Spans}\label{empty-divs-and-spans} +\hypertarget{empty-divs-and-spans}{% +\section{Empty Divs and Spans}\label{empty-divs-and-spans}} Some text and @@ -94,7 +95,8 @@ and more text. Next paragraph with a {span} and a word-thatincludesa{span}right? -\section{Directionality}\label{directionality} +\hypertarget{directionality}{% +\section{Directionality}\label{directionality}} Some text and @@ -111,7 +113,8 @@ and a ltr div. with a \RL{rtl span}. Next paragraph with a \RL{rtl span} and a word-that-includesa\LR{ltrspan}right? -\section{Languages}\label{languages} +\hypertarget{languages}{% +\section{Languages}\label{languages}} Some text and @@ -128,7 +131,8 @@ word-that-includesa\textgerman[variant=swiss]{Swiss German span}right? Some \textspanish{Spanish text}. -\section{Combined}\label{combined} +\hypertarget{combined}{% +\section{Combined}\label{combined}} Some text and -- cgit v1.2.3