git.iko.soy/typeable/pandoc
on master help sign in
Docx reader: read custom styles

This will read all paragraph and character classes as divs and spans, respectively. Dependent styles will still be resolved, but will be wrapped with appropriate style tags. It is controlled by the `+styles` extension (`-f docx+styles`). This can be used in conjunction with the `custom-style` feature in the docx writer for a pandoc-docx editing workflow. Users can convert from an input docx, reading the custom-styles, and then use that same input docx file as a reference-doc for producing an output docx file. Styles will be maintained across the conversion, even if pandoc doesn't understand them. Without the extension: $ pandoc test/docx/custom-style-reference.docx -f docx -t markdown This is some text. This is text with an *emphasized* text style. And this is text with a **strengthened** text style. > Here is a styled paragraph that inherits from Block Text. With the extension: $ pandoc test/docx/custom-style-reference.docx -f docx+styles -t markdown ::: {custom-style="FirstParagraph"} This is some text. ::: ::: {custom-style="BodyText"} This is text with an *[[emphasized]{custom-style="Emphatic"}]{custom-style="Emphatic"}* text style. And this is text with a **[[strengthened]{custom-style="Strengthened"}]{custom-style="Strengthened"}** text style. ::: ::: {custom-style="MyBlockStyle"} Closes: #1843

commit5262c0853acbef6dd25d9d6cbda26120859b45ff authorJesse Rosenthal <jrosenthal@jhu.edu> dateThu 22 Feb 2018, 12:56 (9 years ago) parent88d17c6
1 file changed+96−60
src/Text/Pandoc/Readers/Docx.hs+96−60
src/Text/Pandoc/Readers/Docx.hs+96−60
@@ -278,28 +278,51 @@ resolveDependentRunStyle rPr
278278 , rStyle = rStyle rPr }
279279 | otherwise = rPr
280280
281−runStyleToTransform :: RunStyle -> (Inlines -> Inlines)
281+extraRunStyleInfo :: PandocMonad m => RunStyle -> DocxContext m (Inlines -> Inlines)
282+extraRunStyleInfo rPr
283+ | Just (s, _) <- rStyle rPr = do
284+ opts <- asks docxOptions
285+ return $ if isEnabled Ext_styles opts
286+ then spanWith ("", [], [("custom-style", s)])
287+ else id
288+ | otherwise = return id
289+
290+runStyleToTransform :: PandocMonad m => RunStyle -> DocxContext m (Inlines -> Inlines)
282291runStyleToTransform rPr
283292 | Just (s, _) <- rStyle rPr
284− , s `elem` spansToKeep =
285− let rPr' = rPr{rStyle = Nothing}
286− in
287− spanWith ("", [s], []) . runStyleToTransform rPr'
288− | Just True <- isItalic rPr =
289− emph . runStyleToTransform rPr {isItalic = Nothing}
290− | Just True <- isBold rPr =
291− strong . runStyleToTransform rPr {isBold = Nothing}
292− | Just True <- isSmallCaps rPr =
293− smallcaps . runStyleToTransform rPr {isSmallCaps = Nothing}
294− | Just True <- isStrike rPr =
295− strikeout . runStyleToTransform rPr {isStrike = Nothing}
296− | Just SupScrpt <- rVertAlign rPr =
297− superscript . runStyleToTransform rPr {rVertAlign = Nothing}
298− | Just SubScrpt <- rVertAlign rPr =
299− subscript . runStyleToTransform rPr {rVertAlign = Nothing}
300− | Just "single" <- rUnderline rPr =
301− underlineSpan . runStyleToTransform rPr {rUnderline = Nothing}
302− | otherwise = id
293+ , s `elem` spansToKeep = do
294+ let rPr' = rPr{rStyle = Nothing}
295+ transform <- runStyleToTransform rPr'
296+ return $ spanWith ("", [s], []) . transform
297+ | Just True <- isItalic rPr = do
298+ transform <- runStyleToTransform rPr {isItalic = Nothing}
299+ extraInfo <- extraRunStyleInfo rPr
300+ return $ emph . extraInfo . transform
301+ | Just True <- isBold rPr = do
302+ transform <- runStyleToTransform rPr {isBold = Nothing}
303+ extraInfo <- extraRunStyleInfo rPr
304+ return $ strong . extraInfo . transform
305+ | Just True <- isSmallCaps rPr = do
306+ transform <- runStyleToTransform rPr {isSmallCaps = Nothing}
307+ extraInfo <- extraRunStyleInfo rPr
308+ return $ smallcaps . extraInfo .transform
309+ | Just True <- isStrike rPr = do
310+ transform <- runStyleToTransform rPr {isStrike = Nothing}
311+ extraInfo <- extraRunStyleInfo rPr
312+ return $ strikeout . extraInfo . transform
313+ | Just SupScrpt <- rVertAlign rPr = do
314+ transform <- runStyleToTransform rPr {rVertAlign = Nothing}
315+ extraInfo <- extraRunStyleInfo rPr
316+ return $ superscript . extraInfo . transform
317+ | Just SubScrpt <- rVertAlign rPr = do
318+ transform <- runStyleToTransform rPr {rVertAlign = Nothing}
319+ extraInfo <- extraRunStyleInfo rPr
320+ return $ subscript . extraInfo . transform
321+ | Just "single" <- rUnderline rPr = do
322+ transform <- runStyleToTransform rPr {rUnderline = Nothing}
323+ extraInfo <- extraRunStyleInfo rPr
324+ return $ underlineSpan . extraInfo . transform
325+ | otherwise = extraRunStyleInfo rPr
303326
304327runToInlines :: PandocMonad m => Run -> DocxContext m Inlines
305328runToInlines (Run rs runElems)
@@ -314,7 +337,8 @@ runToInlines (Run rs runElems)
314337 _ -> codeString
315338 | otherwise = do
316339 let ils = smushInlines (map runElemToInlines runElems)
317− return $ (runStyleToTransform $ resolveDependentRunStyle rs) ils
340+ transform <- runStyleToTransform $ resolveDependentRunStyle rs
341+ return $ transform ils
318342runToInlines (Footnote bps) = do
319343 blksList <- smushBlocks <$> mapM bodyPartToBlocks bps
320344 return $ note blksList
@@ -516,51 +540,60 @@ trimSps (Many ils) = Many $ Seq.dropWhileL isSp $Seq.dropWhileR isSp ils
516540 isSp LineBreak = True
517541 isSp _ = False
518542
519−parStyleToTransform :: ParagraphStyle -> (Blocks -> Blocks)
543+parStyleToTransform :: PandocMonad m => ParagraphStyle -> DocxContext m (Blocks -> Blocks)
520544parStyleToTransform pPr
521545 | (c:cs) <- pStyle pPr
522− , c `elem` divsToKeep =
523− let pPr' = pPr { pStyle = cs }
524− in
525− divWith ("", [c], []) . parStyleToTransform pPr'
546+ , c `elem` divsToKeep = do
547+ let pPr' = pPr { pStyle = cs }
548+ transform <- parStyleToTransform pPr'
549+ return $ divWith ("", [c], []) . transform
526550 | (c:cs) <- pStyle pPr,
527− c `elem` listParagraphDivs =
551+ c `elem` listParagraphDivs = do
528552 let pPr' = pPr { pStyle = cs, indentation = Nothing}
529− in
530− divWith ("", [c], []) . parStyleToTransform pPr'
531− | (_:cs) <- pStyle pPr
532− , Just True <- pBlockQuote pPr =
533− let pPr' = pPr { pStyle = cs }
534− in
535− blockQuote . parStyleToTransform pPr'
536− | (_:cs) <- pStyle pPr =
553+ transform <- parStyleToTransform pPr'
554+ return $ divWith ("", [c], []) . transform
555+ | (c:cs) <- pStyle pPr
556+ , Just True <- pBlockQuote pPr = do
557+ opts <- asks docxOptions
558+ let pPr' = pPr { pStyle = cs }
559+ transform <- parStyleToTransform pPr'
560+ let extraInfo = if isEnabled Ext_styles opts
561+ then divWith ("", [], [("custom-style", c)])
562+ else id
563+ return $ extraInfo . blockQuote . transform
564+ | (c:cs) <- pStyle pPr = do
565+ opts <- asks docxOptions
537566 let pPr' = pPr { pStyle = cs}
538− in
539− parStyleToTransform pPr'
567+ transform <- parStyleToTransform pPr'
568+ let extraInfo = if isEnabled Ext_styles opts
569+ then divWith ("", [], [("custom-style", c)])
570+ else id
571+ return $ extraInfo . transform
540572 | null (pStyle pPr)
541573 , Just left <- indentation pPr >>= leftParIndent
542− , Just hang <- indentation pPr >>= hangingParIndent =
574+ , Just hang <- indentation pPr >>= hangingParIndent = do
543575 let pPr' = pPr { indentation = Nothing }
544− in
545− case (left - hang) > 0 of
546− True -> blockQuote . (parStyleToTransform pPr')
547− False -> parStyleToTransform pPr'
576+ transform <- parStyleToTransform pPr'
577+ return $ case (left - hang) > 0 of
578+ True -> blockQuote . transform
579+ False -> transform
548580 | null (pStyle pPr),
549− Just left <- indentation pPr >>= leftParIndent =
581+ Just left <- indentation pPr >>= leftParIndent = do
550582 let pPr' = pPr { indentation = Nothing }
551− in
552− case left > 0 of
553− True -> blockQuote . (parStyleToTransform pPr')
554− False -> parStyleToTransform pPr'
555−parStyleToTransform _ = id
583+ transform <- parStyleToTransform pPr'
584+ return $ case left > 0 of
585+ True -> blockQuote . transform
586+ False -> transform
587+parStyleToTransform _ = return id
556588
557589bodyPartToBlocks :: PandocMonad m => BodyPart -> DocxContext m Blocks
558590bodyPartToBlocks (Paragraph pPr parparts)
559− | not $ null $ codeDivs `intersect` (pStyle pPr) =
560− return
561− $ parStyleToTransform pPr
562− $ codeBlock
563− $ concatMap parPartToString parparts
591+ | not $ null $ codeDivs `intersect` (pStyle pPr) = do
592+ transform <- parStyleToTransform pPr
593+ return $
594+ transform $
595+ codeBlock $
596+ concatMap parPartToString parparts
564597 | Just (style, n) <- pHeading pPr = do
565598 ils <-local (\s-> s{docxInHeaderBlock=True})
566599 (smushInlines <$> mapM parPartToInlines parparts)
@@ -586,7 +619,8 @@ bodyPartToBlocks (Paragraph pPr parparts)
586619 _ | Just (TrackedChange Insertion _) <- pChange pPr
587620 , AcceptChanges <- readerTrackChanges opts -> do
588621 modify $ \s -> s {docxPrevPara = mempty}
589− return $ parStyleToTransform pPr $ para ils''
622+ transform <- parStyleToTransform pPr
623+ return $ transform $ para ils''
590624 _ | Just (TrackedChange Insertion _) <- pChange pPr
591625 , RejectChanges <- readerTrackChanges opts -> do
592626 modify $ \s -> s {docxPrevPara = ils''}
@@ -596,8 +630,8 @@ bodyPartToBlocks (Paragraph pPr parparts)
596630 , ChangeInfo _ cAuthor cDate <- cInfo -> do
597631 let attr = ("", ["paragraph-insertion"], [("author", cAuthor), ("date", cDate)])
598632 insertMark = spanWith attr mempty
599− return $
600− parStyleToTransform pPr $
633+ transform <- parStyleToTransform pPr
634+ return $ transform $
601635 para $ ils'' <> insertMark
602636 _ | Just (TrackedChange Deletion _) <- pChange pPr
603637 , AcceptChanges <- readerTrackChanges opts -> do
@@ -606,18 +640,20 @@ bodyPartToBlocks (Paragraph pPr parparts)
606640 _ | Just (TrackedChange Deletion _) <- pChange pPr
607641 , RejectChanges <- readerTrackChanges opts -> do
608642 modify $ \s -> s {docxPrevPara = mempty}
609− return $ parStyleToTransform pPr $ para ils''
643+ transform <- parStyleToTransform pPr
644+ return $ transform $ para ils''
610645 _ | Just (TrackedChange Deletion cInfo) <- pChange pPr
611646 , AllChanges <- readerTrackChanges opts
612647 , ChangeInfo _ cAuthor cDate <- cInfo -> do
613648 let attr = ("", ["paragraph-deletion"], [("author", cAuthor), ("date", cDate)])
614649 insertMark = spanWith attr mempty
615− return $
616− parStyleToTransform pPr $
650+ transform <- parStyleToTransform pPr
651+ return $ transform $
617652 para $ ils'' <> insertMark
618653 _ | otherwise -> do
619654 modify $ \s -> s {docxPrevPara = mempty}
620− return $ parStyleToTransform pPr $ para ils''
655+ transform <- parStyleToTransform pPr
656+ return $ transform $ para ils''
621657bodyPartToBlocks (ListItem pPr numId lvl (Just levelInfo) parparts) = do
622658 -- We check whether this current numId has previously been used,
623659 -- since Docx expects us to pick up where we left off.