git.iko.soy/typeable/pandoc
on master help sign in
Powerpoint writer: Ignore internal links without targets.

If the user entered an internal link without a corresponding anchor, it would produce a corrupted file. Now we check the anchor map, and make sure the target is in the file. If it isn't, we ignore it.

commit53c48dd2c9417916bfaa15be15fad992c9659af9 authorJesse Rosenthal <jrosenthal@jhu.edu> dateFri 12 Jan 2018, 09:45 (9 years ago) parent0b66b56
1 file changed+31−12
src/Text/Pandoc/Writers/Powerpoint.hs+31−12
src/Text/Pandoc/Writers/Powerpoint.hs+31−12
@@ -57,7 +57,7 @@ import Text.Pandoc.Walk
5757import Text.Pandoc.Writers.Shared (fixDisplayMath)
5858import Text.Pandoc.Writers.OOXML
5959import qualified Data.Map as M
60−import Data.Maybe (mapMaybe, listToMaybe, maybeToList)
60+import Data.Maybe (mapMaybe, listToMaybe, maybeToList, catMaybes)
6161import Text.Pandoc.ImageSize
6262import Control.Applicative ((<|>))
6363
@@ -1158,13 +1158,27 @@ paraElemToElement (Run rpr s) = do
11581158 linkProps <- case rLink rpr of
11591159 Just link -> do
11601160 idNum <- registerLink link
1161− let (url, _) = link
1162− linkAttrs = [("r:id", "rId" ++ show idNum)]
1163− -- we have to add an extra action if it's an anchor.
1164− linkAttrs' = linkAttrs ++ case url of
1165− '#' : _ -> [("action", "ppaction://hlinksldjump")]
1166− _ -> []
1167− return [mknode "a:hlinkClick" linkAttrs' ()]
1161+ -- first we have to make sure that if it's an
1162+ -- anchor, it's in the anchor map. If not, there's
1163+ -- no link.
1164+ anchorMap <- gets stAnchorMap
1165+ return $ case link of
1166+ -- anchor with nothing in the map
1167+ ('#':target, _) | Nothing <- M.lookup target anchorMap ->
1168+ []
1169+ -- anchor that is in the map
1170+ ('#':_, _) ->
1171+ let linkAttrs =
1172+ [ ("r:id", "rId" ++ show idNum)
1173+ , ("action", "ppaction://hlinksldjump")
1174+ ]
1175+ in [mknode "a:hlinkClick" linkAttrs ()]
1176+ -- external
1177+ _ ->
1178+ let linkAttrs =
1179+ [ ("r:id", "rId" ++ show idNum)
1180+ ]
1181+ in [mknode "a:hlinkClick" linkAttrs ()]
11681182 Nothing -> return []
11691183 let propContents = if rPropCode rpr
11701184 then [mknode "a:latin" [("typeface", "Courier")] ()]
@@ -1595,18 +1609,23 @@ slideToSlideRelEntry slide idNum = do
15951609 element <- slideToSlideRelElement slide idNum
15961610 elemToEntry ("ppt/slides/_rels/" ++ slideToFilePath slide idNum ++ ".rels") element
15971611
1598−linkRelElement :: PandocMonad m => Int -> (URL, String) -> P m Element
1612+linkRelElement :: PandocMonad m => Int -> (URL, String) -> P m (Maybe Element)
15991613linkRelElement idNum (url, _) = do
16001614 anchorMap <- gets stAnchorMap
16011615 case url of
1616+ -- if it's an anchor in the map, we use the slide number for an
1617+ -- internal link.
16021618 '#' : anchor | Just num <- M.lookup anchor anchorMap ->
1603− return $
1619+ return $ Just $
16041620 mknode "Relationship" [ ("Id", "rId" ++ show idNum)
16051621 , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide")
16061622 , ("Target", "slide" ++ show num ++ ".xml")
16071623 ] ()
1624+ -- if it's an anchor not in the map, we return nothing.
1625+ '#' : _ -> return Nothing
1626+ -- Anything else we treat as an external link
16081627 _ ->
1609− return $
1628+ return $ Just $
16101629 mknode "Relationship" [ ("Id", "rId" ++ show idNum)
16111630 , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/hyperlink")
16121631 , ("Target", url)
@@ -1614,7 +1633,7 @@ linkRelElement idNum (url, _) = do
16141633 ] ()
16151634
16161635linkRelElements :: PandocMonad m => M.Map Int (URL, String) -> P m [Element]
1617−linkRelElements mp = mapM (\(n, lnk) -> linkRelElement n lnk) (M.toList mp)
1636+linkRelElements mp = catMaybes <$> mapM (\(n, lnk) -> linkRelElement n lnk) (M.toList mp)
16181637
16191638mediaRelElement :: MediaInfo -> Element
16201639mediaRelElement mInfo =