diff options
| author | Michael Hoffmann <[email protected]> | 2022-01-12 00:48:41 +0100 |
|---|---|---|
| committer | GitHub <[email protected]> | 2022-01-11 15:48:41 -0800 |
| commit | 5001fd3f4d0daee5802a78f6d99d538ff9db4336 (patch) | |
| tree | eae58b1ea82078d3d2c3603d7d8811876e52adae | |
| parent | a25e79b5bef9a55c076351d1321675e26513f8ac (diff) | |
Docx writer: Handle bullets correctly in lists by not reusing numIds (#7822)
Make sure that we only create one bullet per list item in docx. In
particular, when a div is a list item, its contained paragraphs will
now no longer wrongly get individual bullets.
This is accomplished by making sure that for each list, we only use
the associated numId once. Any repeated use would add incorrect
bullets to the document.
Closes #7689
| -rw-r--r-- | src/Text/Pandoc/Writers/Docx.hs | 25 | ||||
| -rw-r--r-- | src/Text/Pandoc/Writers/Docx/Types.hs | 3 | ||||
| -rw-r--r-- | test/Tests/Writers/Docx.hs | 5 | ||||
| -rw-r--r-- | test/docx/golden/lists_div_bullets.docx | bin | 0 -> 9878 bytes | |||
| -rw-r--r-- | test/docx/lists_div_bullets.native | 5 |
5 files changed, 28 insertions, 10 deletions
diff --git a/src/Text/Pandoc/Writers/Docx.hs b/src/Text/Pandoc/Writers/Docx.hs index f76a8b86c..6ad91d2bd 100644 --- a/src/Text/Pandoc/Writers/Docx.hs +++ b/src/Text/Pandoc/Writers/Docx.hs @@ -965,8 +965,7 @@ listItemToOpenXML :: (PandocMonad m) => WriterOptions -> Int -> [Block] -> WS m [Content] -listItemToOpenXML _ _ [] = return [] -listItemToOpenXML opts numid (first:rest) = do +listItemToOpenXML opts numid bs = do oldInList <- gets stInList modify $ \st -> st{ stInList = True } let isListBlock = \case @@ -975,14 +974,15 @@ listItemToOpenXML opts numid (first:rest) = do _ -> False -- Prepend an empty string if the first entry is another -- list. Otherwise the outer bullet will disappear. - let (first', rest') = if isListBlock first - then (Plain [Str ""] , first:rest) - else (first, rest) - first'' <- withNumId numid $ blockToOpenXML opts first' - -- baseListId is the code for no list marker: - rest'' <- withNumId baseListId $ blocksToOpenXML opts rest' + let bs' = case bs of + [] -> [] + first:rest -> if isListBlock first + then Plain [Str ""]:first:rest + else first:rest + modify $ \st -> st{ stNumIdUsed = False } + contents <- withNumId numid $ blocksToOpenXML opts bs' modify $ \st -> st{ stInList = oldInList } - return $ first'' ++ rest'' + return contents -- | Convert a list of inline elements to OpenXML. inlinesToOpenXML :: PandocMonad m => WriterOptions -> [Inline] -> WS m [Content] @@ -1015,9 +1015,14 @@ getParaProps displayMathPara = do props <- asks envParaProperties listLevel <- asks envListLevel numid <- asks envListNumId + numIdUsed <- gets stNumIdUsed + -- clear numId after first use to support multiple paragraphs in the same bullet + -- baseListId is the code for no list marker + let numid' = if numIdUsed then baseListId else numid + modify $ \st -> st{ stNumIdUsed = True } let listPr = [mknode "w:numPr" [] [ mknode "w:ilvl" [("w:val",tshow listLevel)] () - , mknode "w:numId" [("w:val",tshow numid)] () ] | listLevel >= 0 && not displayMathPara] + , mknode "w:numId" [("w:val",tshow numid')] () ] | listLevel >= 0 && not displayMathPara] return $ case listPr ++ squashProps props of [] -> [] ps -> [mknode "w:pPr" [] ps] diff --git a/src/Text/Pandoc/Writers/Docx/Types.hs b/src/Text/Pandoc/Writers/Docx/Types.hs index e367e9cbb..15e16cb93 100644 --- a/src/Text/Pandoc/Writers/Docx/Types.hs +++ b/src/Text/Pandoc/Writers/Docx/Types.hs @@ -111,6 +111,8 @@ data WriterState = WriterState{ , stDelId :: Int , stStyleMaps :: StyleMaps , stFirstPara :: Bool + , stNumIdUsed :: Bool -- ^ True if the current numId (envListNumId) has been used. + -- Should only be used once, for the first paragraph. , stInTable :: Bool , stInList :: Bool , stTocTitle :: [Inline] @@ -133,6 +135,7 @@ defaultWriterState = WriterState{ , stDelId = 1 , stStyleMaps = StyleMaps M.empty M.empty , stFirstPara = False + , stNumIdUsed = False , stInTable = False , stInList = False , stTocTitle = [Str "Table of Contents"] diff --git a/test/Tests/Writers/Docx.hs b/test/Tests/Writers/Docx.hs index 93b56e1c2..603aeb0cd 100644 --- a/test/Tests/Writers/Docx.hs +++ b/test/Tests/Writers/Docx.hs @@ -88,6 +88,11 @@ tests = [ testGroup "inlines" "docx/lists_multiple_initial.native" "docx/golden/lists_multiple_initial.docx" , docxTest + "lists with div bullets" + def + "docx/lists_div_bullets.native" + "docx/golden/lists_div_bullets.docx" + , docxTest "definition lists" def "docx/definition_list.native" diff --git a/test/docx/golden/lists_div_bullets.docx b/test/docx/golden/lists_div_bullets.docx Binary files differnew file mode 100644 index 000000000..84b7c6501 --- /dev/null +++ b/test/docx/golden/lists_div_bullets.docx diff --git a/test/docx/lists_div_bullets.native b/test/docx/lists_div_bullets.native new file mode 100644 index 000000000..f86d76083 --- /dev/null +++ b/test/docx/lists_div_bullets.native @@ -0,0 +1,5 @@ +[ BulletList + [ [ Div ( "", [], []) [ Para [ Str "one" ], Para [ Str "two" ] ] ] + , [ Div ( "refs", [], []) [ Header 1 ( "" , [] , [] ) [ Str "three" ], Para [ Str "four" ] ] ] + ] +] |
