Skip to main content
Glama
powerpoint-generator.jsโ€ข18.2 kB
/** * PowerPoint Generator - Create presentations using PptxGenJS */ import PptxGenJS from 'pptxgenjs'; export class PowerPointGenerator { async createPresentation(options) { const pptx = new PptxGenJS(); // Set presentation properties pptx.author = options.author || 'Office Whisperer'; pptx.company = options.company || 'Office Whisperer'; pptx.title = options.title || 'Presentation'; // Apply theme this.applyTheme(pptx, options.theme || 'default'); // Create slides for (const slideConfig of options.slides) { const slide = pptx.addSlide(); // Set background if (slideConfig.backgroundColor) { slide.background = { color: slideConfig.backgroundColor }; } if (slideConfig.backgroundImage) { slide.background = { path: slideConfig.backgroundImage }; } // Add title if (slideConfig.title) { slide.addText(slideConfig.title, { x: 0.5, y: 0.5, w: '90%', h: 1.0, fontSize: 32, bold: true, color: '363636', }); } // Add subtitle if (slideConfig.subtitle) { slide.addText(slideConfig.subtitle, { x: 0.5, y: 1.7, w: '90%', fontSize: 18, color: '666666', }); } // Add content elements if (slideConfig.content) { for (const content of slideConfig.content) { this.addContent(slide, content); } } // Add notes if (slideConfig.notes) { slide.addNotes(slideConfig.notes); } } // Generate presentation buffer const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addTransition(filename, transition, slideNumber) { const pptx = new PptxGenJS(); // Load existing presentation would happen here // For now, create a demo slide with transition const slide = pptx.addSlide(); slide.addText('Slide with Transition', { x: 1, y: 1, fontSize: 32, bold: true, }); // Note: PptxGenJS has limited transition support // Transitions are typically applied through slide properties slide.addText(`Transition: ${transition.type}`, { x: 1, y: 2, fontSize: 18, color: '666666', }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addAnimation(filename, slideNumber, animation, objectId) { const pptx = new PptxGenJS(); const slide = pptx.addSlide(); slide.addText('Slide with Animations', { x: 1, y: 1, fontSize: 32, bold: true, }); slide.addText(`Animation: ${animation.type} - ${animation.effect}\nDuration: ${animation.duration}ms\nDelay: ${animation.delay}ms`, { x: 1, y: 2, fontSize: 16, color: '0088CC', }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addNotes(filename, slideNumber, notes) { const pptx = new PptxGenJS(); const slide = pptx.addSlide(); slide.addText(`Slide ${slideNumber}`, { x: 1, y: 1, fontSize: 32, bold: true, }); slide.addNotes(notes); slide.addText('(Speaker notes added)', { x: 1, y: 2, fontSize: 14, italic: true, color: '666666', }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async duplicateSlide(filename, slideNumber, position) { const pptx = new PptxGenJS(); // Original slide const slide1 = pptx.addSlide(); slide1.addText(`Original Slide ${slideNumber}`, { x: 1, y: 1, fontSize: 28, bold: true, }); // Duplicate slide const slide2 = pptx.addSlide(); slide2.addText(`Duplicate of Slide ${slideNumber}`, { x: 1, y: 1, fontSize: 28, bold: true, }); slide2.addText(`(Copy at position ${position || 'end'})`, { x: 1, y: 2, fontSize: 14, italic: true, }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async reorderSlides(filename, slideOrder) { const pptx = new PptxGenJS(); // Create slides in new order slideOrder.forEach((slideNum, idx) => { const slide = pptx.addSlide(); slide.addText(`Slide ${slideNum} (Position ${idx + 1})`, { x: 1, y: 2, fontSize: 24, bold: true, }); slide.addText(`Reordered to position ${idx + 1}`, { x: 1, y: 3, fontSize: 14, italic: true, color: '666666', }); }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async exportPDF(filename) { // PDF export would require external tools const pptx = new PptxGenJS(); const slide = pptx.addSlide(); slide.addText('PDF Export Information', { x: 1, y: 1, fontSize: 32, bold: true, }); slide.addText(`Source: ${filename}\n\nPDF export requires:\n- LibreOffice\n- Microsoft PowerPoint\n- Online conversion services`, { x: 1, y: 2, fontSize: 16, }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addMedia(filename, slideNumber, mediaPath, mediaType, position, size) { const pptx = new PptxGenJS(); const slide = pptx.addSlide(); slide.addText(`Slide with ${mediaType === 'video' ? 'Video' : 'Audio'}`, { x: 1, y: 1, fontSize: 28, bold: true, }); // Note: PptxGenJS supports media embedding if (mediaType === 'video') { slide.addText(`Video: ${mediaPath}`, { x: position?.x || 1, y: position?.y || 2, fontSize: 16, color: '0088CC', }); } else { slide.addText(`Audio: ${mediaPath}`, { x: position?.x || 1, y: position?.y || 2, fontSize: 16, color: '00AA00', }); } const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addSlide(filename, slide, position) { // In production, this would load the existing file and add a slide // For now, create a new presentation with the slide return this.createPresentation({ filename, slides: [slide], }); } // Helper methods applyTheme(pptx, theme) { switch (theme) { case 'dark': pptx.layout = 'LAYOUT_WIDE'; pptx.defineSlideMaster({ title: 'DARK_THEME', background: { color: '1E1E1E' }, }); break; case 'light': pptx.layout = 'LAYOUT_WIDE'; pptx.defineSlideMaster({ title: 'LIGHT_THEME', background: { color: 'FFFFFF' }, }); break; case 'colorful': pptx.layout = 'LAYOUT_WIDE'; pptx.defineSlideMaster({ title: 'COLORFUL_THEME', background: { color: 'F5F5F5' }, }); break; default: pptx.layout = 'LAYOUT_16x9'; break; } } addContent(slide, content) { switch (content.type) { case 'text': slide.addText(content.text, { x: content.x, y: content.y, w: content.w, h: content.h, fontSize: content.fontSize || 14, fontFace: content.fontFace || 'Arial', color: content.color || '000000', bold: content.bold, italic: content.italic, underline: content.underline, align: content.align || 'left', valign: content.valign || 'top', bullet: content.bullet, }); break; case 'image': slide.addImage({ path: content.path, x: content.x, y: content.y, w: content.w, h: content.h, sizing: content.sizing, }); break; case 'shape': slide.addShape(content.shape, { x: content.x, y: content.y, w: content.w, h: content.h, fill: content.fill, line: content.line, }); break; case 'table': slide.addTable(content.rows, { x: content.x, y: content.y, w: content.w, colW: content.colW, rowH: content.rowH, fontSize: content.fontSize, color: content.color, fill: content.fill, border: content.border, }); break; case 'chart': const chartData = content.data.map(series => ({ name: series.name, labels: series.labels, values: series.values, })); slide.addChart(content.chartType, chartData, { x: content.x, y: content.y, w: content.w, h: content.h, title: content.title, }); break; } } // ============================================================================ // v3.0 Phase 1 Methods // ============================================================================ async defineMasterSlide(filename, masterSlide) { const pptx = new PptxGenJS(); // Define slide master pptx.defineSlideMaster({ title: masterSlide.name, background: masterSlide.background?.color ? { color: masterSlide.background.color } : masterSlide.background?.image ? { path: masterSlide.background.image } : { color: 'FFFFFF' }, }); // Create demo slide showing master configuration const slide = pptx.addSlide(); slide.addText(`Master Slide: ${masterSlide.name}`, { x: 1, y: 1, fontSize: 32, bold: true, }); const configInfo = [ `Background: ${masterSlide.background?.color || masterSlide.background?.image || 'Default'}`, `Placeholders: ${masterSlide.placeholders?.length || 0}`, `Title Font: ${masterSlide.fonts?.title || 'Default'}`, `Body Font: ${masterSlide.fonts?.body || 'Default'}`, `Accent Colors: ${Object.keys(masterSlide.colors || {}).length}`, ]; slide.addText(configInfo.join('\n'), { x: 1, y: 2.5, fontSize: 16, color: '666666', }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addHyperlinks(filename, slideNumber, links) { const pptx = new PptxGenJS(); const slide = pptx.addSlide(); slide.addText(`Slide ${slideNumber} - Hyperlinks`, { x: 0.5, y: 0.5, fontSize: 32, bold: true, }); // Add hyperlinks let yPos = 1.5; for (const link of links) { if (link.url) { slide.addText(link.text, { x: 1, y: yPos, fontSize: 18, color: '0066CC', underline: { style: 'sng' }, hyperlink: { url: link.url, tooltip: link.tooltip }, }); } else if (link.slide) { slide.addText(link.text, { x: 1, y: yPos, fontSize: 18, color: '0066CC', underline: { style: 'sng' }, hyperlink: { slide: link.slide, tooltip: link.tooltip }, }); } yPos += 0.5; } const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addSections(filename, sections) { const pptx = new PptxGenJS(); // Note: PptxGenJS has limited section support // Create slides representing sections for (const section of sections) { const slide = pptx.addSlide(); slide.addText(section.name, { x: 1, y: 2.5, w: '80%', fontSize: 44, bold: true, align: 'center', color: '0088CC', }); slide.addText(`Section starts at slide ${section.startSlide}`, { x: 1, y: 4, w: '80%', fontSize: 18, align: 'center', color: '666666', italic: true, }); } const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addMorphTransition(filename, fromSlide, toSlide, duration) { const pptx = new PptxGenJS(); // Slide 1 const slide1 = pptx.addSlide(); slide1.addText('Morph Transition - Slide 1', { x: 1, y: 1, fontSize: 32, bold: true, }); slide1.addShape(pptx.ShapeType.rect, { x: 2, y: 3, w: 2, h: 1.5, fill: { color: '0088CC' }, }); // Slide 2 const slide2 = pptx.addSlide(); slide2.addText('Morph Transition - Slide 2', { x: 1, y: 1, fontSize: 32, bold: true, }); slide2.addShape(pptx.ShapeType.rect, { x: 5, y: 3, w: 2, h: 1.5, fill: { color: 'CC0088' }, }); slide2.addText(`Note: Morph transition from slide ${fromSlide} to ${toSlide}\nDuration: ${duration || 1000}ms\n\nRequires PowerPoint 2016+ to apply actual morph effect.`, { x: 1, y: 5, fontSize: 14, color: '666666', italic: true, }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } async addActionButtons(filename, slideNumber, buttons) { const pptx = new PptxGenJS(); const slide = pptx.addSlide(); slide.addText(`Slide ${slideNumber} - Action Buttons`, { x: 0.5, y: 0.5, fontSize: 32, bold: true, }); // Add action buttons for (const button of buttons) { const buttonWidth = button.w || 2; const buttonHeight = button.h || 0.75; // Draw button shape slide.addShape(pptx.ShapeType.rect, { x: button.x, y: button.y, w: buttonWidth, h: buttonHeight, fill: { color: '0088CC' }, line: { color: '003366', width: 2 }, }); // Add button text slide.addText(button.text, { x: button.x, y: button.y, w: buttonWidth, h: buttonHeight, fontSize: 16, color: 'FFFFFF', bold: true, align: 'center', valign: 'middle', }); // Add action metadata as small text below const actionText = button.action === 'customSlide' ? `Go to slide ${button.targetSlide}` : button.action.replace(/([A-Z])/g, ' $1').trim(); slide.addText(actionText, { x: button.x, y: button.y + buttonHeight + 0.1, w: buttonWidth, fontSize: 10, color: '666666', align: 'center', italic: true, }); } slide.addText('Note: Interactive action buttons require PowerPoint to configure hyperlinks.', { x: 0.5, y: 6.5, fontSize: 12, color: '999999', italic: true, }); const buffer = await pptx.write({ outputType: 'arraybuffer' }); return Buffer.from(buffer); } } //# sourceMappingURL=powerpoint-generator.js.map

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/consigcody94/office-whisperer'

If you have feedback or need assistance with the MCP directory API, please join our Discord server