diff options
| author | John MacFarlane <[email protected]> | 2023-08-26 16:15:20 -0700 |
|---|---|---|
| committer | John MacFarlane <[email protected]> | 2023-08-26 16:19:01 -0700 |
| commit | f7035d080c617cda3804a7d0932da8283a5c681c (patch) | |
| tree | 996d8a89d682dc15798ae1a1ab6299ea90a17e66 /src | |
| parent | 99340446685eed812895c7fb7028979dc6975ab3 (diff) | |
LaTeX writer link/target improvements.
+ Use `\phantomsection` and `\label` instead of `\hypertarget`.
+ Use `\hyperref` for LaTeX internal links, `\hyperlink` for
beamer (since `\hyperref` doesn't seem to work).
Closes #9022.
Diffstat (limited to 'src')
| -rw-r--r-- | src/Text/Pandoc/Writers/LaTeX.hs | 54 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/LaTeX/Util.hs | 14 |
2 files changed, 27 insertions, 41 deletions
diff --git a/src/Text/Pandoc/Writers/LaTeX.hs b/src/Text/Pandoc/Writers/LaTeX.hs index 3585e1544..d12890bd5 100644 --- a/src/Text/Pandoc/Writers/LaTeX.hs +++ b/src/Text/Pandoc/Writers/LaTeX.hs @@ -281,11 +281,9 @@ blockToLaTeX (Div attr@(identifier,"block":dclasses,_) | "example" `elem` dclasses = "exampleblock" | "alert" `elem` dclasses = "alertblock" | otherwise = "block" - ref <- toLabel identifier - let anchor = if T.null identifier - then empty - else cr <> "\\protect\\hypertarget" <> - braces (literal ref) <> braces empty + anchor <- if T.null identifier + then pure empty + else (cr <>) <$> hypertarget identifier title' <- inlineListToLaTeX ils contents <- blockListToLaTeX bs wrapDiv attr $ ("\\begin" <> braces blockname <> braces title' <> anchor) $$ @@ -318,11 +316,9 @@ blockToLaTeX (Div (identifier,"slide":dclasses,dkvs) slideTitle <- if ils == [Str "\0"] -- marker for hrule then return empty else braces <$> inlineListToLaTeX ils - ref <- toLabel identifier - let slideAnchor = if T.null identifier - then empty - else cr <> "\\protect\\hypertarget" <> - braces (literal ref) <> braces empty + slideAnchor <- if T.null identifier + then pure empty + else (cr <>) <$> hypertarget identifier contents <- blockListToLaTeX bs >>= wrapDiv (identifier,classes,kvs) return $ ("\\begin{frame}" <> options <> slideTitle <> slideAnchor) $$ contents $$ "\\end{frame}" @@ -354,16 +350,8 @@ blockToLaTeX (Div (identifier,classes,kvs) bs) = do $+$ "\\end{CSLReferences}" else blockListToLaTeX bs modify $ \st -> st{ stIncremental = oldIncremental } - linkAnchor' <- hypertarget True identifier empty - -- see #2704 for the motivation for adding \leavevmode - -- and #7078 for \vadjust pre - let linkAnchor = - case bs of - Para _ : _ - | not (isEmpty linkAnchor') - -> "\\leavevmode\\vadjust pre{" <> linkAnchor' <> "}%" - _ -> linkAnchor' - wrapNotes txt = if beamer && "notes" `elem` classes + linkAnchor <- hypertarget identifier + let wrapNotes txt = if beamer && "notes" `elem` classes then "\\note" <> braces txt -- speaker notes else linkAnchor $$ txt wrapNotes <$> wrapDiv (identifier,classes,kvs) result @@ -396,12 +384,10 @@ blockToLaTeX (BlockQuote lst) = do return $ "\\begin{quote}" $$ contents $$ "\\end{quote}" blockToLaTeX (CodeBlock (identifier,classes,keyvalAttr) str) = do opts <- gets stOptions - lab <- labelFor identifier inNote <- stInNote <$> get - linkAnchor' <- hypertarget True identifier lab - let linkAnchor = if isEmpty linkAnchor' - then empty - else linkAnchor' <> "%" + linkAnchor <- if T.null identifier + then pure empty + else ((<> cr) . (<> "%")) <$> hypertarget identifier let lhsCodeBlock = do modify $ \s -> s{ stLHS = True } return $ flush (linkAnchor $$ "\\begin{code}" $$ literal str $$ @@ -575,8 +561,8 @@ blockToLaTeX (Figure (ident, _, _) captnode body) = do [b] -> blockToLaTeX b bs -> mconcat . intersperse (cr <> "\\hfill") <$> mapM (toSubfigure (length bs)) bs - innards <- hypertarget True ident $ - "\\centering" $$ contents $$ caption <> cr + target <- hypertarget ident + let innards = target $$ "\\centering" $$ contents $$ caption <> cr modify $ \st -> st{ stInFigure = isSubfigure , stSubfigure = stSubfigure st || isSubfigure @@ -777,7 +763,7 @@ inlineToLaTeX (Span ("",["mark"],[]) lst) = do modify $ \st -> st{ stStrikeout = True } -- this gives us the soul package inCmd "hl" <$> inlineListToLaTeX lst inlineToLaTeX (Span (id',classes,kvs) ils) = do - linkAnchor <- hypertarget False id' empty + linkAnchor <- hypertarget id' lang <- toLang $ lookup "lang" kvs let classToCmd "csl-no-emph" = Just "textup" classToCmd "csl-no-strong" = Just "textnormal" @@ -806,7 +792,7 @@ inlineToLaTeX (Span (id',classes,kvs) ils) = do else id) $ (if T.null id' then empty - else "\\protect" <> linkAnchor) <> + else linkAnchor) <> (if null cmds then braces contents else foldr inCmd contents cmds) @@ -959,7 +945,11 @@ inlineToLaTeX (Link (id',_,_) txt (src,_)) = Just ('#', ident) -> do contents <- inlineListToLaTeX txt lab <- toLabel ident - return $ text "\\hyperref" <> brackets (literal lab) <> braces contents + beamer <- gets stBeamer + return $ + if beamer + then text "\\hyperlink" <> braces (literal lab) <> braces contents + else text "\\hyperref" <> brackets (literal lab) <> braces contents _ -> case txt of [Str x] | unEscapeString (T.unpack x) == unEscapeString (T.unpack src) -> -- autolink do modify $ \s -> s{ stUrl = True } @@ -979,8 +969,8 @@ inlineToLaTeX (Link (id',_,_) txt (src,_)) = >>= (if T.null id' then return else \x -> do - linkAnchor <- hypertarget False id' x - return ("\\protect" <> linkAnchor)) + linkAnchor <- hypertarget id' + return (linkAnchor <> x)) inlineToLaTeX il@(Image _ _ (src, _)) | Just _ <- T.stripPrefix "data:" src = do report $ InlineNotRendered il diff --git a/src/Text/Pandoc/Writers/LaTeX/Util.hs b/src/Text/Pandoc/Writers/LaTeX/Util.hs index 79937e1fa..fbdd7a59c 100644 --- a/src/Text/Pandoc/Writers/LaTeX/Util.hs +++ b/src/Text/Pandoc/Writers/LaTeX/Util.hs @@ -254,15 +254,11 @@ wrapDiv (_,classes,kvs) t = do Nothing -> txt return $ wrapColumns . wrapColumn . wrapDir . wrapLang $ t -hypertarget :: PandocMonad m => Bool -> Text -> Doc Text -> LW m (Doc Text) -hypertarget _ "" x = return x -hypertarget addnewline ident x = do - ref <- literal `fmap` toLabel ident - return $ text "\\hypertarget" - <> braces ref - <> braces ((if addnewline && not (isEmpty x) - then "%" <> cr - else empty) <> x) +hypertarget :: PandocMonad m => Text -> LW m (Doc Text) +hypertarget "" = return mempty +hypertarget ident = do + label <- labelFor ident + return $ text "\\phantomsection" <> label labelFor :: PandocMonad m => Text -> LW m (Doc Text) labelFor "" = return empty |
