Skip to content

feat(file): hand out the thumbnail the package already carries - #808

Merged
andiwand merged 1 commit into
mainfrom
feat/document-thumbnail
Sep 2, 2026
Merged

feat(file): hand out the thumbnail the package already carries#808
andiwand merged 1 commit into
mainfrom
feat/document-thumbnail

Conversation

@andiwand

@andiwand andiwand commented Sep 2, 2026

Copy link
Copy Markdown
Member

🤖 Generated with Claude Code

Closes #21 — which asked whether we would have to render documents ourselves, and the answer in the comment thread was "there is a thumbnail.png inside which would be easy to use". It is: the archive we already open has it.

/// @brief The preview image the file carries, if it carries one.
[[nodiscard]] std::optional<File> DocumentFile::thumbnail() const;
  • ODF names the part by convention: Thumbnails/thumbnail.png.
  • OOXML names it by package relationship.jpeg, .png, .emf and .wmf all occur — so the relationship is read rather than a filename guessed.

Nothing is rendered to produce it, so it is as current as the last save by an application that writes one, and a great many files carry none — which is a nullopt, not an error. An encrypted package carries none until it is decrypted.

Along the way

parse_relationship_target did not handle the package root: / is not a part, so AbsPath("/").parent() throws "absolute path violation". /_rels/.rels is where the package's own relationships live and its targets resolve against the root, so the two helpers now say so.

Bindings

Mirrored in JNI (DocumentFile.thumbnail(), null for absent), Apple (DocumentFile.thumbnail, a nullable ODRFile * following the ODRImage.file pattern) and Python (DocumentFile.thumbnail(), None for absent). Not in wasm, whose file surface is session-based and exposes no odr::File at all — a separate question.

Verification

  • core: ./odr_test --gtest_filter='-all_test_files/*' — 1117 tests, all pass, including three new ones. The OOXML one builds a package inline with the thumbnail at the deliberately unconventional docProps/preview.emf, so it proves the relationship is what is read.
  • JNI: ctest --test-dir build/jni — 44 tests, thumbnail() among them.
  • Python: ctest --test-dir build/pythontest_document_file_thumbnail passes; it asserts both the absent case (the minimal odt the fixture builds) and the present one.
  • Apple: macOS slices built, ODR_XCFRAMEWORK=OdrCoreObjC.xcframework swift test — 22 tests, ThumbnailTests among them.

The shared mixed-layout.odt fixture is real LibreOffice output and carries a 428-byte Thumbnails/thumbnail.png, so all three binding suites test against it without a new fixture.

@andiwand
andiwand force-pushed the feat/document-thumbnail branch 2 times, most recently from 61a9cf3 to 913008d Compare September 2, 2026 18:55
`DocumentFile::thumbnail()` returns the preview the producing application
stored: ODF's `Thumbnails/thumbnail.png`, and for OOXML the part the package
relationship names — `.jpeg`, `.png`, `.emf` and `.wmf` all occur, so the
relationship is read rather than a filename guessed. Nothing is rendered; a
package that carries none says so, and an encrypted one carries none until it
is decrypted.

`parse_relationship_target` learned the package root, which is not a part and
so has no parent to hang `_rels` off; `/_rels/.rels` is where its relationships
live and its targets resolve against the root.

Mirrored in the JNI, Apple and Python bindings, each with a test — the shared
`mixed-layout.odt` fixture is real LibreOffice output and carries one.

Closes #21.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018cMYRXLJdiCkH65Jm2W9B5
@andiwand
andiwand force-pushed the feat/document-thumbnail branch from 913008d to 3188bdc Compare September 2, 2026 18:56
@andiwand
andiwand merged commit 4c6d22b into main Sep 2, 2026
10 checks passed
@andiwand
andiwand deleted the feat/document-thumbnail branch September 2, 2026 18:57
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.

thumbnails

1 participant