@things-factory/integration-headless 7.0.56 → 7.0.57
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/dist-server/engine/task/headless-pdf-capture-board.js +78 -22
- package/dist-server/engine/task/headless-pdf-capture-board.js.map +1 -1
- package/dist-server/engine/task/index.d.ts +1 -0
- package/dist-server/engine/task/index.js +1 -0
- package/dist-server/engine/task/index.js.map +1 -1
- package/dist-server/engine/task/pdf-capture-util.d.ts +1 -1
- package/dist-server/engine/task/pdf-capture-util.js +8 -4
- package/dist-server/engine/task/pdf-capture-util.js.map +1 -1
- package/dist-server/tsconfig.tsbuildinfo +1 -1
- package/package.json +2 -2
- package/server/engine/task/headless-pdf-capture-board.ts +109 -38
- package/server/engine/task/index.ts +1 -0
- package/server/engine/task/pdf-capture-util.ts +8 -4
- package/translations/en.json +2 -1
- package/translations/ja.json +2 -0
- package/translations/ko.json +1 -0
- package/translations/ms.json +2 -0
- package/translations/zh.json +2 -0
|
@@ -4,44 +4,99 @@ exports.HeadlessPDFCaptureBoard = HeadlessPDFCaptureBoard;
|
|
|
4
4
|
const integration_base_1 = require("@things-factory/integration-base");
|
|
5
5
|
const pdf_capture_util_1 = require("./pdf-capture-util");
|
|
6
6
|
const board_service_1 = require("@things-factory/board-service");
|
|
7
|
+
const utils_1 = require("@things-factory/utils");
|
|
7
8
|
const PAGE_FORMATS = {
|
|
8
9
|
A4: { width: 595.28, height: 841.89 },
|
|
9
10
|
A3: { width: 841.89, height: 1190.55 },
|
|
10
11
|
Letter: { width: 612, height: 792 },
|
|
11
12
|
Legal: { width: 612, height: 1008 }
|
|
12
13
|
};
|
|
14
|
+
function convertToPixels(value) {
|
|
15
|
+
const dpi = 96; // PDF에서 기본적으로 사용하는 DPI
|
|
16
|
+
if (value.endsWith('px')) {
|
|
17
|
+
return parseFloat(value);
|
|
18
|
+
}
|
|
19
|
+
else if (value.endsWith('in')) {
|
|
20
|
+
const inches = parseFloat(value);
|
|
21
|
+
return inches * dpi;
|
|
22
|
+
}
|
|
23
|
+
else if (value.endsWith('cm')) {
|
|
24
|
+
const cm = parseFloat(value);
|
|
25
|
+
return cm * (dpi / 2.54);
|
|
26
|
+
}
|
|
27
|
+
return 0;
|
|
28
|
+
}
|
|
13
29
|
async function HeadlessPDFCaptureBoard(step, context) {
|
|
14
|
-
var _a, _b;
|
|
15
30
|
const pdfUtil = new pdf_capture_util_1.PDFCaptureUtil(context);
|
|
16
31
|
await pdfUtil.initBrowser(step.connection);
|
|
17
32
|
try {
|
|
18
|
-
|
|
19
|
-
|
|
33
|
+
var { board: boardObject, accessor, boardAccessor, draft, format = 'A4', width, height, landscape, marginLeft = 0, marginRight = 0, marginTop = 0, marginBottom = 0 } = step.params;
|
|
34
|
+
var { domain, data, user, logger } = context;
|
|
35
|
+
const boardId = boardAccessor ? (0, utils_1.access)(boardAccessor, data) : boardObject === null || boardObject === void 0 ? void 0 : boardObject.id;
|
|
36
|
+
if (!boardId) {
|
|
20
37
|
throw new Error('The board property must be set');
|
|
21
38
|
}
|
|
22
|
-
const
|
|
23
|
-
const
|
|
39
|
+
const boardInput = (0, utils_1.access)(accessor, data);
|
|
40
|
+
const { model, base } = await board_service_1.BoardFunc.headlessModel({ domain, id: boardId }, draft);
|
|
41
|
+
const [fontsToUse, fontStyles] = await board_service_1.BoardFunc.fonts(domain);
|
|
24
42
|
model.fonts = fontsToUse;
|
|
25
43
|
model.fontStyles = fontStyles;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
if (
|
|
29
|
-
|
|
30
|
-
|
|
44
|
+
var widthN = width ? convertToPixels(width) : 0;
|
|
45
|
+
var heightN = height ? convertToPixels(height) : 0;
|
|
46
|
+
if (!widthN && !heightN && PAGE_FORMATS[format]) {
|
|
47
|
+
const pageDimensions = PAGE_FORMATS[format];
|
|
48
|
+
widthN = pageDimensions.width * (96 / 72);
|
|
49
|
+
heightN = pageDimensions.height * (96 / 72);
|
|
31
50
|
}
|
|
32
|
-
if (landscape &&
|
|
51
|
+
if (landscape && widthN && heightN) {
|
|
33
52
|
;
|
|
34
|
-
[
|
|
53
|
+
[widthN, heightN] = [heightN, widthN];
|
|
35
54
|
}
|
|
55
|
+
marginLeft = convertToPixels(marginLeft);
|
|
56
|
+
marginTop = convertToPixels(marginTop);
|
|
57
|
+
marginBottom = convertToPixels(marginBottom);
|
|
58
|
+
marginRight = convertToPixels(marginRight);
|
|
59
|
+
const contentWidth = widthN - marginLeft - marginRight;
|
|
60
|
+
const contentHeight = heightN - marginTop - marginBottom;
|
|
61
|
+
const page = await pdfUtil.browser.newPage();
|
|
62
|
+
await page.setViewport({ width: Math.round(contentWidth), height: Math.round(contentHeight) });
|
|
63
|
+
await page.setRequestInterception(true);
|
|
64
|
+
await page.setDefaultTimeout(10000);
|
|
65
|
+
page.on('console', async (msg) => {
|
|
66
|
+
console.log(`[browser ${msg.type()}] ${msg.text()}`);
|
|
67
|
+
});
|
|
68
|
+
page.on('requestfailed', request => {
|
|
69
|
+
console.log('Request failed:', request.url());
|
|
70
|
+
});
|
|
36
71
|
const protocol = 'http';
|
|
37
72
|
const host = 'localhost';
|
|
38
73
|
const port = process.env.PORT ? `:${process.env.PORT}` : '';
|
|
39
74
|
const path = '/internal-board-service-view';
|
|
40
75
|
const url = `${protocol}://${host}${port}${path}`;
|
|
41
|
-
const
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
76
|
+
const token = await (user === null || user === void 0 ? void 0 : user.sign());
|
|
77
|
+
page.on('request', request => {
|
|
78
|
+
if (request.url() === url) {
|
|
79
|
+
request.continue({
|
|
80
|
+
method: 'POST',
|
|
81
|
+
headers: {
|
|
82
|
+
'Content-Type': 'application/json',
|
|
83
|
+
'x-things-factory-domain': domain === null || domain === void 0 ? void 0 : domain.subdomain,
|
|
84
|
+
Authorization: 'Bearer ' + token
|
|
85
|
+
},
|
|
86
|
+
postData: JSON.stringify({
|
|
87
|
+
model,
|
|
88
|
+
base
|
|
89
|
+
})
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
else if (request.url().startsWith(`${protocol}://${host}${port}`)) {
|
|
93
|
+
request.continue({
|
|
94
|
+
headers: Object.assign(Object.assign({}, request.headers()), { 'x-things-factory-domain': domain === null || domain === void 0 ? void 0 : domain.subdomain, Authorization: 'Bearer ' + token })
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
else {
|
|
98
|
+
request.continue();
|
|
99
|
+
}
|
|
45
100
|
});
|
|
46
101
|
await page.goto(url);
|
|
47
102
|
await page.evaluate(data => {
|
|
@@ -50,12 +105,8 @@ async function HeadlessPDFCaptureBoard(step, context) {
|
|
|
50
105
|
return new Promise(resolve => {
|
|
51
106
|
requestAnimationFrame(() => resolve(0));
|
|
52
107
|
});
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
const pageOptions = pdfUtil.buildPageOptions(Object.assign(Object.assign({}, step.params), { width: width ? `${width}px` : undefined, height: height ? `${height}px` : undefined }));
|
|
56
|
-
// PDF 생성 및 추가
|
|
57
|
-
const htmlContent = ''; // 보드에서 직접 렌더링되므로 HTML 컨텐츠가 비어있음
|
|
58
|
-
await pdfUtil.processPageAndGeneratePDF(pageOptions, htmlContent); // pageOptions 사용
|
|
108
|
+
}, boardInput);
|
|
109
|
+
await pdfUtil.processPageAndGeneratePDF(step.params, null, page);
|
|
59
110
|
return {
|
|
60
111
|
data: context.__headless_pdf
|
|
61
112
|
};
|
|
@@ -69,6 +120,11 @@ async function HeadlessPDFCaptureBoard(step, context) {
|
|
|
69
120
|
}
|
|
70
121
|
HeadlessPDFCaptureBoard.parameterSpec = [
|
|
71
122
|
...(0, pdf_capture_util_1.getCommonParameterSpec)(),
|
|
123
|
+
{
|
|
124
|
+
type: 'string',
|
|
125
|
+
name: 'boardAccessor',
|
|
126
|
+
label: 'board-accessor'
|
|
127
|
+
},
|
|
72
128
|
{
|
|
73
129
|
type: 'resource-object',
|
|
74
130
|
name: 'board',
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"headless-pdf-capture-board.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-capture-board.ts"],"names":[],"mappings":";;AAaA,0DA0EC;AAvFD,uEAA+D;AAC/D,yDAA2E;AAC3E,iEAAyD;AAEzD,MAAM,YAAY,GAAG;IACnB,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE;IACrC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,EAAE;IACtC,MAAM,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE;IACnC,KAAK,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE;CACpC,CAAA;AAIM,KAAK,UAAU,uBAAuB,CAAC,IAAI,EAAE,OAAO;;IACzD,MAAM,OAAO,GAAG,IAAI,iCAAc,CAAC,OAAO,CAAC,CAAA;IAC3C,MAAM,OAAO,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,CAAA;IAE1C,IAAI,CAAC;QACH,MAAM,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,GAAG,IAAI,EAAE,SAAS,EAAE,iBAAiB,EAAE,GAAG,IAAI,CAAC,MAAM,CAAA;QAEjF,IAAI,CAAC,KAAK,IAAI,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,gCAAgC,CAAC,CAAA;QACnD,CAAC;QAED,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,GAAG,MAAM,yBAAS,CAAC,aAAa,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,EAAE,EAAE,KAAK,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAA;QACtG,MAAM,CAAC,UAAU,EAAE,UAAU,CAAC,GAAG,MAAM,yBAAS,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAA;QAEtE,KAAK,CAAC,KAAK,GAAG,UAAU,CAAA;QACxB,KAAK,CAAC,UAAU,GAAG,UAAU,CAAA;QAE7B,IAAI,KAAK,GAAuB,MAAA,YAAY,CAAC,MAAoB,CAAC,0CAAE,KAAK,CAAA;QACzE,IAAI,MAAM,GAAuB,MAAA,YAAY,CAAC,MAAoB,CAAC,0CAAE,MAAM,CAAA;QAE3E,IAAI,iBAAiB,EAAE,CAAC;YACtB,KAAK,GAAG,SAAS,CAAA;YACjB,MAAM,GAAG,SAAS,CAAA;QACpB,CAAC;QAED,IAAI,SAAS,IAAI,KAAK,IAAI,MAAM,EAAE,CAAC;YACjC,CAAC;YAAA,CAAC,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QACpC,CAAC;QAED,MAAM,QAAQ,GAAG,MAAM,CAAA;QACvB,MAAM,IAAI,GAAG,WAAW,CAAA;QACxB,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAA;QAC3D,MAAM,IAAI,GAAG,8BAA8B,CAAA;QAC3C,MAAM,GAAG,GAAG,GAAG,QAAQ,MAAM,IAAI,GAAG,IAAI,GAAG,IAAI,EAAE,CAAA;QAEjD,MAAM,IAAI,GAAG,MAAM,OAAO,CAAC,OAAQ,CAAC,OAAO,EAAE,CAAA;QAE7C,MAAM,IAAI,CAAC,WAAW,CAAC;YACrB,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,IAAI,GAAG,CAAC,EAAE,oCAAoC;YACrE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,GAAG,CAAC,CAAC,qCAAqC;SACxE,CAAC,CAAA;QAEF,MAAM,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;QAEpB,MAAM,IAAI,CAAC,QAAQ,CACjB,IAAI,CAAC,EAAE;YACL,YAAY;YACZ,CAAC,CAAC,IAAI,GAAG,IAAI,CAAA;YACb,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,EAAE;gBAC3B,qBAAqB,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAA;YACzC,CAAC,CAAC,CAAA;QACJ,CAAC,EACD,EAAE,KAAK,EAAE,IAAI,EAAE,CAChB,CAAA;QAED,YAAY;QACZ,MAAM,WAAW,GAAG,OAAO,CAAC,gBAAgB,iCACvC,IAAI,CAAC,MAAM,KACd,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,EACvC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,MAAM,IAAI,CAAC,CAAC,CAAC,SAAS,IAC1C,CAAA;QAEF,cAAc;QACd,MAAM,WAAW,GAAG,EAAE,CAAA,CAAC,gCAAgC;QACvD,MAAM,OAAO,CAAC,yBAAyB,CAAC,WAAW,EAAE,WAAW,CAAC,CAAA,CAAC,iBAAiB;QAEnF,OAAO;YACL,IAAI,EAAE,OAAO,CAAC,cAAc;SAC7B,CAAA;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,MAAM,KAAK,CAAA;IACb,CAAC;YAAS,CAAC;QACT,MAAM,OAAO,CAAC,YAAY,EAAE,CAAA;IAC9B,CAAC;AACH,CAAC;AAED,uBAAuB,CAAC,aAAa,GAAG;IACtC,GAAG,IAAA,yCAAsB,GAAE;IAC3B;QACE,IAAI,EAAE,iBAAiB;QACvB,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,OAAO;QACd,QAAQ,EAAE;YACR,SAAS,EAAE,QAAQ;SACpB;KACF;IACD;QACE,IAAI,EAAE,SAAS;QACf,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,aAAa;QACpB,YAAY,EAAE,KAAK;QACnB,WAAW,EAAE,6EAA6E;KAC3F;CACF,CAAA;AAED,uBAAuB,CAAC,IAAI,GAAG,6CAA6C,CAAA;AAE5E,+BAAY,CAAC,mBAAmB,CAAC,4BAA4B,EAAE,uBAAuB,CAAC,CAAA","sourcesContent":["import { TaskRegistry } from '@things-factory/integration-base'\nimport { PDFCaptureUtil, getCommonParameterSpec } from './pdf-capture-util'\nimport { BoardFunc } from '@things-factory/board-service'\n\nconst PAGE_FORMATS = {\n A4: { width: 595.28, height: 841.89 },\n A3: { width: 841.89, height: 1190.55 },\n Letter: { width: 612, height: 792 },\n Legal: { width: 612, height: 1008 }\n}\n\ntype PageFormat = keyof typeof PAGE_FORMATS\n\nexport async function HeadlessPDFCaptureBoard(step, context) {\n const pdfUtil = new PDFCaptureUtil(context)\n await pdfUtil.initBrowser(step.connection)\n\n try {\n const { board, draft, format = 'A4', landscape, preferCSSPageSize } = step.params\n\n if (!board || !board.id) {\n throw new Error('The board property must be set')\n }\n\n const { model, base } = await BoardFunc.headlessModel({ domain: context.domain, id: board.id }, draft)\n const [fontsToUse, fontStyles] = await BoardFunc.fonts(context.domain)\n\n model.fonts = fontsToUse\n model.fontStyles = fontStyles\n\n let width: number | undefined = PAGE_FORMATS[format as PageFormat]?.width\n let height: number | undefined = PAGE_FORMATS[format as PageFormat]?.height\n\n if (preferCSSPageSize) {\n width = undefined\n height = undefined\n }\n\n if (landscape && width && height) {\n ;[width, height] = [height, width]\n }\n\n const protocol = 'http'\n const host = 'localhost'\n const port = process.env.PORT ? `:${process.env.PORT}` : ''\n const path = '/internal-board-service-view'\n const url = `${protocol}://${host}${port}${path}`\n\n const page = await pdfUtil.browser!.newPage()\n\n await page.setViewport({\n width: Math.round(width || 800), // Fallback for width if not defined\n height: Math.round(height || 600) // Fallback for height if not defined\n })\n\n await page.goto(url)\n\n await page.evaluate(\n data => {\n //@ts-ignore\n s.data = data\n return new Promise(resolve => {\n requestAnimationFrame(() => resolve(0))\n })\n },\n { model, base }\n )\n\n // 페이지 옵션 설정\n const pageOptions = pdfUtil.buildPageOptions({\n ...step.params,\n width: width ? `${width}px` : undefined,\n height: height ? `${height}px` : undefined\n })\n\n // PDF 생성 및 추가\n const htmlContent = '' // 보드에서 직접 렌더링되므로 HTML 컨텐츠가 비어있음\n await pdfUtil.processPageAndGeneratePDF(pageOptions, htmlContent) // pageOptions 사용\n\n return {\n data: context.__headless_pdf\n }\n } catch (error) {\n throw error\n } finally {\n await pdfUtil.closeBrowser()\n }\n}\n\nHeadlessPDFCaptureBoard.parameterSpec = [\n ...getCommonParameterSpec(),\n {\n type: 'resource-object',\n name: 'board',\n label: 'board',\n property: {\n queryName: 'boards'\n }\n },\n {\n type: 'boolean',\n name: 'draft',\n label: 'board-draft',\n defaultValue: false,\n description: 'Set whether to get the current working version or the last released version'\n }\n]\n\nHeadlessPDFCaptureBoard.help = 'integration/task/headless-pdf-capture-board'\n\nTaskRegistry.registerTaskHandler('headless-pdf-capture-board', HeadlessPDFCaptureBoard)\n"]}
|
|
1
|
+
{"version":3,"file":"headless-pdf-capture-board.js","sourceRoot":"","sources":["../../../server/engine/task/headless-pdf-capture-board.ts"],"names":[],"mappings":"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","sourcesContent":["import { TaskRegistry } from '@things-factory/integration-base'\nimport { PDFCaptureUtil, getCommonParameterSpec } from './pdf-capture-util'\nimport { BoardFunc } from '@things-factory/board-service'\nimport { access } from '@things-factory/utils'\n\nconst PAGE_FORMATS = {\n A4: { width: 595.28, height: 841.89 },\n A3: { width: 841.89, height: 1190.55 },\n Letter: { width: 612, height: 792 },\n Legal: { width: 612, height: 1008 }\n}\n\nfunction convertToPixels(value: string): number {\n const dpi = 96 // PDF에서 기본적으로 사용하는 DPI\n\n if (value.endsWith('px')) {\n return parseFloat(value)\n } else if (value.endsWith('in')) {\n const inches = parseFloat(value)\n return inches * dpi\n } else if (value.endsWith('cm')) {\n const cm = parseFloat(value)\n return cm * (dpi / 2.54)\n }\n\n return 0\n}\n\nexport async function HeadlessPDFCaptureBoard(step, context) {\n const pdfUtil = new PDFCaptureUtil(context)\n await pdfUtil.initBrowser(step.connection)\n\n try {\n var {\n board: boardObject,\n accessor,\n boardAccessor,\n draft,\n format = 'A4',\n width,\n height,\n landscape,\n marginLeft = 0,\n marginRight = 0,\n marginTop = 0,\n marginBottom = 0\n } = step.params\n var { domain, data, user, logger } = context\n\n const boardId = boardAccessor ? access(boardAccessor, data) : boardObject?.id\n\n if (!boardId) {\n throw new Error('The board property must be set')\n }\n\n const boardInput = access(accessor, data)\n\n const { model, base } = await BoardFunc.headlessModel({ domain, id: boardId }, draft)\n const [fontsToUse, fontStyles] = await BoardFunc.fonts(domain)\n\n model.fonts = fontsToUse\n model.fontStyles = fontStyles\n\n var widthN = width ? convertToPixels(width) : 0\n var heightN = height ? convertToPixels(height) : 0\n\n if (!widthN && !heightN && PAGE_FORMATS[format]) {\n const pageDimensions = PAGE_FORMATS[format]\n widthN = pageDimensions.width * (96 / 72)\n heightN = pageDimensions.height * (96 / 72)\n }\n\n if (landscape && widthN && heightN) {\n ;[widthN, heightN] = [heightN, widthN]\n }\n\n marginLeft = convertToPixels(marginLeft)\n marginTop = convertToPixels(marginTop)\n marginBottom = convertToPixels(marginBottom)\n marginRight = convertToPixels(marginRight)\n\n const contentWidth = widthN - marginLeft - marginRight\n const contentHeight = heightN - marginTop - marginBottom\n\n const page = await pdfUtil.browser!.newPage()\n\n await page.setViewport({ width: Math.round(contentWidth), height: Math.round(contentHeight) })\n await page.setRequestInterception(true)\n await page.setDefaultTimeout(10000)\n\n page.on('console', async msg => {\n console.log(`[browser ${msg.type()}] ${msg.text()}`)\n })\n\n page.on('requestfailed', request => {\n console.log('Request failed:', request.url())\n })\n\n const protocol = 'http'\n const host = 'localhost'\n const port = process.env.PORT ? `:${process.env.PORT}` : ''\n const path = '/internal-board-service-view'\n const url = `${protocol}://${host}${port}${path}`\n\n const token = await user?.sign()\n\n page.on('request', request => {\n if (request.url() === url) {\n request.continue({\n method: 'POST',\n headers: {\n 'Content-Type': 'application/json',\n 'x-things-factory-domain': domain?.subdomain,\n Authorization: 'Bearer ' + token\n },\n postData: JSON.stringify({\n model,\n base\n })\n })\n } else if (request.url().startsWith(`${protocol}://${host}${port}`)) {\n request.continue({\n headers: {\n ...request.headers(),\n 'x-things-factory-domain': domain?.subdomain,\n Authorization: 'Bearer ' + token\n }\n })\n } else {\n request.continue()\n }\n })\n\n await page.goto(url)\n\n await page.evaluate(data => {\n //@ts-ignore\n s.data = data\n return new Promise(resolve => {\n requestAnimationFrame(() => resolve(0))\n })\n }, boardInput)\n\n await pdfUtil.processPageAndGeneratePDF(step.params, null, page)\n\n return {\n data: context.__headless_pdf\n }\n } catch (error) {\n throw error\n } finally {\n await pdfUtil.closeBrowser()\n }\n}\n\nHeadlessPDFCaptureBoard.parameterSpec = [\n ...getCommonParameterSpec(),\n {\n type: 'string',\n name: 'boardAccessor',\n label: 'board-accessor'\n },\n {\n type: 'resource-object',\n name: 'board',\n label: 'board',\n property: {\n queryName: 'boards'\n }\n },\n {\n type: 'boolean',\n name: 'draft',\n label: 'board-draft',\n defaultValue: false,\n description: 'Set whether to get the current working version or the last released version'\n }\n]\n\nHeadlessPDFCaptureBoard.help = 'integration/task/headless-pdf-capture-board'\n\nTaskRegistry.registerTaskHandler('headless-pdf-capture-board', HeadlessPDFCaptureBoard)\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/engine/task/index.ts"],"names":[],"mappings":";;AAAA,kCAA+B;AAC/B,2CAAwC;AACxC,wCAAqC;AACrC,+BAA4B;AAC5B,+BAA4B","sourcesContent":["import './headless-pdf-capture'\nimport './headless-pdf-capture-markdown'\nimport './headless-pdf-capture-board'\nimport './headless-pdf-open'\nimport './headless-pdf-save'\n"]}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../server/engine/task/index.ts"],"names":[],"mappings":";;AAAA,kCAA+B;AAC/B,2CAAwC;AACxC,wCAAqC;AACrC,+BAA4B;AAC5B,+BAA4B;AAC5B,8BAA2B","sourcesContent":["import './headless-pdf-capture'\nimport './headless-pdf-capture-markdown'\nimport './headless-pdf-capture-board'\nimport './headless-pdf-open'\nimport './headless-pdf-save'\nimport './pdf-capture-util'\n"]}
|
|
@@ -30,7 +30,7 @@ export declare class PDFCaptureUtil {
|
|
|
30
30
|
renderTemplate(template: string, data: any): string;
|
|
31
31
|
generatePDFContent(page: Page, pageOptions: any): Promise<PDFDocument>;
|
|
32
32
|
appendPDFContentToDocument(pdfDoc: PDFDocument, contentPdfDoc: PDFDocument): Promise<void>;
|
|
33
|
-
processPageAndGeneratePDF(stepOptions: StepOptions, htmlContent: string): Promise<void>;
|
|
33
|
+
processPageAndGeneratePDF(stepOptions: StepOptions, htmlContent: string, page?: Page): Promise<void>;
|
|
34
34
|
buildPageOptions({ format, width, height, marginTop, marginBottom, marginLeft, marginRight, scale, printBackground, landscape, preferCSSPageSize }: StepOptions): any;
|
|
35
35
|
applyHeaderFooterWatermark(page: Page, { header, footer, watermark, landscape, data }: {
|
|
36
36
|
header: string;
|
|
@@ -42,12 +42,16 @@ class PDFCaptureUtil {
|
|
|
42
42
|
copiedPages.forEach(page => pdfDoc.addPage(page));
|
|
43
43
|
this.context.__headless_pdf.pageCount += copiedPages.length;
|
|
44
44
|
}
|
|
45
|
-
async processPageAndGeneratePDF(stepOptions, htmlContent) {
|
|
45
|
+
async processPageAndGeneratePDF(stepOptions, htmlContent, page) {
|
|
46
46
|
if (!this.browser)
|
|
47
47
|
throw new Error('Browser not initialized. Call initBrowser() first.');
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
48
|
+
if (!page) {
|
|
49
|
+
page = page || (await this.browser.newPage());
|
|
50
|
+
}
|
|
51
|
+
if (htmlContent) {
|
|
52
|
+
// 페이지 컨텐츠 설정
|
|
53
|
+
await page.setContent(htmlContent, { waitUntil: 'networkidle0' }); // HTML 컨텐츠가 완전히 로드될 때까지 대기
|
|
54
|
+
}
|
|
51
55
|
// 페이지가 완전히 로드된 후에 워터마크와 머릿글 적용
|
|
52
56
|
const { __headless_pdf } = this.context;
|
|
53
57
|
const { header, footer, watermark, landscape } = __headless_pdf;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pdf-capture-util.js","sourceRoot":"","sources":["../../../server/engine/task/pdf-capture-util.ts"],"names":[],"mappings":"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","sourcesContent":["import * as ejs from 'ejs'\nimport { ConnectionManager } from '@things-factory/integration-base'\nimport { PDFDocument } from 'pdf-lib'\nimport { Browser, Page } from 'puppeteer'\nimport { Logger } from 'winston'\n\ninterface StepOptions {\n format?: string\n width?: string\n height?: string\n marginTop?: string\n marginBottom?: string\n marginLeft?: string\n marginRight?: string\n scale?: number\n printBackground?: boolean\n landscape?: boolean\n preferCSSPageSize?: boolean\n}\n\ninterface PDFContext {\n domain: any\n data: any\n logger: Logger\n __headless_pdf: any\n}\n\nexport class PDFCaptureUtil {\n private context: PDFContext\n private headlessPool: any\n\n public browser: Browser | null = null\n\n constructor(context: PDFContext) {\n this.context = context\n }\n\n async initBrowser(connectionName: string) {\n const { domain } = this.context\n this.headlessPool = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n this.browser = await this.headlessPool.acquire()\n }\n\n async closeBrowser() {\n if (this.browser) {\n await this.browser.close()\n this.headlessPool.release(this.browser)\n }\n }\n\n renderTemplate(template: string, data: any): string {\n const { logger } = this.context\n try {\n return ejs.render(template, data)\n } catch (error) {\n logger.warn(`Template rendering error: ${error.message}`)\n return template\n }\n }\n\n async generatePDFContent(page: Page, pageOptions: any): Promise<PDFDocument> {\n const contentBuffer = await page.pdf(pageOptions)\n const contentPdfDoc = await PDFDocument.load(contentBuffer)\n return contentPdfDoc\n }\n\n async appendPDFContentToDocument(pdfDoc: PDFDocument, contentPdfDoc: PDFDocument) {\n const copiedPages = await pdfDoc.copyPages(contentPdfDoc, contentPdfDoc.getPageIndices())\n copiedPages.forEach(page => pdfDoc.addPage(page))\n this.context.__headless_pdf.pageCount += copiedPages.length\n }\n\n async processPageAndGeneratePDF(stepOptions: StepOptions, htmlContent: string) {\n if (!this.browser) throw new Error('Browser not initialized. Call initBrowser() first.')\n\n const page = await this.browser.newPage()\n\n // 페이지 컨텐츠 설정\n await page.setContent(htmlContent, { waitUntil: 'networkidle0' }) // HTML 컨텐츠가 완전히 로드될 때까지 대기\n\n // 페이지가 완전히 로드된 후에 워터마크와 머릿글 적용\n const { __headless_pdf } = this.context\n const { header, footer, watermark, landscape } = __headless_pdf\n\n if (header || footer || watermark) {\n await this.applyHeaderFooterWatermark(page, { header, footer, watermark, landscape, data: __headless_pdf })\n }\n\n const pageOptions = this.buildPageOptions(stepOptions)\n const contentPdfDoc = await this.generatePDFContent(page, pageOptions)\n await this.appendPDFContentToDocument(__headless_pdf.pdfDoc, contentPdfDoc)\n await page.close()\n }\n\n buildPageOptions({\n format,\n width,\n height,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n scale,\n printBackground,\n landscape,\n preferCSSPageSize\n }: StepOptions): any {\n if (preferCSSPageSize) {\n width = undefined\n height = undefined\n }\n\n return {\n format,\n width,\n height,\n margin: {\n top: marginTop,\n right: marginRight,\n bottom: marginBottom,\n left: marginLeft\n },\n scale,\n printBackground,\n landscape,\n displayHeaderFooter: false,\n preferCSSPageSize\n }\n }\n\n async applyHeaderFooterWatermark(\n page: Page,\n {\n header,\n footer,\n watermark,\n landscape,\n data\n }: { header: string; footer: string; watermark: string; landscape: boolean; data: any }\n ) {\n await page.evaluate(\n ({ header, footer, watermark, landscape, data }) => {\n const setPositioning = (element: HTMLElement, position: 'header' | 'footer') => {\n element.style.position = 'fixed'\n element.style.left = '0'\n element.style.width = '100%'\n element.style.textAlign = 'center'\n element.style.fontSize = '12px'\n element.style.margin = '0'\n element.style.padding = '0'\n element.style.zIndex = '1000'\n\n if (position === 'header') {\n element.style.top = '0'\n } else if (position === 'footer') {\n element.style.bottom = '0'\n }\n }\n\n if (header) {\n const headerElement = document.createElement('div')\n headerElement.innerHTML = header\n setPositioning(headerElement, 'header')\n document.body.appendChild(headerElement)\n }\n\n if (footer) {\n const footerElement = document.createElement('div')\n footerElement.innerHTML = footer\n setPositioning(footerElement, 'footer')\n document.body.appendChild(footerElement)\n }\n\n if (watermark) {\n const watermarkElement = document.createElement('div')\n watermarkElement.innerHTML = watermark\n watermarkElement.style.position = 'fixed'\n watermarkElement.style.top = landscape ? '40%' : '50%'\n watermarkElement.style.left = '50%'\n watermarkElement.style.transform = 'translate(-50%, -50%) rotate(-45deg)'\n watermarkElement.style.opacity = '0.2'\n watermarkElement.style.fontSize = '50px'\n watermarkElement.style.color = 'red'\n watermarkElement.style.pointerEvents = 'none'\n watermarkElement.style.zIndex = '9999'\n document.body.appendChild(watermarkElement)\n }\n },\n {\n header: header && this.renderTemplate(header, data),\n footer: footer && this.renderTemplate(footer, data),\n watermark: watermark && this.renderTemplate(watermark, data),\n landscape,\n data\n }\n )\n }\n\n /**\n * Generates a PDF buffer for the last page.\n * @param stepOptions - Options used for generating the PDF.\n * @param htmlContent - HTML content to be converted to PDF.\n * @returns {Promise<Uint8Array>} - The generated PDF as a buffer.\n */\n async generateLastPageBuffer(stepOptions: StepOptions, htmlContent: string): Promise<Uint8Array> {\n if (!this.browser) throw new Error('Browser not initialized. Call initBrowser() first.')\n\n const page = await this.browser.newPage()\n\n // 페이지에 HTML 콘텐츠를 설정합니다.\n await page.setContent(htmlContent, { waitUntil: 'networkidle0' })\n\n // 페이지가 완전히 로드된 후에 워터마크와 머릿글 적용\n const { __headless_pdf } = this.context\n const { header, footer, watermark, landscape } = __headless_pdf\n\n if (header || footer || watermark) {\n await this.applyHeaderFooterWatermark(page, { header, footer, watermark, landscape, data: __headless_pdf })\n }\n\n // 페이지 옵션 설정\n const pageOptions = this.buildPageOptions(stepOptions)\n\n // PDF를 생성하고 버퍼를 반환합니다.\n const lastPageBuffer = await page.pdf(pageOptions)\n\n // 페이지 닫기\n await page.close()\n\n return lastPageBuffer\n }\n}\n\nexport function getCommonParameterSpec() {\n return [\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n },\n {\n type: 'select',\n name: 'format',\n label: 'page-format',\n property: {\n options: [\n { display: '', value: '' },\n { display: 'A4', value: 'A4' },\n { display: 'A3', value: 'A3' },\n { display: 'Letter', value: 'Letter' },\n { display: 'Legal', value: 'Legal' }\n ]\n },\n description: 'Select the paper format for the PDF'\n },\n {\n type: 'string',\n name: 'width',\n label: 'page-width',\n placeholder: '(e.g., \"8.5in\", \"21cm\", \"600px\")',\n description: 'Specify the width of the page (e.g., \"8.5in\", \"21cm\", \"600px\")'\n },\n {\n type: 'string',\n name: 'height',\n label: 'page-height',\n placeholder: '(e.g., \"11in\", \"29.7cm\", \"800px\")',\n description: 'Specify the height of the page (e.g., \"11in\", \"29.7cm\", \"800px\")'\n },\n {\n type: 'string',\n name: 'marginTop',\n label: 'page-margin-top',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the top margin for the page'\n },\n {\n type: 'string',\n name: 'marginBottom',\n label: 'page-margin-bottom',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the bottom margin for the page'\n },\n {\n type: 'string',\n name: 'marginLeft',\n label: 'page-margin-left',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the left margin for the page'\n },\n {\n type: 'string',\n name: 'marginRight',\n label: 'page-margin-right',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the right margin for the page'\n },\n {\n type: 'number',\n name: 'scale',\n label: 'page-scale',\n defaultValue: 1,\n description: 'Set the scale of the page content (default is 1)'\n },\n {\n type: 'boolean',\n name: 'printBackground',\n label: 'print-background',\n defaultValue: true,\n description: 'Include background graphics when printing the page'\n },\n {\n type: 'boolean',\n name: 'landscape',\n label: 'landscape',\n defaultValue: false,\n description: 'Print the PDF in landscape orientation'\n },\n {\n type: 'boolean',\n name: 'preferCSSPageSize',\n label: 'prefer-css-page-size',\n defaultValue: false,\n description: 'Whether to prefer the CSS-defined page size over the given width and height'\n }\n ]\n}\n"]}
|
|
1
|
+
{"version":3,"file":"pdf-capture-util.js","sourceRoot":"","sources":["../../../server/engine/task/pdf-capture-util.ts"],"names":[],"mappings":";;;AA6OA,wDA6FC;;AA1UD,iDAA0B;AAC1B,uEAAoE;AACpE,qCAAqC;AAyBrC,MAAa,cAAc;IAMzB,YAAY,OAAmB;QAFxB,YAAO,GAAmB,IAAI,CAAA;QAGnC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAA;IACxB,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,cAAsB;QACtC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QAC/B,IAAI,CAAC,YAAY,GAAG,oCAAiB,CAAC,2BAA2B,CAAC,MAAM,EAAE,cAAc,CAAC,CAAA;QACzF,IAAI,CAAC,OAAO,GAAG,MAAM,IAAI,CAAC,YAAY,CAAC,OAAO,EAAE,CAAA;IAClD,CAAC;IAED,KAAK,CAAC,YAAY;QAChB,IAAI,IAAI,CAAC,OAAO,EAAE,CAAC;YACjB,MAAM,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;YAC1B,IAAI,CAAC,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;QACzC,CAAC;IACH,CAAC;IAED,cAAc,CAAC,QAAgB,EAAE,IAAS;QACxC,MAAM,EAAE,MAAM,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QAC/B,IAAI,CAAC;YACH,OAAO,GAAG,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAA;QACnC,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,IAAI,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAA;YACzD,OAAO,QAAQ,CAAA;QACjB,CAAC;IACH,CAAC;IAED,KAAK,CAAC,kBAAkB,CAAC,IAAU,EAAE,WAAgB;QACnD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QACjD,MAAM,aAAa,GAAG,MAAM,qBAAW,CAAC,IAAI,CAAC,aAAa,CAAC,CAAA;QAC3D,OAAO,aAAa,CAAA;IACtB,CAAC;IAED,KAAK,CAAC,0BAA0B,CAAC,MAAmB,EAAE,aAA0B;QAC9E,MAAM,WAAW,GAAG,MAAM,MAAM,CAAC,SAAS,CAAC,aAAa,EAAE,aAAa,CAAC,cAAc,EAAE,CAAC,CAAA;QACzF,WAAW,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAA;QACjD,IAAI,CAAC,OAAO,CAAC,cAAc,CAAC,SAAS,IAAI,WAAW,CAAC,MAAM,CAAA;IAC7D,CAAC;IAED,KAAK,CAAC,yBAAyB,CAAC,WAAwB,EAAE,WAAmB,EAAE,IAAW;QACxF,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;QAExF,IAAI,CAAC,IAAI,EAAE,CAAC;YACV,IAAI,GAAG,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAA;QAC/C,CAAC;QAED,IAAI,WAAW,EAAE,CAAC;YAChB,aAAa;YACb,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,CAAA,CAAC,2BAA2B;QAC/F,CAAC;QAED,+BAA+B;QAC/B,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QACvC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,cAAc,CAAA;QAE/D,IAAI,MAAM,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YAClC,MAAM,IAAI,CAAC,0BAA0B,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAA;QAC7G,CAAC;QAED,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAA;QACtD,MAAM,aAAa,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAA;QACtE,MAAM,IAAI,CAAC,0BAA0B,CAAC,cAAc,CAAC,MAAM,EAAE,aAAa,CAAC,CAAA;QAC3E,MAAM,IAAI,CAAC,KAAK,EAAE,CAAA;IACpB,CAAC;IAED,gBAAgB,CAAC,EACf,MAAM,EACN,KAAK,EACL,MAAM,EACN,SAAS,EACT,YAAY,EACZ,UAAU,EACV,WAAW,EACX,KAAK,EACL,eAAe,EACf,SAAS,EACT,iBAAiB,EACL;QACZ,IAAI,iBAAiB,EAAE,CAAC;YACtB,KAAK,GAAG,SAAS,CAAA;YACjB,MAAM,GAAG,SAAS,CAAA;QACpB,CAAC;QAED,OAAO;YACL,MAAM;YACN,KAAK;YACL,MAAM;YACN,MAAM,EAAE;gBACN,GAAG,EAAE,SAAS;gBACd,KAAK,EAAE,WAAW;gBAClB,MAAM,EAAE,YAAY;gBACpB,IAAI,EAAE,UAAU;aACjB;YACD,KAAK;YACL,eAAe;YACf,SAAS;YACT,mBAAmB,EAAE,KAAK;YAC1B,iBAAiB;SAClB,CAAA;IACH,CAAC;IAED,KAAK,CAAC,0BAA0B,CAC9B,IAAU,EACV,EACE,MAAM,EACN,MAAM,EACN,SAAS,EACT,SAAS,EACT,IAAI,EACiF;QAEvF,MAAM,IAAI,CAAC,QAAQ,CACjB,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,EAAE,EAAE;YACjD,MAAM,cAAc,GAAG,CAAC,OAAoB,EAAE,QAA6B,EAAE,EAAE;gBAC7E,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAA;gBAChC,OAAO,CAAC,KAAK,CAAC,IAAI,GAAG,GAAG,CAAA;gBACxB,OAAO,CAAC,KAAK,CAAC,KAAK,GAAG,MAAM,CAAA;gBAC5B,OAAO,CAAC,KAAK,CAAC,SAAS,GAAG,QAAQ,CAAA;gBAClC,OAAO,CAAC,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAA;gBAC/B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAA;gBAC1B,OAAO,CAAC,KAAK,CAAC,OAAO,GAAG,GAAG,CAAA;gBAC3B,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;gBAE7B,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBAC1B,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAA;gBACzB,CAAC;qBAAM,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;oBACjC,OAAO,CAAC,KAAK,CAAC,MAAM,GAAG,GAAG,CAAA;gBAC5B,CAAC;YACH,CAAC,CAAA;YAED,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;gBACnD,aAAa,CAAC,SAAS,GAAG,MAAM,CAAA;gBAChC,cAAc,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;gBACvC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAA;YAC1C,CAAC;YAED,IAAI,MAAM,EAAE,CAAC;gBACX,MAAM,aAAa,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;gBACnD,aAAa,CAAC,SAAS,GAAG,MAAM,CAAA;gBAChC,cAAc,CAAC,aAAa,EAAE,QAAQ,CAAC,CAAA;gBACvC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,aAAa,CAAC,CAAA;YAC1C,CAAC;YAED,IAAI,SAAS,EAAE,CAAC;gBACd,MAAM,gBAAgB,GAAG,QAAQ,CAAC,aAAa,CAAC,KAAK,CAAC,CAAA;gBACtD,gBAAgB,CAAC,SAAS,GAAG,SAAS,CAAA;gBACtC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,GAAG,OAAO,CAAA;gBACzC,gBAAgB,CAAC,KAAK,CAAC,GAAG,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAA;gBACtD,gBAAgB,CAAC,KAAK,CAAC,IAAI,GAAG,KAAK,CAAA;gBACnC,gBAAgB,CAAC,KAAK,CAAC,SAAS,GAAG,sCAAsC,CAAA;gBACzE,gBAAgB,CAAC,KAAK,CAAC,OAAO,GAAG,KAAK,CAAA;gBACtC,gBAAgB,CAAC,KAAK,CAAC,QAAQ,GAAG,MAAM,CAAA;gBACxC,gBAAgB,CAAC,KAAK,CAAC,KAAK,GAAG,KAAK,CAAA;gBACpC,gBAAgB,CAAC,KAAK,CAAC,aAAa,GAAG,MAAM,CAAA;gBAC7C,gBAAgB,CAAC,KAAK,CAAC,MAAM,GAAG,MAAM,CAAA;gBACtC,QAAQ,CAAC,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAA;YAC7C,CAAC;QACH,CAAC,EACD;YACE,MAAM,EAAE,MAAM,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC;YACnD,MAAM,EAAE,MAAM,IAAI,IAAI,CAAC,cAAc,CAAC,MAAM,EAAE,IAAI,CAAC;YACnD,SAAS,EAAE,SAAS,IAAI,IAAI,CAAC,cAAc,CAAC,SAAS,EAAE,IAAI,CAAC;YAC5D,SAAS;YACT,IAAI;SACL,CACF,CAAA;IACH,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,sBAAsB,CAAC,WAAwB,EAAE,WAAmB;QACxE,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAA;QAExF,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAA;QAEzC,wBAAwB;QACxB,MAAM,IAAI,CAAC,UAAU,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,cAAc,EAAE,CAAC,CAAA;QAEjE,+BAA+B;QAC/B,MAAM,EAAE,cAAc,EAAE,GAAG,IAAI,CAAC,OAAO,CAAA;QACvC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,GAAG,cAAc,CAAA;QAE/D,IAAI,MAAM,IAAI,MAAM,IAAI,SAAS,EAAE,CAAC;YAClC,MAAM,IAAI,CAAC,0BAA0B,CAAC,IAAI,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC,CAAA;QAC7G,CAAC;QAED,YAAY;QACZ,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,WAAW,CAAC,CAAA;QAEtD,uBAAuB;QACvB,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,CAAA;QAElD,SAAS;QACT,MAAM,IAAI,CAAC,KAAK,EAAE,CAAA;QAElB,OAAO,cAAc,CAAA;IACvB,CAAC;CACF;AAhND,wCAgNC;AAED,SAAgB,sBAAsB;IACpC,OAAO;QACL;YACE,IAAI,EAAE,qBAAqB;YAC3B,IAAI,EAAE,UAAU;YAChB,KAAK,EAAE,UAAU;SAClB;QACD;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,aAAa;YACpB,QAAQ,EAAE;gBACR,OAAO,EAAE;oBACP,EAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE;oBAC1B,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;oBAC9B,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE;oBAC9B,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,EAAE;oBACtC,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE;iBACrC;aACF;YACD,WAAW,EAAE,qCAAqC;SACnD;QACD;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,YAAY;YACnB,WAAW,EAAE,kCAAkC;YAC/C,WAAW,EAAE,gEAAgE;SAC9E;QACD;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,QAAQ;YACd,KAAK,EAAE,aAAa;YACpB,WAAW,EAAE,mCAAmC;YAChD,WAAW,EAAE,kEAAkE;SAChF;QACD;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,iBAAiB;YACxB,WAAW,EAAE,iCAAiC;YAC9C,WAAW,EAAE,iCAAiC;SAC/C;QACD;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,cAAc;YACpB,KAAK,EAAE,oBAAoB;YAC3B,WAAW,EAAE,iCAAiC;YAC9C,WAAW,EAAE,oCAAoC;SAClD;QACD;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,YAAY;YAClB,KAAK,EAAE,kBAAkB;YACzB,WAAW,EAAE,iCAAiC;YAC9C,WAAW,EAAE,kCAAkC;SAChD;QACD;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,aAAa;YACnB,KAAK,EAAE,mBAAmB;YAC1B,WAAW,EAAE,iCAAiC;YAC9C,WAAW,EAAE,mCAAmC;SACjD;QACD;YACE,IAAI,EAAE,QAAQ;YACd,IAAI,EAAE,OAAO;YACb,KAAK,EAAE,YAAY;YACnB,YAAY,EAAE,CAAC;YACf,WAAW,EAAE,kDAAkD;SAChE;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,iBAAiB;YACvB,KAAK,EAAE,kBAAkB;YACzB,YAAY,EAAE,IAAI;YAClB,WAAW,EAAE,oDAAoD;SAClE;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,WAAW;YACjB,KAAK,EAAE,WAAW;YAClB,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,wCAAwC;SACtD;QACD;YACE,IAAI,EAAE,SAAS;YACf,IAAI,EAAE,mBAAmB;YACzB,KAAK,EAAE,sBAAsB;YAC7B,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,6EAA6E;SAC3F;KACF,CAAA;AACH,CAAC","sourcesContent":["import * as ejs from 'ejs'\nimport { ConnectionManager } from '@things-factory/integration-base'\nimport { PDFDocument } from 'pdf-lib'\nimport { Browser, Page } from 'puppeteer'\nimport { Logger } from 'winston'\n\ninterface StepOptions {\n format?: string\n width?: string\n height?: string\n marginTop?: string\n marginBottom?: string\n marginLeft?: string\n marginRight?: string\n scale?: number\n printBackground?: boolean\n landscape?: boolean\n preferCSSPageSize?: boolean\n}\n\ninterface PDFContext {\n domain: any\n data: any\n logger: Logger\n __headless_pdf: any\n}\n\nexport class PDFCaptureUtil {\n private context: PDFContext\n private headlessPool: any\n\n public browser: Browser | null = null\n\n constructor(context: PDFContext) {\n this.context = context\n }\n\n async initBrowser(connectionName: string) {\n const { domain } = this.context\n this.headlessPool = ConnectionManager.getConnectionInstanceByName(domain, connectionName)\n this.browser = await this.headlessPool.acquire()\n }\n\n async closeBrowser() {\n if (this.browser) {\n await this.browser.close()\n this.headlessPool.release(this.browser)\n }\n }\n\n renderTemplate(template: string, data: any): string {\n const { logger } = this.context\n try {\n return ejs.render(template, data)\n } catch (error) {\n logger.warn(`Template rendering error: ${error.message}`)\n return template\n }\n }\n\n async generatePDFContent(page: Page, pageOptions: any): Promise<PDFDocument> {\n const contentBuffer = await page.pdf(pageOptions)\n const contentPdfDoc = await PDFDocument.load(contentBuffer)\n return contentPdfDoc\n }\n\n async appendPDFContentToDocument(pdfDoc: PDFDocument, contentPdfDoc: PDFDocument) {\n const copiedPages = await pdfDoc.copyPages(contentPdfDoc, contentPdfDoc.getPageIndices())\n copiedPages.forEach(page => pdfDoc.addPage(page))\n this.context.__headless_pdf.pageCount += copiedPages.length\n }\n\n async processPageAndGeneratePDF(stepOptions: StepOptions, htmlContent: string, page?: Page) {\n if (!this.browser) throw new Error('Browser not initialized. Call initBrowser() first.')\n\n if (!page) {\n page = page || (await this.browser.newPage())\n }\n\n if (htmlContent) {\n // 페이지 컨텐츠 설정\n await page.setContent(htmlContent, { waitUntil: 'networkidle0' }) // HTML 컨텐츠가 완전히 로드될 때까지 대기\n }\n\n // 페이지가 완전히 로드된 후에 워터마크와 머릿글 적용\n const { __headless_pdf } = this.context\n const { header, footer, watermark, landscape } = __headless_pdf\n\n if (header || footer || watermark) {\n await this.applyHeaderFooterWatermark(page, { header, footer, watermark, landscape, data: __headless_pdf })\n }\n\n const pageOptions = this.buildPageOptions(stepOptions)\n const contentPdfDoc = await this.generatePDFContent(page, pageOptions)\n await this.appendPDFContentToDocument(__headless_pdf.pdfDoc, contentPdfDoc)\n await page.close()\n }\n\n buildPageOptions({\n format,\n width,\n height,\n marginTop,\n marginBottom,\n marginLeft,\n marginRight,\n scale,\n printBackground,\n landscape,\n preferCSSPageSize\n }: StepOptions): any {\n if (preferCSSPageSize) {\n width = undefined\n height = undefined\n }\n\n return {\n format,\n width,\n height,\n margin: {\n top: marginTop,\n right: marginRight,\n bottom: marginBottom,\n left: marginLeft\n },\n scale,\n printBackground,\n landscape,\n displayHeaderFooter: false,\n preferCSSPageSize\n }\n }\n\n async applyHeaderFooterWatermark(\n page: Page,\n {\n header,\n footer,\n watermark,\n landscape,\n data\n }: { header: string; footer: string; watermark: string; landscape: boolean; data: any }\n ) {\n await page.evaluate(\n ({ header, footer, watermark, landscape, data }) => {\n const setPositioning = (element: HTMLElement, position: 'header' | 'footer') => {\n element.style.position = 'fixed'\n element.style.left = '0'\n element.style.width = '100%'\n element.style.textAlign = 'center'\n element.style.fontSize = '12px'\n element.style.margin = '0'\n element.style.padding = '0'\n element.style.zIndex = '1000'\n\n if (position === 'header') {\n element.style.top = '0'\n } else if (position === 'footer') {\n element.style.bottom = '0'\n }\n }\n\n if (header) {\n const headerElement = document.createElement('div')\n headerElement.innerHTML = header\n setPositioning(headerElement, 'header')\n document.body.appendChild(headerElement)\n }\n\n if (footer) {\n const footerElement = document.createElement('div')\n footerElement.innerHTML = footer\n setPositioning(footerElement, 'footer')\n document.body.appendChild(footerElement)\n }\n\n if (watermark) {\n const watermarkElement = document.createElement('div')\n watermarkElement.innerHTML = watermark\n watermarkElement.style.position = 'fixed'\n watermarkElement.style.top = landscape ? '40%' : '50%'\n watermarkElement.style.left = '50%'\n watermarkElement.style.transform = 'translate(-50%, -50%) rotate(-45deg)'\n watermarkElement.style.opacity = '0.2'\n watermarkElement.style.fontSize = '50px'\n watermarkElement.style.color = 'red'\n watermarkElement.style.pointerEvents = 'none'\n watermarkElement.style.zIndex = '9999'\n document.body.appendChild(watermarkElement)\n }\n },\n {\n header: header && this.renderTemplate(header, data),\n footer: footer && this.renderTemplate(footer, data),\n watermark: watermark && this.renderTemplate(watermark, data),\n landscape,\n data\n }\n )\n }\n\n /**\n * Generates a PDF buffer for the last page.\n * @param stepOptions - Options used for generating the PDF.\n * @param htmlContent - HTML content to be converted to PDF.\n * @returns {Promise<Uint8Array>} - The generated PDF as a buffer.\n */\n async generateLastPageBuffer(stepOptions: StepOptions, htmlContent: string): Promise<Uint8Array> {\n if (!this.browser) throw new Error('Browser not initialized. Call initBrowser() first.')\n\n const page = await this.browser.newPage()\n\n // 페이지에 HTML 콘텐츠를 설정합니다.\n await page.setContent(htmlContent, { waitUntil: 'networkidle0' })\n\n // 페이지가 완전히 로드된 후에 워터마크와 머릿글 적용\n const { __headless_pdf } = this.context\n const { header, footer, watermark, landscape } = __headless_pdf\n\n if (header || footer || watermark) {\n await this.applyHeaderFooterWatermark(page, { header, footer, watermark, landscape, data: __headless_pdf })\n }\n\n // 페이지 옵션 설정\n const pageOptions = this.buildPageOptions(stepOptions)\n\n // PDF를 생성하고 버퍼를 반환합니다.\n const lastPageBuffer = await page.pdf(pageOptions)\n\n // 페이지 닫기\n await page.close()\n\n return lastPageBuffer\n }\n}\n\nexport function getCommonParameterSpec() {\n return [\n {\n type: 'scenario-step-input',\n name: 'accessor',\n label: 'accessor'\n },\n {\n type: 'select',\n name: 'format',\n label: 'page-format',\n property: {\n options: [\n { display: '', value: '' },\n { display: 'A4', value: 'A4' },\n { display: 'A3', value: 'A3' },\n { display: 'Letter', value: 'Letter' },\n { display: 'Legal', value: 'Legal' }\n ]\n },\n description: 'Select the paper format for the PDF'\n },\n {\n type: 'string',\n name: 'width',\n label: 'page-width',\n placeholder: '(e.g., \"8.5in\", \"21cm\", \"600px\")',\n description: 'Specify the width of the page (e.g., \"8.5in\", \"21cm\", \"600px\")'\n },\n {\n type: 'string',\n name: 'height',\n label: 'page-height',\n placeholder: '(e.g., \"11in\", \"29.7cm\", \"800px\")',\n description: 'Specify the height of the page (e.g., \"11in\", \"29.7cm\", \"800px\")'\n },\n {\n type: 'string',\n name: 'marginTop',\n label: 'page-margin-top',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the top margin for the page'\n },\n {\n type: 'string',\n name: 'marginBottom',\n label: 'page-margin-bottom',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the bottom margin for the page'\n },\n {\n type: 'string',\n name: 'marginLeft',\n label: 'page-margin-left',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the left margin for the page'\n },\n {\n type: 'string',\n name: 'marginRight',\n label: 'page-margin-right',\n placeholder: '(e.g., \"0.5in\", \"1cm\", \"100px\")',\n description: 'Set the right margin for the page'\n },\n {\n type: 'number',\n name: 'scale',\n label: 'page-scale',\n defaultValue: 1,\n description: 'Set the scale of the page content (default is 1)'\n },\n {\n type: 'boolean',\n name: 'printBackground',\n label: 'print-background',\n defaultValue: true,\n description: 'Include background graphics when printing the page'\n },\n {\n type: 'boolean',\n name: 'landscape',\n label: 'landscape',\n defaultValue: false,\n description: 'Print the PDF in landscape orientation'\n },\n {\n type: 'boolean',\n name: 'preferCSSPageSize',\n label: 'prefer-css-page-size',\n defaultValue: false,\n description: 'Whether to prefer the CSS-defined page size over the given width and height'\n }\n ]\n}\n"]}
|