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
|
@@ -3,39 +3,65 @@ import { constants, createReadStream, PathLike, promises } from "fs";
|
|
|
3
3
|
import FormData from "form-data";
|
|
4
4
|
|
|
5
5
|
import { GotenbergUtils, PdfFormat } from "../../common";
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
EmulatedMediaType,
|
|
8
|
+
PageProperties,
|
|
9
|
+
} from "../interfaces/converter.types";
|
|
8
10
|
import { ConverterUtils } from "../utils/converter.utils";
|
|
9
11
|
import { Converter } from "./converter";
|
|
10
12
|
import { ChromiumRoute } from "../../main.config";
|
|
11
13
|
|
|
12
|
-
export class HtmlConverter extends Converter
|
|
14
|
+
export class HtmlConverter extends Converter {
|
|
13
15
|
constructor() {
|
|
14
16
|
super(ChromiumRoute.HTML);
|
|
15
17
|
}
|
|
16
18
|
|
|
17
19
|
async convert({
|
|
18
20
|
html,
|
|
21
|
+
header,
|
|
22
|
+
footer,
|
|
19
23
|
properties,
|
|
20
24
|
pdfFormat,
|
|
25
|
+
pdfUA,
|
|
26
|
+
emulatedMediaType,
|
|
27
|
+
waitDelay,
|
|
28
|
+
waitForExpression,
|
|
29
|
+
userAgent,
|
|
30
|
+
extraHttpHeaders,
|
|
31
|
+
failOnConsoleExceptions,
|
|
21
32
|
}: {
|
|
22
33
|
html: PathLike;
|
|
34
|
+
header?: PathLike;
|
|
35
|
+
footer?: PathLike;
|
|
23
36
|
properties?: PageProperties;
|
|
24
37
|
pdfFormat?: PdfFormat;
|
|
38
|
+
pdfUA?: boolean;
|
|
39
|
+
emulatedMediaType?: EmulatedMediaType;
|
|
40
|
+
waitDelay?: string;
|
|
41
|
+
waitForExpression?: string;
|
|
42
|
+
userAgent?: string;
|
|
43
|
+
extraHttpHeaders?: Record<string, string>;
|
|
44
|
+
failOnConsoleExceptions?: boolean;
|
|
25
45
|
}): Promise<Buffer> {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
46
|
+
await promises.access(html, constants.R_OK);
|
|
47
|
+
const data = new FormData();
|
|
48
|
+
|
|
49
|
+
data.append("index.html", createReadStream(html));
|
|
50
|
+
|
|
51
|
+
ConverterUtils.customize(data, {
|
|
52
|
+
header,
|
|
53
|
+
footer,
|
|
54
|
+
properties,
|
|
55
|
+
pdfFormat,
|
|
56
|
+
pdfUA,
|
|
57
|
+
emulatedMediaType,
|
|
58
|
+
waitDelay,
|
|
59
|
+
waitForExpression,
|
|
60
|
+
userAgent,
|
|
61
|
+
extraHttpHeaders,
|
|
62
|
+
failOnConsoleExceptions,
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
return GotenbergUtils.fetch(this.endpoint, data);
|
|
40
66
|
}
|
|
41
67
|
}
|
|
@@ -3,13 +3,15 @@ import { constants, createReadStream, PathLike, promises } from "fs";
|
|
|
3
3
|
import FormData from "form-data";
|
|
4
4
|
|
|
5
5
|
import { GotenbergUtils, PdfFormat } from "../../common";
|
|
6
|
-
import {
|
|
7
|
-
|
|
6
|
+
import {
|
|
7
|
+
EmulatedMediaType,
|
|
8
|
+
PageProperties,
|
|
9
|
+
} from "../interfaces/converter.types";
|
|
8
10
|
import { ConverterUtils } from "../utils/converter.utils";
|
|
9
11
|
import { Converter } from "./converter";
|
|
10
12
|
import { ChromiumRoute } from "../../main.config";
|
|
11
13
|
|
|
12
|
-
export class MarkdownConverter extends Converter
|
|
14
|
+
export class MarkdownConverter extends Converter {
|
|
13
15
|
constructor() {
|
|
14
16
|
super(ChromiumRoute.MARKDOWN);
|
|
15
17
|
}
|
|
@@ -17,29 +19,53 @@ export class MarkdownConverter extends Converter implements IConverter {
|
|
|
17
19
|
async convert({
|
|
18
20
|
html,
|
|
19
21
|
markdown,
|
|
22
|
+
header,
|
|
23
|
+
footer,
|
|
20
24
|
properties,
|
|
21
25
|
pdfFormat,
|
|
26
|
+
pdfUA,
|
|
27
|
+
emulatedMediaType,
|
|
28
|
+
waitDelay,
|
|
29
|
+
waitForExpression,
|
|
30
|
+
userAgent,
|
|
31
|
+
extraHttpHeaders,
|
|
32
|
+
failOnConsoleExceptions,
|
|
22
33
|
}: {
|
|
23
34
|
html: PathLike;
|
|
24
35
|
markdown: PathLike;
|
|
36
|
+
header?: PathLike;
|
|
37
|
+
footer?: PathLike;
|
|
25
38
|
properties?: PageProperties;
|
|
26
39
|
pdfFormat?: PdfFormat;
|
|
40
|
+
pdfUA?: boolean;
|
|
41
|
+
emulatedMediaType?: EmulatedMediaType;
|
|
42
|
+
waitDelay?: string;
|
|
43
|
+
waitForExpression?: string;
|
|
44
|
+
userAgent?: string;
|
|
45
|
+
extraHttpHeaders?: Record<string, string>;
|
|
46
|
+
failOnConsoleExceptions?: boolean;
|
|
27
47
|
}): Promise<Buffer> {
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
48
|
+
await promises.access(html, constants.R_OK);
|
|
49
|
+
await promises.access(markdown, constants.R_OK);
|
|
50
|
+
const data = new FormData();
|
|
51
|
+
|
|
52
|
+
data.append("index.html", createReadStream(html));
|
|
53
|
+
data.append("file.md", createReadStream(markdown));
|
|
54
|
+
|
|
55
|
+
ConverterUtils.customize(data, {
|
|
56
|
+
header,
|
|
57
|
+
footer,
|
|
58
|
+
properties,
|
|
59
|
+
pdfFormat,
|
|
60
|
+
pdfUA,
|
|
61
|
+
emulatedMediaType,
|
|
62
|
+
waitDelay,
|
|
63
|
+
waitForExpression,
|
|
64
|
+
userAgent,
|
|
65
|
+
extraHttpHeaders,
|
|
66
|
+
failOnConsoleExceptions,
|
|
67
|
+
});
|
|
68
|
+
|
|
69
|
+
return GotenbergUtils.fetch(this.endpoint, data);
|
|
44
70
|
}
|
|
45
71
|
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
|
+
import { createReadStream, promises } from "fs";
|
|
2
3
|
|
|
3
4
|
import fetch from "node-fetch";
|
|
4
5
|
import FormData from "form-data";
|
|
@@ -51,7 +52,7 @@ describe("HtmlConverter", () => {
|
|
|
51
52
|
html: "path/to/index.html",
|
|
52
53
|
pdfFormat: PdfFormat.A_1a,
|
|
53
54
|
});
|
|
54
|
-
expect(mockFormDataAppend).
|
|
55
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
55
56
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
56
57
|
});
|
|
57
58
|
});
|
|
@@ -64,7 +65,63 @@ describe("HtmlConverter", () => {
|
|
|
64
65
|
html: "path/to/index.html",
|
|
65
66
|
properties: { size: { width: 8.3, height: 11.7 } },
|
|
66
67
|
});
|
|
67
|
-
expect(mockFormDataAppend).
|
|
68
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(3);
|
|
69
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
70
|
+
});
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
describe("when header parameter is passed", () => {
|
|
74
|
+
it("should return a buffer", async () => {
|
|
75
|
+
mockPromisesAccess.mockResolvedValue();
|
|
76
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
77
|
+
const buffer = await converter.convert({
|
|
78
|
+
html: "path/to/index.html",
|
|
79
|
+
header: "path/to/header.html",
|
|
80
|
+
});
|
|
81
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
82
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe("when footer parameter is passed", () => {
|
|
87
|
+
it("should return a buffer", async () => {
|
|
88
|
+
mockPromisesAccess.mockResolvedValue();
|
|
89
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
90
|
+
const buffer = await converter.convert({
|
|
91
|
+
html: "path/to/index.html",
|
|
92
|
+
footer: "path/to/footer.html",
|
|
93
|
+
});
|
|
94
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
95
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
96
|
+
});
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
describe("when emulatedMediaType parameter is passed", () => {
|
|
100
|
+
it("should return a buffer", async () => {
|
|
101
|
+
mockPromisesAccess.mockResolvedValue();
|
|
102
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
103
|
+
const buffer = await converter.convert({
|
|
104
|
+
html: "path/to/index.html",
|
|
105
|
+
emulatedMediaType: "screen",
|
|
106
|
+
});
|
|
107
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
108
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
109
|
+
});
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
describe("when all parameters are passed", () => {
|
|
113
|
+
it("should return a buffer", async () => {
|
|
114
|
+
mockPromisesAccess.mockResolvedValue();
|
|
115
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
116
|
+
const buffer = await converter.convert({
|
|
117
|
+
html: "path/to/index.html",
|
|
118
|
+
header: "path/to/header.html",
|
|
119
|
+
footer: "path/to/footer.html",
|
|
120
|
+
pdfFormat: PdfFormat.A_1a,
|
|
121
|
+
emulatedMediaType: "screen",
|
|
122
|
+
properties: { size: { width: 8.3, height: 11.7 } },
|
|
123
|
+
});
|
|
124
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(7);
|
|
68
125
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
69
126
|
});
|
|
70
127
|
});
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
1
2
|
import { createReadStream, promises } from "fs";
|
|
2
3
|
|
|
3
|
-
import fetch from "node-fetch";
|
|
4
4
|
import FormData from "form-data";
|
|
5
|
+
import fetch from "node-fetch";
|
|
5
6
|
|
|
6
7
|
import { PdfFormat } from "../../../common";
|
|
7
8
|
import { MarkdownConverter } from "../markdown.converter";
|
|
@@ -29,7 +30,9 @@ describe("MarkdownConverter", () => {
|
|
|
29
30
|
|
|
30
31
|
describe("convert", () => {
|
|
31
32
|
beforeEach(() => {
|
|
32
|
-
(createReadStream as jest.Mock) = jest
|
|
33
|
+
(createReadStream as jest.Mock) = jest
|
|
34
|
+
.fn()
|
|
35
|
+
.mockImplementation((file) => file);
|
|
33
36
|
});
|
|
34
37
|
|
|
35
38
|
describe("when file exists", () => {
|
|
@@ -53,7 +56,7 @@ describe("MarkdownConverter", () => {
|
|
|
53
56
|
markdown: "path/to/file.md",
|
|
54
57
|
pdfFormat: PdfFormat.A_2b,
|
|
55
58
|
});
|
|
56
|
-
expect(mockFormDataAppend).
|
|
59
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(3);
|
|
57
60
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
58
61
|
});
|
|
59
62
|
});
|
|
@@ -67,7 +70,68 @@ describe("MarkdownConverter", () => {
|
|
|
67
70
|
markdown: "path/to/file.md",
|
|
68
71
|
properties: { size: { width: 8.3, height: 11.7 } },
|
|
69
72
|
});
|
|
70
|
-
expect(mockFormDataAppend).
|
|
73
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(4);
|
|
74
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
describe("when header parameter is passed", () => {
|
|
79
|
+
it("should return a buffer", async () => {
|
|
80
|
+
mockPromisesAccess.mockResolvedValue();
|
|
81
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
82
|
+
const buffer = await converter.convert({
|
|
83
|
+
html: "path/to/index.html",
|
|
84
|
+
markdown: "path/to/file.md",
|
|
85
|
+
header: "path/to/header.html",
|
|
86
|
+
});
|
|
87
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(3);
|
|
88
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
89
|
+
});
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
describe("when footer parameter is passed", () => {
|
|
93
|
+
it("should return a buffer", async () => {
|
|
94
|
+
mockPromisesAccess.mockResolvedValue();
|
|
95
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
96
|
+
const buffer = await converter.convert({
|
|
97
|
+
html: "path/to/index.html",
|
|
98
|
+
markdown: "path/to/file.md",
|
|
99
|
+
footer: "path/to/footer.html",
|
|
100
|
+
});
|
|
101
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(3);
|
|
102
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
|
|
106
|
+
describe("when emulatedMediaType parameter is passed", () => {
|
|
107
|
+
it("should return a buffer", async () => {
|
|
108
|
+
mockPromisesAccess.mockResolvedValue();
|
|
109
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
110
|
+
const buffer = await converter.convert({
|
|
111
|
+
html: "path/to/index.html",
|
|
112
|
+
markdown: "path/to/file.md",
|
|
113
|
+
emulatedMediaType: "screen",
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(3);
|
|
117
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
118
|
+
});
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
describe("when all parameters are passed", () => {
|
|
122
|
+
it("should return a buffer", async () => {
|
|
123
|
+
mockPromisesAccess.mockResolvedValue();
|
|
124
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
125
|
+
const buffer = await converter.convert({
|
|
126
|
+
html: "path/to/index.html",
|
|
127
|
+
markdown: "path/to/file.md",
|
|
128
|
+
header: "path/to/header.html",
|
|
129
|
+
footer: "path/to/footer.html",
|
|
130
|
+
pdfFormat: PdfFormat.A_1a,
|
|
131
|
+
emulatedMediaType: "screen",
|
|
132
|
+
properties: { size: { width: 8.3, height: 11.7 } },
|
|
133
|
+
});
|
|
134
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(8);
|
|
71
135
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
72
136
|
});
|
|
73
137
|
});
|
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
2
|
+
import { createReadStream, promises } from "fs";
|
|
2
3
|
import FormData from "form-data";
|
|
4
|
+
import fetch from "node-fetch";
|
|
3
5
|
|
|
4
6
|
import { PdfFormat } from "../../../common";
|
|
5
7
|
import { UrlConverter } from "../url.converter";
|
|
@@ -10,9 +12,16 @@ jest.mock("node-fetch", () => jest.fn());
|
|
|
10
12
|
describe("HtmlConverter", () => {
|
|
11
13
|
const mockFetch = fetch as jest.MockedFunction<typeof fetch>;
|
|
12
14
|
const mockFormDataAppend = jest.spyOn(FormData.prototype, "append");
|
|
15
|
+
const mockPromisesAccess = jest.spyOn(promises, "access");
|
|
13
16
|
|
|
14
17
|
const converter = new UrlConverter();
|
|
15
18
|
|
|
19
|
+
beforeEach(() => {
|
|
20
|
+
(createReadStream as jest.Mock) = jest
|
|
21
|
+
.fn()
|
|
22
|
+
.mockImplementation((file) => file);
|
|
23
|
+
});
|
|
24
|
+
|
|
16
25
|
afterEach(() => {
|
|
17
26
|
jest.resetAllMocks();
|
|
18
27
|
});
|
|
@@ -36,6 +45,34 @@ describe("HtmlConverter", () => {
|
|
|
36
45
|
});
|
|
37
46
|
});
|
|
38
47
|
|
|
48
|
+
describe("when header parameter is passed", () => {
|
|
49
|
+
it("should return a buffer", async () => {
|
|
50
|
+
mockFetch.mockResolvedValueOnce(new Response("content"));
|
|
51
|
+
mockPromisesAccess.mockResolvedValue();
|
|
52
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
53
|
+
const buffer = await converter.convert({
|
|
54
|
+
url: "http://www.example.com/",
|
|
55
|
+
header: "path/to/header.html",
|
|
56
|
+
});
|
|
57
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
58
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
59
|
+
});
|
|
60
|
+
});
|
|
61
|
+
|
|
62
|
+
describe("when footer parameter is passed", () => {
|
|
63
|
+
it("should return a buffer", async () => {
|
|
64
|
+
mockFetch.mockResolvedValueOnce(new Response("content"));
|
|
65
|
+
mockPromisesAccess.mockResolvedValue();
|
|
66
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
67
|
+
const buffer = await converter.convert({
|
|
68
|
+
url: "http://www.example.com/",
|
|
69
|
+
footer: "path/to/footer.html",
|
|
70
|
+
});
|
|
71
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
72
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
|
|
39
76
|
describe("when pdf format parameter is passed", () => {
|
|
40
77
|
it("should return a buffer", async () => {
|
|
41
78
|
mockFetch.mockResolvedValueOnce(new Response("content"));
|
|
@@ -43,7 +80,7 @@ describe("HtmlConverter", () => {
|
|
|
43
80
|
url: "http://www.example.com/",
|
|
44
81
|
pdfFormat: PdfFormat.A_3b,
|
|
45
82
|
});
|
|
46
|
-
expect(mockFormDataAppend).
|
|
83
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
47
84
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
48
85
|
});
|
|
49
86
|
});
|
|
@@ -55,7 +92,37 @@ describe("HtmlConverter", () => {
|
|
|
55
92
|
url: "http://www.example.com/",
|
|
56
93
|
properties: { size: { width: 8.3, height: 11.7 } },
|
|
57
94
|
});
|
|
58
|
-
expect(mockFormDataAppend).
|
|
95
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(3);
|
|
96
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
97
|
+
});
|
|
98
|
+
});
|
|
99
|
+
|
|
100
|
+
describe("when emulatedMediaType parameter is passed", () => {
|
|
101
|
+
it("should return a buffer", async () => {
|
|
102
|
+
mockPromisesAccess.mockResolvedValue();
|
|
103
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
104
|
+
const buffer = await converter.convert({
|
|
105
|
+
url: "http://www.example.com/",
|
|
106
|
+
emulatedMediaType: "screen",
|
|
107
|
+
});
|
|
108
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(2);
|
|
109
|
+
expect(buffer).toEqual(Buffer.from("content"));
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
|
|
113
|
+
describe("when all parameters are passed", () => {
|
|
114
|
+
it("should return a buffer", async () => {
|
|
115
|
+
mockPromisesAccess.mockResolvedValue();
|
|
116
|
+
mockFetch.mockResolvedValue(new Response("content"));
|
|
117
|
+
const buffer = await converter.convert({
|
|
118
|
+
url: "http://www.example.com/",
|
|
119
|
+
header: "path/to/header.html",
|
|
120
|
+
footer: "path/to/footer.html",
|
|
121
|
+
pdfFormat: PdfFormat.A_1a,
|
|
122
|
+
emulatedMediaType: "screen",
|
|
123
|
+
properties: { size: { width: 8.3, height: 11.7 } },
|
|
124
|
+
});
|
|
125
|
+
expect(mockFormDataAppend).toHaveBeenCalledTimes(7);
|
|
59
126
|
expect(buffer).toEqual(Buffer.from("content"));
|
|
60
127
|
});
|
|
61
128
|
});
|
|
@@ -64,7 +131,7 @@ describe("HtmlConverter", () => {
|
|
|
64
131
|
it("should throw an error", async () => {
|
|
65
132
|
await expect(() =>
|
|
66
133
|
converter.convert({ url: "invalid url" })
|
|
67
|
-
).rejects.toThrow("Invalid URL
|
|
134
|
+
).rejects.toThrow("Invalid URL");
|
|
68
135
|
});
|
|
69
136
|
});
|
|
70
137
|
|
|
@@ -1,41 +1,69 @@
|
|
|
1
|
+
import { PathLike } from "fs";
|
|
2
|
+
|
|
1
3
|
import { URL } from "url";
|
|
2
4
|
|
|
3
5
|
import FormData from "form-data";
|
|
4
6
|
|
|
5
7
|
import { GotenbergUtils, PdfFormat } from "../../common";
|
|
6
|
-
import {
|
|
7
|
-
|
|
8
|
+
import {
|
|
9
|
+
EmulatedMediaType,
|
|
10
|
+
PageProperties,
|
|
11
|
+
} from "../interfaces/converter.types";
|
|
8
12
|
import { ConverterUtils } from "../utils/converter.utils";
|
|
9
13
|
import { Converter } from "./converter";
|
|
10
14
|
import { ChromiumRoute } from "../../main.config";
|
|
11
15
|
|
|
12
|
-
export class UrlConverter extends Converter
|
|
16
|
+
export class UrlConverter extends Converter {
|
|
13
17
|
constructor() {
|
|
14
18
|
super(ChromiumRoute.URL);
|
|
15
19
|
}
|
|
16
20
|
|
|
17
21
|
async convert({
|
|
18
22
|
url,
|
|
23
|
+
header,
|
|
24
|
+
footer,
|
|
19
25
|
properties,
|
|
20
26
|
pdfFormat,
|
|
27
|
+
pdfUA,
|
|
28
|
+
emulatedMediaType,
|
|
29
|
+
waitDelay,
|
|
30
|
+
waitForExpression,
|
|
31
|
+
userAgent,
|
|
32
|
+
extraHttpHeaders,
|
|
33
|
+
failOnConsoleExceptions,
|
|
21
34
|
}: {
|
|
22
35
|
url: string;
|
|
36
|
+
header?: PathLike;
|
|
37
|
+
footer?: PathLike;
|
|
23
38
|
properties?: PageProperties;
|
|
24
39
|
pdfFormat?: PdfFormat;
|
|
40
|
+
pdfUA?: boolean;
|
|
41
|
+
emulatedMediaType?: EmulatedMediaType;
|
|
42
|
+
waitDelay?: string;
|
|
43
|
+
waitForExpression?: string;
|
|
44
|
+
userAgent?: string;
|
|
45
|
+
extraHttpHeaders?: Record<string, string>;
|
|
46
|
+
failOnConsoleExceptions?: boolean;
|
|
25
47
|
}): Promise<Buffer> {
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
48
|
+
const _url = new URL(url);
|
|
49
|
+
const data = new FormData();
|
|
50
|
+
|
|
51
|
+
data.append("url", _url.href);
|
|
52
|
+
|
|
53
|
+
ConverterUtils.customize(data, {
|
|
54
|
+
header,
|
|
55
|
+
footer,
|
|
56
|
+
properties,
|
|
57
|
+
pdfFormat,
|
|
58
|
+
pdfUA,
|
|
59
|
+
emulatedMediaType,
|
|
60
|
+
waitDelay,
|
|
61
|
+
waitForExpression,
|
|
62
|
+
userAgent,
|
|
63
|
+
extraHttpHeaders,
|
|
64
|
+
failOnConsoleExceptions,
|
|
65
|
+
});
|
|
66
|
+
|
|
67
|
+
return GotenbergUtils.fetch(this.endpoint, data);
|
|
40
68
|
}
|
|
41
69
|
}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { PathLike } from "fs";
|
|
2
|
+
import { PdfFormat } from "../../common";
|
|
3
|
+
|
|
1
4
|
type PageSize = {
|
|
2
5
|
width: number; // Paper width, in inches (default 8.5)
|
|
3
6
|
height: number; //Paper height, in inches (default 11)
|
|
@@ -15,7 +18,24 @@ export type PageProperties = {
|
|
|
15
18
|
margins?: PageMargins;
|
|
16
19
|
preferCssPageSize?: boolean; // Define whether to prefer page size as defined by CSS (default false)
|
|
17
20
|
printBackground?: boolean; // Print the background graphics (default false)
|
|
21
|
+
omitBackground?: boolean; // Hide the default white background and allow generating PDFs with transparency (default false)
|
|
18
22
|
landscape?: boolean; // Set the paper orientation to landscape (default false)
|
|
19
23
|
scale?: number; // The scale of the page rendering (default 1.0)
|
|
20
24
|
nativePageRanges?: { from: number; to: number }; // Page ranges to print
|
|
21
25
|
};
|
|
26
|
+
|
|
27
|
+
export type EmulatedMediaType = "screen" | "print";
|
|
28
|
+
|
|
29
|
+
export type ConversionOptions = {
|
|
30
|
+
header?: PathLike;
|
|
31
|
+
footer?: PathLike;
|
|
32
|
+
properties?: PageProperties;
|
|
33
|
+
pdfFormat?: PdfFormat;
|
|
34
|
+
pdfUA?: boolean; // Enable PDF for Universal Access for optimal accessibility (default false)
|
|
35
|
+
emulatedMediaType?: EmulatedMediaType;
|
|
36
|
+
waitDelay?: string; // Duration (e.g, '5s') to wait when loading an HTML document before converting it into PDF
|
|
37
|
+
waitForExpression?: string; // JavaScript expression to wait before converting an HTML document into PDF until it returns true.
|
|
38
|
+
userAgent?: string;
|
|
39
|
+
extraHttpHeaders?: Record<string, string>;
|
|
40
|
+
failOnConsoleExceptions?: boolean; // Return a 409 Conflict response if there are exceptions in the Chromium console (default false)
|
|
41
|
+
};
|
|
@@ -1,7 +1,11 @@
|
|
|
1
|
+
import { constants, createReadStream, promises } from "fs";
|
|
1
2
|
import FormData from "form-data";
|
|
2
3
|
|
|
3
4
|
import { GotenbergUtils } from "../../common/gotenberg.utils";
|
|
4
|
-
import {
|
|
5
|
+
import {
|
|
6
|
+
ConversionOptions,
|
|
7
|
+
PageProperties,
|
|
8
|
+
} from "../interfaces/converter.types";
|
|
5
9
|
|
|
6
10
|
export class ConverterUtils {
|
|
7
11
|
public static injectPageProperties(
|
|
@@ -44,6 +48,10 @@ export class ConverterUtils {
|
|
|
44
48
|
data.append("printBackground", String(pageProperties.printBackground));
|
|
45
49
|
}
|
|
46
50
|
|
|
51
|
+
if (pageProperties.omitBackground) {
|
|
52
|
+
data.append("omitBackground", String(pageProperties.omitBackground));
|
|
53
|
+
}
|
|
54
|
+
|
|
47
55
|
if (pageProperties.landscape) {
|
|
48
56
|
data.append("landscape", String(pageProperties.landscape));
|
|
49
57
|
}
|
|
@@ -72,4 +80,58 @@ export class ConverterUtils {
|
|
|
72
80
|
);
|
|
73
81
|
}
|
|
74
82
|
}
|
|
83
|
+
|
|
84
|
+
public static async customize(
|
|
85
|
+
data: FormData,
|
|
86
|
+
options: ConversionOptions
|
|
87
|
+
): Promise<void> {
|
|
88
|
+
if (options.pdfFormat) {
|
|
89
|
+
data.append("pdfa", options.pdfFormat);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (options.pdfUA) {
|
|
93
|
+
data.append("pdfua", String(options.pdfUA));
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (options.header) {
|
|
97
|
+
await promises.access(options.header, constants.R_OK);
|
|
98
|
+
data.append("header.html", createReadStream(options.header));
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (options.footer) {
|
|
102
|
+
await promises.access(options.footer, constants.R_OK);
|
|
103
|
+
data.append("footer.html", createReadStream(options.footer));
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
if (options.emulatedMediaType) {
|
|
107
|
+
data.append("emulatedMediaType", options.emulatedMediaType);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (options.properties) {
|
|
111
|
+
ConverterUtils.injectPageProperties(data, options.properties);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
if (options.waitDelay) {
|
|
115
|
+
data.append("waitDelay", options.waitDelay);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
if (options.waitForExpression) {
|
|
119
|
+
data.append("waitForExpression", options.waitForExpression);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
if (options.userAgent) {
|
|
123
|
+
data.append("userAgent", options.userAgent);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
if (options.extraHttpHeaders) {
|
|
127
|
+
data.append("extraHttpHeaders", JSON.stringify(options.extraHttpHeaders));
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (options.failOnConsoleExceptions) {
|
|
131
|
+
data.append(
|
|
132
|
+
"failOnConsoleExceptions",
|
|
133
|
+
String(options.failOnConsoleExceptions)
|
|
134
|
+
);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
75
137
|
}
|