Skip to content

feat(pdf): return positioned image files with Markdown - #83

Draft
qin-ctx wants to merge 3 commits into
firecrawl:mainfrom
qin-ctx:feat/pdf-image-placeholders
Draft

feat(pdf): return positioned image files with Markdown#83
qin-ctx wants to merge 3 commits into
firecrawl:mainfrom
qin-ctx:feat/pdf-image-placeholders

Conversation

@qin-ctx

@qin-ctx qin-ctx commented Aug 12, 2026

Copy link
Copy Markdown

Background

AnyDoc uses pdf-inspector to convert PDFs to Markdown. The current PDF API returns Markdown only, so an embedded image is either omitted or represented by a marker that cannot be matched to image data.

OpenViking is integrating AnyDoc as its document parser. It needs one PDF conversion result containing:

  • Markdown with each image in the correct reading position;
  • the matching image file for every Markdown image target;
  • the PDF diagnostics already collected during conversion.

Without this result, OpenViking would have to parse the PDF a second time and guess where each extracted image belongs.

Before

The existing API returns Markdown only:

markdown = anydoc.to_markdown_bytes(pdf_bytes)

It does not return image bytes or a filename that can be matched to a Markdown image target.

After

The new API returns Markdown, positioned PNG files, and PDF diagnostics together:

result = anydoc.pdf_to_markdown_with_images(pdf_bytes)

For a PDF containing text, an image, and more text, the result looks like this:

Before image.

![Image: Im0](p1_i1.png)

After image.

The returned image uses the exact same filename:

image = result.images[0]

assert image.filename == "p1_i1.png"
assert image.page == 1

Path(image.filename).write_bytes(image.data)

The binding rule is simple: the Markdown target equals image.filename. A caller saves image.data under that filename. No generated asset ID, coordinate matching, or second PDF pass is required.

Each image also contains its source bounding box, PNG dimensions, PNG bytes, and renderer warning codes. Repeated placements are returned as separate files because their position and rendered appearance can differ.

The result also includes:

  • page_count;
  • pages_needing_ocr;
  • ocr_reasons_by_page;
  • pages_with_tables;
  • pages_with_columns;
  • is_complex_layout;
  • has_encoding_issues.

Compatibility

The existing to_markdown and to_markdown_bytes APIs do not change. The new behavior is available only through pdf_to_markdown_with_images.

AnyDoc still does not perform OCR. Scanned and image-only PDFs continue to return the existing unsupported error.

API surface

  • Rust: pdf_to_markdown_with_images, behind the optional pdf-images feature
  • Python: pdf_to_markdown_with_images
  • Node.js and WebAssembly: pdfToMarkdownWithImages

Dependency status

This Draft PR depends on pdf-inspector#367, which is stacked on pdf-inspector#280. The Cargo dependency is pinned to the exact Draft commit for reproducible review. It must use a released upstream version before merge.

Validation

  • cargo check --workspace --all-features
  • cargo clippy --workspace --all-targets --all-features -- -D warnings
  • Existing PDF corpus contract case with the pdf-images feature
  • Direct calls through the public Python and Node.js APIs using a generated text-image-text PDF

The generated PDF produced Markdown containing ![Image: Im0](p1_i1.png) and a real PNG named p1_i1.png. The PNG was 557×334 pixels and 1,738 bytes. One existing test case was updated; no test file or test function was added.

OpenViking needs this complete result to integrate AnyDoc without maintaining a second PDF image parser. Thank you for considering this integration requirement.

@qin-ctx
qin-ctx marked this pull request as ready for review August 12, 2026 09:55

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

No issues found across 4 files

Re-trigger cubic

@qin-ctx qin-ctx changed the title feat(pdf): preserve embedded image positions in markdown feat(pdf): return positioned image files with Markdown Aug 12, 2026
@qin-ctx
qin-ctx marked this pull request as draft August 12, 2026 11:18
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.

1 participant