fix(docparser): anydoc 内嵌 EMF/WMF 图片的扩展名与 Rust 序列化器对齐,不再静默丢图 - #3938
Open
linus-liu-web wants to merge 1 commit into
Open
linus-liu-web wants to merge 1 commit into
linus-liu-web wants to merge 1 commit into
Conversation
anydoc 把内嵌图片就地渲染成 ``,`<ext>` 来自 asset_links.rs::extension_for;ImageResolver 再拿这个字符串去一张 map 里查, 键是 anydoc.ImageDir + Asset.Name,而 Name 由 backend_cgo.go::extensionFor 拼出。 查表是精确匹配,两边必须逐字符一致。 EMF/WMF 上两边并不一致:anydoc 对这两类 part 硬编码产出 image/emf 与 image/wmf(shared/assets.rs::media_type_for、shared/officeart.rs),Rust 表 落到 `.bin`,而 Go 侧去查平台 MIME 注册表——在装了 media-types 的 Debian 镜像上拿到 `.emf`/`.wmf`。链接与 ref 于是永远对不上,saveReferencedImage 找不到条目,图片字节从不落盘,且没有任何日志。 - asset_links.rs::extension_for 补 image/emf 与 image/wmf - backend_cgo.go::extensionFor 补同样两项,并改成纯查表 去掉 mime.ExtensionsByType 是有意的:让扩展名取决于宿主的 /etc/mime.types 正是这个 bug 的成因,何况这张表本来就要和 Rust 的静态表逐字符对齐。未知 类型两边都落到 .bin,仍满足「不写出无扩展名 blob」的原意。 新增 TestEmbeddedVectorImageLinksResolve:在内存里构造一个含一张 EMF 与 一张 WMF 的最小 docx,转换后要求每一条 Markdown 图片引用都能在 resolver 建的 ImageRef 表里命中,并固定扩展名为 .emf/.wmf(避免两边一起退化成 .bin 也能通过)。
This branch has not been deployed
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.
Description
Fix embedded EMF/WMF images being silently dropped when the
anydocengine parses a document.anydoc renders an embedded image in place as
. The<ext>comes from the Rust serializer (third_party/anydoc-go/src/asset_links.rs::extension_for).ImageResolverthen looks that exact string up in a map keyed byanydoc.ImageDir + Asset.Name, whereAsset.Nameis built frominternal/infrastructure/docparser/anydoc/backend_cgo.go::extensionFor. The lookup is an exact string match with no normalisation, so the two functions have to agree character for character.They did not agree on EMF/WMF. anydoc emits
image/emfandimage/wmffor those parts (hard-coded inshared/assets.rs::media_type_forandshared/officeart.rs), the Rust table fell through to.bin, and the Go side asked the platform MIME registry instead of using a fixed table — so on a Debian image withmedia-typesinstalled,/etc/mime.typessupplied.emf/.wmf. The Markdown link and theImageRefnever matched,saveReferencedImagefound nothing, and the image bytes were never stored. Nothing was logged and the document still reported success.This change:
image/emfandimage/wmftoextension_forinasset_links.rsextensionForinbackend_cgo.go, and makes it a pure tableDropping the
mime.ExtensionsByTypecall is deliberate. Letting the host's/etc/mime.typesdecide the extension is what caused the divergence, and a table that has to mirror a static Rust table cannot depend on the runtime environment anyway. Unknown types fall back to.binon both sides, which still satisfies the original goal of never writing an extension-less blob.Verified reachable divergences before the fix, by reproducing
extensionForagainst every media type anydoc can produce:.bin.bin.bin.emf.bin.wmfThe other producers of
images/...references derive the link and the map key from the same variable, so they cannot drift this way:builtin_converter.go::imageToResultuses onesafeReffor both, and the Python parser writesimage_pathinto the map and the Markdown together. The Rust/Go boundary was the only place where two independently built strings had to agree.Type of Change
Related Issue
Fixes #3932
Testing
Added
TestEmbeddedVectorImageLinksResolve, which builds a minimal.docxcarrying one EMF and one WMF drawing in memory, converts it through the linked converter, and requires every Markdown image reference to resolve against theImageRefmap the resolver builds. It also pins.emf/.wmf, so agreeing on.binfor everything could not pass.The test runs under the existing
anydocCI job (go test -tags anydoc ./internal/infrastructure/docparser/...).Before/after on that fixture, with the archive rebuilt from this branch:
The test is not vacuous: pointing either table back at ".bin" turns it red with
Also ran
go vet -tags anydoc ./internal/infrastructure/docparser/...,go test -tags anydoc ./internal/infrastructure/docparser/...andgo build -tags anydoc ./cmd/server.