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
21 changes: 20 additions & 1 deletion docling_core/types/doc/document.py
Original file line number Diff line number Diff line change
Expand Up @@ -3750,6 +3750,8 @@ def export_to_markdown(
allowed_meta_names: Optional[set[str]] = None,
blocked_meta_names: Optional[set[str]] = None,
mark_meta: bool = False,
image_dir: Optional[Path] = None,
image_path_prefix: str = "",
) -> str:
r"""Serialize to Markdown.

Expand Down Expand Up @@ -3812,6 +3814,15 @@ def export_to_markdown(
:type allowed_meta_names: Optional[set[str]] = None
:param blocked_meta_names: Optional[set[str]]: Meta names to block; takes precedence over allowed_meta_names.
:type blocked_meta_names: Optional[set[str]] = None
:param image_dir: When set together with `image_mode=ImageRefMode.REFERENCED`, pictures are
saved as PNG files under this directory and referenced from the Markdown output instead
of requiring the caller to save images and rewrite URIs manually. The directory is
created if it does not already exist. (Default value = None).
:type image_dir: Optional[Path] = None
:param image_path_prefix: Prefix prepended to each saved image's filename when building the
Markdown image reference, e.g. "images/" or a URL prefix. Only used when `image_dir` is
set. (Default value = "").
:type image_path_prefix: str = ""
"""
from docling_core.transforms.serializer.markdown import (
MarkdownDocSerializer,
Expand All @@ -3827,8 +3838,16 @@ def export_to_markdown(
DeprecationWarning,
)

export_doc: DoclingDocument = self
if image_dir is not None:
export_doc = self._with_pictures_refs(image_dir=image_dir, page_no=page_no)
for item, _ in export_doc.iterate_items(page_no=page_no, with_groups=False):
if isinstance(item, PictureItem) and item.image is not None and item.image.uri is not None:
filename = Path(str(item.image.uri)).name
item.image.uri = Path(f"{image_path_prefix}{filename}")

serializer = MarkdownDocSerializer(
doc=self,
doc=export_doc,
params=MarkdownParams(
labels=my_labels,
layers=my_layers,
Expand Down
26 changes: 26 additions & 0 deletions test/test_docling_doc.py
Original file line number Diff line number Diff line change
Expand Up @@ -1335,6 +1335,32 @@ def test_save_to_disk(sample_doc):
assert True


def test_export_to_markdown_image_dir(sample_doc: DoclingDocument, tmp_path: Path) -> None:
image_dir = tmp_path / "assets"

md = sample_doc.export_to_markdown(
image_mode=ImageRefMode.REFERENCED,
image_dir=image_dir,
image_path_prefix="assets/",
)

saved_images = list(image_dir.glob("*.png"))
assert len(saved_images) == 1, "expected exactly one image to be saved to image_dir"

image_lines = [line for line in md.splitlines() if "![" in line]
assert len(image_lines) == 1, "expected exactly one image reference in the markdown output"
assert saved_images[0].name in image_lines[0], "markdown should reference the saved image's filename"
assert "assets" in image_lines[0], "markdown reference should include image_path_prefix"


def test_export_to_markdown_without_image_dir_is_unaffected(sample_doc: DoclingDocument) -> None:
# image_dir defaults to None, so no images should be written to disk and
# behavior should match calling export_to_markdown without the new params.
baseline = sample_doc.export_to_markdown(image_mode=ImageRefMode.PLACEHOLDER)
unchanged = sample_doc.export_to_markdown(image_mode=ImageRefMode.PLACEHOLDER, image_path_prefix="assets/")
assert baseline == unchanged


def test_document_stack_operations(sample_doc):
# _print(document=doc)

Expand Down
Loading