- MigraDocExtensions: fix a bug where capping an oversized explicit
width+height image re-derived the other dimension from the image's
native pixel ratio instead of scaling both sides uniformly, silently
distorting a deliberately non-native-ratio (e.g. stretched) image.
- InvoiceService: derive the mfr-portal image whitelist prefix from the
existing Fds:MFR_host config setting (via MFRClientConfig.RestRoot)
instead of a second hardcoded literal, so it can't drift from the
actual configured host; parse <img> sources with HtmlAgilityPack
(already used by the PDF's own HTML converter) instead of a regex, so
a decoy attribute like data-src can't be picked up in place of the
real src; dedup fetch URLs with a HashSet instead of O(n^2) List
scanning; reuse FuchsPdf.MigraDocFilenameFromByteArray instead of
re-spelling the "base64:" prefix.
- Fix a stale log message and comment left over from the
GenerateInvoicePdf -> GenerateInvoicePdfAsync rename, and update
INVOICE_LIFECYCLE.md's references to the old sync method name.
- Add tests for the config-derived whitelist, a decoy-attribute src,
and the 20-image-per-invoice fetch cap boundary.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>