aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Hoffmann <[email protected]>2022-01-12 00:48:41 +0100
committerGitHub <[email protected]>2022-01-11 15:48:41 -0800
commit5001fd3f4d0daee5802a78f6d99d538ff9db4336 (patch)
treeeae58b1ea82078d3d2c3603d7d8811876e52adae
parenta25e79b5bef9a55c076351d1321675e26513f8ac (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.hs25
-rw-r--r--src/Text/Pandoc/Writers/Docx/Types.hs3
-rw-r--r--test/Tests/Writers/Docx.hs5
-rw-r--r--test/docx/golden/lists_div_bullets.docxbin0 -> 9878 bytes
-rw-r--r--test/docx/lists_div_bullets.native5
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
new file mode 100644
index 000000000..84b7c6501
--- /dev/null
+++ b/test/docx/golden/lists_div_bullets.docx
Binary files differ
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" ] ] ]
+ ]
+]