git.iko.soy/typeable/pandoc
on master help sign in
Powerpoint writer: Revamp slide type

This is an internal change to the Presentation type. The algebraic datatype that used to be called `Slide` is now `Layout`, and Slide is defined as `Slide SlideId Layout (Maybe Notes)`. Though there should be no user-visible changes in this commit, it offers two benefits moving forward: 1. Slides now carry their Id with them, instead of being assigned it in deck order. This makes it easier to set up a link to, say, an endnotes slide ahead of time. 2. This makes room for Notes slides, when we implement them.

commit63a2507d0e35036d784eb84badb75811f70a5fb9 authorJesse Rosenthal <jrosenthal@jhu.edu> dateWed 17 Jan 2018, 12:18 (9 years ago) parent80528ea
2 files changed+97−48
src/Text/Pandoc/Writers/Powerpoint/Output.hs+15−15 src/Text/Pandoc/Writers/Powerpoint/Presentation.hs+82−33
src/Text/Pandoc/Writers/Powerpoint/Output.hs+15−15
@@ -279,9 +279,9 @@ presentationToArchive opts pres = do
279279
280280--------------------------------------------------
281281
282−getLayout :: PandocMonad m => Slide -> P m Element
283−getLayout slide = do
284− let layoutpath = case slide of
282+getLayout :: PandocMonad m => Layout -> P m Element
283+getLayout layout = do
284+ let layoutpath = case layout of
285285 (MetadataSlide _ _ _ _) -> "ppt/slideLayouts/slideLayout1.xml"
286286 (TitleSlide _) -> "ppt/slideLayouts/slideLayout3.xml"
287287 (ContentSlide _ _) -> "ppt/slideLayouts/slideLayout2.xml"
@@ -1028,8 +1028,8 @@ metadataToElement layout titleElems subtitleElems authorsElems dateElems
10281028metadataToElement _ _ _ _ _ = return $ mknode "p:sp" [] ()
10291029
10301030slideToElement :: PandocMonad m => Slide -> P m Element
1031−slideToElement s@(ContentSlide hdrElems shapes) = do
1032− layout <- getLayout s
1031+slideToElement (Slide _ l@(ContentSlide hdrElems shapes) _ )= do
1032+ layout <- getLayout l
10331033 spTree <- local (\env -> if null hdrElems
10341034 then env
10351035 else env{envSlideHasHeader=True}) $
@@ -1039,8 +1039,8 @@ slideToElement s@(ContentSlide hdrElems shapes) = do
10391039 ("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"),
10401040 ("xmlns:p", "http://schemas.openxmlformats.org/presentationml/2006/main")
10411041 ] [mknode "p:cSld" [] [spTree]]
1042−slideToElement s@(TwoColumnSlide hdrElems shapesL shapesR) = do
1043− layout <- getLayout s
1042+slideToElement (Slide _ l@(TwoColumnSlide hdrElems shapesL shapesR) _) = do
1043+ layout <- getLayout l
10441044 spTree <- local (\env -> if null hdrElems
10451045 then env
10461046 else env{envSlideHasHeader=True}) $
@@ -1050,16 +1050,16 @@ slideToElement s@(TwoColumnSlide hdrElems shapesL shapesR) = do
10501050 ("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"),
10511051 ("xmlns:p", "http://schemas.openxmlformats.org/presentationml/2006/main")
10521052 ] [mknode "p:cSld" [] [spTree]]
1053−slideToElement s@(TitleSlide hdrElems) = do
1054− layout <- getLayout s
1053+slideToElement (Slide _ l@(TitleSlide hdrElems) _) = do
1054+ layout <- getLayout l
10551055 spTree <- titleToElement layout hdrElems
10561056 return $ mknode "p:sld"
10571057 [ ("xmlns:a", "http://schemas.openxmlformats.org/drawingml/2006/main"),
10581058 ("xmlns:r", "http://schemas.openxmlformats.org/officeDocument/2006/relationships"),
10591059 ("xmlns:p", "http://schemas.openxmlformats.org/presentationml/2006/main")
10601060 ] [mknode "p:cSld" [] [spTree]]
1061−slideToElement s@(MetadataSlide titleElems subtitleElems authorElems dateElems) = do
1062− layout <- getLayout s
1061+slideToElement (Slide _ l@(MetadataSlide titleElems subtitleElems authorElems dateElems) _) = do
1062+ layout <- getLayout l
10631063 spTree <- metadataToElement layout titleElems subtitleElems authorElems dateElems
10641064 return $ mknode "p:sld"
10651065 [ ("xmlns:a", "http://schemas.openxmlformats.org/drawingml/2006/main"),
@@ -1227,10 +1227,10 @@ mediaRelElement mInfo =
12271227slideToSlideRelElement :: PandocMonad m => Slide -> Int -> P m Element
12281228slideToSlideRelElement slide idNum = do
12291229 let target = case slide of
1230− (MetadataSlide _ _ _ _) -> "../slideLayouts/slideLayout1.xml"
1231− (TitleSlide _) -> "../slideLayouts/slideLayout3.xml"
1232− (ContentSlide _ _) -> "../slideLayouts/slideLayout2.xml"
1233− (TwoColumnSlide _ _ _) -> "../slideLayouts/slideLayout4.xml"
1230+ (Slide _ (MetadataSlide _ _ _ _) _) -> "../slideLayouts/slideLayout1.xml"
1231+ (Slide _ (TitleSlide _) _) -> "../slideLayouts/slideLayout3.xml"
1232+ (Slide _ (ContentSlide _ _) _) -> "../slideLayouts/slideLayout2.xml"
1233+ (Slide _ (TwoColumnSlide _ _ _) _) -> "../slideLayouts/slideLayout4.xml"
12341234
12351235 linkIds <- gets stLinkIds
12361236 mediaIds <- gets stMediaIds
src/Text/Pandoc/Writers/Powerpoint/Presentation.hs+82−33
@@ -35,6 +35,9 @@ Presentation.
3535module Text.Pandoc.Writers.Powerpoint.Presentation ( documentToPresentation
3636 , Presentation(..)
3737 , Slide(..)
38+ , Layout(..)
39+ , Notes(..)
40+ , SlideId(..)
3841 , Shape(..)
3942 , Graphic(..)
4043 , BulletType(..)
@@ -76,7 +79,7 @@ data WriterEnv = WriterEnv { envMetadata :: Meta
7679 , envSlideHasHeader :: Bool
7780 , envInList :: Bool
7881 , envInNoteSlide :: Bool
79− , envCurSlideId :: Int
82+ , envCurSlideId :: SlideId
8083 }
8184 deriving (Show)
8285
@@ -89,13 +92,13 @@ instance Default WriterEnv where
8992 , envSlideHasHeader = False
9093 , envInList = False
9194 , envInNoteSlide = False
92− , envCurSlideId = 1
95+ , envCurSlideId = SlideId "1"
9396 }
9497
9598
9699data WriterState = WriterState { stNoteIds :: M.Map Int [Block]
97100 -- associate anchors with slide id
98− , stAnchorMap :: M.Map String Int
101+ , stAnchorMap :: M.Map String SlideId
99102 , stLog :: [LogMessage]
100103 } deriving (Show, Eq)
101104
@@ -124,7 +127,20 @@ type Pixels = Integer
124127data Presentation = Presentation [Slide]
125128 deriving (Show)
126129
127−data Slide = MetadataSlide { metadataSlideTitle :: [ParaElem]
130+
131+data Slide = Slide SlideId Layout (Maybe Notes)
132+ deriving (Show, Eq)
133+
134+newtype SlideId = SlideId String
135+ deriving (Show, Eq)
136+
137+-- In theory you could have anything on a notes slide but it seems
138+-- designed mainly for one textbox, so we'll just put in the contents
139+-- of that textbox, to avoid other shapes that won't work as well.
140+newtype Notes = Notes [Paragraph]
141+ deriving (Show, Eq)
142+
143+data Layout = MetadataSlide { metadataSlideTitle :: [ParaElem]
128144 , metadataSlideSubtitle :: [ParaElem]
129145 , metadataSlideAuthors :: [[ParaElem]]
130146 , metadataSlideDate :: [ParaElem]
@@ -204,7 +220,7 @@ data Capitals = NoCapitals | SmallCapitals | AllCapitals
204220type URL = String
205221
206222data LinkTarget = ExternalTarget (URL, String)
207− | InternalTarget Int -- slideId
223+ | InternalTarget SlideId
208224 deriving (Show, Eq)
209225
210226data RunProps = RunProps { rPropBold :: Bool
@@ -513,18 +529,20 @@ blocksToSlide' :: Int -> [Block] -> Pres Slide
513529blocksToSlide' lvl ((Header n (ident, _, _) ils) : blks)
514530 | n < lvl = do
515531 registerAnchorId ident
532+ slideId <- asks envCurSlideId
516533 hdr <- inlinesToParElems ils
517− return $ TitleSlide {titleSlideHeader = hdr}
534+ return $ Slide slideId (TitleSlide {titleSlideHeader = hdr}) Nothing
518535 | n == lvl = do
519536 registerAnchorId ident
520537 hdr <- inlinesToParElems ils
521538 -- Now get the slide without the header, and then add the header
522539 -- in.
523− slide <- blocksToSlide' lvl blks
524− return $ case slide of
525− ContentSlide _ cont -> ContentSlide hdr cont
526− TwoColumnSlide _ contL contR -> TwoColumnSlide hdr contL contR
527− slide' -> slide'
540+ (Slide slideId layout mbNotes) <- blocksToSlide' lvl blks
541+ let layout' = case layout of
542+ ContentSlide _ cont -> ContentSlide hdr cont
543+ TwoColumnSlide _ contL contR -> TwoColumnSlide hdr contL contR
544+ layout'' -> layout''
545+ return $ Slide slideId layout' mbNotes
528546blocksToSlide' _ (blk : blks)
529547 | Div (_, classes, _) divBlks <- blk
530548 , "columns" `elem` classes
@@ -544,21 +562,36 @@ blocksToSlide' _ (blk : blks)
544562 [] -> []
545563 shapesL <- blocksToShapes blksL'
546564 shapesR <- blocksToShapes blksR'
547− return $ TwoColumnSlide { twoColumnSlideHeader = []
548− , twoColumnSlideLeft = shapesL
549− , twoColumnSlideRight = shapesR
550− }
565+ slideId <- asks envCurSlideId
566+ return $ Slide
567+ slideId
568+ TwoColumnSlide { twoColumnSlideHeader = []
569+ , twoColumnSlideLeft = shapesL
570+ , twoColumnSlideRight = shapesR
571+ }
572+ Nothing
551573blocksToSlide' _ (blk : blks) = do
552574 inNoteSlide <- asks envInNoteSlide
553575 shapes <- if inNoteSlide
554576 then forceFontSize noteSize $ blocksToShapes (blk : blks)
555577 else blocksToShapes (blk : blks)
556− return $ ContentSlide { contentSlideHeader = []
557− , contentSlideContent = shapes
558− }
559−blocksToSlide' _ [] = return $ ContentSlide { contentSlideHeader = []
560− , contentSlideContent = []
561− }
578+ slideId <- asks envCurSlideId
579+ return $
580+ Slide
581+ slideId
582+ ContentSlide { contentSlideHeader = []
583+ , contentSlideContent = shapes
584+ }
585+ Nothing
586+blocksToSlide' _ [] = do
587+ slideId <- asks envCurSlideId
588+ return $
589+ Slide
590+ slideId
591+ ContentSlide { contentSlideHeader = []
592+ , contentSlideContent = []
593+ }
594+ Nothing
562595
563596blocksToSlide :: [Block] -> Pres Slide
564597blocksToSlide blks = do
@@ -612,13 +645,20 @@ getMetaSlide = do
612645 _ -> []
613646 authors <- mapM inlinesToParElems $ docAuthors meta
614647 date <- inlinesToParElems $ docDate meta
648+ slideId <- asks envCurSlideId
615649 if null title && null subtitle && null authors && null date
616650 then return Nothing
617− else return $ Just $ MetadataSlide { metadataSlideTitle = title
618− , metadataSlideSubtitle = subtitle
619− , metadataSlideAuthors = authors
620− , metadataSlideDate = date
621− }
651+ else return $
652+ Just $
653+ Slide
654+ slideId
655+ MetadataSlide { metadataSlideTitle = title
656+ , metadataSlideSubtitle = subtitle
657+ , metadataSlideAuthors = authors
658+ , metadataSlideDate = date
659+ }
660+ Nothing
661+
622662-- adapted from the markdown writer
623663elementToListItem :: Shared.Element -> Pres [Block]
624664elementToListItem (Shared.Sec lev _nums (ident,_,_) headerText subsecs) = do
@@ -676,26 +716,35 @@ applyToShape f (TextBox paras) = do
676716 paras' <- mapM (applyToParagraph f) paras
677717 return $ TextBox paras'
678718
679−applyToSlide :: Monad m => (ParaElem -> m ParaElem) -> Slide -> m Slide
680−applyToSlide f (MetadataSlide title subtitle authors date) = do
719+applyToLayout :: Monad m => (ParaElem -> m ParaElem) -> Layout -> m Layout
720+applyToLayout f (MetadataSlide title subtitle authors date) = do
681721 title' <- mapM f title
682722 subtitle' <- mapM f subtitle
683723 authors' <- mapM (mapM f) authors
684724 date' <- mapM f date
685725 return $ MetadataSlide title' subtitle' authors' date'
686−applyToSlide f (TitleSlide title) = do
726+applyToLayout f (TitleSlide title) = do
687727 title' <- mapM f title
688728 return $ TitleSlide title'
689−applyToSlide f (ContentSlide hdr content) = do
729+applyToLayout f (ContentSlide hdr content) = do
690730 hdr' <- mapM f hdr
691731 content' <- mapM (applyToShape f) content
692732 return $ ContentSlide hdr' content'
693−applyToSlide f (TwoColumnSlide hdr contentL contentR) = do
733+applyToLayout f (TwoColumnSlide hdr contentL contentR) = do
694734 hdr' <- mapM f hdr
695735 contentL' <- mapM (applyToShape f) contentL
696736 contentR' <- mapM (applyToShape f) contentR
697737 return $ TwoColumnSlide hdr' contentL' contentR'
698738
739+applyToSlide :: Monad m => (ParaElem -> m ParaElem) -> Slide -> m Slide
740+applyToSlide f (Slide slideId layout mbNotes) = do
741+ layout' <- applyToLayout f layout
742+ mbNotes' <- case mbNotes of
743+ Just (Notes notes) -> (Just . Notes) <$>
744+ mapM (applyToParagraph f) notes
745+ Nothing -> return Nothing
746+ return $ Slide slideId layout' mbNotes'
747+
699748replaceAnchor :: ParaElem -> Pres ParaElem
700749replaceAnchor (Run rProps s)
701750 | Just (ExternalTarget ('#':anchor, _)) <- rLink rProps = do
@@ -728,7 +777,7 @@ blocksToPresentation blks = do
728777 let bodyStartNum = tocStartNum + tocSlidesLength
729778 blksLst <- splitBlocks blks
730779 bodyslides <- mapM
731− (\(bs, n) -> local (\st -> st{envCurSlideId = n}) (blocksToSlide bs))
780+ (\(bs, n) -> local (\st -> st{envCurSlideId = SlideId $ show n}) (blocksToSlide bs))
732781 (zip blksLst [bodyStartNum..])
733782 let endNoteStartNum = bodyStartNum + length bodyslides
734783 endNotesSlideBlocks <- makeEndNotesSlideBlocks
@@ -742,7 +791,7 @@ blocksToPresentation blks = do
742791 endNotesSlides <- if null endNotesSlideBlocks
743792 then return []
744793 else do endNotesSlide <- local
745− (\env -> env { envCurSlideId = endNoteStartNum
794+ (\env -> env { envCurSlideId = SlideId $ show endNoteStartNum
746795 , envInNoteSlide = True
747796 })
748797 (blocksToSlide $ endNotesSlideBlocks)