Repository navigation
HTML import: images (data: URIs, a caller resolver, sized placeholders) (#1880) - #1897
Merged
Merged
Conversation
inline_picture_run_described adds wp:docPr descr (escaped, line breaks and tabs as references) and an optional 1 px outline, for the HTML import's pictures and placeholders. inline_picture_run delegates to it and writes the same bytes as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
import_html_with(bytes, resolver) converts images: a data: src is decoded, any other is asked of the caller's resolver (told how many bytes it may return); bytes that are not PNG/JPEG/GIF/BMP, a refusal or no room make a grey placeholder of the declared size with the alt as Alt Text, or the alt text when unsized. Sizes: CSS lengths over the attributes, auto clears a side, a percentage leaves the attribute's; the other side by the aspect; capped at the body width. Word's <![if !vml]> image is read; hidden, zero-sized and list-marker images make nothing. HtmlImport::package puts the media in a Markdown package. import_html is unchanged. A picture is content of its paragraph (no whitespace clear, ends it before the next block), and a typed list marker never takes a picture with it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The repo stores LF, which turned the mail fixture's CRLF-wrapped data: URI into an LF one; mark the fixture -text, as the Word corpus is, and check the wrap is there. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…1880) The converting child imports HTML through import_html_with and writes the package with its media. Its resolver reads only a local file beside the page (local_image_path): no scheme but file:, no UNC, device or file://host path, escaped or not, no drive-relative path; a regular file within the import's limit, its size checked before it is read. cid:, http(s): and the rest are placeholders. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Looking at an absolute path can reach the network: an automounter's /net/<host> (macOS's default, Linux autofs -hosts) or /afs contacts the host it names, and on Windows an escaped \%3F%3F\UNC\... became \??\UNC on a relative page folder. So image_src_parts takes only a relative src (no scheme, file: included; no rooted, drive, UNC or device path; no : ? * NUL once escapes are decoded; no .. out of the folder; no name ending in a dot or space), the page folder is made absolute, and read_local_image walks each step below it with symlink_metadata, refusing a symlink or Windows reparse point. A deliberate tightening of plan v2's absolute and file: paths; Word, Outlook and Save Page write relative page_files/ srcs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the import (#1880 r1) The old assertion ran out in the up-front passes, before any image code. The new test's budget covers those and half of what the images spend: it fails with images on and fits with them off, so decoding is charged and running out is not swallowed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…out (#1880 r2) An <img> side was clamped to a page's 31 680 twips (the width attribute's and CSS length's table cap) before the box was scaled to the body, so width=3000 height=1000 came out 9360 x 4431 twips. Image sides now saturate at u32 instead (tables keep their cap), and the box scales as a whole: 624 x 208 px. The converting child moves the document out of the package instead of cloning it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
With image sides no longer capped (r2), a width of u32::MAX twips over a 1 x 1 000 000 pixel header made h = w*ph/pw about 4e15 and h*body passed u64: a panic in debug, a wrap in release. picture_twips now computes in u128 and saturates each side to u64; twips_emu clamps to MAX_EMU as before. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
4 tasks
|
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
Owner
Author
|
[linux] Merged as 3526878 after
|
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.
[linux]
Closes #1880.
HTML import now converts
<img>.docxcore::import::import_html_with(bytes, &mut resolver)returnsHtmlImport { document, media }, andHtmlImport::package()puts each image into a Markdown package asword/media/imageN.<ext>, with its rids renamed (cells and nested tables included).import_htmlis unchanged and converts no images.What an
<img>becomesdata:src is decoded here: percent escapes, then base64, with white space and mail's CRLF wrapping skipped. Any other src goes to the caller's resolver, once per distinct src.image::sniff) are embedded, and equal bytes share one part.autoclears a side; a CSS percentage leaves the attribute's size, so e-mail'swidth=600 style="width:100%"gives 600 px.#F2F2F2PNG with a 1 pxA6A6A6outline and thealtas Alt Text (wp:docPr descr). The colours are by estimate, with no Word oracle.alttext as a run.alt: nothing.display:none,mso-hide:all), a zero-sized one, and a list-marker image (<![if !supportLists]>) make nothing and are never resolved.<![if !vml]><img>is read; its VML twin sits in a comment.take_leading_markerno longer drains a zero-width inline, and never takes a marker past a picture.The suite
The converting child imports Web Pages through
import_html_withand writes the package with its media, so an opened.htmshows its pictures.Its resolver reads only a relative src under the page's own folder:
file:included;: ? * < > | "or NUL after decoding escapes;..out of the folder, and no name ending in a dot or a space;cid:,http(s):and the rest are placeholders, so opening a page never reaches the network.This is a deliberate tightening of the agreed plan, which allowed absolute local paths. Review round 1 showed two ways an absolute path reaches the network: macOS's default
/net/<host>automounter, and Windows\??\UNC\…. Word, Outlook and browsers' Save Page all write relativepage_files/…srcs.Tests
docxcore/tests/html_images.rsover the new fixturecid-message.html: a mail withcid:images in nested tables, a CRLF-wrappeddata:URI, a refused remote image with and without a size, a hidden pixel and a repeated src. It checks sizes, Alt Text, the media, a save/load round trip, and a truncation loop throughimport_html_with.html_image.rsandhtml.rscover decoding, limits, sizing (including extreme aspects), Word's downlevel markup, markers and paragraph content.suite/docxy/src/convert_tests.rs: a Word Web Page with itspage_files, opened in process and through the real child.convert_childtests cover the resolver's refusals (every platform), a relative page folder, and links (unix).The implementer ran:
cargo fmt --all;cargo clippy --workspace --all-targets -D warningsand the same for the suite;cargo test -p docxcore;cargo test --manifest-path suite/Cargo.toml -p docxy-suite(2802 passed).The
cfg(windows)resolver test was not run here; it is for the Windows CI job.Review
revmux (claude-only profile) ran two rounds.
/net, and Windows\??\on a relative page folder) and 2 minor (docs; a budget test that failed before any image code ran). All fixed in ef3f1c6 and 628d48e.The review stopped at round 2: no Major, all findings fixed.
Out of scope (follow-ups)
max-widthand floating images.<base href>and MHTML.background-imageand<picture>/srcset.<a>around images and links go to HTML import: <a href> links become hyperlinks #1879, and cid mapping to the mail host.🤖 Generated with Claude Code