chromiumly 5.2.0 → 6.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (70) hide show
  1. package/README.md +663 -360
  2. package/dist/chromium/converters/html.converter.d.ts +2 -2
  3. package/dist/chromium/converters/html.converter.js +14 -4
  4. package/dist/chromium/converters/html.converter.js.map +1 -1
  5. package/dist/chromium/converters/markdown.converter.d.ts +2 -2
  6. package/dist/chromium/converters/markdown.converter.js +23 -5
  7. package/dist/chromium/converters/markdown.converter.js.map +1 -1
  8. package/dist/chromium/converters/url.converter.d.ts +2 -2
  9. package/dist/chromium/converters/url.converter.js +14 -4
  10. package/dist/chromium/converters/url.converter.js.map +1 -1
  11. package/dist/chromium/interfaces/common.types.d.ts +1 -0
  12. package/dist/chromium/interfaces/converter.types.d.ts +26 -17
  13. package/dist/chromium/interfaces/screenshot.types.d.ts +16 -7
  14. package/dist/chromium/screenshots/html.screenshot.d.ts +1 -2
  15. package/dist/chromium/screenshots/html.screenshot.js +8 -8
  16. package/dist/chromium/screenshots/html.screenshot.js.map +1 -1
  17. package/dist/chromium/screenshots/markdown.screenshot.d.ts +1 -2
  18. package/dist/chromium/screenshots/markdown.screenshot.js +14 -9
  19. package/dist/chromium/screenshots/markdown.screenshot.js.map +1 -1
  20. package/dist/chromium/screenshots/url.screenshot.d.ts +1 -2
  21. package/dist/chromium/screenshots/url.screenshot.js +4 -8
  22. package/dist/chromium/screenshots/url.screenshot.js.map +1 -1
  23. package/dist/chromium/utils/converter.utils.js +69 -43
  24. package/dist/chromium/utils/converter.utils.js.map +1 -1
  25. package/dist/chromium/utils/screenshot.utils.d.ts +0 -10
  26. package/dist/chromium/utils/screenshot.utils.js +6 -44
  27. package/dist/chromium/utils/screenshot.utils.js.map +1 -1
  28. package/dist/common/constants.d.ts +1 -0
  29. package/dist/common/constants.js +1 -0
  30. package/dist/common/constants.js.map +1 -1
  31. package/dist/common/factur-x.types.d.ts +24 -0
  32. package/dist/common/factur-x.types.js +3 -0
  33. package/dist/common/factur-x.types.js.map +1 -0
  34. package/dist/common/factur-x.utils.d.ts +6 -0
  35. package/dist/common/factur-x.utils.js +48 -0
  36. package/dist/common/factur-x.utils.js.map +1 -0
  37. package/dist/common/gotenberg.utils.d.ts +16 -2
  38. package/dist/common/gotenberg.utils.js +39 -6
  39. package/dist/common/gotenberg.utils.js.map +1 -1
  40. package/dist/common/index.d.ts +5 -1
  41. package/dist/common/index.js +5 -1
  42. package/dist/common/index.js.map +1 -1
  43. package/dist/common/pdf-engine-encryption.types.d.ts +14 -0
  44. package/dist/common/pdf-engine-encryption.types.js +3 -0
  45. package/dist/common/pdf-engine-encryption.types.js.map +1 -0
  46. package/dist/common/pdf-engine-encryption.utils.d.ts +7 -0
  47. package/dist/common/pdf-engine-encryption.utils.js +32 -0
  48. package/dist/common/pdf-engine-encryption.utils.js.map +1 -0
  49. package/dist/common/types.d.ts +29 -2
  50. package/dist/libre-office/interfaces/libre-office.types.d.ts +10 -5
  51. package/dist/libre-office/libre-office.d.ts +2 -2
  52. package/dist/libre-office/libre-office.js +12 -4
  53. package/dist/libre-office/libre-office.js.map +1 -1
  54. package/dist/libre-office/utils/constants.js +0 -2
  55. package/dist/libre-office/utils/constants.js.map +1 -1
  56. package/dist/libre-office/utils/libre-office.utils.js +8 -0
  57. package/dist/libre-office/utils/libre-office.utils.js.map +1 -1
  58. package/dist/main.config.d.ts +2 -0
  59. package/dist/main.config.js +2 -0
  60. package/dist/main.config.js.map +1 -1
  61. package/dist/pdf-engines/interfaces/pdf-engines.types.d.ts +18 -8
  62. package/dist/pdf-engines/pdf-engines.d.ts +65 -36
  63. package/dist/pdf-engines/pdf-engines.js +119 -36
  64. package/dist/pdf-engines/pdf-engines.js.map +1 -1
  65. package/dist/pdf-engines/utils/pdf-engines.utils.js +1 -2
  66. package/dist/pdf-engines/utils/pdf-engines.utils.js.map +1 -1
  67. package/dist/system/system.d.ts +20 -5
  68. package/dist/system/system.js +25 -10
  69. package/dist/system/system.js.map +1 -1
  70. package/package.json +85 -82
package/README.md CHANGED
@@ -35,26 +35,26 @@ Once the environment variable is set, Chromiumly will automatically send all req
35
35
  You can also configure the hosted API programmatically without an endpoint:
36
36
 
37
37
  ```typescript
38
- import { Chromiumly } from "chromiumly";
38
+ import { Chromiumly } from 'chromiumly';
39
39
 
40
40
  Chromiumly.configure({
41
- apiKey: "your-api-key",
41
+ apiKey: 'your-api-key'
42
42
  });
43
43
  ```
44
44
 
45
45
  ### Minimal usage example (hosted API)
46
46
 
47
47
  ```typescript
48
- import { UrlConverter } from "chromiumly";
48
+ import { UrlConverter } from 'chromiumly';
49
49
 
50
50
  async function run() {
51
- const urlConverter = new UrlConverter();
51
+ const urlConverter = new UrlConverter();
52
52
 
53
- const buffer = await urlConverter.convert({
54
- url: "https://www.example.com/",
55
- });
53
+ const buffer = await urlConverter.convert({
54
+ url: 'https://www.example.com/'
55
+ });
56
56
 
57
- // Write the buffer to disk, send it over HTTP, etc.
57
+ // Write the buffer to disk, send it over HTTP, etc.
58
58
  }
59
59
 
60
60
  run();
@@ -64,34 +64,41 @@ run();
64
64
 
65
65
  1. [API Key Authentication (Hosted API)](#api-key-authentication-hosted-api)
66
66
  2. [Getting Started](#getting-started)
67
- - [Installation](#installation)
68
- - [Prerequisites](#prerequisites)
69
- - [Configuration](#configuration)
67
+ - [Installation](#installation)
68
+ - [Prerequisites](#prerequisites)
69
+ - [Configuration](#configuration)
70
70
  3. [Authentication](#authentication)
71
- - [Basic Authentication](#basic-authentication)
72
- - [API Key Authentication](#api-key-authentication)
73
- - [Advanced Authentication](#advanced-authentication)
71
+ - [Basic Authentication](#basic-authentication)
72
+ - [API Key Authentication](#api-key-authentication)
73
+ - [Advanced Authentication](#advanced-authentication)
74
74
  4. [Core Features](#core-features)
75
- - [Chromium](#chromium)
76
- - [URL](#url)
77
- - [HTML](#html)
78
- - [Markdown](#markdown)
79
- - [Screenshot](#screenshot)
80
- - [LibreOffice](#libreoffice)
81
- - [PDF Engines](#pdf-engines)
82
- - [Format Conversion](#format-conversion)
83
- - [Merging](#merging)
84
- - [PDF Rotation](#pdf-rotation)
85
- - [Metadata Management](#metadata-management)
86
- - [Bookmarks Management](#bookmarks-management)
87
- - [File Generation](#file-generation)
88
- - [System](#system)
89
- - [PDF Splitting](#pdf-splitting)
90
- - [PDF Flattening](#pdf-flattening)
91
- - [PDF Encryption](#pdf-encryption)
92
- - [Embedding Files](#embedding-files)
93
- - [Templates (hosted API only)](#templates-hosted-api-only)
94
- - [Watermark and stamp](#watermark-and-stamp)
75
+ - [Chromium](#chromium)
76
+ - [URL](#url)
77
+ - [HTML](#html)
78
+ - [Markdown](#markdown)
79
+ - [Screenshot](#screenshot)
80
+ - [LibreOffice](#libreoffice)
81
+ - [PDF Engines](#pdf-engines)
82
+ - [Format Conversion](#format-conversion)
83
+ - [Merging](#merging)
84
+ - [PDF Rotation](#pdf-rotation)
85
+ - [Watermark and stamp (dedicated routes)](#watermark-and-stamp-dedicated-routes)
86
+ - [Metadata Management](#metadata-management)
87
+ - [Bookmarks Management](#bookmarks-management)
88
+ - [Encryption (dedicated route)](#encryption-dedicated-route)
89
+ - [Embedding Files (dedicated route)](#embedding-files-dedicated-route)
90
+ - [Factur-X / ZUGFeRD (dedicated route)](#factur-x--zugferd-dedicated-route)
91
+ - [File Generation](#file-generation)
92
+ - [System](#system)
93
+ - [PDF Splitting](#pdf-splitting)
94
+ - [PDF Flattening](#pdf-flattening)
95
+ - [PDF Encryption](#pdf-encryption)
96
+ - [PDF Permissions](#pdf-permissions)
97
+ - [Embedding Files](#embedding-files)
98
+ - [Factur-X / ZUGFeRD](#factur-x--zugferd)
99
+ - [Output Filename and Request Tracing](#output-filename-and-request-tracing)
100
+ - [Templates (hosted API only)](#templates-hosted-api-only)
101
+ - [Watermark and stamp](#watermark-and-stamp)
95
102
  5. [Usage Example](#snippet)
96
103
 
97
104
  ## Getting Started
@@ -137,18 +144,18 @@ GOTENBERG_ENDPOINT=http://localhost:3000
137
144
 
138
145
  ```json
139
146
  {
140
- "gotenberg": {
141
- "endpoint": "http://localhost:3000"
142
- }
147
+ "gotenberg": {
148
+ "endpoint": "http://localhost:3000"
149
+ }
143
150
  }
144
151
  ```
145
152
 
146
153
  #### code
147
154
 
148
155
  ```typescript
149
- import { Chromiumly } from "chromiumly";
156
+ import { Chromiumly } from 'chromiumly';
150
157
 
151
- Chromiumly.configure({ endpoint: "http://localhost:3000" });
158
+ Chromiumly.configure({ endpoint: 'http://localhost:3000' });
152
159
  ```
153
160
 
154
161
  ## Authentication
@@ -177,15 +184,15 @@ Or
177
184
 
178
185
  ```json
179
186
  {
180
- "gotenberg": {
181
- "endpoint": "http://localhost:3000",
182
- "api": {
183
- "basicAuth": {
184
- "username": "user",
185
- "password": "pass"
186
- }
187
+ "gotenberg": {
188
+ "endpoint": "http://localhost:3000",
189
+ "api": {
190
+ "basicAuth": {
191
+ "username": "user",
192
+ "password": "pass"
193
+ }
194
+ }
187
195
  }
188
- }
189
196
  }
190
197
  ```
191
198
 
@@ -193,9 +200,9 @@ Or
193
200
 
194
201
  ```typescript
195
202
  Chromiumly.configure({
196
- endpoint: "http://localhost:3000",
197
- username: "user",
198
- password: "pass",
203
+ endpoint: 'http://localhost:3000',
204
+ username: 'user',
205
+ password: 'pass'
199
206
  });
200
207
  ```
201
208
 
@@ -213,11 +220,11 @@ For example, you can include a Bearer token for authentication along with a cust
213
220
  const token = await generateToken();
214
221
 
215
222
  Chromiumly.configure({
216
- endpoint: "http://localhost:3000",
217
- customHttpHeaders: {
218
- Authorization: `Bearer ${token}`,
219
- "X-Custom-Header": "value",
220
- },
223
+ endpoint: 'http://localhost:3000',
224
+ customHttpHeaders: {
225
+ Authorization: `Bearer ${token}`,
226
+ 'X-Custom-Header': 'value'
227
+ }
221
228
  });
222
229
  ```
223
230
 
@@ -238,20 +245,20 @@ Similarly, a new set of classes have been added to harness the recently introduc
238
245
  #### URL
239
246
 
240
247
  ```typescript
241
- import { UrlConverter } from "chromiumly";
248
+ import { UrlConverter } from 'chromiumly';
242
249
 
243
250
  const urlConverter = new UrlConverter();
244
251
  const buffer = await urlConverter.convert({
245
- url: "https://www.example.com/",
252
+ url: 'https://www.example.com/'
246
253
  });
247
254
  ```
248
255
 
249
256
  ```typescript
250
- import { UrlScreenshot } from "chromiumly";
257
+ import { UrlScreenshot } from 'chromiumly';
251
258
 
252
259
  const screenshot = new UrlScreenshot();
253
260
  const buffer = await screenshot.capture({
254
- url: "https://www.example.com/",
261
+ url: 'https://www.example.com/'
255
262
  });
256
263
  ```
257
264
 
@@ -260,20 +267,20 @@ const buffer = await screenshot.capture({
260
267
  The only requirement is that the file name should be `index.html`.
261
268
 
262
269
  ```typescript
263
- import { HtmlConverter } from "chromiumly";
270
+ import { HtmlConverter } from 'chromiumly';
264
271
 
265
272
  const htmlConverter = new HtmlConverter();
266
273
  const buffer = await htmlConverter.convert({
267
- html: "path/to/index.html",
274
+ html: 'path/to/index.html'
268
275
  });
269
276
  ```
270
277
 
271
278
  ```typescript
272
- import { HtmlScreenshot } from "chromiumly";
279
+ import { HtmlScreenshot } from 'chromiumly';
273
280
 
274
281
  const screenshot = new HtmlScreenshot();
275
282
  const buffer = await screenshot.capture({
276
- html: "path/to/index.html",
283
+ html: 'path/to/index.html'
277
284
  });
278
285
  ```
279
286
 
@@ -282,22 +289,46 @@ const buffer = await screenshot.capture({
282
289
  This route accepts an `index.html` file plus a markdown file.
283
290
 
284
291
  ```typescript
285
- import { MarkdownConverter } from "chromiumly";
292
+ import { MarkdownConverter } from 'chromiumly';
286
293
 
287
294
  const markdownConverter = new MarkdownConverter();
288
295
  const buffer = await markdownConverter.convert({
289
- html: "path/to/index.html",
290
- markdown: "path/to/file.md",
296
+ html: 'path/to/index.html',
297
+ markdown: 'path/to/file.md'
291
298
  });
292
299
  ```
293
300
 
294
301
  ```typescript
295
- import { MarkdownScreenshot } from "chromiumly";
302
+ import { MarkdownScreenshot } from 'chromiumly';
296
303
 
297
304
  const screenshot = new MarkdownScreenshot();
298
305
  const buffer = await screenshot.capture({
299
- html: "path/to/index.html",
300
- markdown: "path/to/file.md",
306
+ html: 'path/to/index.html',
307
+ markdown: 'path/to/file.md'
308
+ });
309
+ ```
310
+
311
+ The `markdown` field on the Markdown convert and screenshot routes also accepts an array of distinctly-named files, all referenced from the same `index.html` template:
312
+
313
+ ```typescript
314
+ const buffer = await markdownConverter.convert({
315
+ html: 'path/to/index.html',
316
+ markdown: [
317
+ { file: 'path/to/chapter1.md', name: 'chapter1.md' },
318
+ { file: 'path/to/chapter2.md', name: 'chapter2.md' }
319
+ ]
320
+ });
321
+ ```
322
+
323
+ HTML and Markdown convert/screenshot routes also accept an optional `assets` field for images, stylesheets, or other files referenced from the HTML/markdown content:
324
+
325
+ ```typescript
326
+ const buffer = await htmlConverter.convert({
327
+ html: 'path/to/index.html',
328
+ assets: [
329
+ { file: 'path/to/style.css', name: 'style.css' },
330
+ { file: 'path/to/logo.png', name: 'logo.png' }
331
+ ]
301
332
  });
302
333
  ```
303
334
 
@@ -306,38 +337,40 @@ file will look like.
306
337
 
307
338
  ```typescript
308
339
  type PageProperties = {
309
- singlePage?: boolean; // Print the entire content in one single page (default false)
310
- size?: {
311
- width: number | string; // Paper width (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 8.5)
312
- height: number | string; // Paper height (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 11)
313
- };
314
- margins?: {
315
- top: number | string; // Top margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
316
- bottom: number | string; // Bottom margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
317
- left: number | string; // Left margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
318
- right: number | string; // Right margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
319
- };
320
- preferCssPageSize?: boolean; // Define whether to prefer page size as defined by CSS (default false)
321
- printBackground?: boolean; // Print the background graphics (default false)
322
- omitBackground?: boolean; // Hide the default white background and allow generating PDFs with transparency (default false)
323
- landscape?: boolean; // Set the paper orientation to landscape (default false)
324
- scale?: number; // The scale of the page rendering (default 1.0)
325
- nativePageRanges?: { from: number; to: number }; // Page ranges to print
340
+ singlePage?: boolean; // Print the entire content in one single page (default false)
341
+ size?: {
342
+ width?: number | string; // Paper width (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 8.5)
343
+ height?: number | string; // Paper height (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 11)
344
+ };
345
+ margins?: {
346
+ top?: number | string; // Top margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
347
+ bottom?: number | string; // Bottom margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
348
+ left?: number | string; // Left margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
349
+ right?: number | string; // Right margin (number in inches or string with units: 72pt, 96px, 1in, 25.4mm, 2.54cm, 6pc, default 0.39)
350
+ };
351
+ preferCssPageSize?: boolean; // Define whether to prefer page size as defined by CSS (default false)
352
+ printBackground?: boolean; // Print the background graphics (default false)
353
+ omitBackground?: boolean; // Hide the default white background and allow generating PDFs with transparency (default false)
354
+ landscape?: boolean; // Set the paper orientation to landscape (default false)
355
+ scale?: number; // The scale of the page rendering (default 1.0)
356
+ nativePageRanges?: { from: number; to: number } | string; // Page ranges to print, either a single range or the free-form syntax "1-5, 8, 11-13"
326
357
  };
327
358
  ```
328
359
 
360
+ Every field of `size` and `margins` defaults independently, so you can set just one dimension or margin and let Gotenberg fill in the rest.
361
+
329
362
  **Page Size and Margins Units**
330
363
 
331
364
  Both `size` and `margins` properties support two formats:
332
365
 
333
366
  1. **Numeric values** (in inches): For backward compatibility, you can continue using numbers which represent inches.
334
367
  2. **String values with units**: You can now specify explicit units using the following formats:
335
- - `pt` (points): e.g., `"72pt"`
336
- - `px` (pixels): e.g., `"96px"`
337
- - `in` (inches): e.g., `"1in"`
338
- - `mm` (millimeters): e.g., `"25.4mm"`
339
- - `cm` (centimeters): e.g., `"2.54cm"`
340
- - `pc` (picas): e.g., `"6pc"`
368
+ - `pt` (points): e.g., `"72pt"`
369
+ - `px` (pixels): e.g., `"96px"`
370
+ - `in` (inches): e.g., `"1in"`
371
+ - `mm` (millimeters): e.g., `"25.4mm"`
372
+ - `cm` (centimeters): e.g., `"2.54cm"`
373
+ - `pc` (picas): e.g., `"6pc"`
341
374
 
342
375
  **Examples:**
343
376
 
@@ -365,75 +398,104 @@ In addition to the `PageProperties` customization options, the `convert()` metho
365
398
 
366
399
  ```typescript
367
400
  type ConversionOptions = {
368
- properties?: PageProperties; // Customize the appearance of the generated PDF
369
- pdfFormat?: PdfFormat; // Define the PDF format for the conversion
370
- pdfUA?: boolean; // Enable PDF for Universal Access for optimal accessibility (default false)
371
- userAgent?: string; // Customize the user agent string sent during conversion
372
- header?: PathLikeOrReadStream; // Specify a custom header for the PDF
373
- footer?: PathLikeOrReadStream; // Specify a custom footer for the PDF
374
- emulatedMediaType?: EmulatedMediaType; // Specify the emulated media type for conversion
375
- emulatedMediaFeatures?: EmulatedMediaFeature[]; // Override CSS media features (e.g., prefers-color-scheme). Default: None.
376
- waitDelay?: string; // Duration (e.g., '5s') to wait when loading an HTML document before conversion
377
- waitForExpression?: string; // JavaScript expression to wait before converting an HTML document into PDF
378
- waitForSelector?: string; // CSS selector to wait for before converting an HTML document into PDF until it matches a node
379
- extraHttpHeaders?: Record<string, string>; // Include additional HTTP headers in the request
380
- failOnHttpStatusCodes?: number[]; // List of HTTP status codes triggering a 409 Conflict response (default [499, 599])
381
- failOnConsoleExceptions?: boolean; // Return a 409 Conflict response if there are exceptions in the Chromium console (default false)
382
- failOnResourceHttpStatusCodes?: number[]; // Return a 409 Conflict response if resource HTTP status code is in the list (default [499,599])
383
- ignoreResourceHttpStatusDomains?: string[]; // Domains to exclude from resource HTTP status code checks (matches exact domains or subdomains)
384
- failOnResourceLoadingFailed?: boolean; // Return a 409 Conflict response if resource loading failed (default false)
385
- skipNetworkIdleEvent?: boolean; // Do not wait for Chromium network to be idle (default true)
386
- skipNetworkAlmostIdleEvent?: boolean; // Do not wait for Chromium network to be almost idle (default true)
387
- metadata?: Metadata; // Metadata to be written.
388
- cookies?: Cookie[]; // Cookies to be written.
389
- downloadFrom?: DownloadFrom; // Download a file from one or multiple URLs. Each URL must return a Content-Disposition header with a filename parameter.
390
- webhook?: WebhookOptions; // Request-level webhook headers for async callbacks.
391
- split?: SplitOptions; // Split the PDF file into multiple files.
392
- userPassword?: string; // Password for opening the resulting PDF(s).
393
- ownerPassword?: string; // Password for full access on the resulting PDF(s).
394
- embeds?: PathLikeOrReadStream[]; // Files to embed in the generated PDF.
395
- watermark?: PdfEngineWatermark; // Optional PDF-engine post-processing watermark (behind page content).
396
- stamp?: PdfEngineStamp; // Optional PDF-engine post-processing stamp (on top of page content).
401
+ properties?: PageProperties; // Customize the appearance of the generated PDF
402
+ /** @deprecated Chromium no longer supports pdfFormat since Gotenberg 8.0.0; use pdfa instead of pdfFormat. */
403
+ pdfFormat?: PdfFormat;
404
+ pdfUA?: boolean; // Enable PDF for Universal Access for optimal accessibility (default false)
405
+ generateTaggedPdf?: boolean; // Embed PDF/UA accessibility structure tags, independent of pdfUA (default false)
406
+ generateDocumentOutline?: boolean; // Generate a document outline / bookmarks from the page's heading tags (default false)
407
+ userAgent?: string; // Customize the user agent string sent during conversion
408
+ header?: PathLikeOrReadStream; // Specify a custom header for the PDF
409
+ footer?: PathLikeOrReadStream; // Specify a custom footer for the PDF
410
+ emulatedMediaType?: EmulatedMediaType; // Specify the emulated media type for conversion
411
+ emulatedMediaFeatures?: EmulatedMediaFeature[]; // Override CSS media features (e.g., prefers-color-scheme). Default: None.
412
+ waitDelay?: string; // Duration (e.g., '5s') to wait when loading an HTML document before conversion
413
+ waitForExpression?: string; // JavaScript expression to wait before converting an HTML document into PDF
414
+ waitForSelector?: string; // CSS selector to wait for before converting an HTML document into PDF until it matches a node
415
+ extraHttpHeaders?: Record<string, string>; // Include additional HTTP headers in the request
416
+ failOnHttpStatusCodes?: number[]; // List of HTTP status codes triggering a 409 Conflict response (default [499, 599])
417
+ failOnConsoleExceptions?: boolean; // Return a 409 Conflict response if there are exceptions in the Chromium console (default false)
418
+ failOnResourceHttpStatusCodes?: number[]; // Return a 409 Conflict response if resource HTTP status code is in the list (default None)
419
+ ignoreResourceHttpStatusDomains?: string[]; // Domains to exclude from resource HTTP status code checks (matches exact domains or subdomains)
420
+ failOnResourceLoadingFailed?: boolean; // Return a 409 Conflict response if resource loading failed (default false)
421
+ skipNetworkIdleEvent?: boolean; // Do not wait for Chromium network to be idle (default true)
422
+ skipNetworkAlmostIdleEvent?: boolean; // Do not wait for Chromium network to be almost idle (default true)
423
+ metadata?: Metadata; // Metadata to be written.
424
+ cookies?: Cookie[]; // Cookies to be written.
425
+ downloadFrom?: DownloadFrom; // Download a file from one or multiple URLs. Each URL must return a Content-Disposition header with a filename parameter.
426
+ webhook?: WebhookOptions; // Request-level webhook headers for async callbacks.
427
+ outputFilename?: string; // Custom filename for the resulting file; Gotenberg appends the extension.
428
+ trace?: string; // Custom request id to identify the request in the logs, overriding the generated UUID.
429
+ split?: ConvertSplit; // Split the PDF file into multiple files.
430
+ flatten?: boolean; // Flatten the resulting PDF document (default false)
431
+ userPassword?: string; // Password for opening the resulting PDF(s).
432
+ ownerPassword?: string; // Password for full access on the resulting PDF(s).
433
+ allowPrinting?: boolean; // Allow printing the document (default true)
434
+ allowCopying?: boolean; // Allow copying content from the document (default true)
435
+ allowModifying?: boolean; // Allow modifying the document (default true)
436
+ allowAnnotating?: boolean; // Allow adding or modifying annotations (default true)
437
+ allowFillingForms?: boolean; // Allow filling in form fields (default true)
438
+ allowAssembling?: boolean; // Allow document assembly, e.g. inserting, deleting, or rotating pages (default true)
439
+ embeds?: PathLikeOrReadStream[]; // Files to embed in the generated PDF.
440
+ embedsMetadata?: EmbedsMetadata; // Per-attachment metadata keyed by filename, for PDF/A-3 and Factur-X compliance.
441
+ watermark?: PdfEngineWatermark; // Optional PDF-engine post-processing watermark (behind page content).
442
+ stamp?: PdfEngineStamp; // Optional PDF-engine post-processing stamp (on top of page content).
443
+ rotate?: PdfEngineRotate; // Optional PDF-engine post-process page rotation.
444
+ facturx?: FacturXOptions; // Turn the resulting PDF into a Factur-X / ZUGFeRD e-invoice.
397
445
  };
398
446
  ```
399
447
 
400
448
  ```typescript
401
449
  type DownloadFromEntry = {
402
- url: string;
403
- extraHttpHeaders?: Record<string, string>;
404
- embedded?: boolean; // Legacy flag, prefer field
405
- field?: "embedded" | "watermark" | "stamp" | "";
450
+ url: string;
451
+ extraHttpHeaders?: Record<string, string>;
452
+ embedded?: boolean; // Legacy flag, prefer field
453
+ field?: 'embedded' | 'watermark' | 'stamp' | '';
406
454
  };
407
455
 
408
456
  type DownloadFrom = DownloadFromEntry | DownloadFromEntry[];
409
457
 
410
458
  type WebhookOptions = {
411
- webhookUrl: string;
412
- webhookErrorUrl: string;
413
- webhookMethod?: "POST" | "PUT" | "PATCH";
414
- webhookErrorMethod?: "POST" | "PUT" | "PATCH";
415
- webhookExtraHttpHeaders?: Record<string, string>;
416
- webhookEventsUrl?: string;
459
+ webhookUrl?: string; // At least one of webhookUrl or webhookErrorUrl is required.
460
+ /** @deprecated Use webhookEventsUrl instead, together with webhookUrl. */
461
+ webhookErrorUrl?: string;
462
+ webhookMethod?: 'POST' | 'PUT' | 'PATCH';
463
+ webhookErrorMethod?: 'POST' | 'PUT' | 'PATCH';
464
+ webhookExtraHttpHeaders?: Record<string, string>;
465
+ webhookEventsUrl?: string;
417
466
  };
467
+
468
+ type EmbedsMetadata = Record<
469
+ string, // filename, matching an entry in `embeds`
470
+ {
471
+ mimeType?: string; // Written to the embedded file stream's /Subtype
472
+ relationship?:
473
+ | 'Source'
474
+ | 'Data'
475
+ | 'Alternative'
476
+ | 'Supplement'
477
+ | 'Unspecified'; // The /AFRelationship value
478
+ }
479
+ >;
418
480
  ```
419
481
 
420
482
  Optional `watermark` and `stamp` use the same multipart field names as [Gotenberg’s PDF-engine watermark/stamp](https://gotenberg.dev/docs/manipulate-pdfs/watermark-pdfs): text, image, or PDF sources, with JSON `options` depending on your configured engine (e.g. pdfcpu). See [Watermark PDFs](https://gotenberg.dev/docs/manipulate-pdfs/watermark-pdfs) and [Stamp PDFs](https://gotenberg.dev/docs/manipulate-pdfs/stamp-pdfs) in the official docs.
421
483
 
422
484
  ```typescript
423
485
  type PdfEngineWatermark = {
424
- source?: "text" | "image" | "pdf";
425
- expression?: string; // Text, or filename of the uploaded asset when source is image or pdf
426
- pages?: string; // Page ranges (e.g. "1-3"); omit for all pages
427
- options?: Record<string, unknown>; // Serialized as JSON (engine-specific)
428
- file?: PathLikeOrReadStream | Buffer; // Required when source is image or pdf
486
+ source?: 'text' | 'image' | 'pdf';
487
+ expression?: string; // Text, or filename of the uploaded asset when source is image or pdf
488
+ pages?: string; // Page ranges (e.g. "1-3"); omit for all pages
489
+ options?: Record<string, unknown>; // Serialized as JSON (engine-specific)
490
+ file?: PathLikeOrReadStream | Buffer; // Required when source is image or pdf
429
491
  };
430
492
 
431
493
  type PdfEngineStamp = {
432
- source?: "text" | "image" | "pdf";
433
- expression?: string;
434
- pages?: string;
435
- options?: Record<string, unknown>;
436
- file?: PathLikeOrReadStream | Buffer;
494
+ source?: 'text' | 'image' | 'pdf';
495
+ expression?: string;
496
+ pages?: string;
497
+ options?: Record<string, unknown>;
498
+ file?: PathLikeOrReadStream | Buffer;
437
499
  };
438
500
  ```
439
501
 
@@ -443,42 +505,41 @@ Similarly, the `capture()` method takes an optional `properties` parameter of th
443
505
 
444
506
  ```typescript
445
507
  type ImageProperties = {
446
- format: "png" | "jpeg" | "webp"; //The image compression format, either "png", "jpeg" or "webp".
447
- quality?: number; // The compression quality from range 0 to 100 (jpeg only).
448
- omitBackground?: boolean; // Hide the default white background and allow generating screenshots with transparency.
449
- width?: number; // The device screen width in pixels (default 800).
450
- height?: number; // The device screen height in pixels (default 600).
451
- clip?: boolean; // Define whether to clip the screenshot according to the device dimensions (default false).
508
+ format: 'png' | 'jpeg' | 'webp'; //The image compression format, either "png", "jpeg" or "webp".
509
+ quality?: number; // The compression quality from range 0 to 100 (jpeg only).
510
+ omitBackground?: boolean; // Hide the default white background and allow generating screenshots with transparency.
511
+ width?: number; // The device screen width in pixels (default 800).
512
+ height?: number; // The device screen height in pixels (default 600).
513
+ clip?: boolean; // Define whether to clip the screenshot according to the device dimensions (default false).
514
+ deviceScaleFactor?: number; // The device scale factor, useful for HiDPI screenshots (default 1).
452
515
  };
453
516
  ```
454
517
 
455
- Furthermore, alongside the customization options offered by `ImageProperties`, the `capture()` method accommodates a variety of parameters to expand the versatility of the screenshot process. Below is a comprehensive overview of all parameters available:
518
+ Furthermore, alongside the customization options offered by `ImageProperties`, the `capture()` method accommodates a variety of parameters to expand the versatility of the screenshot process. Below is a comprehensive overview of all parameters available. Note that screenshots produce an image rather than a PDF, so PDF-only options like `header`/`footer`, `generateDocumentOutline`, `userPassword`/`ownerPassword`, and `embeds` don't apply here.
456
519
 
457
520
  ```typescript
458
521
  type ScreenshotOptions = {
459
- properties?: ImageProperties;
460
- header?: PathLikeOrReadStream;
461
- footer?: PathLikeOrReadStream;
462
- emulatedMediaType?: EmulatedMediaType;
463
- emulatedMediaFeatures?: EmulatedMediaFeature[]; // Override CSS media features (e.g., prefers-color-scheme). Default: None.
464
- waitDelay?: string; // Duration (e.g, '5s') to wait when loading an HTML document before convertion.
465
- waitForExpression?: string; // JavaScript's expression to wait before converting an HTML document into PDF until it returns true.
466
- waitForSelector?: string; // CSS selector to wait for before converting an HTML document into PDF until it matches a node.
467
- extraHttpHeaders?: Record<string, string>;
468
- failOnHttpStatusCodes?: number[]; // Return a 409 Conflict response if the HTTP status code is in the list (default [499,599])
469
- failOnConsoleExceptions?: boolean; // Return a 409 Conflict response if there are exceptions in the Chromium console (default false)
470
- failOnResourceHttpStatusCodes?: number[]; // Return a 409 Conflict response if resource HTTP status code is in the list (default [499,599])
471
- ignoreResourceHttpStatusDomains?: string[]; // Domains to exclude from resource HTTP status code checks (matches exact domains or subdomains)
472
- failOnResourceLoadingFailed?: boolean; // Return a 409 Conflict response if resource loading failed (default false)
473
- skipNetworkIdleEvent?: boolean; // Do not wait for Chromium network to be idle (default true)
474
- skipNetworkAlmostIdleEvent?: boolean; // Do not wait for Chromium network to be almost idle (default true)
475
- optimizeForSpeed?: boolean; // Define whether to optimize image encoding for speed, not for resulting size.
476
- cookies?: Cookie[]; // Cookies to be written.
477
- downloadFrom?: DownloadFrom; // Download files from one or multiple URLs.
478
- webhook?: WebhookOptions; // Request-level webhook headers for async callbacks.
479
- userPassword?: string; // Password for opening the resulting PDF(s).
480
- ownerPassword?: string; // Password for full access on the resulting PDF(s).
481
- embeds?: PathLikeOrReadStream[]; // Files to embed in the generated PDF.
522
+ properties?: ImageProperties;
523
+ userAgent?: string; // Override the User-Agent header sent by Chromium.
524
+ emulatedMediaType?: EmulatedMediaType;
525
+ emulatedMediaFeatures?: EmulatedMediaFeature[]; // Override CSS media features (e.g., prefers-color-scheme). Default: None.
526
+ waitDelay?: string; // Duration (e.g, '5s') to wait when loading an HTML document before convertion.
527
+ waitForExpression?: string; // JavaScript's expression to wait before converting an HTML document into PDF until it returns true.
528
+ waitForSelector?: string; // CSS selector to wait for before converting an HTML document into PDF until it matches a node.
529
+ extraHttpHeaders?: Record<string, string>;
530
+ failOnHttpStatusCodes?: number[]; // Return a 409 Conflict response if the HTTP status code is in the list (default [499,599])
531
+ failOnConsoleExceptions?: boolean; // Return a 409 Conflict response if there are exceptions in the Chromium console (default false)
532
+ failOnResourceHttpStatusCodes?: number[]; // Return a 409 Conflict response if resource HTTP status code is in the list (default None)
533
+ ignoreResourceHttpStatusDomains?: string[]; // Domains to exclude from resource HTTP status code checks (matches exact domains or subdomains)
534
+ failOnResourceLoadingFailed?: boolean; // Return a 409 Conflict response if resource loading failed (default false)
535
+ skipNetworkIdleEvent?: boolean; // Do not wait for Chromium network to be idle (default true)
536
+ skipNetworkAlmostIdleEvent?: boolean; // Do not wait for Chromium network to be almost idle (default true)
537
+ optimizeForSpeed?: boolean; // Define whether to optimize image encoding for speed, not for resulting size.
538
+ cookies?: Cookie[]; // Cookies to be written.
539
+ downloadFrom?: DownloadFrom; // Download files from one or multiple URLs.
540
+ webhook?: WebhookOptions; // Request-level webhook headers for async callbacks.
541
+ outputFilename?: string; // Custom filename for the resulting file; Gotenberg appends the extension.
542
+ trace?: string; // Custom request id to identify the request in the logs, overriding the generated UUID.
482
543
  };
483
544
  ```
484
545
 
@@ -488,21 +549,47 @@ The `LibreOffice` class comes with a single method `convert`. This method intera
488
549
  accepted [here](https://gotenberg.dev/docs/convert-with-libreoffice/convert-to-pdf).
489
550
 
490
551
  ```typescript
491
- import { LibreOffice } from "chromiumly";
552
+ import { LibreOffice } from 'chromiumly';
492
553
 
493
554
  const buffer = await LibreOffice.convert({
494
- files: [
495
- "path/to/file.docx",
496
- "path/to/file.png",
497
- { data: xlsxFileBuffer, ext: "xlsx" },
498
- ],
555
+ files: [
556
+ 'path/to/file.docx',
557
+ 'path/to/file.png',
558
+ { data: xlsxFileBuffer, ext: 'xlsx' }
559
+ ]
499
560
  });
500
561
  ```
501
562
 
502
- Similarly to Chromium's route `convert` method, this method takes the following optional parameters :
563
+ Similarly to Chromium's route `convert` method, this method takes an optional `properties` parameter of the following type, which
564
+ also includes a `password` field to open the source document:
503
565
 
504
- - `properties`: changes how the PDF generated file will look like. It also includes a `password` parameter to open the source file.
505
- - `pdfa`: PDF format of the conversion resulting file (i.e. `PDF/A-1a`, `PDF/A-2b`, `PDF/A-3b`).
566
+ ```typescript
567
+ type PageProperties = {
568
+ password?: string; // Password to open the source document
569
+ landscape?: boolean; // Paper orientation landscape (default false)
570
+ nativePageRanges?: { from: number; to: number }; // Page ranges to print
571
+ exportFormFields?: boolean; // Export form fields as interactive widgets, or false to flatten them during conversion (default true)
572
+ singlePageSheets?: boolean; // Render entire spreadsheet as a single page (default false)
573
+ allowDuplicateFieldNames?: boolean; // Allow multiple form fields with the same name
574
+ exportBookmarks?: boolean; // Export bookmarks to the resulting PDF (default true)
575
+ exportBookmarksToPdfDestination?: boolean; // Export bookmarks as Named Destination in the PDF
576
+ exportPlaceholders?: boolean; // Export placeholder fields' visual markings only
577
+ exportNotes?: boolean; // Export notes to the resulting PDF
578
+ exportNotesPages?: boolean; // Export notes pages (Impress documents only)
579
+ exportOnlyNotesPages?: boolean; // Export only notes pages, when exportNotesPages is true
580
+ exportNotesInMargin?: boolean; // Export notes in the margin of the resulting PDF
581
+ convertOooTargetToPdfTarget?: boolean; // Change .od[tpgs] extensions to .pdf in exported links
582
+ exportLinksRelativeFsys?: boolean; // Export file system related hyperlinks as relative
583
+ exportHiddenSlides?: boolean; // Export hidden slides (Impress documents only)
584
+ skipEmptyPages?: boolean; // Suppress the automatic insertion of blank pages (Writer documents only)
585
+ updateIndexes?: boolean; // Update the document's indexes/table of contents before export (default true)
586
+ addOriginalDocumentAsStream?: boolean; // Insert the original file as a stream in the resulting PDF
587
+ };
588
+ ```
589
+
590
+ In addition to `properties`, the `convert()` method accepts the following optional parameters:
591
+
592
+ - `pdfa`: PDF format of the conversion resulting file (i.e. `PDF/A-1b`, `PDF/A-2b`, `PDF/A-3b`).
506
593
  - `pdfUA`: enables PDF for Universal Access for optimal accessibility.
507
594
  - `merge`: merges all the resulting files from the conversion into an individual PDF file.
508
595
  - `metadata`: writes metadata to the generated PDF file.
@@ -526,29 +613,37 @@ Similarly to Chromium's route `convert` method, this method takes the following
526
613
  - `useTransitionEffects`: use transition effects for Impress slides.
527
614
  - `openBookmarkLevels`: number of bookmark levels opened on load (`-1` opens all levels).
528
615
  - `downloadFrom`: download files remotely (`DownloadFromEntry` or `DownloadFromEntry[]`).
529
- - `flatten`: a boolean that, when set to true, flattens the split PDF files, making form fields and annotations uneditable.
616
+ - `split`: split the resulting PDF into multiple files same shape as Chromium's `split` (`ConvertSplit`, see [PDF Splitting](#pdf-splitting)).
617
+ - `flatten`: a boolean that, when set to true, flattens the resulting PDF's form fields and annotations, making them uneditable.
530
618
  - `userPassword`: password for opening the resulting PDF(s).
531
619
  - `ownerPassword`: password for full access on the resulting PDF(s).
620
+ - `allowPrinting` / `allowCopying` / `allowModifying` / `allowAnnotating` / `allowFillingForms` / `allowAssembling`: PDF permission booleans, each defaulting to `true` — see [PDF Permissions](#pdf-permissions).
532
621
  - `embeds`: files to embed in the generated PDF (repeatable). This feature enables the creation of PDFs compatible with standards like [ZUGFeRD / Factur-X](https://fnfe-mpe.org/factur-x/), which require embedding XML invoices and other files within the PDF.
622
+ - `embedsMetadata`: per-attachment metadata keyed by filename, for PDF/A-3 and Factur-X compliance — see [Embedding Files](#embedding-files).
623
+ - `facturx`: turn the resulting PDF into a Factur-X / ZUGFeRD e-invoice — see [Factur-X / ZUGFeRD](#factur-x--zugferd).
624
+ - `outputFilename` / `trace`: custom output filename and/or request trace id — see [Output Filename and Request Tracing](#output-filename-and-request-tracing).
533
625
  - `webhook`: request-level webhook headers for async callbacks.
534
626
  - **Native LibreOffice watermarks** (applied during export): `nativeWatermarkText`, `nativeWatermarkColor`, `nativeWatermarkFontHeight`, `nativeWatermarkRotateAngle`, `nativeWatermarkFontName`, `nativeTiledWatermarkText` — see [Convert to PDF](https://gotenberg.dev/docs/convert-with-libreoffice/convert-to-pdf).
535
627
  - **PDF-engine watermark/stamp** (post-processing after conversion): `watermark` and `stamp` — same shapes as in Chromium `ConversionOptions` (`PdfEngineWatermark` / `PdfEngineStamp`). For `{ data, ext }` file objects, use the same pattern as in `files`.
628
+ - `rotate`: PDF-engine post-process page rotation — see [PDF Rotation](#pdf-rotation).
536
629
 
537
630
  ### PDF Engines
538
631
 
539
632
  The `PDFEngines` class interacts with Gotenberg's [PDF Engines](https://gotenberg.dev/docs/manipulate-pdfs/pdfa-pdfua) routes to manipulate PDF files.
540
633
 
634
+ Every method below also accepts the optional cross-cutting parameters `downloadFrom`, `webhook`, `outputFilename`, and `trace` (omitted from most examples for brevity). See the `DownloadFrom`/`WebhookOptions` types under [Chromium](#chromium) and [Output Filename and Request Tracing](#output-filename-and-request-tracing).
635
+
541
636
  #### Format Conversion
542
637
 
543
- This method interacts with [PDF Engines](https://gotenberg.dev/docs/manipulate-pdfs/pdfa-pdfua) convertion route to transform PDF files into the requested PDF/A format and/or PDF/UA.
638
+ This method interacts with [PDF Engines](https://gotenberg.dev/docs/manipulate-pdfs/pdfa-pdfua) convertion route to transform PDF files into the requested PDF/A format and/or PDF/UA. At least one of `pdfa` or `pdfUA` must be provided.
544
639
 
545
640
  ```typescript
546
- import { PDFEngines } from "chromiumly";
641
+ import { PDFEngines } from 'chromiumly';
547
642
 
548
643
  const buffer = await PDFEngines.convert({
549
- files: ["path/to/file_1.pdf", "path/to/file_2.pdf"],
550
- pdfa: PdfFormat.A_2b,
551
- pdfUA: true,
644
+ files: ['path/to/file_1.pdf', 'path/to/file_2.pdf'],
645
+ pdfa: PdfFormat.A_2b,
646
+ pdfUA: true
552
647
  });
553
648
  ```
554
649
 
@@ -560,15 +655,28 @@ as: [PDFtk](https://gitlab.com/pdftk-java/pdftk), [PDFcpu](https://github.com/pd
560
655
  and [UNO](https://github.com/unoconv/unoconv).
561
656
 
562
657
  ```typescript
563
- import { PDFEngines } from "chromiumly";
658
+ import { PDFEngines } from 'chromiumly';
564
659
 
565
660
  const buffer = await PDFEngines.merge({
566
- files: ["path/to/file_1.pdf", "path/to/file_2.pdf"],
567
- pdfa: PdfFormat.A_2b,
568
- pdfUA: true,
661
+ files: ['path/to/file_1.pdf', 'path/to/file_2.pdf'],
662
+ pdfa: PdfFormat.A_2b,
663
+ pdfUA: true,
664
+ metadata: { Author: 'Taha Cherfia' },
665
+ flatten: true,
666
+ bookmarks: [{ title: 'Section 1', page: 1 }],
667
+ autoIndexBookmarks: false, // auto-extract and offset each input's existing bookmarks (default false)
668
+ userPassword: 'my_user_password',
669
+ ownerPassword: 'my_owner_password',
670
+ allowPrinting: false
569
671
  });
570
672
  ```
571
673
 
674
+ Optional `metadata` writes metadata to the merged PDF, and `flatten` flattens its form fields and annotations, both matching [Merge PDFs](https://gotenberg.dev/docs/manipulate-pdfs/merge-pdfs) in the Gotenberg docs.
675
+
676
+ Optional `bookmarks` sets a final bookmark list on the merged PDF, or a filename-keyed map applied to each input before merging (its page indexes get offset automatically). Optional `autoIndexBookmarks` instead auto-extracts and offsets each input's existing bookmarks. `bookmarks` and `autoIndexBookmarks` are mutually exclusive strategies for populating the merged PDF's outline.
677
+
678
+ Optional `userPassword`/`ownerPassword` and the six permission booleans (`allowPrinting`, `allowCopying`, `allowModifying`, `allowAnnotating`, `allowFillingForms`, `allowAssembling`) encrypt the merged output — see [PDF Encryption](#pdf-encryption) and [PDF Permissions](#pdf-permissions).
679
+
572
680
  Optional `watermark` and `stamp` (`PdfEngineWatermark` / `PdfEngineStamp`) apply PDF-engine post-processing to the merged output, matching [Merge PDFs](https://gotenberg.dev/docs/manipulate-pdfs/merge-pdfs) in the Gotenberg docs.
573
681
 
574
682
  Optional `rotate` (`{ angle: 90 | 180 | 270; pages?: string }`) rotates pages after merge via the PDF engine; omit `pages` or leave it empty to rotate all pages.
@@ -578,12 +686,12 @@ Optional `rotate` (`{ angle: 90 | 180 | 270; pages?: string }`) rotates pages af
578
686
  `PDFEngines.rotate()` calls Gotenberg’s [rotate route](https://gotenberg.dev/docs/manipulate-pdfs/rotate-pdfs) to rotate existing PDFs. The same post-processing is available on `PDFEngines.merge()`, `PDFEngines.split()`, and on Chromium and LibreOffice `convert()` through the optional `rotate` property (Gotenberg generates the PDF, then rotates selected pages—an extra pass).
579
687
 
580
688
  ```typescript
581
- import { PDFEngines } from "chromiumly";
689
+ import { PDFEngines } from 'chromiumly';
582
690
 
583
691
  const rotated = await PDFEngines.rotate({
584
- files: ["path/to/document.pdf"],
585
- angle: 90,
586
- pages: "1-3", // optional; omit for all pages
692
+ files: ['path/to/document.pdf'],
693
+ angle: 90,
694
+ pages: '1-3' // optional; omit for all pages
587
695
  });
588
696
  ```
589
697
 
@@ -592,24 +700,24 @@ const rotated = await PDFEngines.rotate({
592
700
  These methods call [`/forms/pdfengines/watermark`](https://gotenberg.dev/docs/manipulate-pdfs/watermark-pdfs) and [`/forms/pdfengines/stamp`](https://gotenberg.dev/docs/manipulate-pdfs/stamp-pdfs).
593
701
 
594
702
  ```typescript
595
- import { PDFEngines } from "chromiumly";
703
+ import { PDFEngines } from 'chromiumly';
596
704
 
597
705
  const watermarked = await PDFEngines.watermark({
598
- files: ["path/to/document.pdf"],
599
- watermark: {
600
- source: "text",
601
- expression: "CONFIDENTIAL",
602
- options: { opacity: 0.25, rotation: 45 },
603
- },
706
+ files: ['path/to/document.pdf'],
707
+ watermark: {
708
+ source: 'text',
709
+ expression: 'CONFIDENTIAL',
710
+ options: { opacity: 0.25, rotation: 45 }
711
+ }
604
712
  });
605
713
 
606
714
  const stamped = await PDFEngines.stamp({
607
- files: ["path/to/document.pdf"],
608
- stamp: {
609
- source: "text",
610
- expression: "APPROVED",
611
- options: { opacity: 0.5, rotation: 0 },
612
- },
715
+ files: ['path/to/document.pdf'],
716
+ stamp: {
717
+ source: 'text',
718
+ expression: 'APPROVED',
719
+ options: { opacity: 0.5, rotation: 0 }
720
+ }
613
721
  });
614
722
  ```
615
723
 
@@ -620,12 +728,12 @@ const stamped = await PDFEngines.stamp({
620
728
  This method reads metadata from the provided PDF files.
621
729
 
622
730
  ```typescript
623
- import { PDFEngines } from "chromiumly";
731
+ import { PDFEngines } from 'chromiumly';
624
732
 
625
- const metadataBuffer = await PDFEngines.readMetadata([
626
- "path/to/file_1.pdf",
627
- "path/to/file_2.pdf",
628
- ]);
733
+ const metadataBuffer = await PDFEngines.readMetadata({
734
+ files: ['path/to/file_1.pdf'],
735
+ downloadFrom: [{ url: 'https://cdn.example.com/file.pdf' }] // optional: read metadata from a remote PDF
736
+ });
629
737
  ```
630
738
 
631
739
  ##### writeMetadata
@@ -633,15 +741,15 @@ const metadataBuffer = await PDFEngines.readMetadata([
633
741
  This method writes metadata to the provided PDF files.
634
742
 
635
743
  ```typescript
636
- import { PDFEngines } from "chromiumly";
744
+ import { PDFEngines } from 'chromiumly';
637
745
 
638
746
  const buffer = await PDFEngines.writeMetadata({
639
- files: ["path/to/file_1.pdf", "path/to/file_2.pdf"],
640
- metadata: {
641
- Author: "Taha Cherfia",
642
- Title: "Chromiumly",
643
- Keywords: ["pdf", "html", "gotenberg"],
644
- },
747
+ files: ['path/to/file_1.pdf', 'path/to/file_2.pdf'],
748
+ metadata: {
749
+ Author: 'Taha Cherfia',
750
+ Title: 'Chromiumly',
751
+ Keywords: ['pdf', 'html', 'gotenberg']
752
+ }
645
753
  });
646
754
  ```
647
755
 
@@ -654,11 +762,11 @@ Please consider referring to [ExifTool](https://exiftool.org/TagNames/XMP.html#p
654
762
  This method reads bookmarks (outline / table of contents) from the provided PDF files.
655
763
 
656
764
  ```typescript
657
- import { PDFEngines } from "chromiumly";
765
+ import { PDFEngines } from 'chromiumly';
658
766
 
659
767
  const bookmarks = await PDFEngines.readBookmarks([
660
- "path/to/file_1.pdf",
661
- "path/to/file_2.pdf",
768
+ 'path/to/file_1.pdf',
769
+ 'path/to/file_2.pdf'
662
770
  ]);
663
771
  ```
664
772
 
@@ -667,20 +775,78 @@ const bookmarks = await PDFEngines.readBookmarks([
667
775
  This method writes bookmarks to the provided PDF files.
668
776
 
669
777
  ```typescript
670
- import { PDFEngines } from "chromiumly";
778
+ import { PDFEngines } from 'chromiumly';
671
779
 
672
780
  const updated = await PDFEngines.writeBookmarks({
673
- files: ["path/to/file_1.pdf"],
674
- bookmarks: [
675
- {
676
- title: "Chapter 1",
677
- page: 1,
678
- children: [],
679
- },
680
- ],
781
+ files: ['path/to/file_1.pdf'],
782
+ bookmarks: [
783
+ {
784
+ title: 'Chapter 1',
785
+ page: 1,
786
+ children: []
787
+ }
788
+ ]
789
+ });
790
+ ```
791
+
792
+ #### Encryption (dedicated route)
793
+
794
+ `PDFEngines.encrypt()` calls Gotenberg's [encrypt route](https://gotenberg.dev/docs/manipulate-pdfs/encrypt-pdfs) to encrypt existing PDFs directly, without going through a conversion. At least one of `userPassword` or `ownerPassword` is required; since Gotenberg 8.34.0, an owner-password-only request produces an owner-only PDF that opens without a password but still enforces the given permissions.
795
+
796
+ ```typescript
797
+ import { PDFEngines } from 'chromiumly';
798
+
799
+ const encrypted = await PDFEngines.encrypt({
800
+ files: ['path/to/document.pdf'],
801
+ options: {
802
+ userPassword: 'my_user_password',
803
+ ownerPassword: 'my_owner_password',
804
+ allowPrinting: false,
805
+ allowCopying: false
806
+ }
807
+ });
808
+ ```
809
+
810
+ See [PDF Encryption](#pdf-encryption) and [PDF Permissions](#pdf-permissions) for the full set of encryption and permission fields, also available on Chromium and LibreOffice `convert()`, and on `PDFEngines.merge()`/`PDFEngines.split()`.
811
+
812
+ #### Embedding Files (dedicated route)
813
+
814
+ `PDFEngines.embed()` calls Gotenberg's [embed route](https://gotenberg.dev/docs/manipulate-pdfs/attachments) to attach files to existing PDFs directly, without going through a conversion.
815
+
816
+ ```typescript
817
+ import { PDFEngines } from 'chromiumly';
818
+
819
+ const embedded = await PDFEngines.embed({
820
+ files: ['path/to/document.pdf'],
821
+ embeds: ['path/to/invoice.xml', 'path/to/logo.png'],
822
+ embedsMetadata: {
823
+ 'invoice.xml': { mimeType: 'text/xml', relationship: 'Data' }
824
+ }
681
825
  });
682
826
  ```
683
827
 
828
+ See [Embedding Files](#embedding-files) for the `embedsMetadata` shape, also available on Chromium and LibreOffice `convert()`.
829
+
830
+ #### Factur-X / ZUGFeRD (dedicated route)
831
+
832
+ `PDFEngines.facturX()` calls Gotenberg's [Factur-X route](https://gotenberg.dev/docs/manipulate-pdfs/factur-x) to turn existing PDFs into Factur-X / ZUGFeRD e-invoices directly, without going through a conversion: it embeds the CII invoice XML under the canonical `factur-x.xml` name and converts the PDF to PDF/A-3.
833
+
834
+ ```typescript
835
+ import { PDFEngines } from 'chromiumly';
836
+
837
+ const invoice = await PDFEngines.facturX({
838
+ files: ['path/to/document.pdf'],
839
+ facturx: {
840
+ facturxXml: 'path/to/invoice.xml',
841
+ facturxConformanceLevel: 'EN 16931',
842
+ facturxDocumentType: 'INVOICE', // optional, defaults to 'INVOICE'
843
+ facturxVersion: '1.0' // optional, defaults to '1.0'
844
+ }
845
+ });
846
+ ```
847
+
848
+ See [Factur-X / ZUGFeRD](#factur-x--zugferd) for the full `facturx` field shape, also available on Chromium and LibreOffice `convert()`.
849
+
684
850
  #### File Generation
685
851
 
686
852
  It is just a generic complementary method that takes the `buffer` returned by the `convert` method, and a
@@ -690,41 +856,46 @@ Please note that all the PDF files can be found `__generated__` folder in the ro
690
856
 
691
857
  ### PDF Splitting
692
858
 
693
- Each [Chromium](#chromium) and [LibreOffice](#libreoffice) route has a `split` parameter that allows splitting the PDF file into multiple files. The `split` parameter is an object with the following properties:
859
+ Each [Chromium](#chromium) and [LibreOffice](#libreoffice) route has a `split` parameter (type `ConvertSplit`) that allows splitting the resulting PDF into multiple files:
694
860
 
695
861
  - `mode`: the mode of the split. It can be `pages` or `intervals`.
696
862
  - `span`: the span of the split. It is a string that represents the range of pages to split.
697
863
  - `unify`: a boolean that allows unifying the split files. Only works when `mode` is `pages`.
698
- - `flatten`: a boolean that, when set to true, flattens the split PDF files, making form fields and annotations uneditable.
864
+
865
+ Note that `flatten` is a separate top-level parameter on these routes (see [PDF Flattening](#pdf-flattening)), not part of `split` itself.
699
866
 
700
867
  ```typescript
701
- import { UrlConverter } from "chromiumly";
868
+ import { UrlConverter } from 'chromiumly';
702
869
  const buffer = await UrlConverter.convert({
703
- url: "https://www.example.com/",
704
- split: {
705
- mode: "pages",
706
- span: "1-2",
707
- unify: true,
708
- },
870
+ url: 'https://www.example.com/',
871
+ split: {
872
+ mode: 'pages',
873
+ span: '1-2',
874
+ unify: true
875
+ }
709
876
  });
710
877
  ```
711
878
 
712
- On the other hand, PDFEngines' has a `split` method that interacts with [PDF Engines](https://gotenberg.dev/docs/manipulate-pdfs/split-pdfs) split route which splits PDF files into multiple files.
879
+ On the other hand, PDFEngines' has a `split` method that interacts with [PDF Engines](https://gotenberg.dev/docs/manipulate-pdfs/split-pdfs) split route which splits PDF files into multiple files. Here, `options.flatten` is part of the split configuration itself, rather than a separate top-level field:
713
880
 
714
881
  ```typescript
715
- import { PDFEngines } from "chromiumly";
882
+ import { PDFEngines } from 'chromiumly';
716
883
 
717
884
  const buffer = await PDFEngines.split({
718
- files: ["path/to/file_1.pdf", "path/to/file_2.pdf"],
719
- options: {
720
- mode: "pages",
721
- span: "1-2",
722
- unify: true,
723
- },
885
+ files: ['path/to/file_1.pdf', 'path/to/file_2.pdf'],
886
+ options: {
887
+ mode: 'pages',
888
+ span: '1-2',
889
+ unify: true,
890
+ flatten: true
891
+ },
892
+ metadata: { Author: 'Taha Cherfia' },
893
+ pdfa: PdfFormat.A_2b,
894
+ userPassword: 'my_user_password'
724
895
  });
725
896
  ```
726
897
 
727
- `PDFEngines.split` also accepts optional `watermark`, `stamp`, and `rotate` for the same PDF-engine post-processing as merge.
898
+ `PDFEngines.split` also accepts optional `metadata`, `pdfa`/`pdfUA`, `userPassword`/`ownerPassword` and the six permission booleans (see [PDF Permissions](#pdf-permissions)), and `watermark`, `stamp`, and `rotate` for the same PDF-engine post-processing as merge.
728
899
 
729
900
  > ⚠️ **Note**: Gotenberg does not currently validate the `span` value when `mode` is set to `pages`, as the validation depends on the chosen engine for the split feature. See [PDF Engines module configuration](https://gotenberg.dev/docs/configuration#pdf-engines) for more details.
730
901
 
@@ -733,28 +904,58 @@ const buffer = await PDFEngines.split({
733
904
  PDF flattening converts interactive elements like forms and annotations into a static PDF. This ensures the document looks the same everywhere and prevents further edits.
734
905
 
735
906
  ```typescript
736
- import { PDFEngines } from "chromiumly";
907
+ import { PDFEngines } from 'chromiumly';
737
908
 
738
909
  const buffer = await PDFEngines.flatten([
739
- "path/to/file_1.pdf",
740
- "path/to/file_2.pdf",
910
+ 'path/to/file_1.pdf',
911
+ 'path/to/file_2.pdf'
741
912
  ]);
742
913
  ```
743
914
 
744
915
  ### PDF Encryption
745
916
 
746
- Each [Chromium](#chromium) and [LibreOffice](#libreoffice) route supports PDF encryption through the `userPassword` and `ownerPassword` parameters. The `userPassword` is required to open the PDF, while the `ownerPassword` provides full access permissions.
917
+ Each [Chromium](#chromium) and [LibreOffice](#libreoffice) route, as well as `PDFEngines.merge()` and `PDFEngines.split()`, supports PDF encryption through the `userPassword` and `ownerPassword` parameters. The `userPassword` is required to open the PDF, while the `ownerPassword` provides full access permissions.
747
918
 
748
919
  ```typescript
749
- import { UrlConverter } from "chromiumly";
920
+ import { UrlConverter } from 'chromiumly';
750
921
 
751
922
  const buffer = await UrlConverter.convert({
752
- url: "https://www.example.com/",
753
- userPassword: "my_user_password",
754
- ownerPassword: "my_owner_password",
923
+ url: 'https://www.example.com/',
924
+ userPassword: 'my_user_password',
925
+ ownerPassword: 'my_owner_password'
755
926
  });
756
927
  ```
757
928
 
929
+ There's also a dedicated `PDFEngines.encrypt()` route for encrypting existing PDFs directly — see [Encryption (dedicated route)](#encryption-dedicated-route). Unlike the routes above, it requires at least one of `userPassword` or `ownerPassword`, and (since Gotenberg 8.34.0) allows an owner-password-only PDF that opens without a password but still enforces permissions.
930
+
931
+ ### PDF Permissions
932
+
933
+ Each route in [PDF Encryption](#pdf-encryption) above also accepts six permission booleans, all defaulting to `true`:
934
+
935
+ ```typescript
936
+ type PdfEnginePermissions = {
937
+ allowPrinting?: boolean; // Allow printing the document
938
+ allowCopying?: boolean; // Allow copying content from the document
939
+ allowModifying?: boolean; // Allow modifying the document
940
+ allowAnnotating?: boolean; // Allow adding or modifying annotations
941
+ allowFillingForms?: boolean; // Allow filling in form fields
942
+ allowAssembling?: boolean; // Allow document assembly, e.g. inserting, deleting, or rotating pages
943
+ };
944
+ ```
945
+
946
+ ```typescript
947
+ import { UrlConverter } from 'chromiumly';
948
+
949
+ const buffer = await UrlConverter.convert({
950
+ url: 'https://www.example.com/',
951
+ ownerPassword: 'my_owner_password',
952
+ allowPrinting: false,
953
+ allowCopying: false
954
+ });
955
+ ```
956
+
957
+ Permission enforcement depends on the active PDF engine: QPDF honors each permission individually, pdfcpu restricts all permissions if any one is denied, and PDFtk supports neither owner-only encryption nor permission restrictions. Restrictions are advisory: PDF viewers honor them, but they aren't cryptographically enforced once the document opens.
958
+
758
959
  ### Embedding Files
759
960
 
760
961
  Each [Chromium](#chromium) and [LibreOffice](#libreoffice) route supports embedding files into the generated PDF through the `embeds` parameter. This feature enables the creation of PDFs compatible with standards like [ZUGFeRD / Factur-X](https://fnfe-mpe.org/factur-x/), which require embedding XML invoices and other files within the PDF.
@@ -762,21 +963,115 @@ Each [Chromium](#chromium) and [LibreOffice](#libreoffice) route supports embedd
762
963
  You can embed multiple files by passing an array of file paths, buffers, or read streams:
763
964
 
764
965
  ```typescript
765
- import { HtmlConverter } from "chromiumly";
966
+ import { HtmlConverter } from 'chromiumly';
766
967
 
767
968
  const htmlConverter = new HtmlConverter();
768
969
  const buffer = await htmlConverter.convert({
769
- html: "path/to/index.html",
770
- embeds: [
771
- "path/to/invoice.xml",
772
- "path/to/logo.png",
773
- Buffer.from("additional data"),
774
- ],
970
+ html: 'path/to/index.html',
971
+ embeds: [
972
+ 'path/to/invoice.xml',
973
+ 'path/to/logo.png',
974
+ Buffer.from('additional data')
975
+ ]
775
976
  });
776
977
  ```
777
978
 
778
979
  All embedded files will be attached to the generated PDF and can be extracted using PDF readers that support file attachments.
779
980
 
981
+ Optional `embedsMetadata` sets per-attachment metadata, keyed by filename, required for PDF/A-3 and Factur-X compliance:
982
+
983
+ ```typescript
984
+ type EmbedsMetadata = Record<
985
+ string, // filename, matching an entry in `embeds`
986
+ {
987
+ mimeType?: string; // Written to the embedded file stream's /Subtype
988
+ relationship?:
989
+ | 'Source'
990
+ | 'Data'
991
+ | 'Alternative'
992
+ | 'Supplement'
993
+ | 'Unspecified'; // The /AFRelationship value
994
+ }
995
+ >;
996
+ ```
997
+
998
+ ```typescript
999
+ const buffer = await htmlConverter.convert({
1000
+ html: 'path/to/index.html',
1001
+ embeds: ['path/to/invoice.xml'],
1002
+ embedsMetadata: {
1003
+ 'invoice.xml': { mimeType: 'text/xml', relationship: 'Data' }
1004
+ }
1005
+ });
1006
+ ```
1007
+
1008
+ There's also a dedicated `PDFEngines.embed()` route for attaching files to existing PDFs directly — see [Embedding Files (dedicated route)](#embedding-files-dedicated-route).
1009
+
1010
+ ### Factur-X / ZUGFeRD
1011
+
1012
+ Each [Chromium](#chromium) and [LibreOffice](#libreoffice) route supports turning the resulting PDF into a [Factur-X / ZUGFeRD](https://fnfe-mpe.org/factur-x/) e-invoice through the `facturx` parameter, which embeds the CII invoice XML under the canonical `factur-x.xml` name and converts the PDF to PDF/A-3:
1013
+
1014
+ ```typescript
1015
+ type FacturXOptions = {
1016
+ facturxXml: PathLikeOrReadStream; // The Factur-X CII invoice XML; embedded as factur-x.xml regardless of the given filename.
1017
+ facturxConformanceLevel:
1018
+ | 'MINIMUM'
1019
+ | 'BASIC WL'
1020
+ | 'BASIC'
1021
+ | 'EN 16931'
1022
+ | 'EXTENDED'
1023
+ | 'XRECHNUNG';
1024
+ facturxDocumentType?: 'INVOICE' | 'ORDER' | 'ORDER_RESPONSE' | 'ORDER_CHANGE'; // Defaults to 'INVOICE'.
1025
+ facturxVersion?: string; // Defaults to '1.0'.
1026
+ pdfa?: 'PDF/A-3a' | 'PDF/A-3b' | 'PDF/A-3u';
1027
+ pdfUA?: boolean;
1028
+ };
1029
+ ```
1030
+
1031
+ ```typescript
1032
+ import { HtmlConverter } from 'chromiumly';
1033
+
1034
+ const htmlConverter = new HtmlConverter();
1035
+ const buffer = await htmlConverter.convert({
1036
+ html: 'path/to/index.html',
1037
+ facturx: {
1038
+ facturxXml: 'path/to/invoice.xml',
1039
+ facturxConformanceLevel: 'EN 16931'
1040
+ }
1041
+ });
1042
+ ```
1043
+
1044
+ There's also a dedicated `PDFEngines.facturX()` route for turning existing PDFs into Factur-X e-invoices directly — see [Factur-X / ZUGFeRD (dedicated route)](#factur-x--zugferd-dedicated-route).
1045
+
1046
+ ### Output Filename and Request Tracing
1047
+
1048
+ Every route accepts optional `outputFilename` and `trace` parameters, mapping to the `Gotenberg-Output-Filename` and `Gotenberg-Trace` request headers:
1049
+
1050
+ ```typescript
1051
+ type OutputOptions = {
1052
+ outputFilename?: string; // Custom filename for the resulting file; Gotenberg appends the extension.
1053
+ trace?: string; // Custom request id to identify the request in the logs, overriding the generated UUID.
1054
+ };
1055
+ ```
1056
+
1057
+ ```typescript
1058
+ import { UrlConverter } from 'chromiumly';
1059
+
1060
+ const buffer = await UrlConverter.convert({
1061
+ url: 'https://www.example.com/',
1062
+ outputFilename: 'my-document',
1063
+ trace: 'my-correlation-id'
1064
+ });
1065
+ ```
1066
+
1067
+ The [System](#system) routes accept `trace` too (there's no resulting file, so no `outputFilename`):
1068
+
1069
+ ```typescript
1070
+ import { System } from 'chromiumly';
1071
+
1072
+ const health = await System.getHealth('my-correlation-id');
1073
+ ```
1074
+
780
1075
  ### Templates (hosted API only)
781
1076
 
782
1077
  The `Templates` class is **not** part of open‑source Gotenberg. It generates PDFs from structured payloads on the Chromiumly hosted API and **requires `CHROMIUMLY_API_KEY`**. Hosted API features (including `Templates`) were introduced in `chromiumly@5.0.0` and require Chromiumly `5.0.0+`—pointing Chromiumly at `GOTENBERG_ENDPOINT` (self‑hosted Gotenberg) will not enable this feature.
@@ -794,48 +1089,48 @@ The following template types are currently available:
794
1089
  #### Basic Usage
795
1090
 
796
1091
  ```typescript
797
- import { Templates } from "chromiumly";
1092
+ import { Templates } from 'chromiumly';
798
1093
 
799
1094
  const templates = new Templates();
800
1095
  const buffer = await templates.generate({
801
- type: "invoice_saas",
802
- data: {
803
- invoiceNumber: "INV-319",
804
- createdDate: "2026-03-19",
805
- dueDate: "2026-04-02",
806
- companyLogo: "https://cdn.acmecloud.com/assets/logo-mark.png",
807
- sender: {
808
- name: "Acme Cloud LLC",
809
- addressLine1: "450 Madison Ave",
810
- addressLine2: "New York, NY 10022",
811
- },
812
- receiver: {
813
- name: "Northwind Health Inc.",
814
- addressLine1: "221 Harbor Blvd",
815
- addressLine2: "San Diego, CA 92101",
816
- },
817
- items: [
818
- {
819
- description: "Platform Subscription (Annual)",
820
- qty: 1,
821
- unitPrice: "1500.00",
822
- amount: "1500.00",
823
- },
824
- {
825
- description: "Onboarding",
826
- qty: 1,
827
- unitPrice: "300.00",
828
- amount: "300.00",
829
- },
830
- ],
831
- currency: "USD",
832
- subTotal: "1800.00",
833
- taxRate: 8.25,
834
- taxAmount: "148.50",
835
- total: "1948.50",
836
- footerNote: "Payment due in 14 days.",
837
- footerDisclaimer: "Late fees may apply.",
838
- },
1096
+ type: 'invoice_saas',
1097
+ data: {
1098
+ invoiceNumber: 'INV-319',
1099
+ createdDate: '2026-03-19',
1100
+ dueDate: '2026-04-02',
1101
+ companyLogo: 'https://cdn.acmecloud.com/assets/logo-mark.png',
1102
+ sender: {
1103
+ name: 'Acme Cloud LLC',
1104
+ addressLine1: '450 Madison Ave',
1105
+ addressLine2: 'New York, NY 10022'
1106
+ },
1107
+ receiver: {
1108
+ name: 'Northwind Health Inc.',
1109
+ addressLine1: '221 Harbor Blvd',
1110
+ addressLine2: 'San Diego, CA 92101'
1111
+ },
1112
+ items: [
1113
+ {
1114
+ description: 'Platform Subscription (Annual)',
1115
+ qty: 1,
1116
+ unitPrice: '1500.00',
1117
+ amount: '1500.00'
1118
+ },
1119
+ {
1120
+ description: 'Onboarding',
1121
+ qty: 1,
1122
+ unitPrice: '300.00',
1123
+ amount: '300.00'
1124
+ }
1125
+ ],
1126
+ currency: 'USD',
1127
+ subTotal: '1800.00',
1128
+ taxRate: 8.25,
1129
+ taxAmount: '148.50',
1130
+ total: '1948.50',
1131
+ footerNote: 'Payment due in 14 days.',
1132
+ footerDisclaimer: 'Late fees may apply.'
1133
+ }
839
1134
  });
840
1135
  ```
841
1136
 
@@ -851,44 +1146,52 @@ const buffer = await templates.generate(request, { validate: true });
851
1146
 
852
1147
  ```typescript
853
1148
  type TemplateRequest<TType extends TemplateType> = {
854
- type: TType;
855
- data: TemplateDataByType[TType];
1149
+ type: TType;
1150
+ data: TemplateDataByType[TType];
856
1151
  };
857
1152
 
858
1153
  interface InvoiceSaasTemplateData {
859
- invoiceNumber: string;
860
- createdDate: string;
861
- dueDate: string;
862
- companyLogo: string;
863
- sender: TemplateParty;
864
- receiver: TemplateParty;
865
- items: InvoiceItem[];
866
- currency: Currency;
867
- subTotal: string;
868
- taxRate: number;
869
- taxAmount: string;
870
- total: string;
871
- footerNote: string;
872
- footerDisclaimer: string;
1154
+ invoiceNumber: string;
1155
+ createdDate: string;
1156
+ dueDate: string;
1157
+ companyLogo?: string;
1158
+ sender: TemplateParty;
1159
+ receiver: TemplateParty;
1160
+ items: InvoiceItem[];
1161
+ currency: Currency;
1162
+ subTotal: string;
1163
+ taxRate: number;
1164
+ taxAmount: string;
1165
+ total: string;
1166
+ footerNote: string;
1167
+ footerDisclaimer?: string;
1168
+ }
1169
+
1170
+ // invoice_classic uses this variant instead, where companyLogo is required.
1171
+ interface InvoiceClassicTemplateData
1172
+ extends Omit<InvoiceSaasTemplateData, 'companyLogo'> {
1173
+ companyLogo: string;
873
1174
  }
874
1175
 
875
1176
  interface TemplateParty {
876
- name: string;
877
- addressLine1: string;
878
- addressLine2: string;
879
- tax?: string;
880
- iban?: string;
881
- bic?: string;
1177
+ name: string;
1178
+ addressLine1: string;
1179
+ addressLine2?: string;
1180
+ tax?: string;
1181
+ iban?: string;
1182
+ bic?: string;
882
1183
  }
883
1184
 
884
1185
  interface InvoiceItem {
885
- description: string;
886
- qty: number;
887
- unitPrice: string;
888
- amount: string;
1186
+ description: string;
1187
+ qty: number;
1188
+ unitPrice: string;
1189
+ amount: string;
889
1190
  }
890
1191
  ```
891
1192
 
1193
+ `invoice_saas`, `invoice_freelancer`, `invoice_minimal`, and `invoice_modern` all use `InvoiceSaasTemplateData`; `invoice_classic` uses `InvoiceClassicTemplateData`, the only variant where `companyLogo` is required.
1194
+
892
1195
  The `currency` field accepts any [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217) currency code exported as the `Currency` type (e.g. `"USD"`, `"EUR"`, `"GBP"`).
893
1196
 
894
1197
  ### Watermark and stamp
@@ -907,16 +1210,17 @@ For image or PDF sources, set `source` to `image` or `pdf`, set `expression` to
907
1210
 
908
1211
  ### System
909
1212
 
910
- The `System` class exposes Gotenberg system endpoints:
1213
+ The `System` class exposes Gotenberg system endpoints. Every method accepts an optional `trace` argument (custom request id, mapped to the `Gotenberg-Trace` header — see [Output Filename and Request Tracing](#output-filename-and-request-tracing)):
911
1214
 
912
1215
  ```typescript
913
- import { System } from "chromiumly";
1216
+ import { System } from 'chromiumly';
914
1217
 
915
1218
  const health = await System.getHealth(); // GET /health
916
1219
  const heartbeat = await System.headHealth(); // HEAD /health
917
1220
  const version = await System.getVersion(); // GET /version
918
1221
  const debug = await System.getDebug(); // GET /debug
919
1222
  const metrics = await System.getPrometheusMetrics(); // GET /prometheus/metrics
1223
+ const tracedHealth = await System.getHealth('my-correlation-id');
920
1224
  ```
921
1225
 
922
1226
  ## Snippet
@@ -924,37 +1228,36 @@ const metrics = await System.getPrometheusMetrics(); // GET /prometheus/metrics
924
1228
  The following is a short snippet of how to use the library.
925
1229
 
926
1230
  ```typescript
927
- import { PDFEngines, UrlConverter } from "chromiumly";
1231
+ import { PDFEngines, UrlConverter } from 'chromiumly';
928
1232
 
929
1233
  async function run() {
930
- const urlConverter = new UrlConverter();
931
- const buffer = await urlConverter.convert({
932
- url: "https://gotenberg.dev/",
933
- properties: {
934
- singlePage: true,
935
- size: {
936
- width: 8.5,
937
- height: 11,
938
- },
939
- },
940
- emulatedMediaType: "screen",
941
- emulatedMediaFeatures: [
942
- { name: "prefers-color-scheme", value: "dark" },
943
- { name: "prefers-reduced-motion", value: "reduce" },
944
- ],
945
- failOnHttpStatusCodes: [404],
946
- failOnConsoleExceptions: true,
947
- skipNetworkIdleEvent: false,
948
- skipNetworkAlmostIdleEvent: false,
949
- optimizeForSpeed: true,
950
- split: {
951
- mode: "pages",
952
- span: "1-2",
953
- unify: true,
954
- },
955
- });
956
-
957
- await PDFEngines.generate("gotenberg.pdf", buffer);
1234
+ const urlConverter = new UrlConverter();
1235
+ const buffer = await urlConverter.convert({
1236
+ url: 'https://gotenberg.dev/',
1237
+ properties: {
1238
+ singlePage: true,
1239
+ size: {
1240
+ width: 8.5,
1241
+ height: 11
1242
+ }
1243
+ },
1244
+ emulatedMediaType: 'screen',
1245
+ emulatedMediaFeatures: [
1246
+ { name: 'prefers-color-scheme', value: 'dark' },
1247
+ { name: 'prefers-reduced-motion', value: 'reduce' }
1248
+ ],
1249
+ failOnHttpStatusCodes: [404],
1250
+ failOnConsoleExceptions: true,
1251
+ skipNetworkIdleEvent: false,
1252
+ skipNetworkAlmostIdleEvent: false,
1253
+ split: {
1254
+ mode: 'pages',
1255
+ span: '1-2',
1256
+ unify: true
1257
+ }
1258
+ });
1259
+
1260
+ await PDFEngines.generate('gotenberg.pdf', buffer);
958
1261
  }
959
1262
 
960
1263
  run();