From 5b4464a741b003112bff418162659578625fa1c7 Mon Sep 17 00:00:00 2001 From: SimJeg Date: Mon, 31 Mar 2025 16:27:50 +0200 Subject: [PATCH] Handle bullet lists Signed-off-by: SimJeg --- docling/backend/msword_backend.py | 72 ++++++++++++++-------- tests/data/docx/unit_test_formatting.docx | Bin 14075 -> 15650 bytes 2 files changed, 45 insertions(+), 27 deletions(-) diff --git a/docling/backend/msword_backend.py b/docling/backend/msword_backend.py index 45083f33..5446602f 100644 --- a/docling/backend/msword_backend.py +++ b/docling/backend/msword_backend.py @@ -379,7 +379,7 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): doc, numid, ilevel, - text, + paragraph_elements, is_numbered, ) self.update_history(p_style_id, p_level, numid, ilevel) @@ -556,7 +556,7 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): doc: DoclingDocument, numid: int, ilevel: int, - text: str, + elements: list[tuple[str, Formatting, str]], is_numbered: bool = False, ) -> None: enum_marker = "" @@ -575,12 +575,17 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): if is_numbered: enum_marker = str(self.listIter) + "." is_numbered = True - doc.add_list_item( - marker=enum_marker, - enumerated=is_numbered, - parent=self.parents[level], - text=text, - ) + + inline_fmt = doc.add_group(label=GroupLabel.INLINE, parent=self.parents[level]) + for text, format, hyperlink in elements: + doc.add_list_item( + marker=enum_marker, + enumerated=is_numbered, + parent=inline_fmt, + text=text, + formatting=format, + hyperlink=hyperlink, + ) elif ( self.prev_numid() == numid @@ -611,13 +616,17 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): if is_numbered: enum_marker = str(self.listIter) + "." is_numbered = True - doc.add_list_item( - marker=enum_marker, - enumerated=is_numbered, - parent=self.parents[self.level_at_new_list + ilevel], - text=text, - ) - + + inline_fmt = doc.add_group(label=GroupLabel.INLINE, parent=self.parents[self.level_at_new_list + ilevel]) + for text, format, hyperlink in elements: + doc.add_list_item( + marker=enum_marker, + enumerated=is_numbered, + parent=inline_fmt, + text=text, + formatting=format, + hyperlink=hyperlink, + ) elif ( self.prev_numid() == numid and self.level_at_new_list is not None @@ -633,12 +642,16 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): if is_numbered: enum_marker = str(self.listIter) + "." is_numbered = True - doc.add_list_item( - marker=enum_marker, - enumerated=is_numbered, - parent=self.parents[self.level_at_new_list + ilevel], - text=text, - ) + inline_fmt = doc.add_group(label=GroupLabel.INLINE, parent=self.parents[self.level_at_new_list + ilevel]) + for text, format, hyperlink in elements: + doc.add_list_item( + marker=enum_marker, + enumerated=is_numbered, + parent=inline_fmt, + text=text, + formatting=format, + hyperlink=hyperlink, + ) self.listIter = 0 elif self.prev_numid() == numid or prev_indent == ilevel: @@ -647,12 +660,17 @@ class MsWordDocumentBackend(DeclarativeDocumentBackend): if is_numbered: enum_marker = str(self.listIter) + "." is_numbered = True - doc.add_list_item( - marker=enum_marker, - enumerated=is_numbered, - parent=self.parents[level - 1], - text=text, - ) + inline_fmt = doc.add_group(label=GroupLabel.INLINE, parent=self.parents[level - 1]) + for text, format, hyperlink in elements: + # Add the list item to the parent group + doc.add_list_item( + marker=enum_marker, + enumerated=is_numbered, + parent=inline_fmt, + text=text, + formatting=format, + hyperlink=hyperlink, + ) return def handle_tables( diff --git a/tests/data/docx/unit_test_formatting.docx b/tests/data/docx/unit_test_formatting.docx index bc5c9d79823e7a7e3202d9454060926722d9af22..2b5a0b65806ef874ccc53d8f0c1bb8f43da4bf89 100644 GIT binary patch delta 10861 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 Q3IGMr^FEuF_g}vM1JJ@O{r~^~