Skip to content

feat(markdown): add picture index to image placeholder#555

Closed
nuri-yoo wants to merge 5 commits intodocling-project:mainfrom
nuri-yoo:feat/image-placeholder-index
Closed

feat(markdown): add picture index to image placeholder#555
nuri-yoo wants to merge 5 commits intodocling-project:mainfrom
nuri-yoo:feat/image-placeholder-index

Conversation

@nuri-yoo
Copy link
Copy Markdown

@nuri-yoo nuri-yoo commented Mar 18, 2026

Summary

Add sequential picture indexing to the markdown image placeholder by introducing a {index} format token in image_placeholder.

  • Default: "<!-- image -->""<!-- image_{index} -->" → renders as <!-- image_0 -->, <!-- image_1 -->, ...
  • Index is extracted from item.self_ref (e.g. "#/pictures/6"6), matching JSON export references
  • Backward compatible: custom placeholders without {index} are unaffected (.replace() is a no-op)

Changes

  • MarkdownParams.image_placeholder default updated
  • MarkdownPictureSerializer._serialize_image_part(): resolve {index} token before emitting placeholder
  • Ground truth test data regenerated

Testing

  • All existing tests pass (369 passed, 0 failed)
  • Verified backward compatibility with explicit image_placeholder="<!-- image -->" (no {index} token → no change)

Resolves docling-project/docling#3078

@github-actions
Copy link
Copy Markdown
Contributor

github-actions bot commented Mar 18, 2026

DCO Check Passed

Thanks @nuri-yoo, all your commits are properly signed off. 🎉

@mergify
Copy link
Copy Markdown
Contributor

mergify bot commented Mar 18, 2026

Merge Protections

Your pull request matches the following merge protections and will not be merged until they are valid.

🔴 Require two reviewer for test updates

Waiting for:

  • #approved-reviews-by >= 2
This rule is failing.

When test data is updated, we require two reviewers

  • #approved-reviews-by >= 2

🟢 Enforce conventional commit

Wonderful, this rule succeeded.

Make sure that we follow https://www.conventionalcommits.org/en/v1.0.0/

  • title ~= ^(fix|feat|docs|style|refactor|perf|test|build|ci|chore|revert)(?:\(.+\))?(!)?:

@dosubot
Copy link
Copy Markdown

dosubot bot commented Mar 18, 2026

Related Documentation

1 document(s) may need updating based on files changed in this PR:

Docling

What are the detailed pipeline options and processing behaviors for PDF, DOCX, PPTX, and XLSX files in the Python SDK?
View Suggested Changes
@@ -7,7 +7,7 @@
     - `do_ocr` (default True): Use OCR
     - `force_ocr`: Replace existing text with OCR-generated text
     - `ocr_engine`, `ocr_lang`: OCR engine and language options
-    - `image_export_mode`: `placeholder`, `embedded`, `referenced`
+    - `image_export_mode`: `placeholder`, `embedded`, `referenced`. When using `placeholder` mode with Markdown export, the default placeholder format is `"<!-- image_{index} -->"`, which renders as sequential placeholders like `<!-- image_0 -->`, `<!-- image_1 -->`, etc. The index corresponds to the picture reference in the JSON export (e.g., `item.self_ref` like `"#/pictures/6"` → `6`). This is backward compatible—custom placeholders without the `{index}` token are unaffected.
     - `do_table_structure`, `table_mode`, `table_cell_matching`: Table extraction options (see Table Structure Models section below for details on TableFormer V1 and V2)
     - `do_code_enrichment`, `do_formula_enrichment`: Code/formula recognition
     - `vlm_pipeline_preset`, `vlm_pipeline_custom_config`, `picture_description_preset`, `picture_description_custom_config`, `code_formula_preset`, `code_formula_custom_config`: New model inference engine and preset options for VLM, picture description, and code/formula extraction

[Accept] [Decline]

Note: You must be authenticated to accept/decline updates.

How did I do? Any feedback?  Join Discord

@codecov
Copy link
Copy Markdown

codecov bot commented Mar 19, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@ceberam ceberam self-requested a review March 19, 2026 13:31
nryoo added 4 commits March 20, 2026 20:42
Use `{index}` token in `image_placeholder` to include the picture index
from `item.self_ref`. Default placeholder changes from `<!-- image -->`
to `<!-- image_{index} -->`, producing `<!-- image_0 -->`, etc.

Backward compatible: custom placeholders without `{index}` are unaffected.

Related: docling-project/docling#3078
I, nryoo <nryoo@nryooui-MacBookPro.local>, hereby add my Signed-off-by to this commit: 5de57a5

Signed-off-by: nryoo <nryoo@nryooui-MacBookPro.local>
Signed-off-by: nryoo <nryoo@nryooui-MacBookPro.local>
Signed-off-by: nryoo <nryoo@nryooui-MacBookPro.local>
@nuri-yoo nuri-yoo force-pushed the feat/image-placeholder-index branch from 4d418c3 to 8ee7731 Compare March 20, 2026 11:43
I, nryoo <nryoo@nryooui-MacBookPro.local>, hereby add my Signed-off-by to this commit: c157073

Signed-off-by: nryoo <nryoo@nryooui-MacBookPro.local>
@ceberam
Copy link
Copy Markdown
Member

ceberam commented Mar 20, 2026

@nuri-yoo I've seen you've been adding new commits lately. Just please let us know when it's ready for review.

@nuri-yoo
Copy link
Copy Markdown
Author

Ready for review. All CI checks are passing now.

@nuri-yoo
Copy link
Copy Markdown
Author

nuri-yoo commented Apr 6, 2026

@ceberam Gentle ping on this PR. Appreciate a review when you get a chance.

Copy link
Copy Markdown
Member

@ceberam ceberam left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks a lot @nuri-yoo for your contribution. However, I don’t think indexed image placeholders should become the library default. Markdown export here is a lossy text representation of DoclingDocument. Embedding self_ref-derived picture identity into the default output makes it application-specific and sets a precedent for exposing internal node indices for other item types as well. The DoclingDocument should be the reference object for document hierarchy.

The same workflow can be achieved with a custom serializer extension (e.g., custom MarkdownPictureSerializer / BasePictureSerializer), as shown in Creating a custom serializer.

For instance:

from pathlib import Path

from docling_core.transforms.serializer.base import SerializationResult
from docling_core.transforms.serializer.common import create_ser_result
from docling_core.transforms.serializer.markdown import (
    MarkdownDocSerializer,
    MarkdownParams,
    MarkdownPictureSerializer,
)
from docling_core.types.doc.base import ImageRefMode
from docling_core.types.doc.document import DoclingDocument, PictureItem


class IndexedMarkdownPictureSerializer(MarkdownPictureSerializer):
    """Custom picture serializer that supports {index} in the placeholder."""

    def _serialize_image_part(
        self,
        item: PictureItem,
        doc: DoclingDocument,
        image_mode: ImageRefMode,
        image_placeholder: str,
        **kwargs,
    ) -> SerializationResult:
        pic_idx = item.self_ref.rsplit("/", 1)[-1]
        resolved_placeholder = image_placeholder.replace("{index}", pic_idx)

        # Reuse the parent implementation for non-placeholder modes if desired.
        if image_mode != ImageRefMode.PLACEHOLDER:
            return super()._serialize_image_part(
                item=item,
                doc=doc,
                image_mode=image_mode,
                image_placeholder=resolved_placeholder,
                **kwargs,
            )

        return create_ser_result(text=resolved_placeholder, span_source=item)


# Example usage with an existing document
src = Path("test/data/doc/2408.09869v3_enriched.json")
doc: DoclingDocument = DoclingDocument.load_from_json(src)

serializer = MarkdownDocSerializer(
    doc=doc,
    picture_serializer=IndexedMarkdownPictureSerializer(),
    params=MarkdownParams(
        image_mode=ImageRefMode.PLACEHOLDER,
        image_placeholder="<!-- image_{index} -->",
    ),
)

markdown = serializer.serialize().text
print(markdown)

My suggestion would be:

@nuri-yoo
Copy link
Copy Markdown
Author

Thanks for the thorough review and the alternative approach. I'll close this and open a docs PR extending serialization.ipynb with the custom serializer example instead.

@nuri-yoo nuri-yoo closed this Apr 14, 2026
@ceberam
Copy link
Copy Markdown
Member

ceberam commented Apr 14, 2026

Thanks for the thorough review and the alternative approach. I'll close this and open a docs PR extending serialization.ipynb with the custom serializer example instead.

Sounds good! You can link the new PR to the same issue docling-project/docling#3078 when it's ready.

nuri-yoo added a commit to nuri-yoo/docling that referenced this pull request Apr 14, 2026
Show how to subclass MarkdownPictureSerializer to resolve {index}
tokens in image placeholders using self_ref, as an alternative to
modifying the library default.

Ref: docling-project/docling-core#555
PeterStaar-IBM pushed a commit to docling-project/docling that referenced this pull request Apr 15, 2026
…ok (#3293)

* docs: add indexed picture placeholder example to serialization notebook

Show how to subclass MarkdownPictureSerializer to resolve {index}
tokens in image placeholders using self_ref, as an alternative to
modifying the library default.

Ref: docling-project/docling-core#555

* DCO Remediation Commit for nuri-yoo <nuri-yoo@users.noreply.github.com>

I, nuri-yoo <nuri-yoo@users.noreply.github.com>, hereby add my Signed-off-by to this commit: 82cb733

Signed-off-by: nuri-yoo <nuri-yoo@users.noreply.github.com>

---------

Signed-off-by: nuri-yoo <nuri-yoo@users.noreply.github.com>
Co-authored-by: nuri-yoo <nuri-yoo@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

image/figure count in md an txt

2 participants