@@ -56,7 +56,7 @@ import Text.Pandoc.MIME
56import qualified Data.ByteString.Lazy as BL
56import qualified Data.ByteString.Lazy as BL
57import Text.Pandoc.Writers.OOXML
57import Text.Pandoc.Writers.OOXML
58import qualified Data.Map as M
58import qualified Data.Map as M
59−import Data.Maybe (mapMaybe, listToMaybe, fromMaybe, isJust)
59+import Data.Maybe (mapMaybe, listToMaybe, fromMaybe, isJust, maybeToList, catMaybes)
60import Text.Pandoc.ImageSize
60import Text.Pandoc.ImageSize
61import Control.Applicative ((<|>))
61import Control.Applicative ((<|>))
62import System.FilePath.Glob
62import System.FilePath.Glob
@@ -109,6 +109,11 @@ data WriterEnv = WriterEnv { envRefArchive :: Archive
109 , envSlideIdOffset :: Int
109 , envSlideIdOffset :: Int
110 , envContentType :: ContentType
110 , envContentType :: ContentType
111 , envSlideIdMap :: M.Map SlideId Int
111 , envSlideIdMap :: M.Map SlideId Int
112+ -- maps the slide number to the
113+ -- corresponding notes id number. If there
114+ -- are no notes for a slide, there will be
115+ -- no entry in the map for it.
116+ , envSpeakerNotesIdMap :: M.Map Int Int
113 deriving (Show)
118 deriving (Show)
@@ -125,6 +130,7 @@ instance Default WriterEnv where
125 , envSlideIdOffset = 1
130 , envSlideIdOffset = 1
126 , envContentType = NormalContent
131 , envContentType = NormalContent
127 , envSlideIdMap = mempty
132 , envSlideIdMap = mempty
133+ , envSpeakerNotesIdMap = mempty
130data ContentType = NormalContent
136data ContentType = NormalContent
@@ -185,7 +191,7 @@ alwaysInheritedPatterns =
185-- We only look for these under special conditions
191-- We only look for these under special conditions
186contingentInheritedPatterns :: Presentation -> [Pattern]
192contingentInheritedPatterns :: Presentation -> [Pattern]
187contingentInheritedPatterns pres = [] ++
193contingentInheritedPatterns pres = [] ++
188− if hasSpeakerNotes pres
194+ if presHasSpeakerNotes pres
189 then map compile [ "ppt/notesMasters/notesMaster*.xml"
195 then map compile [ "ppt/notesMasters/notesMaster*.xml"
190 , "ppt/notesMasters/_rels/notesMaster*.xml.rels"
196 , "ppt/notesMasters/_rels/notesMaster*.xml.rels"
191 , "ppt/theme/theme2.xml"
197 , "ppt/theme/theme2.xml"
@@ -253,6 +259,8 @@ presentationToArchiveP p@(Presentation docProps slides) = do
253 presRelsEntry <- presentationToRelsEntry p
259 presRelsEntry <- presentationToRelsEntry p
254 slideEntries <- mapM slideToEntry slides
260 slideEntries <- mapM slideToEntry slides
255 slideRelEntries <- mapM slideToSlideRelEntry slides
261 slideRelEntries <- mapM slideToSlideRelEntry slides
262+ spkNotesEntries <- catMaybes <$> mapM slideToSpeakerNotesEntry slides
263+ spkNotesRelEntries <- catMaybes <$> mapM slideToSpeakerNotesRelEntry slides
256 -- These have to come after everything, because they need the info
264 -- These have to come after everything, because they need the info
257 -- built up in the state.
265 -- built up in the state.
258 mediaEntries <- makeMediaEntries
266 mediaEntries <- makeMediaEntries
@@ -261,6 +269,8 @@ presentationToArchiveP p@(Presentation docProps slides) = do
261 return $ foldr addEntryToArchive newArch' $
269 return $ foldr addEntryToArchive newArch' $
262 slideEntries ++
270 slideEntries ++
263 slideRelEntries ++
271 slideRelEntries ++
273+ spkNotesRelEntries ++
264 mediaEntries ++
274 mediaEntries ++
265 [contentTypesEntry, docPropsEntry, relsEntry, presEntry, presRelsEntry]
275 [contentTypesEntry, docPropsEntry, relsEntry, presEntry, presRelsEntry]
@@ -268,6 +278,12 @@ makeSlideIdMap :: Presentation -> M.Map SlideId Int
268makeSlideIdMap (Presentation _ slides) =
278makeSlideIdMap (Presentation _ slides) =
269 M.fromList $ (map slideId slides) `zip` [1..]
279 M.fromList $ (map slideId slides) `zip` [1..]
281+makeSpeakerNotesMap :: Presentation -> M.Map Int Int
282+makeSpeakerNotesMap (Presentation _ slides) =
283+ M.fromList $ (mapMaybe f $ slides `zip` [1..]) `zip` [1..]
284+ where f (Slide _ _ Nothing, _) = Nothing
285+ f (Slide _ _ (Just _), n) = Just n
271presentationToArchive :: PandocMonad m => WriterOptions -> Presentation -> m Archive
287presentationToArchive :: PandocMonad m => WriterOptions -> Presentation -> m Archive
272presentationToArchive opts pres = do
288presentationToArchive opts pres = do
273 distArchive <- (toArchive . BL.fromStrict) <$>
289 distArchive <- (toArchive . BL.fromStrict) <$>
@@ -291,6 +307,7 @@ presentationToArchive opts pres = do
291 , envOpts = opts
307 , envOpts = opts
292 , envPresentationSize = presSize
308 , envPresentationSize = presSize
293 , envSlideIdMap = makeSlideIdMap pres
309 , envSlideIdMap = makeSlideIdMap pres
310+ , envSpeakerNotesIdMap = makeSpeakerNotesMap pres
296 let st = def { stMediaGlobalIds = initialGlobalIds refArchive distArchive
313 let st = def { stMediaGlobalIds = initialGlobalIds refArchive distArchive
@@ -304,8 +321,14 @@ presentationToArchive opts pres = do
305-- Check to see if the presentation has speaker notes. This will
322-- Check to see if the presentation has speaker notes. This will
306-- influence whether we import the notesMaster template.
323-- influence whether we import the notesMaster template.
307−hasSpeakerNotes :: Presentation -> Bool
324+presHasSpeakerNotes :: Presentation -> Bool
308−hasSpeakerNotes (Presentation _ slides) = any isJust $ map slideSpeakerNotes slides
325+presHasSpeakerNotes (Presentation _ slides) = any isJust $ map slideSpeakerNotes slides
327+curSlideHasSpeakerNotes :: PandocMonad m => P m Bool
328+curSlideHasSpeakerNotes = do
329+ sldId <- asks envCurSlideId
330+ notesIdMap <- asks envSpeakerNotesIdMap
331+ return $ isJust $ M.lookup sldId notesIdMap
310--------------------------------------------------
333--------------------------------------------------
@@ -448,15 +471,16 @@ registerLink link = do
448 curSlideId <- asks envCurSlideId
471 curSlideId <- asks envCurSlideId
449 linkReg <- gets stLinkIds
472 linkReg <- gets stLinkIds
450 mediaReg <- gets stMediaIds
473 mediaReg <- gets stMediaIds
474+ hasSpeakerNotes <- curSlideHasSpeakerNotes
451 let maxLinkId = case M.lookup curSlideId linkReg of
475 let maxLinkId = case M.lookup curSlideId linkReg of
452 Just mp -> case M.keys mp of
476 Just mp -> case M.keys mp of
453− [] -> 1
477+ [] -> if hasSpeakerNotes then 2 else 1
454 ks -> maximum ks
478 ks -> maximum ks
455− Nothing -> 1
479+ Nothing -> if hasSpeakerNotes then 2 else 1
456 maxMediaId = case M.lookup curSlideId mediaReg of
480 maxMediaId = case M.lookup curSlideId mediaReg of
457− Just [] -> 1
481+ Just [] -> if hasSpeakerNotes then 2 else 1
458 Just mInfos -> maximum $ map mInfoLocalId mInfos
482 Just mInfos -> maximum $ map mInfoLocalId mInfos
459− Nothing -> 1
483+ Nothing -> if hasSpeakerNotes then 2 else 1
460 maxId = max maxLinkId maxMediaId
484 maxId = max maxLinkId maxMediaId
461 slideLinks = case M.lookup curSlideId linkReg of
485 slideLinks = case M.lookup curSlideId linkReg of
462 Just mp -> M.insert (maxId + 1) link mp
486 Just mp -> M.insert (maxId + 1) link mp
@@ -470,15 +494,16 @@ registerMedia fp caption = do
470 linkReg <- gets stLinkIds
494 linkReg <- gets stLinkIds
471 mediaReg <- gets stMediaIds
495 mediaReg <- gets stMediaIds
472 globalIds <- gets stMediaGlobalIds
496 globalIds <- gets stMediaGlobalIds
497+ hasSpeakerNotes <- curSlideHasSpeakerNotes
473 let maxLinkId = case M.lookup curSlideId linkReg of
498 let maxLinkId = case M.lookup curSlideId linkReg of
474 Just mp -> case M.keys mp of
499 Just mp -> case M.keys mp of
475− [] -> 1
500+ [] -> if hasSpeakerNotes then 2 else 1
476 ks -> maximum ks
501 ks -> maximum ks
477− Nothing -> 1
502+ Nothing -> if hasSpeakerNotes then 2 else 1
478 maxMediaId = case M.lookup curSlideId mediaReg of
503 maxMediaId = case M.lookup curSlideId mediaReg of
479− Just [] -> 1
504+ Just [] -> if hasSpeakerNotes then 2 else 1
480 Just mInfos -> maximum $ map mInfoLocalId mInfos
505 Just mInfos -> maximum $ map mInfoLocalId mInfos
481− Nothing -> 1
506+ Nothing -> if hasSpeakerNotes then 2 else 1
482 maxLocalId = max maxLinkId maxMediaId
507 maxLocalId = max maxLinkId maxMediaId
484 maxGlobalId = case M.elems globalIds of
509 maxGlobalId = case M.elems globalIds of
@@ -973,6 +998,21 @@ getShapeByName ns spTreeElem name
973 filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasName ns name e)) spTreeElem
998 filterChild (\e -> (isElem ns "p" "sp" e) && (shapeHasName ns name e)) spTreeElem
974 | otherwise = Nothing
999 | otherwise = Nothing
1003+getShapeByPlaceHolderType :: NameSpaces -> Element -> String -> Maybe Element
1004+getShapeByPlaceHolderType ns spTreeElem phType
1005+ | isElem ns "p" "spTree" spTreeElem =
1006+ let findPhType element = isElem ns "p" "sp" element &&
1007+ Just phType == (Just element >>=
1008+ findChild (elemName ns "p" "nvSpPr") >>=
1009+ findChild (elemName ns "p" "nvPr") >>=
1010+ findChild (elemName ns "p" "ph") >>=
1011+ findAttr (QName "type" Nothing Nothing))
1013+ filterChild findPhType spTreeElem
1014+ | otherwise = Nothing
976-- getShapeById :: NameSpaces -> Element -> String -> Maybe Element
1016-- getShapeById :: NameSpaces -> Element -> String -> Maybe Element
977-- getShapeById ns spTreeElem ident
1017-- getShapeById ns spTreeElem ident
978-- | isElem ns "p" "spTree" spTreeElem =
1018-- | isElem ns "p" "spTree" spTreeElem =
@@ -1109,6 +1149,148 @@ slideToElement (Slide _ l@(MetadataSlide titleElems subtitleElems authorElems da
1109 ("xmlns:p", "http://schemas.openxmlformats.org/presentationml/2006/main")
1149 ("xmlns:p", "http://schemas.openxmlformats.org/presentationml/2006/main")
1110 ] [mknode "p:cSld" [] [spTree]]
1150 ] [mknode "p:cSld" [] [spTree]]
1153+--------------------------------------------------------------------
1156+getNotesMaster :: PandocMonad m => P m Element
1158+ let notesMasterPath = "ppt/notesMasters/notesMaster1.xml"
1159+ distArchive <- asks envDistArchive
1160+ root <- case findEntryByPath notesMasterPath distArchive of
1161+ Just e -> case parseXMLDoc $ UTF8.toStringLazy $ fromEntry e of
1162+ Just element -> return $ element
1163+ Nothing -> throwError $
1165+ notesMasterPath ++ " corrupt in reference file"
1166+ Nothing -> throwError $
1168+ notesMasterPath ++ " missing in reference file"
1171+getSlideNumberFieldId :: PandocMonad m => Element -> P m String
1172+getSlideNumberFieldId notesMaster
1173+ | ns <- elemToNameSpaces notesMaster
1174+ , Just cSld <- findChild (elemName ns "p" "cSld") notesMaster
1175+ , Just spTree <- findChild (elemName ns "p" "spTree") cSld
1176+ , Just sp <- getShapeByPlaceHolderType ns spTree "sldNum"
1177+ , Just txBody <- findChild (elemName ns "p" "txBody") sp
1178+ , Just p <- findChild (elemName ns "a" "p") txBody
1179+ , Just fld <- findChild (elemName ns "a" "fld") p
1180+ , Just fldId <- findAttr (QName "id" Nothing Nothing) fld =
1182+ | otherwise = throwError $
1184+ "No field id for slide numbers in notesMaster.xml"
1186+speakerNotesSlideImage :: Element
1187+speakerNotesSlideImage =
1189+ [ mknode "p:nvSpPr" [] $
1190+ [ mknode "p:cNvPr" [ ("id", "2")
1191+ , ("name", "Slide Image Placeholder 1")
1193+ , mknode "p:cNvSpPr" [] $
1194+ [ mknode "a:spLocks" [ ("noGrp", "1")
1196+ , ("noChangeAspect", "1")
1199+ , mknode "p:nvPr" [] $
1200+ [ mknode "p:ph" [("type", "sldImg")] ()]
1202+ , mknode "p:spPr" [] ()
1205+speakerNotesBody :: PandocMonad m => [Paragraph] -> P m Element
1206+speakerNotesBody paras = do
1207+ elements <- mapM paragraphToElement paras
1208+ let txBody = mknode "p:txBody" [] $
1209+ [mknode "a:bodyPr" [] (), mknode "a:lstStyle" [] ()] ++ elements
1212+ [ mknode "p:nvSpPr" [] $
1213+ [ mknode "p:cNvPr" [ ("id", "3")
1214+ , ("name", "Notes Placeholder 2")
1216+ , mknode "p:cNvSpPr" [] $
1217+ [ mknode "a:spLocks" [("noGrp", "1")] ()]
1218+ , mknode "p:nvPr" [] $
1219+ [ mknode "p:ph" [("type", "body"), ("idx", "1")] ()]
1221+ , mknode "p:spPr" [] ()
1225+speakerNotesSlideNumber :: Int -> String -> Element
1226+speakerNotesSlideNumber pgNum fieldId =
1228+ [ mknode "p:nvSpPr" [] $
1229+ [ mknode "p:cNvPr" [ ("id", "4")
1230+ , ("name", "Slide Number Placeholder 3")
1232+ , mknode "p:cNvSpPr" [] $
1233+ [ mknode "a:spLocks" [("noGrp", "1")] ()]
1234+ , mknode "p:nvPr" [] $
1235+ [ mknode "p:ph" [ ("type", "sldNum")
1236+ , ("sz", "quarter")
1241+ , mknode "p:spPr" [] ()
1242+ , mknode "p:txBody" [] $
1243+ [ mknode "a:bodyPr" [] ()
1244+ , mknode "a:lstStyle" [] ()
1245+ , mknode "a:p" [] $
1246+ [ mknode "a:fld" [ ("id", fieldId)
1247+ , ("type", "slidenum")
1249+ [ mknode "a:rPr" [("lang", "en-US")] ()
1250+ , mknode "a:t" [] (show pgNum)
1252+ , mknode "a:endParaRPr" [("lang", "en-US")] ()
1257+slideToSpeakerNotesElement :: PandocMonad m => Slide -> P m (Maybe Element)
1258+slideToSpeakerNotesElement sld@(Slide _ _ mbNotes)
1259+ | Nothing <- mbNotes = return Nothing
1260+ | Just (SpeakerNotes paras) <- mbNotes = do
1261+ master <- getNotesMaster
1262+ fieldId <- getSlideNumberFieldId master
1263+ num <- slideNum sld
1264+ let imgShape = speakerNotesSlideImage
1265+ sldNumShape = speakerNotesSlideNumber num fieldId
1266+ bodyShape <- speakerNotesBody paras
1269+ [ ("xmlns:a", "http://schemas.openxmlformats.org/drawingml/2006/main")
1270+ , ("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships")
1271+ , ("xmlns:p", "http://schemas.openxmlformats.org/presentationml/2006/main")
1272+ ] [ mknode "p:cSld" []
1273+ [ mknode "p:spTree" []
1274+ [ mknode "p:nvGrpSpPr" []
1275+ [ mknode "p:cNvPr" [("id", "1"), ("name", "")] ()
1276+ , mknode "p:cNvGrpSpPr" [] ()
1277+ , mknode "p:nvPr" [] ()
1279+ , mknode "p:grpSpPr" []
1280+ [ mknode "a:xfrm" []
1281+ [ mknode "a:off" [("x", "0"), ("y", "0")] ()
1282+ , mknode "a:ext" [("cx", "0"), ("cy", "0")] ()
1283+ , mknode "a:chOff" [("x", "0"), ("y", "0")] ()
1284+ , mknode "a:chExt" [("cx", "0"), ("cy", "0")] ()
1112-----------------------------------------------------------------------
1294-----------------------------------------------------------------------
1114getSlideIdNum :: PandocMonad m => SlideId -> P m Int
1296getSlideIdNum :: PandocMonad m => SlideId -> P m Int
@@ -1252,6 +1434,53 @@ slideToEntry slide = do
1252 element <- slideToElement slide
1434 element <- slideToElement slide
1253 elemToEntry ("ppt/slides/" ++ idNumToFilePath idNum) element
1435 elemToEntry ("ppt/slides/" ++ idNumToFilePath idNum) element
1437+slideToSpeakerNotesEntry :: PandocMonad m => Slide -> P m (Maybe Entry)
1438+slideToSpeakerNotesEntry slide = do
1439+ idNum <- slideNum slide
1440+ local (\env -> env{envCurSlideId = idNum}) $ do
1441+ mbElement <- slideToSpeakerNotesElement slide
1442+ mbNotesIdNum <- do mp <- asks envSpeakerNotesIdMap
1443+ return $ M.lookup idNum mp
1445+ Just element | Just notesIdNum <- mbNotesIdNum ->
1448+ ("ppt/notesSlides/notesSlide" ++ show notesIdNum ++ ".xml")
1450+ _ -> return Nothing
1452+slideToSpeakerNotesRelElement :: PandocMonad m => Slide -> P m (Maybe Element)
1453+slideToSpeakerNotesRelElement slide@(Slide _ _ mbNotes)
1454+ | Nothing <- mbNotes = return Nothing
1455+ | Just _ <- mbNotes = do
1456+ idNum <- slideNum slide
1458+ mknode "Relationships"
1459+ [("xmlns", "http://schemas.openxmlformats.org/package/2006/relationships")]
1460+ [ mknode "Relationship" [ ("Id", "rId2")
1461+ , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slide")
1462+ , ("Target", "../slides/slide" ++ show idNum ++ ".xml")
1464+ , mknode "Relationship" [ ("Id", "rId1")
1465+ , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesMaster")
1466+ , ("Target", "../notesMasters/notesMaster1.xml")
1470+slideToSpeakerNotesRelEntry :: PandocMonad m => Slide -> P m (Maybe Entry)
1471+slideToSpeakerNotesRelEntry slide = do
1472+ idNum <- slideNum slide
1473+ mbElement <- slideToSpeakerNotesRelElement slide
1474+ mp <- asks envSpeakerNotesIdMap
1475+ let mbNotesIdNum = M.lookup idNum mp
1477+ Just element | Just notesIdNum <- mbNotesIdNum ->
1480+ ("ppt/notesSlides/_rels/notesSlide" ++ show notesIdNum ++ ".xml.rels")
1482+ _ -> return Nothing
1255slideToSlideRelEntry :: PandocMonad m => Slide -> P m Entry
1484slideToSlideRelEntry :: PandocMonad m => Slide -> P m Entry
1256slideToSlideRelEntry slide = do
1485slideToSlideRelEntry slide = do
1257 idNum <- slideNum slide
1486 idNum <- slideNum slide
@@ -1288,6 +1517,20 @@ mediaRelElement mInfo =
1288 , ("Target", "../media/image" ++ (show $ mInfoGlobalId mInfo) ++ ext)
1517 , ("Target", "../media/image" ++ (show $ mInfoGlobalId mInfo) ++ ext)
1520+speakerNotesSlideRelElement :: PandocMonad m => Slide -> P m (Maybe Element)
1521+speakerNotesSlideRelElement slide = do
1522+ idNum <- slideNum slide
1523+ mp <- asks envSpeakerNotesIdMap
1524+ return $ case M.lookup idNum mp of
1527+ let target = "../notesSlides/notesSlide" ++ show n ++ ".xml"
1529+ mknode "Relationship" [ ("Id", "rId2")
1530+ , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/notesSlide")
1531+ , ("Target", target)
1291slideToSlideRelElement :: PandocMonad m => Slide -> P m Element
1534slideToSlideRelElement :: PandocMonad m => Slide -> P m Element
1292slideToSlideRelElement slide = do
1535slideToSlideRelElement slide = do
1293 idNum <- slideNum slide
1536 idNum <- slideNum slide
@@ -1297,6 +1540,8 @@ slideToSlideRelElement slide = do
1297 (Slide _ (ContentSlide _ _) _) -> "../slideLayouts/slideLayout2.xml"
1540 (Slide _ (ContentSlide _ _) _) -> "../slideLayouts/slideLayout2.xml"
1298 (Slide _ (TwoColumnSlide _ _ _) _) -> "../slideLayouts/slideLayout4.xml"
1541 (Slide _ (TwoColumnSlide _ _ _) _) -> "../slideLayouts/slideLayout4.xml"
1543+ speakerNotesRels <- maybeToList <$> speakerNotesSlideRelElement slide
1300 linkIds <- gets stLinkIds
1545 linkIds <- gets stLinkIds
1301 mediaIds <- gets stMediaIds
1546 mediaIds <- gets stMediaIds
@@ -1313,7 +1558,7 @@ slideToSlideRelElement slide = do
1313 ([mknode "Relationship" [ ("Id", "rId1")
1558 ([mknode "Relationship" [ ("Id", "rId1")
1314 , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout")
1559 , ("Type", "http://schemas.openxmlformats.org/officeDocument/2006/relationships/slideLayout")
1315 , ("Target", target)] ()
1560 , ("Target", target)] ()
1316− ] ++ linkRels ++ mediaRels)
1561+ ] ++ speakerNotesRels ++ linkRels ++ mediaRels)
1318slideToSldIdElement :: PandocMonad m => Slide -> P m Element
1563slideToSldIdElement :: PandocMonad m => Slide -> P m Element
1319slideToSldIdElement slide = do
1564slideToSldIdElement slide = do
@@ -1328,7 +1573,7 @@ presentationToSldIdLst (Presentation _ slides) = do
1328 return $ mknode "p:sldIdLst" [] ids
1573 return $ mknode "p:sldIdLst" [] ids
1330presentationToPresentationElement :: PandocMonad m => Presentation -> P m Element
1575presentationToPresentationElement :: PandocMonad m => Presentation -> P m Element
1331−presentationToPresentationElement pres = do
1576+presentationToPresentationElement pres@(Presentation _ slds) = do
1332 refArchive <- asks envRefArchive
1577 refArchive <- asks envRefArchive
1333 distArchive <- asks envDistArchive
1578 distArchive <- asks envDistArchive
1334 element <- parseXml refArchive distArchive "ppt/presentation.xml"
1579 element <- parseXml refArchive distArchive "ppt/presentation.xml"
@@ -1340,18 +1585,28 @@ presentationToPresentationElement pres = do
1340 _ -> Elem e
1585 _ -> Elem e
1341 modifySldIdLst ct = ct
1586 modifySldIdLst ct = ct
1588+ notesMasterRId = length slds + 2
1343− removeSpeakerNotes' :: Content -> [Content]
1590+ modifySpeakerNotes' :: Content -> [Content]
1344− removeSpeakerNotes' (Elem e) = case elName e of
1591+ modifySpeakerNotes' (Elem e) = case elName e of
1345− (QName "notesMasterIdLst" _ _) -> []
1592+ (QName "notesMasterIdLst" _ _) ->
1593+ if presHasSpeakerNotes pres
1595+ mknode "p:notesMasterIdLst" []
1598+ [("r:id", "rId" ++ show notesMasterRId)]
1346− _ -> [Elem e]
1603+ _ -> [Elem e]
1347− removeSpeakerNotes' ct = [ct]
1604+ modifySpeakerNotes' ct = [ct]
1349− removeSpeakerNotes :: [Content] -> [Content]
1606+ modifySpeakerNotes :: [Content] -> [Content]
1350− removeSpeakerNotes = if not (hasSpeakerNotes pres)
1607+ modifySpeakerNotes = concatMap modifySpeakerNotes'
1351− then concatMap removeSpeakerNotes'
1354− newContent = removeSpeakerNotes $ map modifySldIdLst $ elContent element
1609+ newContent = modifySpeakerNotes $ map modifySldIdLst $ elContent element
1356 return $ element{elContent = newContent}
1611 return $ element{elContent = newContent}
@@ -1452,6 +1707,12 @@ mediaContentType mInfo
1453 | otherwise = Nothing
1708 | otherwise = Nothing
1710+getSpeakerNotesFilePaths :: PandocMonad m => P m [FilePath]
1711+getSpeakerNotesFilePaths = do
1712+ mp <- asks envSpeakerNotesIdMap
1713+ let notesIdNums = M.elems mp
1714+ return $ map (\n -> "ppt/notesSlides/notesSlide" ++ show n ++ ".xml") notesIdNums
1455presentationToContentTypes :: PandocMonad m => Presentation -> P m ContentTypes
1716presentationToContentTypes :: PandocMonad m => Presentation -> P m ContentTypes
1456presentationToContentTypes p@(Presentation _ slides) = do
1717presentationToContentTypes p@(Presentation _ slides) = do
1457 mediaInfos <- (mconcat . M.elems) <$> gets stMediaIds
1718 mediaInfos <- (mconcat . M.elems) <$> gets stMediaIds
@@ -1471,9 +1732,10 @@ presentationToContentTypes p@(Presentation _ slides) = do
1471 let slideOverrides = mapMaybe
1732 let slideOverrides = mapMaybe
1472 (\fp -> pathToOverride $ "ppt/slides/" ++ fp)
1733 (\fp -> pathToOverride $ "ppt/slides/" ++ fp)
1473 relativePaths
1734 relativePaths
1735+ speakerNotesOverrides <- (mapMaybe pathToOverride) <$> getSpeakerNotesFilePaths
1474 return $ ContentTypes
1736 return $ ContentTypes
1475 (defaults ++ mediaDefaults)
1737 (defaults ++ mediaDefaults)
1476− (inheritedOverrides ++ docPropsOverride ++ presOverride ++ slideOverrides)
1738+ (inheritedOverrides ++ docPropsOverride ++ presOverride ++ slideOverrides ++ speakerNotesOverrides)
1478presML :: String
1740presML :: String
1479presML = "application/vnd.openxmlformats-officedocument.presentationml"
1741presML = "application/vnd.openxmlformats-officedocument.presentationml"