UNPKG

@jackiemacklein/nettz-utils

Version:

Serviços de imagem, e-mail, códigos de barras, utilitários numéricos e componentes React para apps Node.js com TypeScript

266 lines (265 loc) 9.78 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PRINT_PRESETS = void 0; exports.pageToPDF = pageToPDF; exports.generateThermalPDF = generateThermalPDF; exports.generateA4PDF = generateA4PDF; exports.generateReceiptPDF = generateReceiptPDF; exports.generateLabelPDF = generateLabelPDF; exports.generateCustomSizePDF = generateCustomSizePDF; exports.getPrintPreset = getPrintPreset; exports.getAvailablePrintTypes = getAvailablePrintTypes; exports.htmlInject = htmlInject; const lodash_1 = require("lodash"); const puppeteer_1 = __importDefault(require("puppeteer")); // Configurações predefinidas para diferentes tipos de impressão exports.PRINT_PRESETS = { thermal: { format: "A4", // Usar A4 como base, mas com CSS customizado margin: { bottom: 5, left: 5, right: 5, top: 5 }, preferCSSPageSize: true, displayHeaderFooter: false, customWidth: 80, // 80mm para impressora térmica customHeight: 297, // Altura A4 }, a4: { format: "A4", margin: { bottom: 25, left: 25, right: 25, top: 25 }, preferCSSPageSize: false, displayHeaderFooter: false, }, a5: { format: "A5", margin: { bottom: 20, left: 20, right: 20, top: 20 }, preferCSSPageSize: false, displayHeaderFooter: false, }, letter: { format: "Letter", margin: { bottom: 25, left: 25, right: 25, top: 25 }, preferCSSPageSize: false, displayHeaderFooter: false, }, legal: { format: "Legal", margin: { bottom: 25, left: 25, right: 25, top: 25 }, preferCSSPageSize: false, displayHeaderFooter: false, }, receipt: { format: "A4", // Usar A4 como base margin: { bottom: 3, left: 3, right: 3, top: 3 }, preferCSSPageSize: true, displayHeaderFooter: false, customWidth: 60, // 60mm para recibo customHeight: 297, // Altura A4 }, label: { format: "A4", // Usar A4 como base margin: { bottom: 2, left: 2, right: 2, top: 2 }, preferCSSPageSize: true, displayHeaderFooter: false, customWidth: 40, // 40mm para etiqueta customHeight: 297, // Altura A4 }, custom: { format: "A4", margin: { bottom: 25, left: 25, right: 25, top: 25 }, preferCSSPageSize: false, displayHeaderFooter: false, }, }; async function pageToPDF({ url, customStyle, specificElement, pages, margin, displayHeaderFooter, preferCSSPageSize, format, content, returnBuffer = false, printType = "a4", customWidth, customHeight, }) { try { // Aplica as configurações do tipo de impressão selecionado const preset = exports.PRINT_PRESETS[printType]; const finalFormat = format || preset.format; const finalMargin = margin || preset.margin; const finalDisplayHeaderFooter = displayHeaderFooter !== null && displayHeaderFooter !== void 0 ? displayHeaderFooter : preset.displayHeaderFooter; const finalPreferCSSPageSize = preferCSSPageSize !== null && preferCSSPageSize !== void 0 ? preferCSSPageSize : preset.preferCSSPageSize; // Configuração customizada de tamanho se especificado const pdfOptions = { pageRanges: pages || "", format: finalFormat, margin: finalMargin, displayHeaderFooter: finalDisplayHeaderFooter, printBackground: true, preferCSSPageSize: finalPreferCSSPageSize, }; // Se especificou largura e altura customizadas, usa elas if (customWidth && customHeight) { pdfOptions.width = `${customWidth}mm`; pdfOptions.height = `${customHeight}mm`; delete pdfOptions.format; // Remove format quando usa dimensões customizadas } else if (preset.customWidth && preset.customHeight) { // Se o preset tem dimensões customizadas, usa elas pdfOptions.width = `${preset.customWidth}mm`; pdfOptions.height = `${preset.customHeight}mm`; delete pdfOptions.format; // Remove format quando usa dimensões customizadas } // cria o navegador virtual const browser = await puppeteer_1.default.launch({ headless: true, args: [ "--no-sandbox", "--disable-setuid-sandbox", "--disable-dev-shm-usage", "--disable-accelerated-2d-canvas", "--no-first-run", "--no-zygote", "--disable-gpu", ], }); const page = await browser.newPage(); // Configurações importantes para renderização de imagens await page.setViewport({ width: 1200, height: 800 }); // Aguarda o carregamento completo das imagens await page.setDefaultNavigationTimeout(30000); await page.setDefaultTimeout(30000); if (url) { await page.goto(url, { waitUntil: "networkidle0", timeout: 30000, }); } if (content) { // Aguarda um pouco para garantir que as imagens carreguem await page.setContent(`<html><head><style type="text/css">${customStyle}</style></head><body>${content}</body></html>`, { waitUntil: "networkidle0", }); } else { if (specificElement) { const innerHTML = await page.$eval(specificElement, (element) => { return element.innerHTML; }); await page.setContent(`<html><head><style type="text/css">${customStyle}</style></head><body>${innerHTML}</body></html>`, { waitUntil: "networkidle0", }); } } if (customStyle) { await page.addStyleTag({ content: customStyle }); } // Aguarda um pouco mais para garantir que tudo foi renderizado // Aguarda especificamente pelas imagens carregarem se existirem try { await page.waitForSelector("img", { timeout: 5000 }); } catch (error) { console.log("Imagem não carregada", error); } // gera o pdf const pdf = await page.pdf(pdfOptions); await browser.close(); return returnBuffer ? Buffer.from(pdf) : Buffer.from(pdf).toString("base64"); } catch (err) { console.log("err2", err); return ""; } } /** * Função auxiliar para gerar PDF para impressora térmica (cupom) */ async function generateThermalPDF(props) { return pageToPDF({ ...props, printType: "thermal" }); } /** * Função auxiliar para gerar PDF para papel A4 */ async function generateA4PDF(props) { return pageToPDF({ ...props, printType: "a4" }); } /** * Função auxiliar para gerar PDF para recibo pequeno */ async function generateReceiptPDF(props) { return pageToPDF({ ...props, printType: "receipt" }); } /** * Função auxiliar para gerar PDF para etiqueta */ async function generateLabelPDF(props) { return pageToPDF({ ...props, printType: "label" }); } /** * Função auxiliar para gerar PDF com dimensões customizadas */ async function generateCustomSizePDF(props) { const { width, height, ...rest } = props; return pageToPDF({ ...rest, printType: "custom", customWidth: width, customHeight: height, }); } /** * Função auxiliar para obter as configurações de um tipo de impressão */ function getPrintPreset(printType) { return exports.PRINT_PRESETS[printType]; } /** * Função auxiliar para listar todos os tipos de impressão disponíveis */ function getAvailablePrintTypes() { return Object.keys(exports.PRINT_PRESETS); } /** * @author Jackiê Macklein * @company Onside tecnologia/Nettz * @copyright Todos direitos reservados. * @description Injeção de variáveis em um conteúdo HTML * @param {HtmlInjectProps} props * @returns {string} * @example * const htmlContent = ` * <h1>{{name}}</h1> * <p>{{age}}</p> * `; * const data = { name: "John", age: 30 }; * const data2 = {person: { name: "John", age: 30 }}; * const variables = [{ key: "name", column_name: "name", table_alias: "", function: "" }]; * const variables2 = [{ key: "name", column_name: "name", table_alias: "person", function: "" }]; * const result = htmlInject({ data: data, variables: variables, htmlContent: htmlContent }); * const result2 = htmlInject({ data: data2, variables: variables2, htmlContent: htmlContent }); * result === "<h1>John</h1><p>30</p>" * result2 === "<h1>John</h1><p>30</p>" */ function htmlInject({ data, variables, htmlContent, }) { try { let converted = htmlContent; for (let i = 0; i < variables.length; i++) { const variable = variables[i]; let path = ""; let value = ""; if (variable.table_alias) { path = `${variable.table_alias}.${variable.column_name}`; } else { path = variable.column_name; } if (variable.function) { value = eval(variable.function); console.log({ value }); } else { value = (0, lodash_1.get)(data, path); } converted = converted.replace(new RegExp(`{{${variable.key}}}`, "g"), value); } return converted; } catch (error) { console.log(error); return ""; } }