From 71ff8222f33137c4b1efb88b3111817988e9e60f Mon Sep 17 00:00:00 2001 From: campersau Date: Fri, 18 Oct 2024 19:13:17 +0200 Subject: [PATCH] Use object for Top / Left / Bottom / Right in MarginOptions (#2788) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Use object for Top / Left / Bottom / Right in MarginOptions This is similar to the object Width / Height in PdfOptions and all of them already got converted by ConvertPrintParameterToInches * Add back PdfOptionsShouldWorkWithMarginWithNoUnits test * Expand comment for PrimitiveTypeConverter * Turn test into unit test * bump System.Text.Json * chrome 129.0.6668.100 --------- Co-authored-by: DarĂ­o Kondratiuk --- README.md | 2 +- .../PageTests/PdfTests.cs | 27 ++---- lib/PuppeteerSharp/BrowserData/Chrome.cs | 2 +- lib/PuppeteerSharp/Cdp/CdpPage.cs | 84 +++++++++---------- .../Helpers/Json/PrimitiveTypeConverter.cs | 65 ++++++++++++++ lib/PuppeteerSharp/Media/MarginOptions.cs | 58 +++---------- lib/PuppeteerSharp/Media/PaperFormat.cs | 41 +-------- lib/PuppeteerSharp/PdfOptions.cs | 4 + 8 files changed, 134 insertions(+), 149 deletions(-) create mode 100644 lib/PuppeteerSharp/Helpers/Json/PrimitiveTypeConverter.cs diff --git a/README.md b/README.md index ce28f974d..9d918e8d6 100644 --- a/README.md +++ b/README.md @@ -90,7 +90,7 @@ await page.GoToAsync("http://www.google.com"); // In case of fonts being loaded await page.EvaluateExpressionHandleAsync("document.fonts.ready"); // Wait for fonts to be loaded. Omitting this might result in no text rendered in pdf. await page.PdfAsync(outputFile); ``` -snippet source | anchor +snippet source | anchor ### Inject HTML diff --git a/lib/PuppeteerSharp.Tests/PageTests/PdfTests.cs b/lib/PuppeteerSharp.Tests/PageTests/PdfTests.cs index 3cc0b7a92..ea4c2e917 100644 --- a/lib/PuppeteerSharp.Tests/PageTests/PdfTests.cs +++ b/lib/PuppeteerSharp.Tests/PageTests/PdfTests.cs @@ -3,6 +3,7 @@ using System.Text.Json; using System.Threading.Tasks; using NUnit.Framework; +using PuppeteerSharp.Cdp; using PuppeteerSharp.Media; using PuppeteerSharp.Nunit; @@ -127,6 +128,8 @@ public void PdfOptionsShouldBeSerializable() { var pdfOptions = new PdfOptions { + Width = 100, + Height = 100, Format = PaperFormat.A4, DisplayHeaderFooter = true, MarginOptions = new MarginOptions @@ -145,25 +148,13 @@ public void PdfOptionsShouldBeSerializable() } [Test] - public void PdfOptionsShouldWorkWithMarginWithNoUnits() + public void ConvertPrintParameterToInchesTests() { - var pdfOptions = new PdfOptions - { - Format = PaperFormat.A4, - DisplayHeaderFooter = true, - MarginOptions = new MarginOptions - { - Top = "0", - Right = "0", - Bottom = "0", - Left = "0" - }, - FooterTemplate = "
- -
" - }; - - var serialized = JsonSerializer.Serialize(pdfOptions); - var newPdfOptions = JsonSerializer.Deserialize(serialized); - Assert.That(newPdfOptions, Is.EqualTo(pdfOptions)); + Assert.That(CdpPage.ConvertPrintParameterToInches("10"), Is.EqualTo(10m / 96)); + Assert.That(CdpPage.ConvertPrintParameterToInches("10px"), Is.EqualTo(10m / 96)); + Assert.That(CdpPage.ConvertPrintParameterToInches("0"), Is.EqualTo(0)); + Assert.That(CdpPage.ConvertPrintParameterToInches("0px"), Is.EqualTo(0)); + Assert.That(CdpPage.ConvertPrintParameterToInches("10in"), Is.EqualTo(10)); } } } diff --git a/lib/PuppeteerSharp/BrowserData/Chrome.cs b/lib/PuppeteerSharp/BrowserData/Chrome.cs index 7522fa3d8..8b3fe7ef6 100644 --- a/lib/PuppeteerSharp/BrowserData/Chrome.cs +++ b/lib/PuppeteerSharp/BrowserData/Chrome.cs @@ -13,7 +13,7 @@ public static class Chrome /// /// Default chrome build. /// - public static string DefaultBuildId => "128.0.6613.119"; + public static string DefaultBuildId => "129.0.6668.100"; internal static async Task ResolveBuildIdAsync(ChromeReleaseChannel channel) => (await GetLastKnownGoodReleaseForChannel(channel).ConfigureAwait(false)).Version; diff --git a/lib/PuppeteerSharp/Cdp/CdpPage.cs b/lib/PuppeteerSharp/Cdp/CdpPage.cs index 94db19b92..792a9f305 100644 --- a/lib/PuppeteerSharp/Cdp/CdpPage.cs +++ b/lib/PuppeteerSharp/Cdp/CdpPage.cs @@ -731,6 +731,48 @@ internal static async Task CreateAsync( } } + internal static decimal ConvertPrintParameterToInches(object parameter) + { + if (parameter == null) + { + return 0; + } + + decimal pixels; + if (parameter is decimal or int) + { + pixels = Convert.ToDecimal(parameter, CultureInfo.CurrentCulture); + } + else + { + var text = parameter.ToString(); + var unit = text.Length > 2 ? text.Substring(text.Length - 2).ToLower(CultureInfo.CurrentCulture) : string.Empty; + string valueText; + if (GetPixels(unit) is { }) + { + valueText = text.Substring(0, text.Length - 2); + } + else + { + // In case of unknown unit try to parse the whole parameter as number of pixels. + // This is consistent with phantom's paperSize behavior. + unit = "px"; + valueText = text; + } + + if (decimal.TryParse(valueText, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out var number)) + { + pixels = number * GetPixels(unit).Value; + } + else + { + throw new ArgumentException($"Failed to parse parameter value: '{text}'", nameof(parameter)); + } + } + + return pixels / 96; + } + /// protected override async Task ExposeFunctionAsync(string name, Delegate puppeteerFunction) { @@ -1214,48 +1256,6 @@ await PrimaryTargetClient.SendAsync( } } - private decimal ConvertPrintParameterToInches(object parameter) - { - if (parameter == null) - { - return 0; - } - - decimal pixels; - if (parameter is decimal or int) - { - pixels = Convert.ToDecimal(parameter, CultureInfo.CurrentCulture); - } - else - { - var text = parameter.ToString(); - var unit = text.Length > 2 ? text.Substring(text.Length - 2).ToLower(CultureInfo.CurrentCulture) : string.Empty; - string valueText; - if (GetPixels(unit) is { }) - { - valueText = text.Substring(0, text.Length - 2); - } - else - { - // In case of unknown unit try to parse the whole parameter as number of pixels. - // This is consistent with phantom's paperSize behavior. - unit = "px"; - valueText = text; - } - - if (decimal.TryParse(valueText, NumberStyles.Any, CultureInfo.InvariantCulture.NumberFormat, out var number)) - { - pixels = number * GetPixels(unit).Value; - } - else - { - throw new ArgumentException($"Failed to parse parameter value: '{text}'", nameof(parameter)); - } - } - - return pixels / 96; - } - private Clip GetIntersectionRect(Clip clip, BoundingBox viewport) { var x = Math.Max(clip.X, viewport.X); diff --git a/lib/PuppeteerSharp/Helpers/Json/PrimitiveTypeConverter.cs b/lib/PuppeteerSharp/Helpers/Json/PrimitiveTypeConverter.cs new file mode 100644 index 000000000..e16772c64 --- /dev/null +++ b/lib/PuppeteerSharp/Helpers/Json/PrimitiveTypeConverter.cs @@ -0,0 +1,65 @@ +#nullable enable + +using System; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace PuppeteerSharp.Helpers.Json +{ + /// + /// Support types (, and ) + /// used by and for serialization / deserialization. + /// For usecases like . + /// + internal sealed class PrimitiveTypeConverter : JsonConverter + { + public override object? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.Null) + { + return null; + } + else if (reader.TokenType == JsonTokenType.String) + { + return reader.GetString(); + } + else if (reader.TokenType == JsonTokenType.Number) + { + if (reader.TryGetInt32(out var i)) + { + return i; + } + else if (reader.TryGetDecimal(out var dec)) + { + return dec; + } + } + + return JsonSerializer.Deserialize(ref reader, typeToConvert, options); + } + + public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOptions options) + { + if (value is null) + { + writer.WriteNullValue(); + } + else if (value is string str) + { + writer.WriteStringValue(str); + } + else if (value is decimal dec) + { + writer.WriteNumberValue(dec); + } + else if (value is int i) + { + writer.WriteNumberValue(i); + } + else + { + JsonSerializer.Serialize(writer, value, options); + } + } + } +} diff --git a/lib/PuppeteerSharp/Media/MarginOptions.cs b/lib/PuppeteerSharp/Media/MarginOptions.cs index 64b326c50..056470a8a 100644 --- a/lib/PuppeteerSharp/Media/MarginOptions.cs +++ b/lib/PuppeteerSharp/Media/MarginOptions.cs @@ -1,12 +1,12 @@ -using System; -using System.Collections.Generic; +using System.Text.Json.Serialization; +using PuppeteerSharp.Helpers.Json; namespace PuppeteerSharp.Media { /// /// margin options used in . /// - public class MarginOptions : IEquatable + public record MarginOptions { /// /// Initializes a new instance of the class. @@ -18,61 +18,25 @@ public MarginOptions() /// /// Top margin, accepts values labeled with units. /// - public string Top { get; set; } + [JsonConverter(typeof(PrimitiveTypeConverter))] + public object Top { get; set; } /// /// Left margin, accepts values labeled with units. /// - public string Left { get; set; } + [JsonConverter(typeof(PrimitiveTypeConverter))] + public object Left { get; set; } /// /// Bottom margin, accepts values labeled with units. /// - public string Bottom { get; set; } + [JsonConverter(typeof(PrimitiveTypeConverter))] + public object Bottom { get; set; } /// /// Right margin, accepts values labeled with units. /// - public string Right { get; set; } - - /// Overriding == operator for . - /// the value to compare against . - /// the value to compare against . - /// true if the two instances are equal to the same value. - public static bool operator ==(MarginOptions left, MarginOptions right) - => EqualityComparer.Default.Equals(left, right); - - /// Overriding != operator for . - /// the value to compare against . - /// the value to compare against . - /// true if the two instances are not equal to the same value. - public static bool operator !=(MarginOptions left, MarginOptions right) => !(left == right); - - /// - public override bool Equals(object obj) - { - if (obj == null || GetType() != obj.GetType()) - { - return false; - } - - return Equals((MarginOptions)obj); - } - - /// - public bool Equals(MarginOptions options) - => options != null && - Top == options.Top && - Left == options.Left && - Bottom == options.Bottom && - Right == options.Right; - - /// - public override int GetHashCode() - => -481391125 - ^ EqualityComparer.Default.GetHashCode(Top) - ^ EqualityComparer.Default.GetHashCode(Left) - ^ EqualityComparer.Default.GetHashCode(Bottom) - ^ EqualityComparer.Default.GetHashCode(Right); + [JsonConverter(typeof(PrimitiveTypeConverter))] + public object Right { get; set; } } } diff --git a/lib/PuppeteerSharp/Media/PaperFormat.cs b/lib/PuppeteerSharp/Media/PaperFormat.cs index bd798300a..42c642132 100644 --- a/lib/PuppeteerSharp/Media/PaperFormat.cs +++ b/lib/PuppeteerSharp/Media/PaperFormat.cs @@ -1,13 +1,10 @@ -using System; -using System.Collections.Generic; - namespace PuppeteerSharp.Media { /// /// Paper format. /// /// - public class PaperFormat : IEquatable + public record PaperFormat { /// /// Initializes a new instance of the class. @@ -87,41 +84,5 @@ public PaperFormat(decimal width, decimal height) /// /// The Height. public decimal Height { get; set; } - - /// Overriding == operator for . - /// the value to compare against . - /// the value to compare against . - /// true if the two instances are equal to the same value. - public static bool operator ==(PaperFormat left, PaperFormat right) - => EqualityComparer.Default.Equals(left, right); - - /// Overriding != operator for . - /// the value to compare against . - /// the value to compare against . - /// true if the two instances are not equal to the same value. - public static bool operator !=(PaperFormat left, PaperFormat right) => !(left == right); - - /// - public override bool Equals(object obj) - { - if (obj == null || GetType() != obj.GetType()) - { - return false; - } - - return Equals((PaperFormat)obj); - } - - /// - public bool Equals(PaperFormat format) - => format != null && - Width == format.Width && - Height == format.Height; - - /// - public override int GetHashCode() - => 859600377 - ^ Width.GetHashCode() - ^ Height.GetHashCode(); } } diff --git a/lib/PuppeteerSharp/PdfOptions.cs b/lib/PuppeteerSharp/PdfOptions.cs index f079f9c04..d76760706 100644 --- a/lib/PuppeteerSharp/PdfOptions.cs +++ b/lib/PuppeteerSharp/PdfOptions.cs @@ -1,3 +1,5 @@ +using System.Text.Json.Serialization; +using PuppeteerSharp.Helpers.Json; using PuppeteerSharp.Media; namespace PuppeteerSharp @@ -67,11 +69,13 @@ public PdfOptions() /// /// Paper width, accepts values labeled with units. /// + [JsonConverter(typeof(PrimitiveTypeConverter))] public object Width { get; set; } /// /// Paper height, accepts values labeled with units. /// + [JsonConverter(typeof(PrimitiveTypeConverter))] public object Height { get; set; } ///