UNPKG

n8n-nodes-doc-fill-handwritten-finalyy

Version:
238 lines 10.8 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.DocFill = void 0; const n8n_workflow_1 = require("n8n-workflow"); const DocFillUtils_1 = require("./DocFillUtils"); const pdf_lib_1 = require("pdf-lib"); const fontkit_1 = __importDefault(require("@pdf-lib/fontkit")); const promises_1 = require("fs/promises"); const path_1 = require("path"); function wrapText(text, fonts, fontSize, maxWidth, getRandomFont) { const chars = text.split(''); const lines = []; const fontsPerChar = []; let currentLine = ''; let currentLineFonts = []; let currentWidth = 0; for (const char of chars) { const font = getRandomFont(); const charWidth = font.widthOfTextAtSize(char, fontSize); if (currentWidth + charWidth <= maxWidth) { currentLine += char; currentLineFonts.push(font); currentWidth += charWidth; } else { if (currentLine) { lines.push(currentLine); fontsPerChar.push(currentLineFonts); } currentLine = char; currentLineFonts = [font]; currentWidth = charWidth; } } if (currentLine) { lines.push(currentLine); fontsPerChar.push(currentLineFonts); } return { lines, fontsPerChar }; } const nodeOperationOptions = [ { displayName: 'Property Name', name: 'dataPropertyName', type: 'string', default: 'data', description: 'Name of the binary property which holds the document to be used', }, { displayName: 'Property Name Out', name: 'dataPropertyNameOut', type: 'string', default: 'data', description: 'Name of the binary property for the output', }, { displayName: 'Configuration JSON', name: 'configurationJson', type: 'json', default: '', description: 'JSON used to map the keys in the PDF form to the corresponding values', }, ]; class DocFill { constructor() { this.description = { displayName: 'Doc Fill HAND', name: 'docFill', group: ['transform'], version: 1, description: 'Node made for filling a pdf form.', defaults: { name: 'Doc Fill HAND', }, inputs: ['main'], inputNames: ['Document'], outputs: ['main'], properties: [...nodeOperationOptions], }; } async execute() { const items = this.getInputData(); let itemBinaryData; let dataPropertyName; let dataPropertyNameOut; let jsonString; let docFillConfigs; let docBinaryData; let docBuffer; let pdfDoc; let pdfForm; const returnData = []; for (let itemIndex = 0; itemIndex < items.length; itemIndex++) { dataPropertyName = this.getNodeParameter('dataPropertyName', itemIndex, ''); dataPropertyNameOut = this.getNodeParameter('dataPropertyNameOut', itemIndex, ''); jsonString = this.getNodeParameter('configurationJson', itemIndex, ''); try { itemBinaryData = items[itemIndex].binary; docBinaryData = itemBinaryData[dataPropertyName]; if (!(0, DocFillUtils_1.isPDFDocument)(docBinaryData)) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Input (on binary property "${dataPropertyName}") should be a PDF file, was ${docBinaryData.mimeType} instead`, { itemIndex }); } docBuffer = await this.helpers.getBinaryDataBuffer(itemIndex, dataPropertyName); pdfDoc = await pdf_lib_1.PDFDocument.load(docBuffer); pdfDoc.registerFontkit(fontkit_1.default); const fontFiles = [ 'handwritten1.ttf', 'handwritten2.ttf', 'handwritten3.ttf', 'handwritten4.ttf', 'handwritten5.ttf', 'handwritten6.ttf', 'handwritten7.ttf', 'handwritten8.ttf', 'handwritten9.ttf', ]; const customFonts = []; for (const fontFile of fontFiles) { try { const fontPath = (0, path_1.resolve)(__dirname, '..', '..', '..', 'fonts', fontFile); console.log('Attempting to load font from:', fontPath); const fontBytes = await (0, promises_1.readFile)(fontPath); const font = await pdfDoc.embedFont(fontBytes); customFonts.push(font); console.log(`Font ${fontFile} loaded successfully`); } catch (error) { throw new n8n_workflow_1.NodeOperationError(this.getNode(), `Failed to load font ${fontFile}: ${error.message}`, { itemIndex }); } } const getRandomFont = () => { const randomIndex = Math.floor(Math.random() * customFonts.length); return customFonts[randomIndex]; }; const getRandomSpacing = () => { return Math.random() * 0.7 - 0.5; }; pdfForm = pdfDoc.getForm(); docFillConfigs = JSON.parse(jsonString); docFillConfigs.forEach((el) => { var _a, _b; if (el.type === 'textfield') { const pdfTextField = pdfForm.getTextField(el.key); const widget = pdfTextField.acroField.getWidgets()[0]; if (widget) { const page = pdfDoc.getPages()[0]; const { x, y, width, height } = widget.getRectangle(); pdfTextField.setText(''); const xOffset = (_a = el.xOffset) !== null && _a !== void 0 ? _a : 0; const yOffset = (_b = el.yOffset) !== null && _b !== void 0 ? _b : 0; if (el.key === 'BT' || el.key === 'U') { const { lines, fontsPerChar } = wrapText(el.value, customFonts, 12, width, getRandomFont); let currentY = y + height - 12; for (let i = 0; i < lines.length; i++) { const line = lines[i]; const lineFonts = fontsPerChar[i]; if (currentY < y) break; let currentX = x + xOffset; for (let j = 0; j < line.length; j++) { const char = line[j]; const font = lineFonts[j]; const charWidth = font.widthOfTextAtSize(char, 12); page.drawText(char, { x: currentX, y: currentY + yOffset, font: font, size: 12, color: (0, pdf_lib_1.rgb)(0, 0, 0), }); currentX += charWidth + getRandomSpacing(); } currentY -= 14; } } else { const { lines, fontsPerChar } = wrapText(el.value, customFonts, 12, width, getRandomFont); if (lines.length > 0) { const line = lines[0]; const lineFonts = fontsPerChar[0]; let currentX = x + xOffset; for (let j = 0; j < line.length; j++) { const char = line[j]; const font = lineFonts[j]; const charWidth = font.widthOfTextAtSize(char, 12); page.drawText(char, { x: currentX, y: y + yOffset, font: font, size: 12, color: (0, pdf_lib_1.rgb)(0, 0, 0), }); currentX += charWidth + getRandomSpacing(); } } } } } else { (0, DocFillUtils_1.fillForm)(pdfForm, el, customFonts[0]); } }); let savedDoc = await pdfDoc.save(); const result = { json: { ...items[itemIndex].json, }, binary: { ...items[itemIndex].binary, [dataPropertyNameOut]: await this.helpers.prepareBinaryData(Buffer.from(savedDoc), docBinaryData.fileName ? docBinaryData.fileName : dataPropertyNameOut + '.pdf', 'application/pdf'), }, pairedItem: [items[itemIndex].pairedItem], }; returnData.push(result); } catch (error) { if (this.continueOnFail()) { items.push({ json: this.getInputData(itemIndex)[0].json, error, pairedItem: itemIndex }); } else { if (error.context) { error.context.itemIndex = itemIndex; throw error; } throw new n8n_workflow_1.NodeOperationError(this.getNode(), error, { itemIndex, }); } } } return this.prepareOutputData(returnData); } } exports.DocFill = DocFill; //# sourceMappingURL=DocFill.node.js.map