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
This commit is contained in:
parent
a25e79b5be
commit
5001fd3f4d
5 changed files with 28 additions and 10 deletions
|
@ -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]
|
||||
|
|
|
@ -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"]
|
||||
|
|
|
@ -87,6 +87,11 @@ tests = [ testGroup "inlines"
|
|||
def
|
||||
"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
|
||||
|
|
BIN
test/docx/golden/lists_div_bullets.docx
Normal file
BIN
test/docx/golden/lists_div_bullets.docx
Normal file
Binary file not shown.
5
test/docx/lists_div_bullets.native
Normal file
5
test/docx/lists_div_bullets.native
Normal file
|
@ -0,0 +1,5 @@
|
|||
[ BulletList
|
||||
[ [ Div ( "", [], []) [ Para [ Str "one" ], Para [ Str "two" ] ] ]
|
||||
, [ Div ( "refs", [], []) [ Header 1 ( "" , [] , [] ) [ Str "three" ], Para [ Str "four" ] ] ]
|
||||
]
|
||||
]
|
Loading…
Add table
Reference in a new issue