Skip to content

Commit e1d0597

Browse files
authored
fix: enable caption serialization for all floating items (#216)
Signed-off-by: Panos Vagenas <[email protected]>
1 parent 2efb71a commit e1d0597

File tree

2 files changed

+87
-58
lines changed

2 files changed

+87
-58
lines changed

docling_core/experimental/serializer/doctags.py

Lines changed: 66 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
CodeItem,
2424
DocItem,
2525
DoclingDocument,
26+
FloatingItem,
2627
FormItem,
2728
InlineGroup,
2829
KeyValueItem,
@@ -126,10 +127,15 @@ def serialize(
126127
if text_part:
127128
parts.append(text_part)
128129

129-
res = "".join(parts)
130+
if params.add_caption and isinstance(item, FloatingItem):
131+
cap_text = doc_serializer.serialize_captions(item=item, **kwargs).text
132+
if cap_text:
133+
parts.append(cap_text)
134+
135+
text_res = "".join(parts)
130136
if wrap_tag is not None:
131-
res = _wrap(text=res, wrap_tag=wrap_tag)
132-
return SerializationResult(text=res)
137+
text_res = _wrap(text=text_res, wrap_tag=wrap_tag)
138+
return SerializationResult(text=text_res)
133139

134140

135141
class DocTagsTableSerializer(BaseTableSerializer):
@@ -147,44 +153,36 @@ def serialize(
147153
"""Serializes the passed item."""
148154
params = DocTagsParams(**kwargs)
149155

150-
body = ""
156+
parts: list[str] = []
151157

152158
if item.self_ref not in doc_serializer.get_excluded_refs(**kwargs):
153159
if params.add_location:
154-
body += item.get_location_tokens(
160+
loc_text = item.get_location_tokens(
155161
doc=doc,
156162
xsize=params.xsize,
157163
ysize=params.ysize,
158164
)
165+
parts.append(loc_text)
159166

160-
body += item.export_to_otsl(
167+
otsl_text = item.export_to_otsl(
161168
doc=doc,
162169
add_cell_location=params.add_table_cell_location,
163170
add_cell_text=params.add_table_cell_text,
164171
xsize=params.xsize,
165172
ysize=params.ysize,
166173
)
174+
parts.append(otsl_text)
167175

168-
if params.add_caption and len(item.captions):
169-
text = doc_serializer.serialize_captions(item, **kwargs).text
170-
171-
if len(text):
172-
body += f"<{DocumentToken.CAPTION.value}>"
173-
for caption in item.captions:
174-
if caption.cref not in doc_serializer.get_excluded_refs(**kwargs):
175-
if isinstance(cap := caption.resolve(doc), DocItem):
176-
body += cap.get_location_tokens(
177-
doc=doc,
178-
xsize=params.xsize,
179-
ysize=params.ysize,
180-
)
181-
body += f"{text.strip()}"
182-
body += f"</{DocumentToken.CAPTION.value}>"
183-
184-
if body:
185-
body = _wrap(text=body, wrap_tag=DocumentToken.OTSL.value)
176+
if params.add_caption:
177+
cap_text = doc_serializer.serialize_captions(item=item, **kwargs).text
178+
if cap_text:
179+
parts.append(cap_text)
186180

187-
return SerializationResult(text=body)
181+
text_res = "".join(parts)
182+
if text_res:
183+
text_res = _wrap(text=text_res, wrap_tag=DocumentToken.OTSL.value)
184+
185+
return SerializationResult(text=text_res)
188186

189187

190188
class DocTagsPictureSerializer(BasePictureSerializer):
@@ -230,31 +228,18 @@ def serialize(
230228
)
231229
parts.append(body)
232230

233-
if params.add_caption and len(item.captions):
234-
text = doc_serializer.serialize_captions(item, **kwargs).text
235-
236-
if len(text):
237-
body = ""
238-
for caption in item.captions:
239-
if caption.cref not in doc_serializer.get_excluded_refs(**kwargs):
240-
if isinstance(cap := caption.resolve(doc), DocItem):
241-
body += cap.get_location_tokens(
242-
doc=doc,
243-
xsize=params.xsize,
244-
ysize=params.ysize,
245-
)
246-
body += f"{text.strip()}"
247-
if body:
248-
body = _wrap(text=body, wrap_tag=DocumentToken.CAPTION.value)
249-
parts.append(body)
250-
251-
text = "".join(parts)
252-
if text:
231+
if params.add_caption:
232+
cap_text = doc_serializer.serialize_captions(item=item, **kwargs).text
233+
if cap_text:
234+
parts.append(cap_text)
235+
236+
text_res = "".join(parts)
237+
if text_res:
253238
token = DocumentToken.create_token_name_from_doc_item_label(
254239
label=item.label
255240
)
256-
text = _wrap(text=text, wrap_tag=token)
257-
return SerializationResult(text=text)
241+
text_res = _wrap(text=text_res, wrap_tag=token)
242+
return SerializationResult(text=text_res)
258243

259244

260245
class DocTagsKeyValueSerializer(BaseKeyValueSerializer):
@@ -318,6 +303,11 @@ def serialize(
318303
cell_txt = _wrap(text=cell_txt, wrap_tag=tok)
319304
body += cell_txt
320305

306+
if params.add_caption:
307+
cap_text = doc_serializer.serialize_captions(item=item, **kwargs).text
308+
if cap_text:
309+
body += cap_text
310+
321311
body = _wrap(body, DocumentToken.KEY_VALUE_REGION.value)
322312
return SerializationResult(text=body)
323313

@@ -471,3 +461,32 @@ def serialize_doc(self, pages: list[SerializationResult]) -> SerializationResult
471461
wrap_tag = DocumentToken.DOCUMENT.value
472462
text_res = f"<{wrap_tag}>{content}{delim}</{wrap_tag}>"
473463
return SerializationResult(text=text_res)
464+
465+
@override
466+
def serialize_captions(
467+
self,
468+
item: FloatingItem,
469+
**kwargs,
470+
) -> SerializationResult:
471+
"""Serialize the item's captions."""
472+
params = DocTagsParams(**kwargs)
473+
parts: list[str] = []
474+
475+
if item.captions:
476+
cap_text = super().serialize_captions(item, **kwargs).text
477+
if cap_text:
478+
if params.add_location:
479+
for caption in item.captions:
480+
if caption.cref not in self.get_excluded_refs(**kwargs):
481+
if isinstance(cap := caption.resolve(self.doc), DocItem):
482+
loc_txt = cap.get_location_tokens(
483+
doc=self.doc,
484+
xsize=params.xsize,
485+
ysize=params.ysize,
486+
)
487+
parts.append(loc_txt)
488+
parts.append(cap_text)
489+
text_res = "".join(parts)
490+
if text_res:
491+
text_res = _wrap(text=text_res, wrap_tag=DocumentToken.CAPTION.value)
492+
return SerializationResult(text=text_res)

docling_core/experimental/serializer/markdown.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
ContentLayer,
3434
DocItem,
3535
DoclingDocument,
36+
FloatingItem,
3637
Formatting,
3738
FormItem,
3839
FormulaItem,
@@ -77,37 +78,46 @@ def serialize(
7778
) -> SerializationResult:
7879
"""Serializes the passed item."""
7980
params = MarkdownParams(**kwargs)
81+
parts: list[str] = []
8082
escape_html = True
8183
escape_underscores = True
8284
if isinstance(item, TitleItem):
83-
res = f"# {item.text}"
85+
text = f"# {item.text}"
8486
elif isinstance(item, SectionHeaderItem):
85-
res = f"{(item.level + 1) * '#'} {item.text}"
87+
text = f"{(item.level + 1) * '#'} {item.text}"
8688
elif isinstance(item, CodeItem):
87-
res = f"`{item.text}`" if is_inline_scope else f"```\n{item.text}\n```"
89+
text = f"`{item.text}`" if is_inline_scope else f"```\n{item.text}\n```"
8890
escape_html = False
8991
escape_underscores = False
9092
elif isinstance(item, FormulaItem):
9193
if item.text:
92-
res = f"${item.text}$" if is_inline_scope else f"$${item.text}$$"
94+
text = f"${item.text}$" if is_inline_scope else f"$${item.text}$$"
9395
elif item.orig:
94-
res = "<!-- formula-not-decoded -->"
96+
text = "<!-- formula-not-decoded -->"
9597
else:
96-
res = ""
98+
text = ""
9799
escape_html = False
98100
escape_underscores = False
99101
elif params.wrap_width:
100-
res = textwrap.fill(item.text, width=params.wrap_width)
102+
text = textwrap.fill(item.text, width=params.wrap_width)
101103
else:
102-
res = item.text
103-
res = doc_serializer.post_process(
104-
text=res,
104+
text = item.text
105+
parts.append(text)
106+
107+
if isinstance(item, FloatingItem):
108+
cap_text = doc_serializer.serialize_captions(item=item, **kwargs).text
109+
if cap_text:
110+
parts.append(cap_text)
111+
112+
text_res = (" " if is_inline_scope else "\n\n").join(parts)
113+
text_res = doc_serializer.post_process(
114+
text=text_res,
105115
escape_html=escape_html,
106116
escape_underscores=escape_underscores,
107117
formatting=item.formatting,
108118
hyperlink=item.hyperlink,
109119
)
110-
return SerializationResult(text=res)
120+
return SerializationResult(text=text_res)
111121

112122

113123
class MarkdownTableSerializer(BaseTableSerializer):

0 commit comments

Comments
 (0)