UNPKG

n8n-nodes-json-to-pdf

Version:

Convert Markdown/JSON into PDF (single document or e-book) for n8n

176 lines 7.75 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.JsonToPdf = void 0; const pdfkit_1 = __importDefault(require("pdfkit")); const markdown_it_1 = __importDefault(require("markdown-it")); const get_stream_1 = __importDefault(require("get-stream")); const stream_1 = require("stream"); class JsonToPdf { constructor() { this.description = { displayName: 'JSON to PDF', name: 'jsonToPdf', icon: 'file:pdf-file-svgrepo-com.svg', group: ['transform'], version: 1, subtitle: '={{$parameter["operation"]}}', description: 'Convert JSON / Markdown into a PDF (single page or e-book)', defaults: { name: 'JSON to PDF' }, inputs: ['main'], outputs: ['main'], properties: [ /* core */ { displayName: 'Operation', name: 'operation', type: 'options', options: [ { name: 'Single PDF', value: 'single' }, { name: 'Generate E-book', value: 'ebook' }, ], default: 'single', }, { displayName: 'Raw Input', name: 'rawInput', type: 'json', default: '', description: 'Single PDF: string ou { data } — E-book: { title, data[] }', }, { displayName: 'Filename', name: 'fileName', type: 'string', default: 'output.pdf', }, /* appearance */ { displayName: 'Font', name: 'font', type: 'options', options: [ { name: 'Helvetica', value: 'Helvetica' }, { name: 'Times-Roman', value: 'Times-Roman' }, { name: 'Courier', value: 'Courier' }, { name: 'Helvetica-Bold', value: 'Helvetica-Bold' }, ], default: 'Helvetica', }, { displayName: 'Font Size', name: 'fontSize', type: 'number', default: 12 }, { displayName: 'Line Spacing', name: 'lineSpacing', type: 'number', default: 1.15 }, { displayName: 'Page-break Keyword', name: 'pageBreakKey', type: 'string', default: '## Chapter', displayOptions: { show: { operation: ['single'] } }, }, /* e-book */ { displayName: 'Include TOC', name: 'includeToc', type: 'boolean', default: true, displayOptions: { show: { operation: ['ebook'] } }, }, { displayName: 'TOC Title', name: 'tocTitle', type: 'string', default: 'Table of Contents', displayOptions: { show: { operation: ['ebook'], includeToc: [true] } }, }, { displayName: 'Chapter Title Style', name: 'chapterTitleStyle', type: 'options', options: [ { name: 'New page at title', value: 'newPage' }, { name: 'Inline', value: 'inline' }, ], default: 'newPage', displayOptions: { show: { operation: ['ebook'] } }, }, ], }; } async execute() { const md = new markdown_it_1.default(); const op = this.getNodeParameter('operation', 0); const raw = this.getNodeParameter('rawInput', 0); const fileName = this.getNodeParameter('fileName', 0); const font = this.getNodeParameter('font', 0); const fontSize = this.getNodeParameter('fontSize', 0); const lineSpacing = this.getNodeParameter('lineSpacing', 0); /* PDF setup */ const doc = new pdfkit_1.default({ margin: 50 }); const stream = new stream_1.PassThrough(); doc.pipe(stream); doc.font(font).fontSize(fontSize); /* ─── SINGLE PDF ─────────────────────────────────────────────── */ if (op === 'single') { const source = typeof raw === 'string' ? raw : raw?.data && typeof raw.data === 'string' ? raw.data : (() => { throw new Error('Single PDF expects string or { data }'); })(); const breakKey = this.getNodeParameter('pageBreakKey', 0); for (const line of source.split('\n')) { if (line.startsWith(breakKey)) doc.addPage(); doc.moveDown(lineSpacing - 1).text(md.renderInline(line), { align: 'justify' }); } } /* ─── E-BOOK ─────────────────────────────────────────────────── */ else { const obj = Array.isArray(raw) ? { data: raw } : raw; const chapters = obj?.data || (() => { throw new Error('E-book expects array or { title, data }'); })(); const bookTitle = typeof obj?.title === 'string' ? obj.title : ''; if (bookTitle) { doc.fontSize(fontSize + 6).text(bookTitle, { align: 'center' }); doc.addPage(); } if (this.getNodeParameter('includeToc', 0)) { doc.fontSize(fontSize + 2) .text(this.getNodeParameter('tocTitle', 0), { underline: true }) .moveDown(); chapters.forEach((c, i) => doc.text(`${i + 1}. ${c.title}`)); doc.addPage(); } const titleStyle = this.getNodeParameter('chapterTitleStyle', 0); for (const ch of chapters) { if (titleStyle === 'newPage') { doc.addPage(); doc.fontSize(fontSize + 4).text(ch.title, { align: 'center' }); } else { doc.fontSize(fontSize + 4).text(ch.title); } doc.moveDown().fontSize(fontSize); for (const ln of ch.content.split('\n')) { doc.moveDown(lineSpacing - 1).text(md.renderInline(ln), { align: 'justify' }); } } } /* finalize */ doc.end(); const pdfBuffer = await (0, get_stream_1.default)(stream, { encoding: 'buffer' }); return this.prepareOutputData([{ json: {}, binary: { data: { data: pdfBuffer, mimeType: 'application/pdf', fileName, // exibido pelo n8n fileExtension: 'pdf', fileSize: pdfBuffer.length, }, // `as any` evita erro de tipagem no stub }, }]); } } exports.JsonToPdf = JsonToPdf; //# sourceMappingURL=JsonToPdf.node.js.map