From 5d7f822bd02b9fc32e14f47b9eaf5df0e24e30c5 Mon Sep 17 00:00:00 2001 From: Simon Cropp Date: Wed, 22 Jul 2026 23:24:03 +1000 Subject: [PATCH] Add a deterministic pdf target The Excel and Word paths emit the source document as a target, made deterministic via DeterministicPackage. The pdf path emitted only the rendered pages. It now emits the document too, neutralized with DeterministicPdf. The info is still built before the targets, preserving the existing evaluation order: GetDocumentText re-saves the document, and the page rendering has always run after that. Not verified locally: the test suite requires the AsposeLicense environment variable. --- src/Directory.Build.props | 2 +- src/Directory.Packages.props | 1 + src/Verify.Aspose/GlobalUsings.cs | 1 + src/Verify.Aspose/Verify.Aspose.csproj | 1 + src/Verify.Aspose/VerifyAspose_Pdf.cs | 35 +++++++++++++++++++++++--- 5 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/Directory.Build.props b/src/Directory.Build.props index f7e7ca4..92240eb 100644 --- a/src/Directory.Build.props +++ b/src/Directory.Build.props @@ -2,7 +2,7 @@ CS1591;CS0649;CA1416;NU1608;NU1109 - 5.26.0 + 5.27.0 preview 1.0.0 Aspose, Verify diff --git a/src/Directory.Packages.props b/src/Directory.Packages.props index 0f28686..fdabab5 100644 --- a/src/Directory.Packages.props +++ b/src/Directory.Packages.props @@ -10,6 +10,7 @@ + diff --git a/src/Verify.Aspose/GlobalUsings.cs b/src/Verify.Aspose/GlobalUsings.cs index 09209a7..e7bfd8d 100644 --- a/src/Verify.Aspose/GlobalUsings.cs +++ b/src/Verify.Aspose/GlobalUsings.cs @@ -4,4 +4,5 @@ global using System.Xml.Linq; global using Aspose.Pdf.Devices; global using DeterministicIoPackaging; +global using DeterministicPdf; global using VerifyTestsAspose; \ No newline at end of file diff --git a/src/Verify.Aspose/Verify.Aspose.csproj b/src/Verify.Aspose/Verify.Aspose.csproj index cf6bab6..f6b5ec5 100644 --- a/src/Verify.Aspose/Verify.Aspose.csproj +++ b/src/Verify.Aspose/Verify.Aspose.csproj @@ -5,6 +5,7 @@ + diff --git a/src/Verify.Aspose/VerifyAspose_Pdf.cs b/src/Verify.Aspose/VerifyAspose_Pdf.cs index 74a5c89..bc0f3cf 100644 --- a/src/Verify.Aspose/VerifyAspose_Pdf.cs +++ b/src/Verify.Aspose/VerifyAspose_Pdf.cs @@ -94,7 +94,11 @@ static ConversionResult ConvertPdf(string? name, Document document, IReadOnlyDic } var (fonts, embeddedFonts) = GetPdfFonts(document); - return new( + + // Built before the targets, preserving the original evaluation order: GetDocumentText below + // re-saves the document to extract its text, and the page rendering in GetPdfStreams has + // always run after that. + var snapshotInfo = new { Pages = document.Pages.Count, @@ -124,8 +128,33 @@ static ConversionResult ConvertPdf(string? name, Document document, IReadOnlyDic Fonts = fonts, EmbeddedFonts = embeddedFonts, Text = GetDocumentText(document) - }, - GetPdfStreams(name, document, settings).ToList()); + }; + + List targets = []; + // Building the deterministic pdf is expensive, so skip it when the pdf target is excluded. + if (!settings.IsTargetExcluded("pdf")) + { + targets.Add(BuildPdfTarget(document)); + } + + targets.AddRange(GetPdfStreams(name, document, settings)); + + return new(snapshotInfo, targets); + } + + // The pdf snapshot is always the full document, regardless of PagesToInclude: PagesToInclude + // only trims the rendered png pages in GetPdfStreams. Mirrors BuildXlsxTarget/BuildDocxTarget, + // which do the same for the OOXML formats via DeterministicPackage. + static Target BuildPdfTarget(Document document) + { + using var source = new MemoryStream(); + document.Save(source); + var resultStream = PdfNormalizer.Normalize(source); + + return new("pdf", resultStream, performConversion: false) + { + BypassComparersForSubsequentOnDifference = true + }; } static string GetDocumentText(Document document)