From f5df8951e2882405541512a183b29a6ee058d5bc Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Tue, 29 Aug 2023 12:50:54 +0200 Subject: [PATCH 1/9] Adapted to breaking changes --- .../Codeuctivity.HtmlRenderer.csproj | 6 +- Codeuctivity.HtmlRenderer/Renderer.cs | 26 ++++---- .../Codeuctivity.HtmlRendererCli.csproj | 2 + Codeuctivity.HtmlRendererCli/Program.cs | 13 ++-- .../Codeuctivity.HtmlRendererCliTests.csproj | 8 +-- .../RendererCliTests.cs | 4 +- .../Codeuctivity.HtmlRendererTests.csproj | 60 +++++++++--------- ...TextFormatedInlineBackground.html.True.png | Bin 28987 -> 31355 bytes .../RendererTests.cs | 2 +- 9 files changed, 63 insertions(+), 58 deletions(-) diff --git a/Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj b/Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj index 2be0aac..ba5e71a 100644 --- a/Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj +++ b/Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj @@ -31,6 +31,8 @@ Codeuctivity.HtmlRenderer Codeuctivity.HtmlRenderer true + AllEnabledByDefault + latest true True Codeuctivity.HtmlRenderer.snk @@ -39,8 +41,8 @@ - - + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/Codeuctivity.HtmlRenderer/Renderer.cs b/Codeuctivity.HtmlRenderer/Renderer.cs index cc83756..fd20289 100644 --- a/Codeuctivity.HtmlRenderer/Renderer.cs +++ b/Codeuctivity.HtmlRenderer/Renderer.cs @@ -20,7 +20,7 @@ public Renderer(string? customChromiumArgs) { if (customChromiumArgs == null) { - LaunchOptions = SystemSpecificConfig(); + LaunchOptions = Renderer.SystemSpecificConfig(); } else { @@ -36,7 +36,7 @@ public Renderer(LaunchOptions? launchOptions = null) { if (launchOptions == null) { - LaunchOptions = SystemSpecificConfig(); + LaunchOptions = Renderer.SystemSpecificConfig(); } else { @@ -91,13 +91,13 @@ private async Task InitializeAsync(BrowserFetcher browserFetcher) { BrowserFetcher = browserFetcher; BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; - var revisionInfo = await BrowserFetcher.DownloadAsync(BrowserFetcher.DefaultChromiumRevision ?? string.Empty).ConfigureAwait(false); - LaunchOptions.ExecutablePath = revisionInfo.ExecutablePath; + var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId ?? string.Empty).ConfigureAwait(false); + LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); return this; } - private LaunchOptions SystemSpecificConfig() + private static LaunchOptions SystemSpecificConfig() { if (IsRunningOnWslOrAzure() || IsRunningOnAzureLinux()) { @@ -126,8 +126,8 @@ private static bool IsRunningOnWslOrAzure() } var version = File.ReadAllText("/proc/version"); - var IsWsl = version.IndexOf("Microsoft", StringComparison.OrdinalIgnoreCase) >= 0; - var IsAzure = version.IndexOf("azure", StringComparison.OrdinalIgnoreCase) >= 0; + var IsWsl = version?.IndexOf("Microsoft", StringComparison.OrdinalIgnoreCase) >= 0; + var IsAzure = version?.IndexOf("azure", StringComparison.OrdinalIgnoreCase) >= 0; return IsWsl || IsAzure; } @@ -157,10 +157,10 @@ public async Task ConvertHtmlToPdf(string sourceHtmlFilePath, string destination } var absolutePath = Path.GetFullPath(sourceHtmlFilePath); - await using var page = (await Browser.NewPageAsync().ConfigureAwait(false)); + await using var page = await Browser.NewPageAsync().ConfigureAwait(false); await page.GoToAsync($"file://{absolutePath}").ConfigureAwait(false); // Wait for fonts to be loaded. Omitting this might result in no text rendered in PDF. - await page.EvaluateExpressionHandleAsync("document.fonts.ready"); + await page.EvaluateExpressionHandleAsync("document.fonts.ready").ConfigureAwait(false); await page.PdfAsync(destinationPdfFilePath, pdfOptions).ConfigureAwait(false); } @@ -188,10 +188,10 @@ public async Task ConvertHtmlToPng(string sourceHtmlFilePath, string destination } var absolutePath = Path.GetFullPath(sourceHtmlFilePath); - await using var page = (await Browser.NewPageAsync().ConfigureAwait(false)); + await using var page = await Browser.NewPageAsync().ConfigureAwait(false); await page.GoToAsync($"file://{absolutePath}").ConfigureAwait(false); // Wait for fonts to be loaded. Omitting this might result in no text the screenshot. - await page.EvaluateExpressionHandleAsync("document.fonts.ready"); + await page.EvaluateExpressionHandleAsync("document.fonts.ready").ConfigureAwait(false); await page.ScreenshotAsync(destinationPngFilePath, screenshotOptions).ConfigureAwait(false); } @@ -214,7 +214,7 @@ public async Task ConvertHtmlStringToPngData(string sourceHtmlData, Scre await using var page = await Browser.NewPageAsync().ConfigureAwait(false); await page.SetContentAsync(sourceHtmlData).ConfigureAwait(false); // Wait for fonts to be loaded. Omitting this might result in no text the screenshot. - await page.EvaluateExpressionHandleAsync("document.fonts.ready"); + await page.EvaluateExpressionHandleAsync("document.fonts.ready").ConfigureAwait(false); return await page.ScreenshotDataAsync(screenshotOptions).ConfigureAwait(false); } @@ -243,9 +243,7 @@ public async ValueTask DisposeAsync() await DisposeAsyncCore().ConfigureAwait(false); Dispose(disposing: false); -#pragma warning disable CA1816 // Dispose methods should call SuppressFinalize GC.SuppressFinalize(this); -#pragma warning restore CA1816 // Dispose methods should call SuppressFinalize } /// diff --git a/Codeuctivity.HtmlRendererCli/Codeuctivity.HtmlRendererCli.csproj b/Codeuctivity.HtmlRendererCli/Codeuctivity.HtmlRendererCli.csproj index 111418d..dd18dd4 100644 --- a/Codeuctivity.HtmlRendererCli/Codeuctivity.HtmlRendererCli.csproj +++ b/Codeuctivity.HtmlRendererCli/Codeuctivity.HtmlRendererCli.csproj @@ -4,6 +4,8 @@ Exe net6.0 true + AllEnabledByDefault + latest Codeuctivity.HtmlRendererCli true embedded diff --git a/Codeuctivity.HtmlRendererCli/Program.cs b/Codeuctivity.HtmlRendererCli/Program.cs index 186364a..7578a85 100644 --- a/Codeuctivity.HtmlRendererCli/Program.cs +++ b/Codeuctivity.HtmlRendererCli/Program.cs @@ -7,7 +7,7 @@ namespace Codeuctivity.HtmlRendererCli { - public class Program + public static class Program { public static readonly Assembly Reference = typeof(Renderer).Assembly; public static readonly Version Version = Reference.GetName().Version; @@ -39,11 +39,14 @@ public static async Task Main(string[] args) Console.WriteLine($"Converting {inputPathDocx} to {outputPathHtml} using PuppeteerSharp.Renderer {Version}"); BrowserFetcherOptions options = new BrowserFetcherOptions(); options.Path = Path.GetTempPath(); - var browserFetcher = new BrowserFetcher(options); - Console.WriteLine($"Fetching chromium from web, to {browserFetcher.DownloadsFolder} .... "); + using var browserFetcher = new BrowserFetcher(options); + Console.WriteLine($"Fetching chromium from web, to {browserFetcher.CacheDir} .... "); browserFetcher.DownloadProgressChanged += BrowserFetcher_DownloadProgressChanged; - await using var chromiumRenderer = await Renderer.CreateAsync(browserFetcher, string.Empty); - await chromiumRenderer.ConvertHtmlToPdf(inputPathDocx, outputPathHtml); + + await using (var chromiumRenderer = await Renderer.CreateAsync(browserFetcher, string.Empty)) + { + await chromiumRenderer.ConvertHtmlToPdf(inputPathDocx, outputPathHtml); + } return 0; } diff --git a/Codeuctivity.HtmlRendererCliTests/Codeuctivity.HtmlRendererCliTests.csproj b/Codeuctivity.HtmlRendererCliTests/Codeuctivity.HtmlRendererCliTests.csproj index 7b34c5a..69f3607 100644 --- a/Codeuctivity.HtmlRendererCliTests/Codeuctivity.HtmlRendererCliTests.csproj +++ b/Codeuctivity.HtmlRendererCliTests/Codeuctivity.HtmlRendererCliTests.csproj @@ -7,13 +7,13 @@ - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all diff --git a/Codeuctivity.HtmlRendererCliTests/RendererCliTests.cs b/Codeuctivity.HtmlRendererCliTests/RendererCliTests.cs index c8be10f..17d3683 100644 --- a/Codeuctivity.HtmlRendererCliTests/RendererCliTests.cs +++ b/Codeuctivity.HtmlRendererCliTests/RendererCliTests.cs @@ -40,13 +40,13 @@ public void PublishedSelfContainedBinaryShouldWork() File.Delete(actualFilePath); } - var acutualWindowsBinary = DotnetPublishFolderProfileWindows("Codeuctivity.HtmlRendererCli"); + var actualWindowsBinary = DotnetPublishFolderProfileWindows("Codeuctivity.HtmlRendererCli"); using var process = new Process { StartInfo = new ProcessStartInfo { - FileName = acutualWindowsBinary, + FileName = actualWindowsBinary, Arguments = $" {sourceHtmlFilePath} {actualFilePath}", RedirectStandardOutput = true, RedirectStandardError = true, diff --git a/Codeuctivity.HtmlRendererTests/Codeuctivity.HtmlRendererTests.csproj b/Codeuctivity.HtmlRendererTests/Codeuctivity.HtmlRendererTests.csproj index e8f2288..5498951 100644 --- a/Codeuctivity.HtmlRendererTests/Codeuctivity.HtmlRendererTests.csproj +++ b/Codeuctivity.HtmlRendererTests/Codeuctivity.HtmlRendererTests.csproj @@ -1,36 +1,36 @@  - - net7.0;net6.0 - false - 9.0 - enable - false - true - + + net7.0;net6.0 + false + 9.0 + enable + false + true + - - - - - + + + + + - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - - - - runtime; build; native; contentfiles; analyzers; buildtransitive - all - - + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + + + + runtime; build; native; contentfiles; analyzers; buildtransitive + all + + - - - + + + diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatedInlineBackground.html.True.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatedInlineBackground.html.True.png index 92e3da234968ce9a6c0ff7988004f3b97b214072..ee8ad3d704a18a8aa8623a736dff3454e18814e6 100644 GIT binary patch literal 31355 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 diff --git a/Codeuctivity.HtmlRendererTests/RendererTests.cs b/Codeuctivity.HtmlRendererTests/RendererTests.cs index ec50f9f..6768062 100644 --- a/Codeuctivity.HtmlRendererTests/RendererTests.cs +++ b/Codeuctivity.HtmlRendererTests/RendererTests.cs @@ -199,7 +199,7 @@ public async Task ShouldConvertHtmlToPngBufferOptions(string testFileName, bool } [Fact] - public async Task ShouldDisposeGracefull() + public async Task ShouldDisposeGraceful() { var initialChromiumTasks = ChromiumProcessDisposedAsserter.CountChromiumTasks(); From 445f1ea9a5128496589cfeae91eb317913ade499 Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Tue, 29 Aug 2023 22:06:32 +0200 Subject: [PATCH 2/9] Typos --- Codeuctivity.HtmlRenderer/Renderer.cs | 2 +- Codeuctivity.HtmlRendererCli/Program.cs | 21 +++++++----------- .../FactRunableOnWindowsAttribute.cs | 4 ++-- .../RendererCliTests.cs | 6 ++--- ...tFormated.html => BasicTextFormatted.html} | 0 ...nvertHtmlToPngBasicTextFormatted.html.png} | Bin ...asicTextFormatted.html.png.diff.linux.png} | Bin ...gBasicTextFormatted.html.png.diff.win.png} | Bin ...tFormattedInlineBackground.html.False.png} | Bin ...xtFormattedInlineBackground.html.True.png} | Bin ...nvertHtmlToPdfBasicTextFormatted.html.png} | Bin ...asicTextFormatted.html.png.diff.linux.png} | Bin ...fBasicTextFormatted.html.png.diff.win.png} | Bin ...tFormattedInlineBackground.html.False.png} | Bin ...xtFormattedInlineBackground.html.True.png} | Bin .../Infrastructure/DocumentAsserter.cs | 2 ++ .../RendererTests.cs | 18 +++++++-------- ...tFormated.html => BasicTextFormatted.html} | 0 ...> BasicTextFormattedInlineBackground.html} | 0 19 files changed, 25 insertions(+), 28 deletions(-) rename Codeuctivity.HtmlRendererCliTests/TestInput/{BasicTextFormated.html => BasicTextFormatted.html} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedConvertHtmlToPngBasicTextFormated.html.png => ExpectedConvertHtmlToPngBasicTextFormatted.html.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedConvertHtmlToPngBasicTextFormated.html.png.diff.linux.png => ExpectedConvertHtmlToPngBasicTextFormatted.html.png.diff.linux.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedConvertHtmlToPngBasicTextFormated.html.png.diff.win.png => ExpectedConvertHtmlToPngBasicTextFormatted.html.png.diff.win.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedConvertHtmlToPngBasicTextFormatedInlineBackground.html.False.png => ExpectedConvertHtmlToPngBasicTextFormattedInlineBackground.html.False.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedConvertHtmlToPngBasicTextFormatedInlineBackground.html.True.png => ExpectedConvertHtmlToPngBasicTextFormattedInlineBackground.html.True.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png => ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png.diff.linux.png => ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png.diff.linux.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png.diff.win.png => ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png.diff.win.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatedInlineBackground.html.False.png => ExpectedFromHtmlConvertHtmlToPdfBasicTextFormattedInlineBackground.html.False.png} (100%) rename Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/{ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatedInlineBackground.html.True.png => ExpectedFromHtmlConvertHtmlToPdfBasicTextFormattedInlineBackground.html.True.png} (100%) rename Codeuctivity.HtmlRendererTests/TestInput/{BasicTextFormated.html => BasicTextFormatted.html} (100%) rename Codeuctivity.HtmlRendererTests/TestInput/{BasicTextFormatedInlineBackground.html => BasicTextFormattedInlineBackground.html} (100%) diff --git a/Codeuctivity.HtmlRenderer/Renderer.cs b/Codeuctivity.HtmlRenderer/Renderer.cs index fd20289..a84e784 100644 --- a/Codeuctivity.HtmlRenderer/Renderer.cs +++ b/Codeuctivity.HtmlRenderer/Renderer.cs @@ -91,7 +91,7 @@ private async Task InitializeAsync(BrowserFetcher browserFetcher) { BrowserFetcher = browserFetcher; BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; - var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId ?? string.Empty).ConfigureAwait(false); + var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); return this; diff --git a/Codeuctivity.HtmlRendererCli/Program.cs b/Codeuctivity.HtmlRendererCli/Program.cs index 7578a85..af2d8ff 100644 --- a/Codeuctivity.HtmlRendererCli/Program.cs +++ b/Codeuctivity.HtmlRendererCli/Program.cs @@ -15,18 +15,18 @@ public static class Program public static async Task Main(string[] args) { - if (args.Length != 2) + if (args?.Length != 2) { Console.WriteLine("Usage: PuppeteerSharp.RendererCli "); return 1; } - var inputPathDocx = args[0]; + var inputPathDocX = args[0]; var outputPathHtml = args[1]; - if (!File.Exists(inputPathDocx)) + if (!File.Exists(inputPathDocX)) { - Console.WriteLine($"Could not find source {inputPathDocx}."); + Console.WriteLine($"Could not find source {inputPathDocX}."); return 1; } @@ -36,17 +36,12 @@ public static async Task Main(string[] args) return 1; } - Console.WriteLine($"Converting {inputPathDocx} to {outputPathHtml} using PuppeteerSharp.Renderer {Version}"); - BrowserFetcherOptions options = new BrowserFetcherOptions(); - options.Path = Path.GetTempPath(); - using var browserFetcher = new BrowserFetcher(options); + Console.WriteLine($"Converting {inputPathDocX} to {outputPathHtml} using PuppeteerSharp.Renderer {Version}"); + using var browserFetcher = new BrowserFetcher(); Console.WriteLine($"Fetching chromium from web, to {browserFetcher.CacheDir} .... "); browserFetcher.DownloadProgressChanged += BrowserFetcher_DownloadProgressChanged; - - await using (var chromiumRenderer = await Renderer.CreateAsync(browserFetcher, string.Empty)) - { - await chromiumRenderer.ConvertHtmlToPdf(inputPathDocx, outputPathHtml); - } + await using var chromiumRenderer = await Renderer.CreateAsync(browserFetcher); + await chromiumRenderer.ConvertHtmlToPdf(inputPathDocX, outputPathHtml); return 0; } diff --git a/Codeuctivity.HtmlRendererCliTests/FactRunableOnWindowsAttribute.cs b/Codeuctivity.HtmlRendererCliTests/FactRunableOnWindowsAttribute.cs index 94182dd..fa82906 100644 --- a/Codeuctivity.HtmlRendererCliTests/FactRunableOnWindowsAttribute.cs +++ b/Codeuctivity.HtmlRendererCliTests/FactRunableOnWindowsAttribute.cs @@ -3,9 +3,9 @@ namespace Codeuctivity.HtmlRendererCliTests { - internal class FactRunableOnWindowsAttribute : FactAttribute + internal class FactRunnableOnWindowsAttribute : FactAttribute { - public FactRunableOnWindowsAttribute() + public FactRunnableOnWindowsAttribute() { if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { diff --git a/Codeuctivity.HtmlRendererCliTests/RendererCliTests.cs b/Codeuctivity.HtmlRendererCliTests/RendererCliTests.cs index 17d3683..38283e0 100644 --- a/Codeuctivity.HtmlRendererCliTests/RendererCliTests.cs +++ b/Codeuctivity.HtmlRendererCliTests/RendererCliTests.cs @@ -19,7 +19,7 @@ public void VersionShouldBeProcessed() [Fact] public async Task ConversionShouldWork() { - var testFileName = "BasicTextFormated.html"; + var testFileName = "BasicTextFormatted.html"; var sourceHtmlFilePath = $"../../../TestInput/{testFileName}"; var actualFilePath = Path.Combine(Path.GetTempPath(), $"Actual{testFileName}.pdf"); @@ -28,10 +28,10 @@ public async Task ConversionShouldWork() Assert.True(File.Exists(actualFilePath)); } - [FactRunableOnWindows] + [FactRunnableOnWindows] public void PublishedSelfContainedBinaryShouldWork() { - var testFileName = "BasicTextFormated.html"; + var testFileName = "BasicTextFormatted.html"; var sourceHtmlFilePath = Path.GetFullPath($"../../../TestInput/{testFileName}"); var actualFilePath = Path.Combine(Path.GetTempPath(), $"Actual{testFileName}.pdf"); diff --git a/Codeuctivity.HtmlRendererCliTests/TestInput/BasicTextFormated.html b/Codeuctivity.HtmlRendererCliTests/TestInput/BasicTextFormatted.html similarity index 100% rename from Codeuctivity.HtmlRendererCliTests/TestInput/BasicTextFormated.html rename to Codeuctivity.HtmlRendererCliTests/TestInput/BasicTextFormatted.html diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormated.html.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatted.html.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormated.html.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatted.html.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormated.html.png.diff.linux.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatted.html.png.diff.linux.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormated.html.png.diff.linux.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatted.html.png.diff.linux.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormated.html.png.diff.win.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatted.html.png.diff.win.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormated.html.png.diff.win.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatted.html.png.diff.win.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatedInlineBackground.html.False.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormattedInlineBackground.html.False.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatedInlineBackground.html.False.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormattedInlineBackground.html.False.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatedInlineBackground.html.True.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormattedInlineBackground.html.True.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormatedInlineBackground.html.True.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedConvertHtmlToPngBasicTextFormattedInlineBackground.html.True.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png.diff.linux.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png.diff.linux.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png.diff.linux.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png.diff.linux.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png.diff.win.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png.diff.win.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormated.html.png.diff.win.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatted.html.png.diff.win.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatedInlineBackground.html.False.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormattedInlineBackground.html.False.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatedInlineBackground.html.False.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormattedInlineBackground.html.False.png diff --git a/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatedInlineBackground.html.True.png b/Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormattedInlineBackground.html.True.png similarity index 100% rename from Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormatedInlineBackground.html.True.png rename to Codeuctivity.HtmlRendererTests/ExpectedTestOutcome/ExpectedFromHtmlConvertHtmlToPdfBasicTextFormattedInlineBackground.html.True.png diff --git a/Codeuctivity.HtmlRendererTests/Infrastructure/DocumentAsserter.cs b/Codeuctivity.HtmlRendererTests/Infrastructure/DocumentAsserter.cs index c80f8d3..b403d52 100644 --- a/Codeuctivity.HtmlRendererTests/Infrastructure/DocumentAsserter.cs +++ b/Codeuctivity.HtmlRendererTests/Infrastructure/DocumentAsserter.cs @@ -71,7 +71,9 @@ private static void CopyToTestOutput(string testOutputFile) } if (!Directory.Exists(TestOutputFirectory)) + { Directory.CreateDirectory(TestOutputFirectory); + } File.Copy(testOutputFile, Path.Combine(TestOutputFirectory, Path.GetFileName(testOutputFile)), true); } diff --git a/Codeuctivity.HtmlRendererTests/RendererTests.cs b/Codeuctivity.HtmlRendererTests/RendererTests.cs index 6768062..451264e 100644 --- a/Codeuctivity.HtmlRendererTests/RendererTests.cs +++ b/Codeuctivity.HtmlRendererTests/RendererTests.cs @@ -24,7 +24,7 @@ public RendererTests() public Rasterizer Rasterize { get; private set; } [Theory] - [InlineData("BasicTextFormated.html")] + [InlineData("BasicTextFormatted.html")] public async Task ShouldConvertHtmlToPdf(string testFileName) { var sourceHtmlFilePath = $"../../../TestInput/{testFileName}"; @@ -55,8 +55,8 @@ public async Task ShouldConvertHtmlToPdf(string testFileName) } [Theory] - [InlineData("BasicTextFormatedInlineBackground.html", false, 9000)] - [InlineData("BasicTextFormatedInlineBackground.html", true, 9000)] + [InlineData("BasicTextFormattedInlineBackground.html", false, 9000)] + [InlineData("BasicTextFormattedInlineBackground.html", true, 9000)] public async Task ShouldConvertHtmlToPdfWithOptions(string testFileName, bool printBackground, int allowedPixelDiff) { var sourceHtmlFilePath = $"../../../TestInput/{testFileName}"; @@ -113,7 +113,7 @@ private static bool IsRunningOnAzureOrMacos() } [Theory] - [InlineData("BasicTextFormated.html")] + [InlineData("BasicTextFormatted.html")] public async Task ShouldConvertHtmlToPng(string testFileName) { var sourceHtmlFilePath = $"../../../TestInput/{testFileName}"; @@ -137,8 +137,8 @@ public async Task ShouldConvertHtmlToPng(string testFileName) } [Theory] - [InlineData("BasicTextFormatedInlineBackground.html", false, 15000)] - [InlineData("BasicTextFormatedInlineBackground.html", true, 9500)] + [InlineData("BasicTextFormattedInlineBackground.html", false, 15000)] + [InlineData("BasicTextFormattedInlineBackground.html", true, 9500)] public async Task ShouldConvertHtmlToPngScreenshotOptions(string testFileName, bool omitBackground, int allowedPixelDiff) { var sourceHtmlFilePath = $"../../../TestInput/{testFileName}"; @@ -167,8 +167,8 @@ public async Task ShouldConvertHtmlToPngScreenshotOptions(string testFileName, b } [Theory] - [InlineData("BasicTextFormatedInlineBackground.html", false, 15000)] - [InlineData("BasicTextFormatedInlineBackground.html", true, 9500)] + [InlineData("BasicTextFormattedInlineBackground.html", false, 15000)] + [InlineData("BasicTextFormattedInlineBackground.html", true, 9500)] public async Task ShouldConvertHtmlToPngBufferOptions(string testFileName, bool omitBackground, int allowedPixelDiff) { var sourceHtmlFilePath = $"../../../TestInput/{testFileName}"; @@ -212,7 +212,7 @@ public async Task ShouldDisposeGraceful() } [Theory] - [InlineData("BasicTextFormated.html")] + [InlineData("BasicTextFormatted.html")] public async Task ShouldConvertHtmlToPngNoSandbox(string testFileName) { var sourceHtmlFilePath = $"../../../TestInput/{testFileName}"; diff --git a/Codeuctivity.HtmlRendererTests/TestInput/BasicTextFormated.html b/Codeuctivity.HtmlRendererTests/TestInput/BasicTextFormatted.html similarity index 100% rename from Codeuctivity.HtmlRendererTests/TestInput/BasicTextFormated.html rename to Codeuctivity.HtmlRendererTests/TestInput/BasicTextFormatted.html diff --git a/Codeuctivity.HtmlRendererTests/TestInput/BasicTextFormatedInlineBackground.html b/Codeuctivity.HtmlRendererTests/TestInput/BasicTextFormattedInlineBackground.html similarity index 100% rename from Codeuctivity.HtmlRendererTests/TestInput/BasicTextFormatedInlineBackground.html rename to Codeuctivity.HtmlRendererTests/TestInput/BasicTextFormattedInlineBackground.html From b585c61d7bae945a5cbfdeeca6f0c1b2c3df67c8 Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Tue, 29 Aug 2023 22:59:39 +0200 Subject: [PATCH 3/9] MacOsX experiment --- Codeuctivity.HtmlRenderer/Renderer.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Codeuctivity.HtmlRenderer/Renderer.cs b/Codeuctivity.HtmlRenderer/Renderer.cs index a84e784..62c3dcb 100644 --- a/Codeuctivity.HtmlRenderer/Renderer.cs +++ b/Codeuctivity.HtmlRenderer/Renderer.cs @@ -89,7 +89,12 @@ public static Task CreateAsync(BrowserFetcher browserFetcher, LaunchOp private async Task InitializeAsync(BrowserFetcher browserFetcher) { - BrowserFetcher = browserFetcher; + // for macsome reason the download progress is not called on macos + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + BrowserFetcher = new BrowserFetcher(); + else + BrowserFetcher = browserFetcher; + BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); From 7d44d51722abee8573c25495fb85f7f32a66c1d5 Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:04:08 +0200 Subject: [PATCH 4/9] Update Renderer.cs --- Codeuctivity.HtmlRenderer/Renderer.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/Codeuctivity.HtmlRenderer/Renderer.cs b/Codeuctivity.HtmlRenderer/Renderer.cs index 62c3dcb..72bc575 100644 --- a/Codeuctivity.HtmlRenderer/Renderer.cs +++ b/Codeuctivity.HtmlRenderer/Renderer.cs @@ -93,11 +93,13 @@ private async Task InitializeAsync(BrowserFetcher browserFetcher) if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) BrowserFetcher = new BrowserFetcher(); else + { BrowserFetcher = browserFetcher; + BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; + var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); + LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); + } - BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; - var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); - LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); return this; } From a33f04bc138a4ba26a7ce20fb043e50652b27383 Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:14:05 +0200 Subject: [PATCH 5/9] MacOsX experiment --- .github/workflows/dotnet.yml | 2 +- Codeuctivity.HtmlRenderer/Renderer.cs | 15 ++++----------- 2 files changed, 5 insertions(+), 12 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index e6b8815..16541fc 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [windows-latest, ubuntu-latest, macos-latest] + os: [windows-latest, ubuntu-latest] steps: - uses: actions/checkout@v3 - name: Setup .NET diff --git a/Codeuctivity.HtmlRenderer/Renderer.cs b/Codeuctivity.HtmlRenderer/Renderer.cs index 72bc575..a84e784 100644 --- a/Codeuctivity.HtmlRenderer/Renderer.cs +++ b/Codeuctivity.HtmlRenderer/Renderer.cs @@ -89,17 +89,10 @@ public static Task CreateAsync(BrowserFetcher browserFetcher, LaunchOp private async Task InitializeAsync(BrowserFetcher browserFetcher) { - // for macsome reason the download progress is not called on macos - if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) - BrowserFetcher = new BrowserFetcher(); - else - { - BrowserFetcher = browserFetcher; - BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; - var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); - LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); - } - + BrowserFetcher = browserFetcher; + BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; + var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); + LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); return this; } From d62f13e5b85bcca24d4bf19fb9a453cff2ebf7fc Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:30:53 +0200 Subject: [PATCH 6/9] MacOs experiment --- .github/workflows/dotnet.yml | 2 +- Codeuctivity.HtmlRenderer/Renderer.cs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 16541fc..e6b8815 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -12,7 +12,7 @@ jobs: runs-on: ${{ matrix.os }} strategy: matrix: - os: [windows-latest, ubuntu-latest] + os: [windows-latest, ubuntu-latest, macos-latest] steps: - uses: actions/checkout@v3 - name: Setup .NET diff --git a/Codeuctivity.HtmlRenderer/Renderer.cs b/Codeuctivity.HtmlRenderer/Renderer.cs index a84e784..154735f 100644 --- a/Codeuctivity.HtmlRenderer/Renderer.cs +++ b/Codeuctivity.HtmlRenderer/Renderer.cs @@ -94,6 +94,7 @@ private async Task InitializeAsync(BrowserFetcher browserFetcher) var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); + Browser = await Puppeteer.LaunchAsync(new LaunchOptions()).ConfigureAwait(false); return this; } From f212a60f20464933275fed77e41a2579e21c70ae Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:31:11 +0200 Subject: [PATCH 7/9] Update Renderer.cs --- Codeuctivity.HtmlRenderer/Renderer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Codeuctivity.HtmlRenderer/Renderer.cs b/Codeuctivity.HtmlRenderer/Renderer.cs index 154735f..4ac75b8 100644 --- a/Codeuctivity.HtmlRenderer/Renderer.cs +++ b/Codeuctivity.HtmlRenderer/Renderer.cs @@ -93,7 +93,7 @@ private async Task InitializeAsync(BrowserFetcher browserFetcher) BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); - Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); + //Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); Browser = await Puppeteer.LaunchAsync(new LaunchOptions()).ConfigureAwait(false); return this; } From 9f4b2729f74ca3128203e6854d8116b55b36cde4 Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Tue, 29 Aug 2023 23:34:39 +0200 Subject: [PATCH 8/9] Update Renderer.cs --- Codeuctivity.HtmlRenderer/Renderer.cs | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Codeuctivity.HtmlRenderer/Renderer.cs b/Codeuctivity.HtmlRenderer/Renderer.cs index 4ac75b8..5d757a1 100644 --- a/Codeuctivity.HtmlRenderer/Renderer.cs +++ b/Codeuctivity.HtmlRenderer/Renderer.cs @@ -89,12 +89,22 @@ public static Task CreateAsync(BrowserFetcher browserFetcher, LaunchOp private async Task InitializeAsync(BrowserFetcher browserFetcher) { - BrowserFetcher = browserFetcher; - BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; - var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); - LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); - //Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); - Browser = await Puppeteer.LaunchAsync(new LaunchOptions()).ConfigureAwait(false); + // for macsome reason the download progress is not called on macos + if (RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) + { + using var browserFetcher1 = new BrowserFetcher(); + await browserFetcher1.DownloadAsync(); + Browser = await Puppeteer.LaunchAsync(new LaunchOptions { Headless = true }); + } + else + { + BrowserFetcher = browserFetcher; + BrowserFetcher.DownloadProgressChanged += DownloadProgressChanged; + var revisionInfo = await BrowserFetcher.DownloadAsync(PuppeteerSharp.BrowserData.Chrome.DefaultBuildId).ConfigureAwait(false); + LaunchOptions.ExecutablePath = revisionInfo.GetExecutablePath(); + Browser = await Puppeteer.LaunchAsync(LaunchOptions).ConfigureAwait(false); + } + return this; } From 52d0172af60e6f7573b908b93a6f33c548266349 Mon Sep 17 00:00:00 2001 From: "Stefan.Seeland" <168659+stesee@users.noreply.github.com> Date: Wed, 30 Aug 2023 20:04:08 +0200 Subject: [PATCH 9/9] Bumped PuppeteerSharp 11.0.2 -> 11.0.3 --- Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj b/Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj index ba5e71a..0e9a7a5 100644 --- a/Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj +++ b/Codeuctivity.HtmlRenderer/Codeuctivity.HtmlRenderer.csproj @@ -41,7 +41,7 @@ - + all runtime; build; native; contentfiles; analyzers; buildtransitive