@websy/websy-designs 1.9.4 → 1.9.6

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.
@@ -0,0 +1,92 @@
1
+ Object.defineProperty(exports, '__esModule', { value: true })
2
+ exports.createReport = void 0
3
+ const pdfLib1 = require('pdf-lib')
4
+ async function createReport (baseDoc, headersPdfBuffer, headerHeight, footerHeight) {
5
+ const headerDoc = await pdfLib1.PDFDocument.load(headersPdfBuffer)
6
+ const basePages = baseDoc.getPages()
7
+ const headerPages = headerDoc.getPages()
8
+ const hasBoth = !!headerHeight && !!footerHeight
9
+ // get pages dimensions
10
+ const x = basePages[0].getWidth()
11
+ const y = basePages[0].getHeight()
12
+ // 1 inch = 96 px
13
+ // PDF unit = inch * 72/1
14
+ const pdfHeaderHeight = (headerHeight / 96) * 72
15
+ const pdfFooterHeight = (footerHeight / 96) * 72
16
+ // embed all headers pdf pages in the base pdf
17
+ const pages = []
18
+ const boxes = []
19
+ for (let i = 1; i <= headerPages.length; i++) {
20
+ pages.push(headerPages[i - 1])
21
+ const isOdd = i % 2 !== 0
22
+ // have only header or
23
+ // have both header and footer and we are in odd pages
24
+ // 1, 3, 5, etc
25
+ if (headerHeight && (!hasBoth || isOdd)) {
26
+ boxes.push({
27
+ bottom: y - pdfHeaderHeight,
28
+ left: 0,
29
+ right: x,
30
+ top: y
31
+ })
32
+ }
33
+ // have only footer or
34
+ // have both header and footer and we are in plural pages
35
+ // 2, 4, 6, etc
36
+ if (footerHeight && (!hasBoth || !isOdd)) {
37
+ boxes.push({
38
+ bottom: y - pdfFooterHeight,
39
+ left: 0,
40
+ right: x,
41
+ top: y
42
+ })
43
+ }
44
+ }
45
+ const embeddedPages = await baseDoc.embedPages(pages, boxes)
46
+ // draw headers and/or footers over the base pages
47
+ let baseIndex = 0
48
+ for (let i = 1; i <= headerPages.length; i++) {
49
+ const embeddedPage = embeddedPages[i - 1]
50
+ const size = embeddedPage.size()
51
+ const isOdd = i % 2 !== 0
52
+ if (headerHeight && (!hasBoth || isOdd) && basePages[baseIndex]) {
53
+ console.log('attempting to draw page x')
54
+ basePages[baseIndex].drawPage(embeddedPage, Object.assign({},
55
+ size,
56
+ {
57
+ x: x - size.width,
58
+ y: y - size.height,
59
+ blendMode: pdfLib1.BlendMode.Multiply
60
+ }
61
+ ))
62
+ }
63
+ if (footerHeight && (!hasBoth || !isOdd) && basePages[baseIndex]) {
64
+ basePages[baseIndex].drawPage(embeddedPage, Object.assign({},
65
+ size,
66
+ {
67
+ x: x - size.width,
68
+ y: 0,
69
+ blendMode: pdfLib1.BlendMode.Multiply
70
+ }
71
+ ))
72
+ }
73
+ // when we have both header and footer
74
+ // two pages of headers pdf belong to one page of the base doc
75
+ // ------------
76
+ // | header 1 |
77
+ // | | ------------
78
+ // | | | header 1 |
79
+ // ------------ => | xxxxxxxxxx |
80
+ // | footer 1 | | footer 1 |
81
+ // | | ------------
82
+ // | |
83
+ if (hasBoth && !isOdd) {
84
+ baseIndex++
85
+ }
86
+ else if (!hasBoth) {
87
+ baseIndex++
88
+ }
89
+ }
90
+ return baseDoc.save()
91
+ }
92
+ exports.createReport = createReport
@@ -1,5 +1,6 @@
1
1
  const puppeteer = require('puppeteer')
2
- const report = require('puppeteer-report')
2
+ // const report = require('puppeteer-report')
3
+ const report = require('./puppeteer-report/index')
3
4
  const fs = require('fs')
4
5
  const utils = require('../../utils')
5
6
  const http = require('http')
@@ -0,0 +1,2 @@
1
+ import { PDFDocument } from "pdf-lib";
2
+ export declare function createReport(baseDoc: PDFDocument, headersPdfBuffer: Uint8Array, headerHeight: number, footerHeight: number): Promise<Uint8Array>;
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createReport = void 0;
4
+ const pdf_lib_1 = require("pdf-lib");
5
+ async function createReport(baseDoc, headersPdfBuffer, headerHeight, footerHeight) {
6
+ const headerDoc = await pdf_lib_1.PDFDocument.load(headersPdfBuffer);
7
+ const basePages = baseDoc.getPages();
8
+ const headerPages = headerDoc.getPages();
9
+ const hasBoth = !!headerHeight && !!footerHeight;
10
+ // get pages dimensions
11
+ const x = basePages[0].getWidth();
12
+ const y = basePages[0].getHeight();
13
+ // 1 inch = 96 px
14
+ // PDF unit = inch * 72/1
15
+ const pdfHeaderHeight = (headerHeight / 96) * 72;
16
+ const pdfFooterHeight = (footerHeight / 96) * 72;
17
+ // embed all headers pdf pages in the base pdf
18
+ const pages = [];
19
+ const boxes = [];
20
+ for (let i = 1; i <= headerPages.length; i++) {
21
+ pages.push(headerPages[i - 1]);
22
+ const isOdd = i % 2 != 0;
23
+ // have only header or
24
+ // have both header and footer and we are in odd pages
25
+ // 1, 3, 5, etc
26
+ if (headerHeight && (!hasBoth || isOdd)) {
27
+ boxes.push({
28
+ bottom: y - pdfHeaderHeight,
29
+ left: 0,
30
+ right: x,
31
+ top: y,
32
+ });
33
+ }
34
+ // have only footer or
35
+ // have both header and footer and we are in plural pages
36
+ // 2, 4, 6, etc
37
+ if (footerHeight && (!hasBoth || !isOdd)) {
38
+ boxes.push({
39
+ bottom: y - pdfFooterHeight,
40
+ left: 0,
41
+ right: x,
42
+ top: y,
43
+ });
44
+ }
45
+ }
46
+ const embeddedPages = await baseDoc.embedPages(pages, boxes);
47
+ // draw headers and/or footers over the base pages
48
+ let baseIndex = 0;
49
+ for (let i = 1; i <= headerPages.length; i++) {
50
+ const embeddedPage = embeddedPages[i - 1];
51
+ const size = embeddedPage.size();
52
+ const isOdd = i % 2 != 0;
53
+ if (headerHeight && (!hasBoth || isOdd) && basePages[baseIndex]) {
54
+ basePages[baseIndex].drawPage(embeddedPage, {
55
+ ...size,
56
+ x: x - size.width,
57
+ y: y - size.height,
58
+ blendMode: pdf_lib_1.BlendMode.Multiply
59
+ });
60
+ }
61
+ if (footerHeight && (!hasBoth || !isOdd) && basePages[baseIndex]) {
62
+ basePages[baseIndex].drawPage(embeddedPage, {
63
+ ...size,
64
+ x: x - size.width,
65
+ y: 0,
66
+ blendMode: pdf_lib_1.BlendMode.Multiply
67
+ });
68
+ }
69
+ // when we have both header and footer
70
+ // two pages of headers pdf belong to one page of the base doc
71
+ // ------------
72
+ // | header 1 |
73
+ // | | ------------
74
+ // | | | header 1 |
75
+ // ------------ => | xxxxxxxxxx |
76
+ // | footer 1 | | footer 1 |
77
+ // | | ------------
78
+ // | |
79
+ if (hasBoth && !isOdd) {
80
+ baseIndex++;
81
+ }
82
+ else if (!hasBoth) {
83
+ baseIndex++;
84
+ }
85
+ }
86
+ return await baseDoc.save();
87
+ }
88
+ exports.createReport = createReport;
@@ -0,0 +1,25 @@
1
+ import { PDFDocument } from "pdf-lib";
2
+ export declare function getHeightEvaluator(marginTop: number | string, marginBottom: number | string, scale?: number): [pageFunc: ({ marginTop, marginBottom, scale }: {
3
+ marginTop: string;
4
+ marginBottom: string;
5
+ scale: number;
6
+ }) => {
7
+ headerHeight: number;
8
+ footerHeight: number;
9
+ }, argument: {
10
+ marginTop: string;
11
+ marginBottom: string;
12
+ scale: number;
13
+ }];
14
+ export declare function getBaseEvaluator(headerHeight: number, footerHeight: number): [pageFunc: ({ headerHeight, footerHeight }: {
15
+ headerHeight: number;
16
+ footerHeight: number;
17
+ }) => void, argument: {
18
+ headerHeight: number;
19
+ footerHeight: number;
20
+ }];
21
+ export declare function getHeadersEvaluator(basePdfBuffer: Uint8Array): Promise<[doc: PDFDocument, pageFunc: ({ pagesCount }: {
22
+ pagesCount: number;
23
+ }) => void, argument: {
24
+ pagesCount: number;
25
+ }]>;
@@ -0,0 +1,186 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getHeadersEvaluator = exports.getBaseEvaluator = exports.getHeightEvaluator = void 0;
4
+ const pdf_lib_1 = require("pdf-lib");
5
+ // get header and/or footer height from html
6
+ function getHeightEvaluator(marginTop, marginBottom, scale) {
7
+ const normalizeMargin = (margin) => {
8
+ if (typeof margin == "number") {
9
+ return margin + "px";
10
+ }
11
+ return margin;
12
+ };
13
+ const argument = {
14
+ marginTop: normalizeMargin(marginTop),
15
+ marginBottom: normalizeMargin(marginBottom),
16
+ scale: scale !== null && scale !== void 0 ? scale : 1,
17
+ };
18
+ const pageFunc = ({ marginTop, marginBottom, scale }) => {
19
+ // get element height include margins
20
+ const getHeight = (element) => {
21
+ if (element) {
22
+ const styles = window.getComputedStyle(element);
23
+ const margin = parseFloat(styles["marginTop"]) + parseFloat(styles["marginBottom"]);
24
+ // change position to ignore margin collapse
25
+ const position = element.style.position;
26
+ element.style.position = "absolute";
27
+ const height = element.offsetHeight + margin;
28
+ // reset element position
29
+ element.style.position = position;
30
+ return Math.ceil(height * scale);
31
+ }
32
+ return 0;
33
+ };
34
+ const header = document.getElementById("header");
35
+ const footer = document.getElementById("footer");
36
+ // inject a style sheet
37
+ const styleEl = document.createElement("style");
38
+ styleEl.setAttribute("id", "header__style");
39
+ document.head.appendChild(styleEl);
40
+ const styleSheet = styleEl.sheet;
41
+ // to respect user-defined PDF margins,
42
+ if (header) {
43
+ styleSheet.insertRule(`#header { margin-top: ${marginTop}`);
44
+ }
45
+ if (footer) {
46
+ styleSheet.insertRule(`#footer { margin-bottom: ${marginBottom}`);
47
+ }
48
+ const headerHeight = getHeight(header);
49
+ const footerHeight = getHeight(footer);
50
+ return { headerHeight, footerHeight };
51
+ };
52
+ return [pageFunc, argument];
53
+ }
54
+ exports.getHeightEvaluator = getHeightEvaluator;
55
+ // remove header and footer from HTML content to create
56
+ // base doc pdf, for reserving the space for header and/or footer
57
+ // we inject a @page top/bottom margin
58
+ // ------------
59
+ // | header |
60
+ // | xxxxxxxxxx |
61
+ // | xxxxxxxxxx |
62
+ // ...
63
+ // | xxxxxxxxxx |
64
+ // | footer |
65
+ // to:
66
+ // ------------
67
+ // | |
68
+ // | xxxxxxxxxx |
69
+ // | |
70
+ // ------------
71
+ // | |
72
+ // | xxxxxxxxxx |
73
+ // | |
74
+ // ------------
75
+ // | |
76
+ // ...
77
+ function getBaseEvaluator(headerHeight, footerHeight) {
78
+ const argument = { headerHeight, footerHeight };
79
+ const pageFunc = ({ headerHeight, footerHeight }) => {
80
+ const header = document.getElementById("header");
81
+ const footer = document.getElementById("footer");
82
+ // reset body margin
83
+ document.body.style.margin = "0";
84
+ // inject a style sheet
85
+ const styleEl = document.createElement("style");
86
+ styleEl.setAttribute("id", "page__style");
87
+ document.head.appendChild(styleEl);
88
+ const styleSheet = styleEl.sheet;
89
+ // hide the element and add the height of it
90
+ // as page margin
91
+ const evaluate = (element, height, isTop) => {
92
+ if (element) {
93
+ element.style.display = "none";
94
+ if (isTop) {
95
+ styleSheet.insertRule(`@page { margin-top: ${height}px}`);
96
+ }
97
+ else {
98
+ styleSheet.insertRule(`@page { margin-bottom: ${height}px}`);
99
+ }
100
+ }
101
+ };
102
+ evaluate(header, headerHeight, true);
103
+ evaluate(footer, footerHeight, false);
104
+ };
105
+ return [pageFunc, argument];
106
+ }
107
+ exports.getBaseEvaluator = getBaseEvaluator;
108
+ // convert HTML content to a header/footer only pages, for each base doc's pages.
109
+ // if you have both headers and footers the output pdf pages will be:
110
+ // page = base doc's pages * 2
111
+ // ------------
112
+ // | header 1 |
113
+ // | |
114
+ // | |
115
+ // ------------
116
+ // | footer 1 |
117
+ // | |
118
+ // | |
119
+ // ------------
120
+ // | header 2 |
121
+ // ...
122
+ async function getHeadersEvaluator(basePdfBuffer) {
123
+ const doc = await pdf_lib_1.PDFDocument.load(basePdfBuffer);
124
+ const argument = { pagesCount: doc.getPageCount() };
125
+ const pageFunc = ({ pagesCount }) => {
126
+ // set a value for all selected elements
127
+ const setElementsValue = (elements, value) => {
128
+ for (const element of elements) {
129
+ element.textContent = value;
130
+ }
131
+ };
132
+ const resetStyle = (element) => {
133
+ if (element) {
134
+ element.style.display = "block";
135
+ }
136
+ };
137
+ // add a page break after each element
138
+ const addPageBreak = () => {
139
+ const pageBreak = document.createElement("div");
140
+ pageBreak.style.pageBreakAfter = "always";
141
+ document.body.appendChild(pageBreak);
142
+ };
143
+ // duplicate an element in the page
144
+ const cloneElement = (element, pageNumber) => {
145
+ const cloned = element.cloneNode(true);
146
+ // fill pageNumber
147
+ const pageNumberElements = cloned.getElementsByClassName("pageNumber");
148
+ setElementsValue(pageNumberElements, pageNumber);
149
+ // fill total page
150
+ const totalPagesElements = cloned.getElementsByClassName("totalPages");
151
+ setElementsValue(totalPagesElements, pagesCount.toString());
152
+ document.body.appendChild(cloned);
153
+ // trigger element onchange to support JS
154
+ cloned.dispatchEvent(new Event("change", { bubbles: true }));
155
+ addPageBreak();
156
+ };
157
+ const header = document.getElementById("header");
158
+ const footer = document.getElementById("footer");
159
+ resetStyle(header);
160
+ resetStyle(footer);
161
+ // clear the page content
162
+ document.body.innerHTML = "";
163
+ // remove page margin
164
+ const styleEl = document.getElementById("page__style");
165
+ const styleSheet = styleEl.sheet;
166
+ while (styleSheet.rules.length > 0) {
167
+ styleSheet.deleteRule(0);
168
+ }
169
+ // inject new style
170
+ styleSheet.insertRule(`@page { margin-top: 0; margin-bottom:0; }`);
171
+ // duplicate the header and footer element for each page
172
+ for (let i = 0; i < pagesCount; i++) {
173
+ if (header) {
174
+ cloneElement(header, (i + 1).toString());
175
+ }
176
+ if (footer) {
177
+ cloneElement(footer, (i + 1).toString());
178
+ }
179
+ }
180
+ // fill title
181
+ const titleElements = document.getElementsByClassName("title");
182
+ setElementsValue(titleElements, document.title);
183
+ };
184
+ return [doc, pageFunc, argument];
185
+ }
186
+ exports.getHeadersEvaluator = getHeadersEvaluator;
@@ -0,0 +1,2 @@
1
+ export { createReport } from "./createReport";
2
+ export { getBaseEvaluator, getHeadersEvaluator, getHeightEvaluator, } from "./evaluators";
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getHeightEvaluator = exports.getHeadersEvaluator = exports.getBaseEvaluator = exports.createReport = void 0;
4
+ var createReport_1 = require("./createReport");
5
+ Object.defineProperty(exports, "createReport", { enumerable: true, get: function () { return createReport_1.createReport; } });
6
+ var evaluators_1 = require("./evaluators");
7
+ Object.defineProperty(exports, "getBaseEvaluator", { enumerable: true, get: function () { return evaluators_1.getBaseEvaluator; } });
8
+ Object.defineProperty(exports, "getHeadersEvaluator", { enumerable: true, get: function () { return evaluators_1.getHeadersEvaluator; } });
9
+ Object.defineProperty(exports, "getHeightEvaluator", { enumerable: true, get: function () { return evaluators_1.getHeightEvaluator; } });
@@ -0,0 +1,22 @@
1
+ import type { Page, Browser, PDFOptions } from "./types";
2
+ /**
3
+ * Convert HTML file to PDF
4
+ * @param browser puppeteer/puppeteer-core browser object
5
+ * @param file full path of HTML file
6
+ * @param options output PDF options
7
+ * @returns PDF as an array of bytes
8
+ */
9
+ declare function pdf(browser: Browser, file: string, options?: PDFOptions): Promise<Uint8Array>;
10
+ /**
11
+ * Convert a Page to PDF
12
+ * @param page puppeteer/puppeteer-core page object
13
+ * @param options output PDF options
14
+ * @returns PDF as an array of bytes
15
+ */
16
+ declare function pdfPage(page: Page, options?: PDFOptions): Promise<Uint8Array>;
17
+ export { pdf, pdfPage };
18
+ declare const _default: {
19
+ pdf: typeof pdf;
20
+ pdfPage: typeof pdfPage;
21
+ };
22
+ export default _default;
@@ -0,0 +1,75 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.pdfPage = exports.pdf = void 0;
27
+ const fs = __importStar(require("fs"));
28
+ const core = __importStar(require("./core"));
29
+ /**
30
+ * Convert HTML file to PDF
31
+ * @param browser puppeteer/puppeteer-core browser object
32
+ * @param file full path of HTML file
33
+ * @param options output PDF options
34
+ * @returns PDF as an array of bytes
35
+ */
36
+ async function pdf(browser, file, options) {
37
+ const page = await browser.newPage();
38
+ try {
39
+ await page.goto("file:///" + file);
40
+ return await pdfPage(page, options);
41
+ }
42
+ finally {
43
+ await page.close();
44
+ }
45
+ }
46
+ exports.pdf = pdf;
47
+ /**
48
+ * Convert a Page to PDF
49
+ * @param page puppeteer/puppeteer-core page object
50
+ * @param options output PDF options
51
+ * @returns PDF as an array of bytes
52
+ */
53
+ async function pdfPage(page, options) {
54
+ var _a, _b, _c, _d;
55
+ const { path, ...pdfOptions } = options !== null && options !== void 0 ? options : {};
56
+ const margin = {
57
+ marginTop: (_b = (_a = pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.margin) === null || _a === void 0 ? void 0 : _a.top) !== null && _b !== void 0 ? _b : 0,
58
+ marginBottom: (_d = (_c = pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.margin) === null || _c === void 0 ? void 0 : _c.bottom) !== null && _d !== void 0 ? _d : 0,
59
+ };
60
+ const [getHeightFunc, getHeightArg] = core.getHeightEvaluator(margin.marginTop, margin.marginBottom, pdfOptions === null || pdfOptions === void 0 ? void 0 : pdfOptions.scale);
61
+ const { headerHeight, footerHeight } = await page.evaluate(getHeightFunc, getHeightArg);
62
+ const [basePageEvalFunc, basePageEvalArg] = core.getBaseEvaluator(headerHeight, footerHeight);
63
+ await page.evaluate(basePageEvalFunc, basePageEvalArg);
64
+ const basePdfBuffer = await page.pdf(pdfOptions);
65
+ const [doc, headerEvalFunc, headerEvalArg] = await core.getHeadersEvaluator(basePdfBuffer);
66
+ await page.evaluate(headerEvalFunc, headerEvalArg);
67
+ const headerPdfBuffer = await page.pdf(pdfOptions);
68
+ const result = await core.createReport(doc, headerPdfBuffer, headerHeight, footerHeight);
69
+ if (path) {
70
+ await fs.promises.writeFile(path, result);
71
+ }
72
+ return result;
73
+ }
74
+ exports.pdfPage = pdfPage;
75
+ exports.default = { pdf, pdfPage };
@@ -0,0 +1,18 @@
1
+ /// <reference types="node" />
2
+ import type { PDFOptions, Awaitable, WaitForOptions } from "puppeteer-core";
3
+ export type { PDFOptions } from "puppeteer-core";
4
+ type InnerParams<T extends unknown[]> = {
5
+ [K in keyof T]: T[K];
6
+ };
7
+ type EvaluateFunc<T extends unknown[]> = (...params: InnerParams<T>) => Awaitable<unknown>;
8
+ export interface Page {
9
+ pdf(options?: PDFOptions): Promise<Buffer>;
10
+ close(): Promise<void>;
11
+ goto(url: string, options?: WaitForOptions & {
12
+ referer?: string;
13
+ }): Promise<unknown | null>;
14
+ evaluate<Params extends unknown[], Func extends EvaluateFunc<Params> = EvaluateFunc<Params>>(pageFunction: Func | string, ...args: Params): Promise<Awaited<ReturnType<Func>>>;
15
+ }
16
+ export interface Browser {
17
+ newPage(): Promise<Page>;
18
+ }
@@ -0,0 +1,4 @@
1
+ "use strict";
2
+ //TODO: puppeteer-core types differ from puppeteer
3
+ // https://github.com/puppeteer/puppeteer/issues/6904
4
+ Object.defineProperty(exports, "__esModule", { value: true });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@websy/websy-designs",
3
- "version": "1.9.4",
3
+ "version": "1.9.6",
4
4
  "main": "index.js",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"