From 015dead0bb2bb5cea06a0fa366fdd651c8e07889 Mon Sep 17 00:00:00 2001 From: hubertp-lshift Date: Sat, 26 Nov 2016 21:45:56 +0100 Subject: [PATCH] [odt] Infer table's caption from the paragraph (#3224) ODT's reader always put empty captions for the parsed tables. This commit 1) checks paragraphs that follow the table definition 2) treats specially a paragraph with a style named 'Table' 3) does some postprocessing of the paragraphs that combines tables followed immediately by captions The ODT writer used 'TableCaption' style name for the caption paragraph. This commit follows the open office approach which allows for appending captions to table but uses a built-in style named 'Table' instead of 'TableCaption'. Any users of odt format (both writer and reader) are therefore required to change the style's name to 'Table', if necessary. --- data/odt/styles.xml | 2 +- src/Text/Pandoc/Readers/Odt/ContentReader.hs | 27 ++++++++++++++---- src/Text/Pandoc/Writers/OpenDocument.hs | 2 +- tests/Tests/Readers/Odt.hs | 1 + .../odt/native/simpleTableWithCaption.native | 1 + tests/odt/odt/simpleTableWithCaption.odt | Bin 0 -> 10396 bytes tests/tables.opendocument | 10 +++---- 7 files changed, 29 insertions(+), 14 deletions(-) create mode 100644 tests/odt/native/simpleTableWithCaption.native create mode 100644 tests/odt/odt/simpleTableWithCaption.odt diff --git a/data/odt/styles.xml b/data/odt/styles.xml index 1f1e2c5c8..623a89051 100644 --- a/data/odt/styles.xml +++ b/data/odt/styles.xml @@ -133,7 +133,7 @@ xmlns:css3t="http://www.w3.org/TR/css3-text/" office:version="1.2"> style:font-size-complex="12pt" style:font-style-complex="italic" /> - do where isCodeStyle :: StyleName -> Bool isCodeStyle "Source_Text" = True - isCodeStyle _ = False + isCodeStyle _ = False inlineCode :: Inlines -> Inlines inlineCode = code . intercalate "" . map stringify . toList @@ -415,12 +415,18 @@ constructPara reader = proc blocks -> do fStyle <- readStyleByName -< blocks case fStyle of Left _ -> reader -< blocks + Right (styleName, _) | isTableCaptionStyle styleName -> do + blocks' <- reader -< blocks + arr tableCaptionP -< blocks' Right (_, style) -> do let modifier = getParaModifier style - blocks' <- reader -< blocks - arr modifier -<< blocks' - - + blocks' <- reader -< blocks + arr modifier -<< blocks' + where + isTableCaptionStyle :: StyleName -> Bool + isTableCaptionStyle "Table" = True + isTableCaptionStyle _ = False + tableCaptionP b = divWith ("", ["caption"], []) b type ListConstructor = [Blocks] -> Blocks @@ -904,6 +910,15 @@ read_text = matchChildContent' [ read_header ] >>^ doc +post_process :: Pandoc -> Pandoc +post_process (Pandoc m blocks) = + Pandoc m (post_process' blocks) + +post_process' :: [Block] -> [Block] +post_process' ((Table _ a w h r) : (Div ("", ["caption"], _) [Para inlines] ) : xs) = + (Table inlines a w h r) : ( post_process' xs ) +post_process' bs = bs + read_body :: OdtReader _x (Pandoc, MediaBag) read_body = executeIn NsOffice "body" $ executeIn NsOffice "text" @@ -911,4 +926,4 @@ read_body = executeIn NsOffice "body" $ proc inlines -> do txt <- read_text -< inlines state <- getExtraState -< () - returnA -< (txt, getMediaBag state) + returnA -< (post_process txt, getMediaBag state) diff --git a/src/Text/Pandoc/Writers/OpenDocument.hs b/src/Text/Pandoc/Writers/OpenDocument.hs index 42c151780..8bd0f469e 100644 --- a/src/Text/Pandoc/Writers/OpenDocument.hs +++ b/src/Text/Pandoc/Writers/OpenDocument.hs @@ -336,7 +336,7 @@ blockToOpenDocument o bs mapM_ addParaStyle . newPara $ paraHStyles ++ paraStyles captionDoc <- if null c then return empty - else withParagraphStyle o "TableCaption" [Para c] + else withParagraphStyle o "Table" [Para c] th <- if all null h then return empty else colHeadsToOpenDocument o name (map fst paraHStyles) h diff --git a/tests/Tests/Readers/Odt.hs b/tests/Tests/Readers/Odt.hs index d6ed48f8d..cd764dd62 100644 --- a/tests/Tests/Readers/Odt.hs +++ b/tests/Tests/Readers/Odt.hs @@ -157,6 +157,7 @@ namesOfTestsComparingToNative = [ "blockquote" , "referenceToListItem" , "referenceToText" , "simpleTable" + , "simpleTableWithCaption" -- , "table" , "unicode" , "unorderedList" diff --git a/tests/odt/native/simpleTableWithCaption.native b/tests/odt/native/simpleTableWithCaption.native new file mode 100644 index 000000000..18d68b772 --- /dev/null +++ b/tests/odt/native/simpleTableWithCaption.native @@ -0,0 +1 @@ +[Table [Str "Table",Space,Str "1:",Space,Str "Some",Space,Str "caption",Space,Str "for",Space,Str "a",Space,Str "table"] [AlignDefault,AlignDefault] [0.0,0.0] [[],[]] [[[Plain [Str "Content"]],[Plain [Str "More",Space,Str "content"]]]],Para []] diff --git a/tests/odt/odt/simpleTableWithCaption.odt b/tests/odt/odt/simpleTableWithCaption.odt new file mode 100644 index 0000000000000000000000000000000000000000..ec6fac89471c6124d2defc78057f6e908dfb0ce8 GIT binary patch literal 10396 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 literal 0 HcmV?d00001 diff --git a/tests/tables.opendocument b/tests/tables.opendocument index aa35abc91..0765bb783 100644 --- a/tests/tables.opendocument +++ b/tests/tables.opendocument @@ -63,8 +63,7 @@ -Demonstration of simple table -syntax. +Demonstration of simple table syntax. Simple table without caption: @@ -197,8 +196,7 @@ spaces: -Demonstration of simple table -syntax. +Demonstration of simple table syntax. Multiline table with caption: @@ -253,8 +251,8 @@ caption: -Here's the caption. It may span -multiple lines. +Here's the caption. It may span multiple +lines. Multiline table without caption: