fix(html): name a linked ooxml image relative to the document - #727
Merged
Conversation
The odf engines return an image href as it is written in the file, which is relative; the ooxml ones resolve the relationship into an absolute container path. The html layer emitted either verbatim, so an absolute one resolved against the server root rather than against the document - every image in a docx or xlsx 404ed for a host serving the service under a mount point, and `bring_offline` threw `not a relative path` outright. Make the location relative where the resource is built, so it holds for every engine. The reference output embeds its images and never rendered the linked form, hence the new test. Closes opendocument-app/OpenDocument.droid#551 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HuzekTz46XJdLDrLgt4hnJ
andiwand
force-pushed
the
fix/ooxml-linked-image-paths
branch
from
August 21, 2026 08:34
7910ce2 to
c24e4cb
Compare
andiwand
enabled auto-merge (squash)
August 21, 2026 08:35
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🤖 Generated with Claude Code
Closes opendocument-app/OpenDocument.droid#551.
Every image in a
.docx/.xlsxrenders as the broken-image placeholder when the host links images rather than embedding them. ODF is fine, which is what made it easy to miss.Cause
The engines disagree on what an image href is.
odf_document.cpp:935returns the rawxlink:href, which is relative —Pictures/x.png. The ooxml ones resolve the relationship into an absolute container path —ooxml_text_document.cpp:573joins ontoAbsPath("/word"),ooxml_spreadsheet_document.cpp:416onto the part's directory — andtranslate_imageemitted whichever it got.An absolute location cannot work.
resource_atmatches it against the request path by exact string, and the http route strips the leading/, so/word/media/image1.jpegserved under/file/<prefix>/misses either way.bring_offlineis worse than a 404: it doesPath(output).join(RelPath(*location))andRelPaththrows on an absolute string, sotranslate --embed-images=falseon a docx fails before writing anything.Neither knob the downstream issue proposed helps.
relative_resource_pathsgates its rebase onresource.is_shipped(), andHttpServer::prefix_patternis([a-zA-Z0-9_-]+), so there is no root to mount at.Fix
Make the location relative where the resource is built, once, for every engine:
const std::string path = Path(image.href()).make_relative().string();image_file()andimage_is_internal()alreadymake_absolute()the href, so the engines stay as they are andImage::href()keeps its meaning.Tests
html.linked_images_are_servedrenders an odt, a docx and an xlsx withembed_images = falseand asserts each image location is relative, exists on the service, and serves bytes. It fails on both ooxml paths without the change.The reference output renders with
embed_images = true, so it never exercised the linked form — that is the gap this closes. Its docx / xlsx / odt output is byte-identical after the change, since an embedded image carries no location.Not in scope
Two neighbours found while confirming this, each worth its own issue:
ooxml_text_parser.cpp:226maps everya:graphicDatatoElementType::image, so a chart, SmartArt or embedded OLE becomes an image with an empty href — thesrc=""seen in a handful of reference documents.file-sample_100kB.docxis one: a picture and a chart, and the chart is the empty one.document_element.cpp:508creates a non-internal image resource withis_external = false.