Skip to content

Commit

Permalink
Merge branch 'release/2.7.0'
Browse files Browse the repository at this point in the history
  • Loading branch information
Jaben committed Feb 18, 2025
2 parents 7e567a6 + aacc127 commit 857abf8
Show file tree
Hide file tree
Showing 6 changed files with 157 additions and 28 deletions.
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -164,9 +164,9 @@ public async Task<Stream> CreateFromMarkdown()
.AddAsyncHeaderFooter(async
b => b.SetHeader(await System.IO.File.ReadAllTextAsync(headerPath))
.SetFooter(await System.IO.File.ReadAllBytesAsync(footerPath))
).WithDimensions(dimBuilder =>
).WithPageProperties(pp =>
{
dimBuilder.SetPaperSize(PaperSizes.A4)
pp.SetPaperSize(PaperSizes.A4)
.SetMargins(Margins.None)
.SetScale(.90)
.SetLandscape();
Expand Down Expand Up @@ -213,9 +213,9 @@ IEnumerable<UrlRequestBuilder> CreateBuilders(IEnumerable<Uri> uris)
docBuilder.SetHeader(GetHeadFoot(uri.Host.Replace("www.", string.Empty).ToUpper()))
.SetFooter(GetHeadFoot(uri.ToString()));
})
.WithDimensions(dimBuilder =>
.WithPageProperties(pp =>
{
dimBuilder.UseChromeDefaults()
pp.UseChromeDefaults()
.SetScale(.90)
.SetLandscape()
.SetMarginLeft(.5)
Expand Down
14 changes: 10 additions & 4 deletions lib/Domain/Builders/Faceted/ConfigBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using Gotenberg.Sharp.API.Client.Domain.Pages;

namespace Gotenberg.Sharp.API.Client.Domain.Builders.Faceted;

public sealed class ConfigBuilder
Expand All @@ -25,12 +27,16 @@ internal ConfigBuilder(RequestConfig requestConfig)
}


public ConfigBuilder SetPageRanges(string pageRanges)
public ConfigBuilder SetPageRanges(string? pageRanges)
{
if (pageRanges.IsNotSet())
throw new ArgumentException("Cannot be null or empty", nameof(pageRanges));
this._requestConfig.PageRanges = Pages.PageRanges.Create(pageRanges);

this._requestConfig.PageRanges = pageRanges;
return this;
}

public ConfigBuilder SetPageRanges(PageRanges? pageRanges)
{
this._requestConfig.PageRanges = pageRanges ?? Pages.PageRanges.All;

return this;
}
Expand Down
36 changes: 19 additions & 17 deletions lib/Domain/Dimensions/Dimension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace Gotenberg.Sharp.API.Client.Domain.Dimensions;
public sealed class Dimension(double value, DimensionUnitType unitType) : IEquatable<Dimension?>
{
private static readonly Regex ValidDimensionRegex =
new(@"^\s*(\d+(\.\d+)?)\s*(pt|px|in|mm|cm|pc)\s*$", RegexOptions.IgnoreCase);
new(@"^\s*(\d+(\.\d+)?)\s*(pt|px|in|mm|cm|pc)?\s*$", RegexOptions.IgnoreCase);

/// <summary>
/// UnitType value
Expand All @@ -73,29 +73,28 @@ public bool Equals(Dimension? other)
UnitType == other.UnitType;
}

/// <summary>
/// Parses a string like "200px", "11in", or defaults to inches if no unit is provided (e.g., "3.4").
/// </summary>
/// <param name="dimension"></param>
/// <returns></returns>
/// <exception cref="ArgumentException"></exception>
public static Dimension Parse(string dimension)
{
if (string.IsNullOrWhiteSpace(dimension))
{
throw new ArgumentException("Dimension cannot be null or empty.",
nameof(dimension));
}
throw new ArgumentException("Dimension cannot be null or empty.", nameof(dimension));

var match = ValidDimensionRegex.Match(dimension);
if (!match.Success)
{
throw new ArgumentException(
"Invalid dimension format. Expected formats: '200px', '11in', etc.",
nameof(dimension));
}
throw new ArgumentException("Invalid dimension format. Expected formats: '200px', '11in', or default to inches.", nameof(dimension));

var value = double.Parse(match.Groups[1].Value);
var unitStr = match.Groups[3].Value.ToLower();
double value = double.Parse(match.Groups[1].Value);
string? unitStr = match.Groups[3].Success ? match.Groups[3].Value.ToLower() : null;

if (!TryParseUnit(unitStr, out var unit))
{
throw new ArgumentException($"Unknown unitType '{unitStr}'", nameof(dimension));
}
// Default to Inches if no unit is provided
DimensionUnitType unit = unitStr is not null && TryParseUnit(unitStr, out var parsedUnit)
? parsedUnit
: DimensionUnitType.Inches;

return new Dimension(value, unit);
}
Expand Down Expand Up @@ -147,7 +146,10 @@ public static Dimension FromPicas(double picas)

public override string ToString()
{
return $"{Value}{UnitType.GetDescription()}";
// if it's inches, don't supply anything.
var unitType = UnitType == DimensionUnitType.Inches ? "" : UnitType.GetDescription();

return $"{Value}{unitType}";
}

public override bool Equals(object? obj)
Expand Down
118 changes: 118 additions & 0 deletions lib/Domain/Pages/PageRanges.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// Copyright 2019-2025 Chris Mohan, Jaben Cargman
// and GotenbergSharpApiClient Contributors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using System.Text.RegularExpressions;

namespace Gotenberg.Sharp.API.Client.Domain.Pages;

public sealed class PageRanges : IEquatable<PageRanges>
{
private static readonly Regex PageRangePattern =
new(@"^\s*(\d+(-\d+)?)(\s*,\s*(\d+(-\d+)?))*\s*$");

private PageRanges(IReadOnlyCollection<int> pages)
{
Pages = pages.OrderBy(p => p).ToArray();
}

public static PageRanges All { get; } = new(Array.Empty<int>());

public IReadOnlyCollection<int> Pages { get; }

public bool Equals(PageRanges? other)
{
return other is not null && Pages.SequenceEqual(other.Pages);
}

public static PageRanges Create(string? input)
{
if (string.IsNullOrWhiteSpace(input))
{
return All;
}

if (!PageRangePattern.IsMatch(input))
{
throw new ArgumentOutOfRangeException(nameof(input),
"Invalid page range format. Expected format: '1-5, 8, 11-13'.");
}

var pages = new SortedSet<int>();
foreach (var part in input!.Split([','], StringSplitOptions.RemoveEmptyEntries))
{
var trimmed = part.Trim();
if (trimmed.Contains('-'))
{
var bounds = trimmed.Split('-').Select(int.Parse).ToArray();
if (bounds.Length == 2 && bounds[0] <= bounds[1])
{
for (var i = bounds[0]; i <= bounds[1]; i++)
{
pages.Add(i);
}
}
}
else if (int.TryParse(trimmed, out var singlePage))
{
pages.Add(singlePage);
}
}

return new PageRanges(pages);
}

private string GetPageRangeString()
{
// empty is "all"
if (Pages.Count == 0)
{
return "";
}

var ranges = new List<string>();
int start = Pages.First(), end = start;

foreach (var page in Pages.Skip(1))
{
if (page == end + 1)
{
end = page;
}
else
{
ranges.Add(start == end ? start.ToString() : $"{start}-{end}");
start = end = page;
}
}

ranges.Add(start == end ? start.ToString() : $"{start}-{end}");
return string.Join(", ", ranges);
}

public override string ToString()
{
return GetPageRangeString();
}

public override bool Equals(object? obj)
{
return obj is PageRanges other && Pages.SequenceEqual(other.Pages);
}

public override int GetHashCode()
{
return Pages.Aggregate(0, (hash, page) => hash ^ page.GetHashCode());
}
}
6 changes: 4 additions & 2 deletions lib/Domain/Requests/Facets/RequestConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
// See the License for the specific language governing permissions and
// limitations under the License.

using Gotenberg.Sharp.API.Client.Domain.Pages;

namespace Gotenberg.Sharp.API.Client.Domain.Requests.Facets;

/// <summary>
Expand All @@ -29,7 +31,7 @@ public sealed class RequestConfig : IConvertToHttpContent
// ReSharper disable once MethodTooLong
public IEnumerable<HttpContent> ToHttpContent()
{
if (this.PageRanges.IsSet())
if (this.PageRanges?.Pages.Any() ?? false)
yield return BuildRequestBase.CreateFormDataItem(
this.PageRanges,
Constants.Gotenberg.Chromium.Shared.PageProperties.PageRanges);
Expand Down Expand Up @@ -64,7 +66,7 @@ public void Validate()
/// The format is the same as the one from the print options of Google Chrome, e.g. 1-5,8,11-13.
/// This may move...
/// </remarks>
public string? PageRanges { get; set; }
public PageRanges? PageRanges { get; set; }

/// <summary>
/// If provided, the API will return the resulting PDF file with the given filename. Otherwise a random filename is
Expand Down
3 changes: 2 additions & 1 deletion lib/Gotenberg.Sharp.Api.Client.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,14 @@
</PropertyGroup>

<PropertyGroup Label="PackageInfo">
<PackageVersion>2.6</PackageVersion>
<PackageVersion>2.7</PackageVersion>
<PackageTags>Gotenberg pdf C# ApiClient unoconv</PackageTags>
<Description>
C# API client for interacting with the Gotenberg v7 &amp; v8 micro-service's API, a docker-powered stateless API for converting &amp; merging HTML, Markdown and Office documents to PDF. The client supports a configurable Polly retry policy with exponential back-off for handling transient exceptions.
</Description>
<IncludeSymbols>True</IncludeSymbols>
<PackageReleaseNotes>
v2.7 - Fixes issue with "Inches".
v2.6 - Updated office Extensions. Added document metadata support. Add Dimension.FromUnit() support for dimensional values.
v2.5 - Renamed "Dimentions" to "PageProperties". Added support for 'GenerateDocumentOutline' and 'OmitBackground.'
v2.4 - Updated dependencies. Removed Annotations. Add support for PDF/UA form field. Thank you for the PR @lennartb-!
Expand Down

0 comments on commit 857abf8

Please sign in to comment.