UNPKG

@couleetech/n8n-nodes-pandoc

Version:
283 lines (282 loc) 11.5 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PandocConvert = void 0; const node_pandoc_1 = __importDefault(require("node-pandoc")); const util_1 = require("util"); const promises_1 = require("fs/promises"); const path_1 = require("path"); const os_1 = require("os"); const uuid_1 = require("uuid"); const mime_types_1 = __importDefault(require("mime-types")); const pandocAsync = (0, util_1.promisify)(node_pandoc_1.default); const NAMESPACE_UUID = '6ba7b810-9dad-11d1-80b4-00c04fd430c8'; class PandocConvert { constructor() { this.description = { displayName: 'Pandoc Convert', name: 'pandocConvert', icon: 'file:pandoc.svg', group: ['transform'], version: 1, description: 'Convert documents between different formats using Pandoc', defaults: { name: 'Pandoc Convert', }, inputs: ['main'], outputs: [ { type: 'main', displayName: 'Converted Document', required: true, }, { type: 'main', displayName: 'Extracted Images', required: false, }, ], properties: [ { displayName: 'Binary Property', name: 'binaryPropertyName', type: 'string', default: 'data', description: 'Name of the binary property that contains the file to convert', }, { displayName: 'From Format', name: 'fromFormat', type: 'options', options: [ { name: 'Markdown', value: 'markdown' }, { name: 'HTML', value: 'html' }, { name: 'Microsoft Word', value: 'docx' }, { name: 'LaTeX', value: 'latex' }, { name: 'Plain Text', value: 'plain' } ], default: 'markdown', description: 'Input format of the document', }, { displayName: 'To Format', name: 'toFormat', type: 'options', options: [ { name: 'Markdown', value: 'markdown' }, { name: 'HTML', value: 'html' }, { name: 'Microsoft Word', value: 'docx' }, { name: 'PDF', value: 'pdf' }, { name: 'LaTeX', value: 'latex' }, { name: 'Plain Text', value: 'plain' } ], default: 'html', description: 'Output format for the document', }, { displayName: 'Additional Options', name: 'options', type: 'string', default: '', description: 'Additional pandoc options (e.g., --standalone --toc)', required: false, } ], }; } static getMimeType(format) { const mimeTypes = { 'pdf': 'application/pdf', 'docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', 'html': 'text/html', 'markdown': 'text/markdown', 'latex': 'application/x-latex', 'plain': 'text/plain', }; return mimeTypes[format] || 'application/octet-stream'; } static getFileName(originalName, newFormat) { const baseName = originalName.split('.').slice(0, -1).join('.'); return `${baseName}.${PandocConvert.getFileExtension(newFormat)}`; } static getFileExtension(format) { const extensions = { 'pdf': 'pdf', 'docx': 'docx', 'html': 'html', 'markdown': 'md', 'latex': 'tex', 'plain': 'txt', }; return extensions[format] || format; } async execute() { var _a; const items = this.getInputData(); const returnData = []; const imageData = []; const cleanupFiles = async (paths) => { await Promise.all(paths.map(async (path) => { try { const stat = await Promise.resolve().then(() => __importStar(require('fs/promises'))).then(fs => fs.stat(path)); if (stat.isDirectory()) { await (0, promises_1.rmdir)(path, { recursive: true }); } else { await (0, promises_1.unlink)(path); } } catch (error) { } })); }; for (let i = 0; i < items.length; i++) { const tempPaths = []; try { const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i); const fromFormat = this.getNodeParameter('fromFormat', i); const toFormat = this.getNodeParameter('toFormat', i); const options = this.getNodeParameter('options', i, ''); const binaryData = (_a = items[i].binary) === null || _a === void 0 ? void 0 : _a[binaryPropertyName]; if (!binaryData) { throw new Error(`No binary data found in property "${binaryPropertyName}"`); } const tempId = (0, uuid_1.v5)(binaryData.fileName || 'unnamed', NAMESPACE_UUID); const tempDir = (0, os_1.tmpdir)(); const inputPath = (0, path_1.join)(tempDir, `pandoc_input_${tempId}`); const outputPath = (0, path_1.join)(tempDir, `pandoc_output_${tempId}`); const mediaDir = (0, path_1.join)(tempDir, `media_${tempId}`); tempPaths.push(inputPath, outputPath, mediaDir); await (0, promises_1.mkdir)(mediaDir, { recursive: true }); const buffer = Buffer.from(binaryData.data, 'base64'); await (0, promises_1.writeFile)(inputPath, buffer); const args = [ '-f', fromFormat, '-t', toFormat, '-o', outputPath, '--extract-media', mediaDir, ...options.split(' ').filter(Boolean) ]; await pandocAsync(inputPath, args); const outputContent = await (0, promises_1.readFile)(outputPath); const newBinaryData = { [binaryPropertyName]: { data: outputContent.toString('base64'), mimeType: PandocConvert.getMimeType(toFormat), fileName: PandocConvert.getFileName(binaryData.fileName || 'document', toFormat), } }; returnData.push({ json: items[i].json, binary: newBinaryData, }); try { const mediaFiles = await (0, promises_1.readdir)(mediaDir); for (const file of mediaFiles) { const filePath = (0, path_1.join)(mediaDir, file); const fileContent = await (0, promises_1.readFile)(filePath); const mimeType = mime_types_1.default.lookup(file) || 'application/octet-stream'; const imageId = (0, uuid_1.v5)(`${binaryData.fileName}-${file}`, NAMESPACE_UUID); const fileExt = file.split('.').pop() || ''; const deterministicImageName = `${imageId}.${fileExt}`; imageData.push({ json: { sourceDocument: binaryData.fileName, originalImageName: file, imageName: deterministicImageName, }, binary: { image: { data: fileContent.toString('base64'), mimeType, fileName: deterministicImageName, } } }); } } catch (error) { } } catch (error) { const pandocError = error; if (this.continueOnFail()) { returnData.push({ json: { error: pandocError.message, code: pandocError.code, stdout: pandocError.stdout, stderr: pandocError.stderr, }, binary: {}, }); continue; } throw error; } finally { await cleanupFiles(tempPaths); } } return [returnData, imageData]; } } exports.PandocConvert = PandocConvert;