From 0f37bfffb7a19b3ec7099eed0480cd1c93c9f04b Mon Sep 17 00:00:00 2001 From: kartik tongaria Date: Sat, 19 Aug 2023 12:59:08 +0530 Subject: [PATCH 1/3] Added img to pdf and docx to pdf file --- src/Plugins/docsx-input-plugin.ts | 34 ++++++++ src/Plugins/image-input-plugin.ts | 23 ++++++ src/Plugins/officegen.d.ts | 4 + src/Plugins/pdf-poppler.d.ts | 4 + src/Plugins/plugin.controller.ts | 126 ++++++++++++++++++++++++++++++ 5 files changed, 191 insertions(+) create mode 100644 src/Plugins/docsx-input-plugin.ts create mode 100644 src/Plugins/image-input-plugin.ts create mode 100644 src/Plugins/officegen.d.ts create mode 100644 src/Plugins/pdf-poppler.d.ts create mode 100644 src/Plugins/plugin.controller.ts diff --git a/src/Plugins/docsx-input-plugin.ts b/src/Plugins/docsx-input-plugin.ts new file mode 100644 index 0000000..1175515 --- /dev/null +++ b/src/Plugins/docsx-input-plugin.ts @@ -0,0 +1,34 @@ +import * as path from 'path'; +import * as mammoth from 'mammoth'; +import * as puppeteer from 'puppeteer'; +import { PluginOutput } from './pdf-plugin.interfaces'; + +export class DocxInputPlugin { + public async convertDocxToPdf(docxFilePath: string): Promise { + try { + const outputPdfPath = path.join(__dirname, './generatedPdfDocument.pdf'); + const htmlContent = await this.convertDocxToHtml(docxFilePath); + await this.htmlToPdf(htmlContent, outputPdfPath); + + console.log('PDF file generated successfully'); + return { file: outputPdfPath }; + } catch (error) { + console.error('Error generating PDF:', error); + throw new Error('Failed to convert DOCX to PDF'); + } + } + + private async convertDocxToHtml(docxFilePath: string): Promise { + const result = await mammoth.convertToHtml({ path: docxFilePath }); + return result.value; + } + + private async htmlToPdf(htmlContent: string, pdfPath: string): Promise { + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + await page.setContent(htmlContent); + await page.pdf({ path: pdfPath, format: 'A4' }); + + await browser.close(); + } +} diff --git a/src/Plugins/image-input-plugin.ts b/src/Plugins/image-input-plugin.ts new file mode 100644 index 0000000..b90a37c --- /dev/null +++ b/src/Plugins/image-input-plugin.ts @@ -0,0 +1,23 @@ +import * as fs from 'fs'; +import PDFDocument from 'pdfkit'; + +export class ImageInputPlugin { + async convertImageToPdf( + imageFilePath: string, + pdfFilePath: string, + ): Promise { + const doc = new PDFDocument(); + const output = fs.createWriteStream(pdfFilePath); + + try { + doc.image(imageFilePath, { fit: [600, 800] }); // Adjust dimensions as needed + doc.pipe(output); + doc.end(); + + console.log('Image converted to PDF successfully'); + } catch (error) { + console.error('Error converting image to PDF:', error); + throw new Error('Image to PDF conversion failed'); + } + } +} diff --git a/src/Plugins/officegen.d.ts b/src/Plugins/officegen.d.ts new file mode 100644 index 0000000..4ec4378 --- /dev/null +++ b/src/Plugins/officegen.d.ts @@ -0,0 +1,4 @@ +declare module 'officegen' { + const officegen: any; + export default officegen; // +} diff --git a/src/Plugins/pdf-poppler.d.ts b/src/Plugins/pdf-poppler.d.ts new file mode 100644 index 0000000..8bc32ff --- /dev/null +++ b/src/Plugins/pdf-poppler.d.ts @@ -0,0 +1,4 @@ +declare module 'pdf-poppler' { + export function info(filePath: string): Promise; // + export function convert(filePath: string, options: any): Promise; +} diff --git a/src/Plugins/plugin.controller.ts b/src/Plugins/plugin.controller.ts new file mode 100644 index 0000000..8153394 --- /dev/null +++ b/src/Plugins/plugin.controller.ts @@ -0,0 +1,126 @@ +import { Controller, Post, Get, Param, Dependencies } from '@nestjs/common'; +import * as fs from 'fs'; +import { PluginService } from './pdf-plugin.service'; +import { PluginOutput } from './pdf-plugin.interfaces'; +import { PdfOutputPlugin } from './pdf-output-plugin'; +import { PdfInputPlugin } from './pdf-input-plugin'; +import { DocxOutputPlugin } from './docsx-output-plugin'; +import { DocxInputPlugin } from './docsx-input-plugin'; +import { ImageOutputPlugin } from './image-output-plugin'; // Import the ImageOutputPlugin +import { ImageInputPlugin } from './image-input-plugin'; + +@Controller('plugin') +@Dependencies(PluginService) +export class PluginController { + private pdfOutputPlugin!: PdfOutputPlugin; + private pdfInputPlugin!: PdfInputPlugin; + private docxOutputPlugin!: DocxOutputPlugin; + private docxInputPlugin!: DocxInputPlugin; + private imageOutputPlugin!: ImageOutputPlugin; // Add the ImageOutputPlugin + private imageInputPlugin!: ImageInputPlugin; + constructor(private readonly pluginService: PluginService) {} + + onModuleInit() { + this.pdfOutputPlugin = new PdfOutputPlugin(); + this.pdfInputPlugin = new PdfInputPlugin(); + this.docxOutputPlugin = new DocxOutputPlugin(); + this.docxInputPlugin = new DocxInputPlugin(); + this.imageOutputPlugin = new ImageOutputPlugin(); // Initialize the ImageOutputPlugin + this.imageInputPlugin = new ImageInputPlugin(); + } + + @Post('generate-doc/:outputType') + async generateDocument( + @Param('outputType') outputType: string, + ): Promise { + try { + if (outputType === 'PDF') { + return this.pdfOutputPlugin.generateDoc(outputType); + } else if (outputType === 'DOCX') { + return this.docxOutputPlugin.generateDoc(outputType); + } else if (outputType === 'IMG') { + // Add this condition for image generation + return this.imageOutputPlugin.generateImage(outputType); + } else { + throw new Error('Unsupported output type'); + } + } catch (error: any) { + console.error('Error generating document:', error.message); + throw new Error('Failed to generate document'); + } + } + + @Get('convert-img-to-pdf') + async convertImageToPdf(): Promise { + try { + const imageFilePath = './generatedImage.png'; // Replace with the actual path to the image + const pdfFilePath = './generatedImage.pdf'; + + await this.imageInputPlugin.convertImageToPdf(imageFilePath, pdfFilePath); + + return { file: 'generatedImage.pdf' }; + } catch (error: any) { + console.error('Error converting image to PDF:', error.message); + throw new Error('Failed to convert image to PDF'); + } + } + + @Get('convert-docx-to-pdf') + async convertDocxToPdf(): Promise { + try { + const docxFilePath = './generatedDocxDocument.docx'; // Adjust the path accordingly + const pdfFilePath = './generated-document.pdf'; + + const pluginOutput = await this.docxInputPlugin.convertDocxToPdf( + docxFilePath, + ); + + if (!pluginOutput.file) { + throw new Error('Generated PDF file not found.'); + } + + fs.renameSync(pluginOutput.file, pdfFilePath); + + return { file: 'generated-document.pdf' }; + } catch (error: any) { + console.error('Error converting DOCX to PDF:', error.message); + throw new Error('Failed to convert DOCX to PDF'); + } + } + @Get() + getPluginStatus(): string { + return 'Plugin is running!'; + } + + @Get('/pdf-to-image') + async convertPdfToImage(): Promise<{ images?: { url: string }[] }> { + const pdfFilePath = './generatedDocument.pdf'; + try { + const pluginOutput = await this.pdfInputPlugin.transformPdfToImage( + pdfFilePath, + ); + + if (pluginOutput.images) { + const images = pluginOutput.images; + images.forEach((image: { url: string }) => { + console.log('Image URL:', image.url); + }); + } + + return { images: pluginOutput.images }; + } catch (error) { + console.error('Error converting PDF to image:', error); + throw new Error('PDF to image conversion failed'); + } + } + + @Post('create-default-pdf') + async createDefaultPdf(): Promise { + try { + return this.pdfOutputPlugin.createDefaultPdf(); + } catch (error: any) { + console.error('Error creating default PDF:', error.message); + throw new Error('Failed to create default PDF'); + } + } +} From 51be085dd5a315f8d1cbd52edf018b740baf2211 Mon Sep 17 00:00:00 2001 From: kartik tongaria Date: Sat, 26 Aug 2023 01:25:47 +0530 Subject: [PATCH 2/3] Added Remaing Plugins --- src/Plugins/Drawio-input-plugin.ts | 51 ++++++ src/Plugins/Mermaid.input.plugin.ts | 30 ++++ src/Plugins/excalidraw.input-plugin.ts | 33 ++++ src/Plugins/officegen.d.ts | 2 +- src/Plugins/pdf-poppler.d.ts | 2 +- src/Plugins/plugin.controller.ts | 215 +++++++++++++++++++------ src/Plugins/puppeteer-html-to-pdf.d.ts | 16 ++ 7 files changed, 294 insertions(+), 55 deletions(-) create mode 100644 src/Plugins/Drawio-input-plugin.ts create mode 100644 src/Plugins/Mermaid.input.plugin.ts create mode 100644 src/Plugins/excalidraw.input-plugin.ts create mode 100644 src/Plugins/puppeteer-html-to-pdf.d.ts diff --git a/src/Plugins/Drawio-input-plugin.ts b/src/Plugins/Drawio-input-plugin.ts new file mode 100644 index 0000000..a5c0a12 --- /dev/null +++ b/src/Plugins/Drawio-input-plugin.ts @@ -0,0 +1,51 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { PluginOutput } from './pdf-plugin.interfaces'; +import puppeteer from 'puppeteer'; +import { parseString } from 'xml2js'; + +export class DrawioInputPlugin { + public async convertDrawioFileToPdf( + drawioFilePath: string, + ): Promise { + try { + // Read Draw.io file content + const drawioXml = fs.readFileSync(drawioFilePath, 'utf-8'); + + // Parse Draw.io XML to JavaScript object + let drawioJson; + parseString(drawioXml, (err, result) => { + if (err) { + throw err; + } + drawioJson = result; + }); + + // Convert Draw.io JSON object to HTML (manually or using a templating engine) + const drawioHtml = `
${JSON.stringify(drawioJson)}
`; + + // Launch a headless browser instance + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + + // Set the content of the page to the Draw.io HTML + await page.setContent(drawioHtml); + + // Generate a PDF from the rendered HTML content + const pdfBuffer = await page.pdf(); + + // Close the browser + await browser.close(); + + const pdfFilePath = path.join(__dirname, 'generatedDrawio.pdf'); // Adjust the path accordingly + fs.writeFileSync(pdfFilePath, pdfBuffer); + + console.log('Draw.io PDF generated successfully'); + + return { file: 'generatedDrawio.pdf' }; + } catch (error) { + console.error('Error converting Draw.io file to PDF:', error); + throw new Error('Failed to convert Draw.io file to PDF'); + } + } +} diff --git a/src/Plugins/Mermaid.input.plugin.ts b/src/Plugins/Mermaid.input.plugin.ts new file mode 100644 index 0000000..78bb703 --- /dev/null +++ b/src/Plugins/Mermaid.input.plugin.ts @@ -0,0 +1,30 @@ +import { PluginOutput } from './pdf-plugin.interfaces'; // Make sure you import the correct interface +import puppeteer from 'puppeteer'; + +export class MermaidInputPlugin { + public async convertMermaidToPdf(mermaidContent: any): Promise { + try { + const pdfFilePath = `./generatedMermaid.pdf`; // Adjust the path + + // Launch a headless browser + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + + // Set the content of the page to the Mermaid diagram HTML + const htmlContent = `
${mermaidContent}
`; + await page.setContent(htmlContent); + + // Generate a PDF from the Mermaid diagram HTML + await page.pdf({ path: pdfFilePath, format: 'A4' }); + + await browser.close(); + + console.log('Mermaid PDF generated successfully'); + + return { file: 'generatedMermaid.pdf' }; + } catch (error) { + console.error('Error generating Mermaid PDF:', error); + throw new Error('Failed to convert Mermaid to PDF'); + } + } +} diff --git a/src/Plugins/excalidraw.input-plugin.ts b/src/Plugins/excalidraw.input-plugin.ts new file mode 100644 index 0000000..4a97cc0 --- /dev/null +++ b/src/Plugins/excalidraw.input-plugin.ts @@ -0,0 +1,33 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { PluginOutput } from './pdf-plugin.interfaces'; // Make sure you import the correct interface +import puppeteer from 'puppeteer'; + +export class ExcalidrawInputPlugin { + public async convertExcalidrawToPdf( + excalidrawContent: string, + ): Promise { + try { + const pdfFilePath = path.join(__dirname, 'generatedExcalidraw.pdf'); // Adjust the path + + // Launch a headless browser + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + + // Set the content of the page to the Excalidraw SVG + await page.setContent(excalidrawContent); + + // Generate a PDF from the SVG + await page.pdf({ path: pdfFilePath, format: 'A4' }); + + await browser.close(); + + console.log('Excalidraw PDF generated successfully'); + + return { file: pdfFilePath }; + } catch (error) { + console.error('Error generating Excalidraw PDF:', error); + throw new Error('Failed to convert Excalidraw to PDF'); + } + } +} diff --git a/src/Plugins/officegen.d.ts b/src/Plugins/officegen.d.ts index 4ec4378..a6f8d2d 100644 --- a/src/Plugins/officegen.d.ts +++ b/src/Plugins/officegen.d.ts @@ -1,4 +1,4 @@ declare module 'officegen' { const officegen: any; - export default officegen; // + export default officegen; } diff --git a/src/Plugins/pdf-poppler.d.ts b/src/Plugins/pdf-poppler.d.ts index 8bc32ff..7872b86 100644 --- a/src/Plugins/pdf-poppler.d.ts +++ b/src/Plugins/pdf-poppler.d.ts @@ -1,4 +1,4 @@ declare module 'pdf-poppler' { export function info(filePath: string): Promise; // export function convert(filePath: string, options: any): Promise; -} +} // diff --git a/src/Plugins/plugin.controller.ts b/src/Plugins/plugin.controller.ts index 8153394..d25aa36 100644 --- a/src/Plugins/plugin.controller.ts +++ b/src/Plugins/plugin.controller.ts @@ -1,4 +1,14 @@ -import { Controller, Post, Get, Param, Dependencies } from '@nestjs/common'; +import { + Controller, + Post, + Query, + UseInterceptors, + Res, + Get, + Body, + Param, + Dependencies, +} from '@nestjs/common'; import * as fs from 'fs'; import { PluginService } from './pdf-plugin.service'; import { PluginOutput } from './pdf-plugin.interfaces'; @@ -8,6 +18,12 @@ import { DocxOutputPlugin } from './docsx-output-plugin'; import { DocxInputPlugin } from './docsx-input-plugin'; import { ImageOutputPlugin } from './image-output-plugin'; // Import the ImageOutputPlugin import { ImageInputPlugin } from './image-input-plugin'; +import { DrawioInputPlugin } from './Drawio-input-plugin'; +import * as path from 'path'; +import { parseString } from 'xml2js'; // Import parseString from xml2js +import puppeteer from 'puppeteer'; +import { ExcalidrawInputPlugin } from './excalidraw.input-plugin'; // Adjust the import path +import { MermaidInputPlugin } from './Mermaid.input.plugin'; // Adjust the import path @Controller('plugin') @Dependencies(PluginService) @@ -18,6 +34,9 @@ export class PluginController { private docxInputPlugin!: DocxInputPlugin; private imageOutputPlugin!: ImageOutputPlugin; // Add the ImageOutputPlugin private imageInputPlugin!: ImageInputPlugin; + private ExcalidrawInputPlugin!: ExcalidrawInputPlugin; + private MermaidInputPlugin!: MermaidInputPlugin; + private DrawioInputPlugin!: DrawioInputPlugin; constructor(private readonly pluginService: PluginService) {} onModuleInit() { @@ -27,38 +46,71 @@ export class PluginController { this.docxInputPlugin = new DocxInputPlugin(); this.imageOutputPlugin = new ImageOutputPlugin(); // Initialize the ImageOutputPlugin this.imageInputPlugin = new ImageInputPlugin(); + this.ExcalidrawInputPlugin = new ExcalidrawInputPlugin(); + this.DrawioInputPlugin = new DrawioInputPlugin(); + this.MermaidInputPlugin = new MermaidInputPlugin(); } - @Post('generate-doc/:outputType') - async generateDocument( - @Param('outputType') outputType: string, - ): Promise { + @Get() + getPluginStatus(): string { + return 'Plugin is running!'; + } + + @Post('generate-pdf') + async generatePdf(@Body() userInput: string[]): Promise { try { - if (outputType === 'PDF') { - return this.pdfOutputPlugin.generateDoc(outputType); - } else if (outputType === 'DOCX') { - return this.docxOutputPlugin.generateDoc(outputType); - } else if (outputType === 'IMG') { - // Add this condition for image generation - return this.imageOutputPlugin.generateImage(outputType); - } else { - throw new Error('Unsupported output type'); - } + const result = await this.pdfOutputPlugin.generateDoc('pdf', userInput); + return result; + } catch (error: any) { + console.error('Error generating PDF:', error.message); + throw new Error('Failed to generate PDF'); + } + } + + @Post('create-default-pdf') + async createDefaultPdf(): Promise { + try { + return this.pdfOutputPlugin.createDefaultPdf(); + } catch (error: any) { + console.error('Error creating default PDF:', error.message); + throw new Error('Failed to create default PDF'); + } + } + @Post('generate-docx') + async generateDocx(@Body() userInput: string[]): Promise { + try { + const result = await this.docxOutputPlugin.generateDoc('docx', userInput); + return result; } catch (error: any) { - console.error('Error generating document:', error.message); - throw new Error('Failed to generate document'); + console.error('Error generating DOCX:', error.message); + throw new Error('Failed to generate DOCX'); + } + } + @Post('generate-image') + async generateImage(@Body() userInput: string): Promise { + try { + return await this.imageOutputPlugin.generateImage('img', userInput); + } catch (error: any) { + console.error('Error generating image:', error.message); + throw new Error('Failed to generate image'); } } - @Get('convert-img-to-pdf') - async convertImageToPdf(): Promise { + @Get('convert-image-to-pdf') + async convertImageToPdf( + @Query('imagePath') imagePath: string, + ): Promise { try { - const imageFilePath = './generatedImage.png'; // Replace with the actual path to the image - const pdfFilePath = './generatedImage.pdf'; + if (!imagePath) { + console.error('Image file path not provided.'); + throw new Error('Image file path not provided.'); + } - await this.imageInputPlugin.convertImageToPdf(imageFilePath, pdfFilePath); + const pdfFilePath = `./generatedImage.pdf`; // Output PDF file path - return { file: 'generatedImage.pdf' }; + await this.imageInputPlugin.convertImageToPdf(imagePath, pdfFilePath); + + return { pdfPath: pdfFilePath }; } catch (error: any) { console.error('Error converting image to PDF:', error.message); throw new Error('Failed to convert image to PDF'); @@ -66,61 +118,118 @@ export class PluginController { } @Get('convert-docx-to-pdf') - async convertDocxToPdf(): Promise { + async convertDocxToPdf( + @Query('docxPath') docxPath: string, + ): Promise { try { - const docxFilePath = './generatedDocxDocument.docx'; // Adjust the path accordingly - const pdfFilePath = './generated-document.pdf'; + if (!docxPath) { + console.error('DOCX file path not provided.'); + throw new Error('DOCX file path not provided.'); + } const pluginOutput = await this.docxInputPlugin.convertDocxToPdf( - docxFilePath, + docxPath, ); if (!pluginOutput.file) { throw new Error('Generated PDF file not found.'); } - fs.renameSync(pluginOutput.file, pdfFilePath); - - return { file: 'generated-document.pdf' }; + return { file: 'generatedPdfDocument.pdf' }; } catch (error: any) { console.error('Error converting DOCX to PDF:', error.message); throw new Error('Failed to convert DOCX to PDF'); } } - @Get() - getPluginStatus(): string { - return 'Plugin is running!'; - } - @Get('/pdf-to-image') - async convertPdfToImage(): Promise<{ images?: { url: string }[] }> { - const pdfFilePath = './generatedDocument.pdf'; + @Get('convert-docx-to-images') + async convertDocxToImages( + @Query('docxPath') docxPath: string, + ): Promise { try { - const pluginOutput = await this.pdfInputPlugin.transformPdfToImage( - pdfFilePath, + if (!docxPath) { + console.error('DOCX file path not provided.'); + throw new Error('DOCX file path not provided.'); + } + + const pluginOutput = await this.docxInputPlugin.convertDocxToImages( + docxPath, ); - if (pluginOutput.images) { - const images = pluginOutput.images; - images.forEach((image: { url: string }) => { - console.log('Image URL:', image.url); - }); + if (!pluginOutput.folder) { + throw new Error('Generated images folder not found.'); } - return { images: pluginOutput.images }; - } catch (error) { - console.error('Error converting PDF to image:', error); - throw new Error('PDF to image conversion failed'); + return { folder: pluginOutput.folder }; + } catch (error: any) { + console.error('Error converting DOCX to images:', error.message); + throw new Error('Failed to convert DOCX to images'); } } - @Post('create-default-pdf') - async createDefaultPdf(): Promise { + @Get('convert-drawio-to-pdf') + async convertDrawioFileToPdf(): Promise { try { - return this.pdfOutputPlugin.createDefaultPdf(); + const drawioFilePath = + 'C:/Users/Kartik/Documents/C4gt/Doc-Generator/abc.drawio'; // Adjust the path accordingly + const pluginOutput = await this.DrawioInputPlugin.convertDrawioFileToPdf( + drawioFilePath, + ); + + return pluginOutput; } catch (error: any) { - console.error('Error creating default PDF:', error.message); - throw new Error('Failed to create default PDF'); + console.error('Error converting Draw.io file to PDF:', error.message); + throw new Error('Failed to convert Draw.io file to PDF'); + } + } + + @Get('convert-excalidraw-to-pdf') + async convertExcalidrawToPdf( + @Query('excalidrawpath') excalidrawContent: string, + ): Promise { + try { + if (!excalidrawContent) { + console.error('Excalidraw content not provided.'); + throw new Error('Excalidraw content not provided.'); + } + + const pluginOutput = + await this.ExcalidrawInputPlugin.convertExcalidrawToPdf( + excalidrawContent, + ); + + if (!pluginOutput.file) { + throw new Error('Generated PDF file not found.'); + } + + return { file: pluginOutput.file }; // Use the correct property from the pluginOutput + } catch (error: any) { + console.error('Error converting Excalidraw to PDF:', error.message); + throw new Error('Failed to convert Excalidraw to PDF'); + } + } + @Get('convert-drawio-to-pdf') + async convertDrawioToPdf( + @Query('drawioFilePath') drawioFilePath: string, + ): Promise { + try { + if (!drawioFilePath) { + console.error('Draw.io file path not provided.'); + throw new Error('Draw.io file path not provided.'); + } + + const pluginOutput = await this.DrawioInputPlugin.convertDrawioFileToPdf( + drawioFilePath, + ); + + if (!pluginOutput.file) { + throw new Error('Generated PDF file not found.'); + } + + return { file: pluginOutput.file }; + } catch (error: any) { + console.error('Error converting Draw.io to PDF:', error.message); + throw new Error('Failed to convert Draw.io to PDF'); } } } diff --git a/src/Plugins/puppeteer-html-to-pdf.d.ts b/src/Plugins/puppeteer-html-to-pdf.d.ts new file mode 100644 index 0000000..f530b8a --- /dev/null +++ b/src/Plugins/puppeteer-html-to-pdf.d.ts @@ -0,0 +1,16 @@ +declare module 'puppeteer-html-to-pdf' { + interface Page { + goto: (url: string) => Promise; + waitForSelector: (selector: string) => Promise; + evaluate: (fn: (xml: string) => void, xml: string) => Promise; + } + + interface Browser { + newPage: () => Promise; + close: () => Promise; + } + + function initBrowser(): Promise; + + function generatePdfBuffer(page: Page): Promise; +} From a9d6aa377471c2117b1ff44690f301150f6f3ce4 Mon Sep 17 00:00:00 2001 From: kartik tongaria Date: Mon, 18 Sep 2023 18:50:40 +0530 Subject: [PATCH 3/3] completed_plugin --- src/Plugins/Drawio-input-plugin.ts | 6 +- src/Plugins/Mermaid.input.plugin.ts | 2 +- src/Plugins/docsx-input-plugin.ts | 48 +++++++++++++- src/Plugins/docsx-output-plugin.ts | 37 +++++++++++ src/Plugins/docx-plugin.service.ts | 25 ++++++++ src/Plugins/excalidraw.input-plugin.ts | 2 +- src/Plugins/image-input-plugin.ts | 28 +++++--- src/Plugins/image-output-plugin.ts | 45 +++++++++++++ src/Plugins/officegen.d.ts | 2 +- src/Plugins/pdf-input-plugin.ts | 34 ++++++++++ src/Plugins/pdf-output-plugin.ts | 72 +++++++++++++++++++++ src/Plugins/pdf-plugin.interfaces.ts | 19 ++++++ src/Plugins/pdf-plugin.service.ts | 89 ++++++++++++++++++++++++++ src/Plugins/pdf-poppler.d.ts | 4 +- src/Plugins/plugin.controller.ts | 51 ++++++++++----- src/Plugins/plugin.module.ts | 16 +++++ src/Plugins/puppeteer-html-to-pdf.d.ts | 2 +- 17 files changed, 445 insertions(+), 37 deletions(-) create mode 100644 src/Plugins/docsx-output-plugin.ts create mode 100644 src/Plugins/docx-plugin.service.ts create mode 100644 src/Plugins/image-output-plugin.ts create mode 100644 src/Plugins/pdf-input-plugin.ts create mode 100644 src/Plugins/pdf-output-plugin.ts create mode 100644 src/Plugins/pdf-plugin.interfaces.ts create mode 100644 src/Plugins/pdf-plugin.service.ts create mode 100644 src/Plugins/plugin.module.ts diff --git a/src/Plugins/Drawio-input-plugin.ts b/src/Plugins/Drawio-input-plugin.ts index a5c0a12..2d3560d 100644 --- a/src/Plugins/Drawio-input-plugin.ts +++ b/src/Plugins/Drawio-input-plugin.ts @@ -9,10 +9,10 @@ export class DrawioInputPlugin { drawioFilePath: string, ): Promise { try { - // Read Draw.io file content + // Read Draw.io file conten const drawioXml = fs.readFileSync(drawioFilePath, 'utf-8'); - // Parse Draw.io XML to JavaScript object + // Parse Draw.io XML to JavaScript object// let drawioJson; parseString(drawioXml, (err, result) => { if (err) { @@ -34,7 +34,7 @@ export class DrawioInputPlugin { // Generate a PDF from the rendered HTML content const pdfBuffer = await page.pdf(); - // Close the browser + // Close the browsers await browser.close(); const pdfFilePath = path.join(__dirname, 'generatedDrawio.pdf'); // Adjust the path accordingly diff --git a/src/Plugins/Mermaid.input.plugin.ts b/src/Plugins/Mermaid.input.plugin.ts index 78bb703..13de642 100644 --- a/src/Plugins/Mermaid.input.plugin.ts +++ b/src/Plugins/Mermaid.input.plugin.ts @@ -10,7 +10,7 @@ export class MermaidInputPlugin { const browser = await puppeteer.launch(); const page = await browser.newPage(); - // Set the content of the page to the Mermaid diagram HTML + // Set the content of the page to the Mermaid diagram HTML// const htmlContent = `
${mermaidContent}
`; await page.setContent(htmlContent); diff --git a/src/Plugins/docsx-input-plugin.ts b/src/Plugins/docsx-input-plugin.ts index 1175515..568214a 100644 --- a/src/Plugins/docsx-input-plugin.ts +++ b/src/Plugins/docsx-input-plugin.ts @@ -1,12 +1,12 @@ import * as path from 'path'; import * as mammoth from 'mammoth'; import * as puppeteer from 'puppeteer'; -import { PluginOutput } from './pdf-plugin.interfaces'; +import { PluginOutput } from './pdf-plugin.interfaces'; // export class DocxInputPlugin { public async convertDocxToPdf(docxFilePath: string): Promise { try { - const outputPdfPath = path.join(__dirname, './generatedPdfDocument.pdf'); + const outputPdfPath = `./DocxToPdf.pdf`; const htmlContent = await this.convertDocxToHtml(docxFilePath); await this.htmlToPdf(htmlContent, outputPdfPath); @@ -29,6 +29,50 @@ export class DocxInputPlugin { await page.setContent(htmlContent); await page.pdf({ path: pdfPath, format: 'A4' }); + await browser.close(); + } + public async convertDocxToImages( + docxFilePath: string, + ): Promise { + try { + const imagesFolderPath = path.join(__dirname, './generatedImages'); + const htmlContent = await this.convertDocxToHtml(docxFilePath); + await this.htmlToImages(htmlContent, imagesFolderPath); + + console.log('Images generated successfully'); + return { folder: imagesFolderPath }; + } catch (error) { + console.error('Error generating images:', error); + throw new Error('Failed to convert DOCX to images'); + } + } + + private async htmlToImages( + htmlContent: string, + imagesFolderPath: string, + ): Promise { + const browser = await puppeteer.launch(); + const page = await browser.newPage(); + await page.setContent(htmlContent); + + const elements = await page.$$('img'); // Get all img elements in the HTML + for (let i = 0; i < elements.length; i++) { + const imgElement = elements[i]; + const imgSrc = await imgElement.evaluate((node) => + node.getAttribute('src'), + ); + const imgName = `image_${i}.png`; + const imgPath = path.join(imagesFolderPath, imgName); + + // Wait for images to load + await page.waitForFunction(() => { + const images = document.getElementsByTagName('img'); + return Array.from(images).every((img) => img.complete); + }); + + await imgElement.screenshot({ path: imgPath }); + } + await browser.close(); } } diff --git a/src/Plugins/docsx-output-plugin.ts b/src/Plugins/docsx-output-plugin.ts new file mode 100644 index 0000000..b07a41a --- /dev/null +++ b/src/Plugins/docsx-output-plugin.ts @@ -0,0 +1,37 @@ +import * as path from 'path'; +import * as fs from 'fs'; +import officegen from 'officegen'; +import { PluginOutput } from './pdf-plugin.interfaces'; // + +export class DocxOutputPlugin { + public async generateDoc( + outputType: string, + userInput: string[], + ): Promise { + const docFilePath = path.join('./generatedDocxDocument.docx'); + + return new Promise((resolve, reject) => { + const docx = new officegen('docx'); + + // Iterate through user input and add paragraphs to the document + userInput.forEach((input) => { + const paragraph = docx.createP(); + paragraph.addText(input); + }); + + // Generate the DOCX file + const outputStream = fs.createWriteStream(docFilePath); + docx.generate(outputStream); + + outputStream.on('finish', () => { + console.log('DOCX file generated successfully'); + resolve({ file: 'generatedDocxDocument.docx' }); + }); + + outputStream.on('error', (error) => { + console.error('Error generating DOCX:', error); + reject(error); + }); + }); + } +} diff --git a/src/Plugins/docx-plugin.service.ts b/src/Plugins/docx-plugin.service.ts new file mode 100644 index 0000000..f62de1c --- /dev/null +++ b/src/Plugins/docx-plugin.service.ts @@ -0,0 +1,25 @@ +import { Injectable } from '@nestjs/common'; +import { PluginOutput } from './pdf-plugin.interfaces'; +import { promisify } from 'util'; +import { exec } from 'child_process'; // + +@Injectable() +export class DocxInputService { + async convertToPdf(docxFilePath: string): Promise { + const pdfFilePath = docxFilePath.replace('.docx', '.pdf'); + + const execAsync = promisify(exec); + + try { + const command = `pandoc ${docxFilePath} -o ${pdfFilePath}`; + await execAsync(command); + + console.log('PDF file generated successfully'); + return { file: pdfFilePath }; + } catch (error: any) { + // Cast error to 'any' type + console.error('Error converting to PDF:', error.message); + throw new Error('Failed to convert DOCX to PDF'); + } + } +} diff --git a/src/Plugins/excalidraw.input-plugin.ts b/src/Plugins/excalidraw.input-plugin.ts index 4a97cc0..1d514f2 100644 --- a/src/Plugins/excalidraw.input-plugin.ts +++ b/src/Plugins/excalidraw.input-plugin.ts @@ -17,7 +17,7 @@ export class ExcalidrawInputPlugin { // Set the content of the page to the Excalidraw SVG await page.setContent(excalidrawContent); - // Generate a PDF from the SVG + // Generate a PDF from the SVG // await page.pdf({ path: pdfFilePath, format: 'A4' }); await browser.close(); diff --git a/src/Plugins/image-input-plugin.ts b/src/Plugins/image-input-plugin.ts index b90a37c..45cdbff 100644 --- a/src/Plugins/image-input-plugin.ts +++ b/src/Plugins/image-input-plugin.ts @@ -9,15 +9,25 @@ export class ImageInputPlugin { const doc = new PDFDocument(); const output = fs.createWriteStream(pdfFilePath); - try { - doc.image(imageFilePath, { fit: [600, 800] }); // Adjust dimensions as needed - doc.pipe(output); - doc.end(); + return new Promise((resolve, reject) => { + try { + doc.image(imageFilePath, { fit: [600, 800] }); // Adjust dimensions as needed// + doc.pipe(output); + doc.end(); - console.log('Image converted to PDF successfully'); - } catch (error) { - console.error('Error converting image to PDF:', error); - throw new Error('Image to PDF conversion failed'); - } + output.on('finish', () => { + console.log('Image converted to PDF successfully'); + resolve(); + }); + + output.on('error', (error) => { + console.error('Error converting image to PDF:', error); + reject(new Error('Image to PDF conversion failed')); + }); + } catch (error) { + console.error('Error converting image to PDF:', error); + reject(new Error('Image to PDF conversion failed')); + } + }); } } diff --git a/src/Plugins/image-output-plugin.ts b/src/Plugins/image-output-plugin.ts new file mode 100644 index 0000000..2f95072 --- /dev/null +++ b/src/Plugins/image-output-plugin.ts @@ -0,0 +1,45 @@ +import * as fs from 'fs'; +import * as path from 'path'; +import { createCanvas } from 'canvas'; +import { PluginOutput } from './pdf-plugin.interfaces'; + +export class ImageOutputPlugin { + public async generateImage( + outputType: string, + userInput: string, + ): Promise { + if (outputType.toUpperCase() === 'IMG') { + const canvas = createCanvas(400, 200); + const context = canvas.getContext('2d'); + + context.fillStyle = '#FF0000'; + context.fillRect(0, 0, 400, 200); + + // Draw user input text on the images// + context.fillStyle = '#FFFFFF'; + context.font = '20px Arial'; + context.fillText(userInput, 50, 100); + + const imageFilePath = path.join('./generatedImage.png'); + + return new Promise((resolve, reject) => { + const stream = fs.createWriteStream(imageFilePath); + const streamOutput = canvas.createPNGStream(); + + streamOutput.pipe(stream); + + stream.on('finish', () => { + console.log('Image generated successfully'); + resolve({ file: 'generatedImage.png' }); + }); + + stream.on('error', (error) => { + console.error('Error generating image:', error); + reject(error); + }); + }); + } else { + throw new Error('Unsupported output type'); + } + } +} diff --git a/src/Plugins/officegen.d.ts b/src/Plugins/officegen.d.ts index a6f8d2d..934350b 100644 --- a/src/Plugins/officegen.d.ts +++ b/src/Plugins/officegen.d.ts @@ -1,4 +1,4 @@ declare module 'officegen' { const officegen: any; export default officegen; -} +} // diff --git a/src/Plugins/pdf-input-plugin.ts b/src/Plugins/pdf-input-plugin.ts new file mode 100644 index 0000000..5f128cc --- /dev/null +++ b/src/Plugins/pdf-input-plugin.ts @@ -0,0 +1,34 @@ +import * as path from 'path'; +import { PluginOutput } from './pdf-plugin.interfaces'; +import * as pdfPoppler from 'pdf-poppler'; + +export class PdfInputPlugin { + public async transformPdfToImage(pdfFilePath: string): Promise { + const outDir = path.dirname(pdfFilePath); + const outPrefix = path.basename(pdfFilePath, path.extname(pdfFilePath)); + + const pdfImageOptions = { + format: 'jpeg', + out_dir: outDir, + out_prefix: outPrefix, + page: null, + }; + + try { + const result = await pdfPoppler.convert(pdfFilePath, pdfImageOptions); + + console.log('Successfully converted'); + console.log(result); + + const images = Array.isArray(result) + ? result.map((imagePath: string) => ({ url: imagePath })) + : [{ url: result }]; + + return { images: images }; + } catch (error) { + console.error('Error converting PDF to image:', error); + throw new Error('PDF to image conversion failed'); + } + } + // +} diff --git a/src/Plugins/pdf-output-plugin.ts b/src/Plugins/pdf-output-plugin.ts new file mode 100644 index 0000000..13fa3a8 --- /dev/null +++ b/src/Plugins/pdf-output-plugin.ts @@ -0,0 +1,72 @@ +import { TDocumentDefinitions } from 'pdfmake/interfaces'; +import * as pdfMake from 'pdfmake/build/pdfmake'; +import * as pdfFonts from 'pdfmake/build/vfs_fonts'; +import * as fs from 'fs'; +import * as path from 'path'; +import { PluginOutput } from './pdf-plugin.interfaces'; + +(pdfMake as any).vfs = pdfFonts.pdfMake.vfs; + +export class PdfOutputPlugin { + public async generateDoc( + outputType: string, + userInput: string[], + ): Promise { + if (outputType.toUpperCase() === 'PDF') { + const pdfContent: TDocumentDefinitions = { + content: [ + { + text: '', + fontSize: 16, + alignment: 'center', + margin: [0, 10, 0, 0], + }, + { + ul: userInput, // Assuming userInput is an array of string + }, + ], + }; + + const pdfDoc = pdfMake.createPdf(pdfContent); + const pdfFilePath = path.join('./generatedDocument.pdf'); + + return new Promise((resolve, reject) => { + pdfDoc.getBuffer((buffer) => { + fs.writeFileSync(pdfFilePath, buffer); + console.log('PDF generated successfully'); + resolve({ file: 'generatedDocument.pdf' }); + }); + }); + } else { + throw new Error('Unsupported output type'); + } + } + + public async createDefaultPdf(): Promise { + const pdfContent: TDocumentDefinitions = { + content: [ + { + text: 'Hello, this is a default PDF document!', + fontSize: 16, + alignment: 'center', + margin: [0, 100, 0, 0], + }, + ], + }; + + const pdfDoc = pdfMake.createPdf(pdfContent); + const pdfFilePath = './defaultDocument.pdf'; + + return new Promise((resolve, reject) => { + pdfDoc.getBuffer((buffer) => { + fs.writeFileSync(pdfFilePath, buffer); + console.log('Default PDF generated successfully'); + + resolve({ + file: 'defaultDocument.pdf', + url: 'http://your-domain.com/defaultDocument.pdf', // Replace with the actual PDF URL + }); + }); + }); + } +} diff --git a/src/Plugins/pdf-plugin.interfaces.ts b/src/Plugins/pdf-plugin.interfaces.ts new file mode 100644 index 0000000..8823c4f --- /dev/null +++ b/src/Plugins/pdf-plugin.interfaces.ts @@ -0,0 +1,19 @@ +export interface PluginOutput { + file?: string; + url?: string; + pdfPath?: string; + folder?: string; // Add this line to include the 'folder' properties + images?: { url: string }[]; +} + +export interface Plugin { + generateDoc(outputType: string): Promise; + validateTemplate(template: string): boolean; + getName(): string; + getSupportedOutputs(): string[]; + getSupportedInputs(): string[]; + transformToPDFMake( + inputType: string, + outputType: string, + ): Promise; +} diff --git a/src/Plugins/pdf-plugin.service.ts b/src/Plugins/pdf-plugin.service.ts new file mode 100644 index 0000000..8be7008 --- /dev/null +++ b/src/Plugins/pdf-plugin.service.ts @@ -0,0 +1,89 @@ +import { Injectable } from '@nestjs/common'; +import { Plugin, PluginOutput } from './pdf-plugin.interfaces'; +import * as path from 'path'; +import * as fs from 'fs'; +import { TDocumentDefinitions } from 'pdfmake/interfaces'; +import { PdfInputPlugin } from './pdf-input-plugin'; // Import PdfInputPlugin + +@Injectable() +export class PluginService implements Plugin { + constructor(private readonly pdfInputPlugin: PdfInputPlugin) {} // Use PdfInputPlugin here + + validateTemplate(template: string): boolean { + if (template === 'PDF') { + return true; + } else { + return false; + } + } + + getName(): string { + return 'PDF Plugin'; + } + + getSupportedOutputs(): string[] { + return ['PDF', 'Image']; + } + + getSupportedInputs(): string[] { + return ['PDF']; + } + // + + public async transformPdfToImage(pdfFilePath: string): Promise { + const outDir = path.dirname(pdfFilePath); + const outPrefix = path.basename(pdfFilePath, path.extname(pdfFilePath)); + + const pdfImageOptions = { + format: 'jpeg', + out_dir: outDir, + out_prefix: outPrefix, + page: null, + }; + + try { + await this.pdfInputPlugin.transformPdfToImage(pdfFilePath); + + console.log('Successfully converted'); + + const images = fs.readdirSync(outDir).map((fileName) => ({ + url: path.join(outDir, fileName), + })); + + return { images: images }; + } catch (error) { + console.error('Error converting PDF to image:', error); + throw new Error('PDF to image conversion failed'); + } + } + + transformToPDFMake( + inputType: string, + outputType: string, + ): Promise { + throw new Error('Method not implemented.'); + } + + transformPdfToDocsx(pdfFilePath: string): Promise { + throw new Error('Method not implemented.'); + } + + transformPdfToExcalidraw(inputFile: string): PluginOutput { + throw new Error('Method not implemented.'); + } + + transformPdfToDrawio(inputFile: string): PluginOutput { + throw new Error('Method not implemented.'); + } + + transformPdfMakeToMermaid(pdfMakeContent: TDocumentDefinitions): string { + throw new Error('Method not implemented.'); + } + + isSupportedConversion(inputType: string, outputType: string): boolean { + return true; + } + generateDoc(outputType: string): Promise { + throw new Error('Method not implemented.'); + } +} diff --git a/src/Plugins/pdf-poppler.d.ts b/src/Plugins/pdf-poppler.d.ts index 7872b86..8ebaaf9 100644 --- a/src/Plugins/pdf-poppler.d.ts +++ b/src/Plugins/pdf-poppler.d.ts @@ -1,4 +1,4 @@ declare module 'pdf-poppler' { - export function info(filePath: string): Promise; // + export function info(filePath: string): Promise; export function convert(filePath: string, options: any): Promise; -} // +} diff --git a/src/Plugins/plugin.controller.ts b/src/Plugins/plugin.controller.ts index d25aa36..9dc569a 100644 --- a/src/Plugins/plugin.controller.ts +++ b/src/Plugins/plugin.controller.ts @@ -96,6 +96,39 @@ export class PluginController { } } + @Get('convert-pdf-to-images') + async convertPdfToImages( + @Query('pdfPath') pdfPath: string, + ): Promise { + try { + if (!pdfPath) { + console.error('PDF file path not provided.'); + throw new Error('PDF file path not provided.'); + } + + // Define the output folder where the images will be saved + const outputFolder = './generatedImages'; // Change this path as needed + + // Call a function to convert the PDF to images (you should implement this function) + const pluginOutput = await this.pdfInputPlugin.transformPdfToImage( + pdfPath, + ); + + // Check if the plugin output contains the list of image URLs + if (pluginOutput.images) { + const images = pluginOutput.images; + images.forEach((image: { url: string }) => { + console.log('Image', image.url); + }); + } + + return { images: pluginOutput.images }; + } catch (error: any) { + console.error('Error converting PDF to images:', error.message); + throw new Error('PDF to images conversion failed'); + } + } + @Get('convert-image-to-pdf') async convertImageToPdf( @Query('imagePath') imagePath: string, @@ -167,22 +200,6 @@ export class PluginController { } } - @Get('convert-drawio-to-pdf') - async convertDrawioFileToPdf(): Promise { - try { - const drawioFilePath = - 'C:/Users/Kartik/Documents/C4gt/Doc-Generator/abc.drawio'; // Adjust the path accordingly - const pluginOutput = await this.DrawioInputPlugin.convertDrawioFileToPdf( - drawioFilePath, - ); - - return pluginOutput; - } catch (error: any) { - console.error('Error converting Draw.io file to PDF:', error.message); - throw new Error('Failed to convert Draw.io file to PDF'); - } - } - @Get('convert-excalidraw-to-pdf') async convertExcalidrawToPdf( @Query('excalidrawpath') excalidrawContent: string, @@ -202,7 +219,7 @@ export class PluginController { throw new Error('Generated PDF file not found.'); } - return { file: pluginOutput.file }; // Use the correct property from the pluginOutput + return { file: pluginOutput.file }; // Use the correct property from the pluginOutput// } catch (error: any) { console.error('Error converting Excalidraw to PDF:', error.message); throw new Error('Failed to convert Excalidraw to PDF'); diff --git a/src/Plugins/plugin.module.ts b/src/Plugins/plugin.module.ts new file mode 100644 index 0000000..61d3b3e --- /dev/null +++ b/src/Plugins/plugin.module.ts @@ -0,0 +1,16 @@ +import { Module } from '@nestjs/common'; +import { MulterModule } from '@nestjs/platform-express'; // Import MulterModule +import { PluginController } from './plugin.controller'; +import { PluginService } from './pdf-plugin.service'; +import { PdfInputPlugin } from './pdf-input-plugin'; + +@Module({ + imports: [ + MulterModule.register({ + dest: './uploads', // Specify the directory to store uploaded file + }), + ], + controllers: [PluginController], + providers: [PluginService, PdfInputPlugin], +}) +export class PluginModule {} diff --git a/src/Plugins/puppeteer-html-to-pdf.d.ts b/src/Plugins/puppeteer-html-to-pdf.d.ts index f530b8a..2fc607c 100644 --- a/src/Plugins/puppeteer-html-to-pdf.d.ts +++ b/src/Plugins/puppeteer-html-to-pdf.d.ts @@ -13,4 +13,4 @@ declare module 'puppeteer-html-to-pdf' { function initBrowser(): Promise; function generatePdfBuffer(page: Page): Promise; -} +} //