chromiumly 2.1.0 → 2.3.1
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.
- package/README.md +1 -0
- package/dist/chromium/converters/html.converter.d.ts +12 -4
- package/dist/chromium/converters/html.converter.js +18 -16
- package/dist/chromium/converters/html.converter.js.map +1 -1
- package/dist/chromium/converters/markdown.converter.d.ts +12 -4
- package/dist/chromium/converters/markdown.converter.js +20 -18
- package/dist/chromium/converters/markdown.converter.js.map +1 -1
- package/dist/chromium/converters/url.converter.d.ts +14 -4
- package/dist/chromium/converters/url.converter.js +18 -16
- package/dist/chromium/converters/url.converter.js.map +1 -1
- package/dist/chromium/interfaces/converter.types.d.ts +18 -0
- package/dist/chromium/utils/converter.utils.d.ts +2 -1
- package/dist/chromium/utils/converter.utils.js +44 -0
- package/dist/chromium/utils/converter.utils.js.map +1 -1
- package/dist/common/gotenberg.utils.js.map +1 -1
- package/dist/gotenberg.js.map +1 -1
- package/dist/libre-office/utils/libre-office.utils.js +7 -12
- package/dist/libre-office/utils/libre-office.utils.js.map +1 -1
- package/dist/pdf-engines/pdf.engine.d.ts +2 -1
- package/dist/pdf-engines/pdf.engine.js +5 -2
- package/dist/pdf-engines/pdf.engine.js.map +1 -1
- package/dist/pdf-engines/utils/engine.utils.js +7 -12
- package/dist/pdf-engines/utils/engine.utils.js.map +1 -1
- package/package.json +30 -14
- package/src/chromium/converters/html.converter.ts +43 -17
- package/src/chromium/converters/markdown.converter.ts +45 -19
- package/src/chromium/converters/tests/html.converter.test.ts +60 -3
- package/src/chromium/converters/tests/markdown.converter.test.ts +68 -4
- package/src/chromium/converters/tests/url.converter.test.ts +71 -4
- package/src/chromium/converters/url.converter.ts +45 -17
- package/src/chromium/interfaces/converter.types.ts +20 -0
- package/src/chromium/utils/converter.utils.ts +63 -1
- package/src/chromium/utils/tests/converter.utils.test.ts +233 -7
- package/src/libre-office/utils/libre-office.utils.ts +7 -11
- package/src/libre-office/utils/tests/libre-office.utils.test.ts +5 -4
- package/src/pdf-engines/pdf.engine.ts +13 -1
- package/src/pdf-engines/tests/pdf.engine.test.ts +57 -18
- package/src/pdf-engines/utils/engine.utils.ts +7 -11
- package/src/pdf-engines/utils/tests/engine.utils.test.ts +5 -4
- package/dist/chromium/interfaces/converter.interface.d.ts +0 -10
- package/dist/chromium/interfaces/converter.interface.js +0 -3
- package/dist/chromium/interfaces/converter.interface.js.map +0 -1
- package/src/chromium/interfaces/converter.interface.ts +0 -12
|
@@ -1,10 +1,20 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
|
+
import { createReadStream, promises } from "fs";
|
|
1
3
|
import FormData from "form-data";
|
|
2
4
|
import { ConverterUtils } from "../converter.utils";
|
|
5
|
+
import { PdfFormat } from "../../../common";
|
|
3
6
|
|
|
4
7
|
describe("ConverterUtils", () => {
|
|
5
8
|
const mockFormDataAppend = jest.spyOn(FormData.prototype, "append");
|
|
9
|
+
const mockPromisesAccess = jest.spyOn(promises, "access");
|
|
6
10
|
const data = new FormData();
|
|
7
11
|
|
|
12
|
+
beforeEach(() => {
|
|
13
|
+
(createReadStream as jest.Mock) = jest
|
|
14
|
+
.fn()
|
|
15
|
+
.mockImplementation((file) => file);
|
|
16
|
+
});
|
|
17
|
+
|
|
8
18
|
afterEach(() => {
|
|
9
19
|
jest.resetAllMocks();
|
|
10
20
|
});
|
|
@@ -16,7 +26,7 @@ describe("ConverterUtils", () => {
|
|
|
16
26
|
ConverterUtils.injectPageProperties(data, {
|
|
17
27
|
size: { width: 8.3, height: 11.7 },
|
|
18
28
|
});
|
|
19
|
-
expect(mockFormDataAppend).
|
|
29
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
20
30
|
expect(data.append).toHaveBeenCalledWith("paperWidth", 8.3);
|
|
21
31
|
expect(data.append).toHaveBeenNthCalledWith(2, "paperHeight", 11.7);
|
|
22
32
|
});
|
|
@@ -29,7 +39,7 @@ describe("ConverterUtils", () => {
|
|
|
29
39
|
ConverterUtils.injectPageProperties(data, {
|
|
30
40
|
margins: { top: 0.5, bottom: 0.5, left: 1, right: 1 },
|
|
31
41
|
});
|
|
32
|
-
expect(mockFormDataAppend).
|
|
42
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(4);
|
|
33
43
|
expect(data.append).toHaveBeenCalledWith("marginTop", 0.5);
|
|
34
44
|
expect(data.append).toHaveBeenNthCalledWith(2, "marginBottom", 0.5);
|
|
35
45
|
expect(data.append).toHaveBeenNthCalledWith(3, "marginLeft", 1);
|
|
@@ -44,7 +54,7 @@ describe("ConverterUtils", () => {
|
|
|
44
54
|
ConverterUtils.injectPageProperties(data, {
|
|
45
55
|
preferCssPageSize: true,
|
|
46
56
|
});
|
|
47
|
-
expect(mockFormDataAppend).
|
|
57
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
48
58
|
expect(data.append).toHaveBeenCalledWith("preferCssPageSize", "true");
|
|
49
59
|
});
|
|
50
60
|
});
|
|
@@ -56,10 +66,20 @@ describe("ConverterUtils", () => {
|
|
|
56
66
|
ConverterUtils.injectPageProperties(data, {
|
|
57
67
|
printBackground: true,
|
|
58
68
|
});
|
|
59
|
-
expect(mockFormDataAppend).
|
|
69
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
60
70
|
expect(data.append).toHaveBeenCalledWith("printBackground", "true");
|
|
61
71
|
});
|
|
62
72
|
});
|
|
73
|
+
|
|
74
|
+
describe("when omitBackground parameter is set", () => {
|
|
75
|
+
it("should append omitBackground to data", () => {
|
|
76
|
+
ConverterUtils.injectPageProperties(data, {
|
|
77
|
+
omitBackground: true,
|
|
78
|
+
});
|
|
79
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
80
|
+
expect(data.append).toHaveBeenCalledWith("omitBackground", "true");
|
|
81
|
+
});
|
|
82
|
+
});
|
|
63
83
|
});
|
|
64
84
|
|
|
65
85
|
describe("Page landscape", () => {
|
|
@@ -68,7 +88,7 @@ describe("ConverterUtils", () => {
|
|
|
68
88
|
ConverterUtils.injectPageProperties(data, {
|
|
69
89
|
landscape: true,
|
|
70
90
|
});
|
|
71
|
-
expect(mockFormDataAppend).
|
|
91
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
72
92
|
expect(data.append).toHaveBeenCalledWith("landscape", "true");
|
|
73
93
|
});
|
|
74
94
|
});
|
|
@@ -80,7 +100,7 @@ describe("ConverterUtils", () => {
|
|
|
80
100
|
ConverterUtils.injectPageProperties(data, {
|
|
81
101
|
scale: 1.5,
|
|
82
102
|
});
|
|
83
|
-
expect(mockFormDataAppend).
|
|
103
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
84
104
|
expect(data.append).toHaveBeenCalledWith("scale", 1.5);
|
|
85
105
|
});
|
|
86
106
|
});
|
|
@@ -92,10 +112,216 @@ describe("ConverterUtils", () => {
|
|
|
92
112
|
ConverterUtils.injectPageProperties(data, {
|
|
93
113
|
nativePageRanges: { from: 1, to: 6 },
|
|
94
114
|
});
|
|
95
|
-
expect(mockFormDataAppend).
|
|
115
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
96
116
|
expect(data.append).toHaveBeenCalledWith("nativePageRanges", "1-6");
|
|
97
117
|
});
|
|
98
118
|
});
|
|
99
119
|
});
|
|
100
120
|
});
|
|
121
|
+
|
|
122
|
+
describe("customize", () => {
|
|
123
|
+
describe("when no option is passed", () => {
|
|
124
|
+
it("should not append anything", async () => {
|
|
125
|
+
await ConverterUtils.customize(data, {});
|
|
126
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(0);
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
describe("when header parameter is passed", () => {
|
|
131
|
+
it("should append header", async () => {
|
|
132
|
+
mockPromisesAccess.mockResolvedValue();
|
|
133
|
+
await ConverterUtils.customize(data, {
|
|
134
|
+
header: "path/to/header.html",
|
|
135
|
+
});
|
|
136
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
137
|
+
expect(data.append).toHaveBeenCalledWith(
|
|
138
|
+
"header.html",
|
|
139
|
+
"path/to/header.html"
|
|
140
|
+
);
|
|
141
|
+
});
|
|
142
|
+
});
|
|
143
|
+
|
|
144
|
+
describe("when footer parameter is passed", () => {
|
|
145
|
+
it("should append footer", async () => {
|
|
146
|
+
mockPromisesAccess.mockResolvedValue();
|
|
147
|
+
await ConverterUtils.customize(data, {
|
|
148
|
+
footer: "path/to/footer.html",
|
|
149
|
+
});
|
|
150
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
151
|
+
expect(data.append).toHaveBeenCalledWith(
|
|
152
|
+
"footer.html",
|
|
153
|
+
"path/to/footer.html"
|
|
154
|
+
);
|
|
155
|
+
});
|
|
156
|
+
});
|
|
157
|
+
|
|
158
|
+
describe("when pdf format parameter is passed", () => {
|
|
159
|
+
it("should append pdf format", async () => {
|
|
160
|
+
await ConverterUtils.customize(data, {
|
|
161
|
+
pdfFormat: PdfFormat.A_1a,
|
|
162
|
+
});
|
|
163
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
164
|
+
expect(data.append).toHaveBeenCalledWith("pdfa", "PDF/A-1a");
|
|
165
|
+
});
|
|
166
|
+
});
|
|
167
|
+
|
|
168
|
+
describe("when pdf universal access parameter is passed", () => {
|
|
169
|
+
it("should append pdfua format", async () => {
|
|
170
|
+
await ConverterUtils.customize(data, {
|
|
171
|
+
pdfUA: true,
|
|
172
|
+
});
|
|
173
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
174
|
+
expect(data.append).toHaveBeenCalledWith("pdfua", "true");
|
|
175
|
+
});
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
describe("when page properties parameter is passed", () => {
|
|
179
|
+
it("should append page propertiers", async () => {
|
|
180
|
+
await ConverterUtils.customize(data, {
|
|
181
|
+
properties: { size: { width: 8.3, height: 11.7 } },
|
|
182
|
+
});
|
|
183
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
184
|
+
expect(data.append).toHaveBeenCalledWith("paperWidth", 8.3);
|
|
185
|
+
expect(data.append).toHaveBeenNthCalledWith(2, "paperHeight", 11.7);
|
|
186
|
+
});
|
|
187
|
+
});
|
|
188
|
+
|
|
189
|
+
describe("when emulatedMediaType parameter is passed", () => {
|
|
190
|
+
it("should append emulatedMediaType", async () => {
|
|
191
|
+
await ConverterUtils.customize(data, {
|
|
192
|
+
emulatedMediaType: "screen",
|
|
193
|
+
});
|
|
194
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
195
|
+
expect(data.append).toHaveBeenCalledWith("emulatedMediaType", "screen");
|
|
196
|
+
});
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
describe("when waitDelay parameter is passed", () => {
|
|
200
|
+
it("should append waitDelay", async () => {
|
|
201
|
+
await ConverterUtils.customize(data, {
|
|
202
|
+
waitDelay: "5s",
|
|
203
|
+
});
|
|
204
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
205
|
+
expect(data.append).toHaveBeenCalledWith("waitDelay", "5s");
|
|
206
|
+
});
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
describe("when waitForExpression parameter is passed", () => {
|
|
210
|
+
it("should append waitForExpression", async () => {
|
|
211
|
+
await ConverterUtils.customize(data, {
|
|
212
|
+
waitForExpression: "document.readyState === 'complete'",
|
|
213
|
+
});
|
|
214
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
215
|
+
expect(data.append).toHaveBeenCalledWith(
|
|
216
|
+
"waitForExpression",
|
|
217
|
+
"document.readyState === 'complete'"
|
|
218
|
+
);
|
|
219
|
+
});
|
|
220
|
+
});
|
|
221
|
+
|
|
222
|
+
describe("when userAgent parameter is passed", () => {
|
|
223
|
+
it("should append userAgent", async () => {
|
|
224
|
+
const userAgent =
|
|
225
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36";
|
|
226
|
+
|
|
227
|
+
await ConverterUtils.customize(data, {
|
|
228
|
+
userAgent,
|
|
229
|
+
});
|
|
230
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
231
|
+
expect(data.append).toHaveBeenCalledWith("userAgent", userAgent);
|
|
232
|
+
});
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
describe("when extraHttpHeaders parameter is passed", () => {
|
|
236
|
+
it("should append extraHttpHeaders", async () => {
|
|
237
|
+
const extraHttpHeaders = {
|
|
238
|
+
"X-Custom-Header": "value",
|
|
239
|
+
};
|
|
240
|
+
|
|
241
|
+
await ConverterUtils.customize(data, {
|
|
242
|
+
extraHttpHeaders,
|
|
243
|
+
});
|
|
244
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
245
|
+
expect(data.append).toHaveBeenCalledWith(
|
|
246
|
+
"extraHttpHeaders",
|
|
247
|
+
JSON.stringify(extraHttpHeaders)
|
|
248
|
+
);
|
|
249
|
+
});
|
|
250
|
+
});
|
|
251
|
+
|
|
252
|
+
describe("when failOnConsoleExceptions parameter is passed", () => {
|
|
253
|
+
it("should append failOnConsoleExceptions", async () => {
|
|
254
|
+
await ConverterUtils.customize(data, {
|
|
255
|
+
failOnConsoleExceptions: true,
|
|
256
|
+
});
|
|
257
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
258
|
+
expect(data.append).toHaveBeenCalledWith(
|
|
259
|
+
"failOnConsoleExceptions",
|
|
260
|
+
"true"
|
|
261
|
+
);
|
|
262
|
+
});
|
|
263
|
+
});
|
|
264
|
+
|
|
265
|
+
describe("when all options are passed", () => {
|
|
266
|
+
it("should append all options", async () => {
|
|
267
|
+
mockPromisesAccess.mockResolvedValue();
|
|
268
|
+
|
|
269
|
+
await ConverterUtils.customize(data, {
|
|
270
|
+
header: "path/to/header.html",
|
|
271
|
+
footer: "path/to/footer.html",
|
|
272
|
+
pdfFormat: PdfFormat.A_1a,
|
|
273
|
+
pdfUA: true,
|
|
274
|
+
emulatedMediaType: "screen",
|
|
275
|
+
properties: { size: { width: 8.3, height: 11.7 } },
|
|
276
|
+
waitDelay: "5s",
|
|
277
|
+
waitForExpression: "document.readyState === 'complete'",
|
|
278
|
+
userAgent:
|
|
279
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36",
|
|
280
|
+
extraHttpHeaders: { "X-Custom-Header": "value" },
|
|
281
|
+
failOnConsoleExceptions: true,
|
|
282
|
+
});
|
|
283
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(12);
|
|
284
|
+
expect(data.append).toHaveBeenNthCalledWith(1, "pdfa", "PDF/A-1a");
|
|
285
|
+
expect(data.append).toHaveBeenNthCalledWith(2, "pdfua", "true");
|
|
286
|
+
expect(data.append).toHaveBeenNthCalledWith(
|
|
287
|
+
3,
|
|
288
|
+
"header.html",
|
|
289
|
+
"path/to/header.html"
|
|
290
|
+
);
|
|
291
|
+
expect(data.append).toHaveBeenNthCalledWith(
|
|
292
|
+
4,
|
|
293
|
+
"footer.html",
|
|
294
|
+
"path/to/footer.html"
|
|
295
|
+
);
|
|
296
|
+
expect(data.append).toHaveBeenNthCalledWith(
|
|
297
|
+
5,
|
|
298
|
+
"emulatedMediaType",
|
|
299
|
+
"screen"
|
|
300
|
+
);
|
|
301
|
+
expect(data.append).toHaveBeenNthCalledWith(6, "paperWidth", 8.3);
|
|
302
|
+
expect(data.append).toHaveBeenNthCalledWith(7, "paperHeight", 11.7);
|
|
303
|
+
expect(data.append).toHaveBeenNthCalledWith(8, "waitDelay", "5s");
|
|
304
|
+
expect(data.append).toHaveBeenNthCalledWith(
|
|
305
|
+
9,
|
|
306
|
+
"waitForExpression",
|
|
307
|
+
"document.readyState === 'complete'"
|
|
308
|
+
);
|
|
309
|
+
expect(data.append).toHaveBeenNthCalledWith(
|
|
310
|
+
10,
|
|
311
|
+
"userAgent",
|
|
312
|
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36"
|
|
313
|
+
);
|
|
314
|
+
expect(data.append).toHaveBeenNthCalledWith(
|
|
315
|
+
11,
|
|
316
|
+
"extraHttpHeaders",
|
|
317
|
+
JSON.stringify({ "X-Custom-Header": "value" })
|
|
318
|
+
);
|
|
319
|
+
expect(data.append).toHaveBeenNthCalledWith(
|
|
320
|
+
12,
|
|
321
|
+
"failOnConsoleExceptions",
|
|
322
|
+
"true"
|
|
323
|
+
);
|
|
324
|
+
});
|
|
325
|
+
});
|
|
326
|
+
});
|
|
101
327
|
});
|
|
@@ -10,17 +10,13 @@ import { PageProperties } from "../interfaces/libre-office.types";
|
|
|
10
10
|
export class LibreOfficeUtils {
|
|
11
11
|
public static async injectFiles(files: PathLike[], data: FormData) {
|
|
12
12
|
for (const file of files) {
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
}
|
|
20
|
-
throw new Error(`${extension} is not supported`);
|
|
21
|
-
}
|
|
22
|
-
} catch (error) {
|
|
23
|
-
throw error;
|
|
13
|
+
await promises.access(file, constants.R_OK);
|
|
14
|
+
const filename = path.basename(file.toString());
|
|
15
|
+
const extension = path.extname(filename);
|
|
16
|
+
if (LIBRE_OFFICE_EXTENSIONS.includes(extension)) {
|
|
17
|
+
data.append(filename, createReadStream(file));
|
|
18
|
+
} else {
|
|
19
|
+
throw new Error(`${extension} is not supported`);
|
|
24
20
|
}
|
|
25
21
|
}
|
|
26
22
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
2
|
import { promises, createReadStream } from "fs";
|
|
3
|
+
import { LibreOfficeUtils } from "../libre-office.utils";
|
|
3
4
|
|
|
4
5
|
import FormData from "form-data";
|
|
5
6
|
|
|
@@ -26,7 +27,7 @@ describe("LibreOfficeUtils", () => {
|
|
|
26
27
|
["path/to/file.docx", "path/to/file.bib"],
|
|
27
28
|
data
|
|
28
29
|
);
|
|
29
|
-
expect(mockFormDataAppend).
|
|
30
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
30
31
|
});
|
|
31
32
|
});
|
|
32
33
|
|
|
@@ -64,7 +65,7 @@ describe("LibreOfficeUtils", () => {
|
|
|
64
65
|
LibreOfficeUtils.injectPageProperties(data, {
|
|
65
66
|
landscape: true,
|
|
66
67
|
});
|
|
67
|
-
expect(mockFormDataAppend).
|
|
68
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
68
69
|
expect(data.append).toHaveBeenCalledWith("landscape", "true");
|
|
69
70
|
});
|
|
70
71
|
});
|
|
@@ -76,7 +77,7 @@ describe("LibreOfficeUtils", () => {
|
|
|
76
77
|
LibreOfficeUtils.injectPageProperties(data, {
|
|
77
78
|
nativePageRanges: { from: 1, to: 6 },
|
|
78
79
|
});
|
|
79
|
-
expect(mockFormDataAppend).
|
|
80
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(1);
|
|
80
81
|
expect(data.append).toHaveBeenCalledWith("nativePageRanges", "1-6");
|
|
81
82
|
});
|
|
82
83
|
});
|
|
@@ -20,25 +20,37 @@ export class PDFEngine {
|
|
|
20
20
|
files,
|
|
21
21
|
properties,
|
|
22
22
|
pdfFormat,
|
|
23
|
+
pdfUA,
|
|
23
24
|
merge,
|
|
24
25
|
}: {
|
|
25
26
|
files: PathLike[];
|
|
26
27
|
properties?: PageProperties;
|
|
27
28
|
pdfFormat?: PdfFormat;
|
|
29
|
+
pdfUA?: boolean;
|
|
28
30
|
merge?: boolean;
|
|
29
31
|
}): Promise<Buffer> {
|
|
30
32
|
const data = new FormData();
|
|
33
|
+
|
|
31
34
|
if (pdfFormat) {
|
|
32
|
-
data.append("
|
|
35
|
+
data.append("pdfa", pdfFormat);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (pdfUA) {
|
|
39
|
+
data.append("pdfUA", String(pdfUA));
|
|
33
40
|
}
|
|
41
|
+
|
|
34
42
|
if (merge) {
|
|
35
43
|
data.append("merge", String(merge));
|
|
36
44
|
}
|
|
45
|
+
|
|
37
46
|
if (properties) {
|
|
38
47
|
LibreOfficeUtils.injectPageProperties(data, properties);
|
|
39
48
|
}
|
|
49
|
+
|
|
40
50
|
await LibreOfficeUtils.injectFiles(files, data);
|
|
51
|
+
|
|
41
52
|
const endpoint = `${Chromiumly.GOTENBERG_ENDPOINT}/${Chromiumly.LIBRE_OFFICE_PATH}/${Chromiumly.LIBRE_OFFICE_ROUTES.convert}`;
|
|
53
|
+
|
|
42
54
|
return GotenbergUtils.fetch(endpoint, data);
|
|
43
55
|
}
|
|
44
56
|
|
|
@@ -1,21 +1,18 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
|
+
import { createReadStream, promises } from "fs";
|
|
3
|
+
import FormData from "form-data";
|
|
4
|
+
import fs from "fs/promises";
|
|
5
|
+
import fetch from "node-fetch";
|
|
1
6
|
import path from "path";
|
|
2
7
|
|
|
3
|
-
import { PDFEngine } from "./../pdf.engine";
|
|
4
8
|
import { PdfFormat } from "../../common";
|
|
5
|
-
|
|
6
|
-
import { promises, createReadStream } from "fs";
|
|
7
|
-
|
|
8
|
-
import fetch from "node-fetch";
|
|
9
|
-
import FormData from "form-data";
|
|
9
|
+
import { PDFEngine } from "../pdf.engine";
|
|
10
10
|
|
|
11
11
|
const { Response } = jest.requireActual("node-fetch");
|
|
12
12
|
jest.mock("node-fetch", () => jest.fn());
|
|
13
13
|
|
|
14
14
|
describe("PDFEngine", () => {
|
|
15
|
-
const mockProcessCwd = jest.spyOn(process, "cwd");
|
|
16
15
|
const mockPromisesAccess = jest.spyOn(promises, "access");
|
|
17
|
-
const mockPromisesMkDir = jest.spyOn(promises, "mkdir");
|
|
18
|
-
const mockPromisesWriteFile = jest.spyOn(promises, "writeFile");
|
|
19
16
|
const mockFetch = fetch as jest.MockedFunction<typeof fetch>;
|
|
20
17
|
const mockFormDataAppend = jest.spyOn(FormData.prototype, "append");
|
|
21
18
|
|
|
@@ -38,7 +35,7 @@ describe("PDFEngine", () => {
|
|
|
38
35
|
files: ["path/to/file.docx", "path/to/file.bib"],
|
|
39
36
|
});
|
|
40
37
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
41
|
-
expect(mockFormDataAppend).
|
|
38
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
42
39
|
});
|
|
43
40
|
});
|
|
44
41
|
|
|
@@ -50,10 +47,11 @@ describe("PDFEngine", () => {
|
|
|
50
47
|
files: ["path/to/file.docx", "path/to/file.bib"],
|
|
51
48
|
properties: { landscape: true },
|
|
52
49
|
pdfFormat: PdfFormat.A_1a,
|
|
50
|
+
pdfUA: true,
|
|
53
51
|
merge: true,
|
|
54
52
|
});
|
|
55
53
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
56
|
-
expect(mockFormDataAppend).
|
|
54
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(6);
|
|
57
55
|
});
|
|
58
56
|
});
|
|
59
57
|
});
|
|
@@ -66,19 +64,60 @@ describe("PDFEngine", () => {
|
|
|
66
64
|
files: ["path/to/file.pdf", "path/to/another-file.pdf"],
|
|
67
65
|
});
|
|
68
66
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
69
|
-
expect(mockFormDataAppend).
|
|
67
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
70
68
|
});
|
|
71
69
|
});
|
|
72
70
|
|
|
73
71
|
describe("generate", () => {
|
|
72
|
+
const mockFilename = "test.pdf";
|
|
73
|
+
const mockBuffer = Buffer.from("mock pdf content");
|
|
74
|
+
|
|
75
|
+
afterAll(() => {
|
|
76
|
+
jest.restoreAllMocks();
|
|
77
|
+
});
|
|
78
|
+
|
|
74
79
|
it("should generate a PDF file", async () => {
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
80
|
+
const mockGeneratedDir = path.join(process.cwd(), "__generated__");
|
|
81
|
+
const mockGeneratedFilePath = path.join(mockGeneratedDir, mockFilename);
|
|
82
|
+
|
|
83
|
+
const mockPromisesMkDir = jest
|
|
84
|
+
.spyOn(fs, "mkdir")
|
|
85
|
+
.mockResolvedValueOnce(mockGeneratedDir);
|
|
86
|
+
|
|
87
|
+
const mockPromisesWriteFile = jest
|
|
88
|
+
.spyOn(fs, "writeFile")
|
|
89
|
+
.mockResolvedValueOnce();
|
|
90
|
+
|
|
91
|
+
await PDFEngine.generate(mockFilename, mockBuffer);
|
|
92
|
+
|
|
93
|
+
expect(mockPromisesMkDir).toHaveBeenCalledWith(mockGeneratedDir, {
|
|
94
|
+
recursive: true,
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
expect(mockPromisesWriteFile).toHaveBeenCalledWith(
|
|
98
|
+
mockGeneratedFilePath,
|
|
99
|
+
mockBuffer
|
|
81
100
|
);
|
|
82
101
|
});
|
|
102
|
+
|
|
103
|
+
it("should handle errors during file generation", async () => {
|
|
104
|
+
jest
|
|
105
|
+
.spyOn(fs, "mkdir")
|
|
106
|
+
.mockRejectedValueOnce(new Error("Cannot create directory"));
|
|
107
|
+
|
|
108
|
+
await expect(
|
|
109
|
+
PDFEngine.generate(mockFilename, mockBuffer)
|
|
110
|
+
).rejects.toThrow("Cannot create directory");
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
it("should handle errors during file writing", async () => {
|
|
114
|
+
jest
|
|
115
|
+
.spyOn(fs, "writeFile")
|
|
116
|
+
.mockRejectedValueOnce(new Error("Failed to write to file"));
|
|
117
|
+
|
|
118
|
+
await expect(
|
|
119
|
+
PDFEngine.generate(mockFilename, mockBuffer)
|
|
120
|
+
).rejects.toThrow("Failed to write to file");
|
|
121
|
+
});
|
|
83
122
|
});
|
|
84
123
|
});
|
|
@@ -6,17 +6,13 @@ import FormData from "form-data";
|
|
|
6
6
|
export class PDFEngineUtils {
|
|
7
7
|
public static async injectFiles(files: PathLike[], data: FormData) {
|
|
8
8
|
for (const file of files) {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
}
|
|
16
|
-
throw new Error(`${extension} is not supported`);
|
|
17
|
-
}
|
|
18
|
-
} catch (error) {
|
|
19
|
-
throw error;
|
|
9
|
+
await promises.access(file, constants.R_OK);
|
|
10
|
+
const filename = path.basename(file.toString());
|
|
11
|
+
const extension = path.extname(filename);
|
|
12
|
+
if (extension === ".pdf") {
|
|
13
|
+
data.append(filename, createReadStream(file));
|
|
14
|
+
} else {
|
|
15
|
+
throw new Error(`${extension} is not supported`);
|
|
20
16
|
}
|
|
21
17
|
}
|
|
22
18
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
import {
|
|
3
|
-
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
|
+
import { createReadStream, promises } from "fs";
|
|
4
3
|
import FormData from "form-data";
|
|
5
4
|
|
|
5
|
+
import { PDFEngineUtils } from "./../engine.utils";
|
|
6
|
+
|
|
6
7
|
describe("PDFEngineUtils", () => {
|
|
7
8
|
const mockPromisesAccess = jest.spyOn(promises, "access");
|
|
8
9
|
const mockFormDataAppend = jest.spyOn(FormData.prototype, "append");
|
|
@@ -26,7 +27,7 @@ describe("PDFEngineUtils", () => {
|
|
|
26
27
|
["path/to/file.pdf", "path/to/another-file.pdf"],
|
|
27
28
|
data
|
|
28
29
|
);
|
|
29
|
-
expect(mockFormDataAppend).
|
|
30
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
30
31
|
});
|
|
31
32
|
});
|
|
32
33
|
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
/// <reference types="node" />
|
|
2
|
-
/// <reference types="node" />
|
|
3
|
-
import { PathLike } from "fs";
|
|
4
|
-
import { PdfFormat } from "../../common";
|
|
5
|
-
import { PageProperties } from "./converter.types";
|
|
6
|
-
export interface IConverter {
|
|
7
|
-
convert({ ...args }: {
|
|
8
|
-
[x: string]: string | PathLike | PageProperties | PdfFormat;
|
|
9
|
-
}): Promise<Buffer>;
|
|
10
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"converter.interface.js","sourceRoot":"","sources":["../../../src/chromium/interfaces/converter.interface.ts"],"names":[],"mappings":""}
|
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
import { PathLike } from "fs";
|
|
2
|
-
|
|
3
|
-
import { PdfFormat } from "../../common";
|
|
4
|
-
import { PageProperties } from "./converter.types";
|
|
5
|
-
|
|
6
|
-
export interface IConverter {
|
|
7
|
-
convert({
|
|
8
|
-
...args
|
|
9
|
-
}: {
|
|
10
|
-
[x: string]: string | PathLike | PageProperties | PdfFormat;
|
|
11
|
-
}): Promise<Buffer>;
|
|
12
|
-
}
|