Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docling_core/types/doc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@
OrderedList,
Orientation,
PageItem,
PageMeta,
PictureBarChartData,
PictureChartData,
PictureClassificationClass,
Expand Down
17 changes: 15 additions & 2 deletions docling_core/types/doc/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -1679,6 +1679,10 @@ class FloatingMeta(BaseMeta):
description: Optional[DescriptionMetaField] = None


class PageMeta(BaseMeta):
"""Metadata model for pages."""


class CodeMetaField(BasePrediction):
"""Code representation for the respective item."""

Expand Down Expand Up @@ -2870,6 +2874,7 @@ class PageItem(BaseModel):
# only referencing items on the page
size: Size
image: Optional[ImageRef] = None
meta: Optional[PageMeta] = None
page_no: int


Expand Down Expand Up @@ -7539,14 +7544,22 @@ def get_text(text: str, max_text_len: int):

return "\n".join(result)

def add_page(self, page_no: int, size: Size, image: Optional[ImageRef] = None) -> PageItem:
def add_page(
self,
page_no: int,
size: Size,
image: Optional[ImageRef] = None,
meta: Optional[PageMeta] = None,
) -> PageItem:
"""add_page.

:param page_no: int:
:param size: Size:
:param image: Optional[ImageRef]:
:param meta: Optional[PageMeta]:

"""
pitem = PageItem(page_no=page_no, size=size, image=image)
pitem = PageItem(page_no=page_no, size=size, image=image, meta=meta)

self.pages[page_no] = pitem
return pitem
Expand Down
46 changes: 44 additions & 2 deletions test/test_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@
)
from docling_core.transforms.serializer.webvtt import WebVTTDocSerializer, WebVTTParams
from docling_core.transforms.visualizer.layout_visualizer import LayoutVisualizer
from docling_core.types.doc import DoclingDocument
from docling_core.types.doc.base import ImageRefMode
from docling_core.types.doc import DoclingDocument, PageMeta
from docling_core.types.doc.base import ImageRefMode, Size
from docling_core.types.doc.document import (
BaseMeta,
CharSpan,
Expand Down Expand Up @@ -74,6 +74,48 @@ def _normalize_quotes(s: str) -> str:
# ===============================


def test_page_item_meta_round_trips_in_exported_document():
doc = DoclingDocument(name="page meta")
page_meta = PageMeta(
summary=SummaryMetaField(
text="Summary of page 1",
created_by="page-summary-model",
),
)
page_meta.set_custom_field(
namespace="research",
name="source_scope",
value={"source_type": "10-K", "valid_as_of": "2026-06-18"},
)

doc.add_page(
page_no=1,
size=Size(width=612, height=792),
meta=page_meta,
)

exported = doc.export_to_dict()
assert exported["pages"]["1"]["meta"]["summary"] == {
"text": "Summary of page 1",
"created_by": "page-summary-model",
}
assert exported["pages"]["1"]["meta"]["research__source_scope"] == {
"source_type": "10-K",
"valid_as_of": "2026-06-18",
}

loaded = DoclingDocument.model_validate(exported)
assert loaded.pages[1].meta is not None
assert loaded.pages[1].meta.summary is not None
assert loaded.pages[1].meta.summary.text == "Summary of page 1"
assert loaded.pages[1].meta.get_custom_part() == {
"research__source_scope": {
"source_type": "10-K",
"valid_as_of": "2026-06-18",
},
}


def test_md_cross_page_list_page_break():
src = Path("./test/data/doc/activities.json")
doc = DoclingDocument.load_from_json(src)
Expand Down
Loading