Skip to content

Commit bbdea37

Browse files
committed
Add LibreOffice-specific conversion options with DDD value objects
Introduce LibreOfficeOptions facet with ~25 fields covering layout, image compression, notes/slides export, links, document outline, form fields, native watermark, and source file password. Add ImageQuality (1-100) and ImageResolution (75/150/300/600/1200 DPI) value objects to enforce valid ranges. Wire into MergeOfficeRequest and expose via SetLibreOfficeOptions on MergeOfficeBuilder.
1 parent 09b6c02 commit bbdea37

8 files changed

Lines changed: 830 additions & 0 deletions

File tree

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
// Copyright 2019-2026 Chris Mohan, Jaben Cargman
2+
// and GotenbergSharpApiClient Contributors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
using Gotenberg.Sharp.API.Client.Domain.ValueObjects;
17+
18+
namespace Gotenberg.Sharp.API.Client.Domain.Builders.Faceted;
19+
20+
/// <summary>
21+
/// Configures LibreOffice-specific conversion options for the /forms/libreoffice/convert route.
22+
/// </summary>
23+
public sealed class LibreOfficeOptionsBuilder
24+
{
25+
private readonly LibreOfficeOptions _options;
26+
27+
internal LibreOfficeOptionsBuilder(LibreOfficeOptions options)
28+
{
29+
_options = options;
30+
}
31+
32+
// Layout
33+
34+
public LibreOfficeOptionsBuilder SetSinglePageSheets(bool value = true)
35+
{
36+
_options.SinglePageSheets = value;
37+
return this;
38+
}
39+
40+
public LibreOfficeOptionsBuilder SetSkipEmptyPages(bool value = true)
41+
{
42+
_options.SkipEmptyPages = value;
43+
return this;
44+
}
45+
46+
public LibreOfficeOptionsBuilder SetExportPlaceholders(bool value = true)
47+
{
48+
_options.ExportPlaceholders = value;
49+
return this;
50+
}
51+
52+
// Image compression
53+
54+
public LibreOfficeOptionsBuilder SetLosslessImageCompression(bool value = true)
55+
{
56+
_options.LosslessImageCompression = value;
57+
return this;
58+
}
59+
60+
public LibreOfficeOptionsBuilder SetQuality(ImageQuality quality)
61+
{
62+
_options.Quality = quality ?? throw new ArgumentNullException(nameof(quality));
63+
return this;
64+
}
65+
66+
public LibreOfficeOptionsBuilder SetQuality(int quality)
67+
{
68+
return SetQuality(ImageQuality.Create(quality));
69+
}
70+
71+
public LibreOfficeOptionsBuilder SetReduceImageResolution(bool value = true)
72+
{
73+
_options.ReduceImageResolution = value;
74+
return this;
75+
}
76+
77+
public LibreOfficeOptionsBuilder SetMaxImageResolution(ImageResolution resolution)
78+
{
79+
_options.MaxImageResolution = resolution ?? throw new ArgumentNullException(nameof(resolution));
80+
return this;
81+
}
82+
83+
public LibreOfficeOptionsBuilder SetMaxImageResolution(int dpi)
84+
{
85+
return SetMaxImageResolution(ImageResolution.Create(dpi));
86+
}
87+
88+
// Notes & slides
89+
90+
public LibreOfficeOptionsBuilder SetExportNotes(bool value = true)
91+
{
92+
_options.ExportNotes = value;
93+
return this;
94+
}
95+
96+
public LibreOfficeOptionsBuilder SetExportNotesPages(bool value = true)
97+
{
98+
_options.ExportNotesPages = value;
99+
return this;
100+
}
101+
102+
public LibreOfficeOptionsBuilder SetExportOnlyNotesPages(bool value = true)
103+
{
104+
_options.ExportOnlyNotesPages = value;
105+
return this;
106+
}
107+
108+
public LibreOfficeOptionsBuilder SetExportNotesInMargin(bool value = true)
109+
{
110+
_options.ExportNotesInMargin = value;
111+
return this;
112+
}
113+
114+
public LibreOfficeOptionsBuilder SetExportHiddenSlides(bool value = true)
115+
{
116+
_options.ExportHiddenSlides = value;
117+
return this;
118+
}
119+
120+
// Links
121+
122+
public LibreOfficeOptionsBuilder SetConvertOooTargetToPdfTarget(bool value = true)
123+
{
124+
_options.ConvertOooTargetToPdfTarget = value;
125+
return this;
126+
}
127+
128+
public LibreOfficeOptionsBuilder SetExportLinksRelativeFsys(bool value = true)
129+
{
130+
_options.ExportLinksRelativeFsys = value;
131+
return this;
132+
}
133+
134+
// Document outline
135+
136+
public LibreOfficeOptionsBuilder SetUpdateIndexes(bool value = true)
137+
{
138+
_options.UpdateIndexes = value;
139+
return this;
140+
}
141+
142+
public LibreOfficeOptionsBuilder SetExportBookmarks(bool value = true)
143+
{
144+
_options.ExportBookmarks = value;
145+
return this;
146+
}
147+
148+
public LibreOfficeOptionsBuilder SetExportBookmarksToPdfDestination(bool value = true)
149+
{
150+
_options.ExportBookmarksToPdfDestination = value;
151+
return this;
152+
}
153+
154+
public LibreOfficeOptionsBuilder SetAddOriginalDocumentAsStream(bool value = true)
155+
{
156+
_options.AddOriginalDocumentAsStream = value;
157+
return this;
158+
}
159+
160+
// Form fields
161+
162+
public LibreOfficeOptionsBuilder SetExportFormFields(bool value = true)
163+
{
164+
_options.ExportFormFields = value;
165+
return this;
166+
}
167+
168+
public LibreOfficeOptionsBuilder SetAllowDuplicateFieldNames(bool value = true)
169+
{
170+
_options.AllowDuplicateFieldNames = value;
171+
return this;
172+
}
173+
174+
// Native watermark
175+
176+
public LibreOfficeOptionsBuilder SetNativeWatermarkText(string text)
177+
{
178+
if (string.IsNullOrWhiteSpace(text))
179+
throw new ArgumentException("Watermark text must not be null or empty.", nameof(text));
180+
181+
_options.NativeWatermarkText = text;
182+
return this;
183+
}
184+
185+
public LibreOfficeOptionsBuilder SetNativeWatermarkColor(int rgbDecimal)
186+
{
187+
_options.NativeWatermarkColor = rgbDecimal;
188+
return this;
189+
}
190+
191+
public LibreOfficeOptionsBuilder SetNativeWatermarkFontHeight(int fontHeight)
192+
{
193+
if (fontHeight < 0)
194+
throw new ArgumentOutOfRangeException(nameof(fontHeight), "Font height must be non-negative.");
195+
196+
_options.NativeWatermarkFontHeight = fontHeight;
197+
return this;
198+
}
199+
200+
public LibreOfficeOptionsBuilder SetNativeWatermarkRotateAngle(int angle)
201+
{
202+
_options.NativeWatermarkRotateAngle = angle;
203+
return this;
204+
}
205+
206+
public LibreOfficeOptionsBuilder SetNativeWatermarkFontName(string fontName)
207+
{
208+
if (string.IsNullOrWhiteSpace(fontName))
209+
throw new ArgumentException("Font name must not be null or empty.", nameof(fontName));
210+
211+
_options.NativeWatermarkFontName = fontName;
212+
return this;
213+
}
214+
215+
public LibreOfficeOptionsBuilder SetNativeTiledWatermarkText(string text)
216+
{
217+
if (string.IsNullOrWhiteSpace(text))
218+
throw new ArgumentException("Tiled watermark text must not be null or empty.", nameof(text));
219+
220+
_options.NativeTiledWatermarkText = text;
221+
return this;
222+
}
223+
224+
// Source file password
225+
226+
public LibreOfficeOptionsBuilder SetPassword(string password)
227+
{
228+
if (string.IsNullOrWhiteSpace(password))
229+
throw new ArgumentException("Password must not be null or empty.", nameof(password));
230+
231+
_options.Password = password;
232+
return this;
233+
}
234+
}

src/Gotenberg.Sharp.Api.Client/Domain/Builders/MergeOfficeBuilder.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,23 @@ public MergeOfficeBuilder SetPageRanges(string pageRanges)
4747
return this;
4848
}
4949

50+
/// <summary>
51+
/// Configures LibreOffice-specific conversion options such as image compression,
52+
/// notes export, bookmarks, form fields, and native watermarks.
53+
/// </summary>
54+
/// <param name="action">Configuration action for LibreOffice options.</param>
55+
/// <returns>The builder instance for method chaining.</returns>
56+
public MergeOfficeBuilder SetLibreOfficeOptions(Action<LibreOfficeOptionsBuilder> action)
57+
{
58+
if (action == null) throw new ArgumentNullException(nameof(action));
59+
60+
this.Request.LibreOfficeOptions ??= new LibreOfficeOptions();
61+
62+
action(new LibreOfficeOptionsBuilder(this.Request.LibreOfficeOptions));
63+
64+
return this;
65+
}
66+
5067
/// <summary>
5168
/// Converts the resulting merged PDF to the specified PDF/A format for long-term archival.
5269
/// </summary>
Lines changed: 119 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,119 @@
1+
// Copyright 2019-2026 Chris Mohan, Jaben Cargman
2+
// and GotenbergSharpApiClient Contributors
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License");
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
16+
using Gotenberg.Sharp.API.Client.Domain.ValueObjects;
17+
18+
namespace Gotenberg.Sharp.API.Client.Domain.Requests.Facets;
19+
20+
/// <summary>
21+
/// LibreOffice-specific conversion options. These apply only to the LibreOffice route
22+
/// (/forms/libreoffice/convert) and control layout, image compression, notes/slides,
23+
/// links, document outline, form fields, and native watermark features.
24+
/// </summary>
25+
public class LibreOfficeOptions : FacetBase
26+
{
27+
// Layout
28+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.SinglePageSheets)]
29+
public bool? SinglePageSheets { get; set; }
30+
31+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.SkipEmptyPages)]
32+
public bool? SkipEmptyPages { get; set; }
33+
34+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportPlaceholders)]
35+
public bool? ExportPlaceholders { get; set; }
36+
37+
// Image compression
38+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.LosslessImageCompression)]
39+
public bool? LosslessImageCompression { get; set; }
40+
41+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.Quality)]
42+
public ImageQuality? Quality { get; set; }
43+
44+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ReduceImageResolution)]
45+
public bool? ReduceImageResolution { get; set; }
46+
47+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.MaxImageResolution)]
48+
public ImageResolution? MaxImageResolution { get; set; }
49+
50+
// Notes & slides
51+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportNotes)]
52+
public bool? ExportNotes { get; set; }
53+
54+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportNotesPages)]
55+
public bool? ExportNotesPages { get; set; }
56+
57+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportOnlyNotesPages)]
58+
public bool? ExportOnlyNotesPages { get; set; }
59+
60+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportNotesInMargin)]
61+
public bool? ExportNotesInMargin { get; set; }
62+
63+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportHiddenSlides)]
64+
public bool? ExportHiddenSlides { get; set; }
65+
66+
// Links
67+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ConvertOooTargetToPdfTarget)]
68+
public bool? ConvertOooTargetToPdfTarget { get; set; }
69+
70+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportLinksRelativeFsys)]
71+
public bool? ExportLinksRelativeFsys { get; set; }
72+
73+
// Document outline
74+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.UpdateIndexes)]
75+
public bool? UpdateIndexes { get; set; }
76+
77+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportBookmarks)]
78+
public bool? ExportBookmarks { get; set; }
79+
80+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportBookmarksToPdfDestination)]
81+
public bool? ExportBookmarksToPdfDestination { get; set; }
82+
83+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.AddOriginalDocumentAsStream)]
84+
public bool? AddOriginalDocumentAsStream { get; set; }
85+
86+
// Form fields
87+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.ExportFormFields)]
88+
public bool? ExportFormFields { get; set; }
89+
90+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.AllowDuplicateFieldNames)]
91+
public bool? AllowDuplicateFieldNames { get; set; }
92+
93+
// Native watermark
94+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.NativeWatermarkText)]
95+
public string? NativeWatermarkText { get; set; }
96+
97+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.NativeWatermarkColor)]
98+
public int? NativeWatermarkColor { get; set; }
99+
100+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.NativeWatermarkFontHeight)]
101+
public int? NativeWatermarkFontHeight { get; set; }
102+
103+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.NativeWatermarkRotateAngle)]
104+
public int? NativeWatermarkRotateAngle { get; set; }
105+
106+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.NativeWatermarkFontName)]
107+
public string? NativeWatermarkFontName { get; set; }
108+
109+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.NativeTiledWatermarkText)]
110+
public string? NativeTiledWatermarkText { get; set; }
111+
112+
// Source file password
113+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.Password)]
114+
public string? Password { get; set; }
115+
116+
// Merge multiple documents into one PDF
117+
[MultiFormHeader(Constants.Gotenberg.LibreOffice.Options.Merge)]
118+
public bool? Merge { get; set; }
119+
}

0 commit comments

Comments
 (0)