UNPKG

omniscript-converters

Version:

Format converters for OmniScript Format (OSF) - Convert to/from DOCX, PPTX, XLSX, PDF

362 lines 13.5 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.PPTXConverter = void 0; const pptxgenjs_1 = __importDefault(require("pptxgenjs")); class PPTXConverter { getSupportedFormats() { return ['pptx']; } async convert(document, options = {}) { const pptx = new pptxgenjs_1.default(); // Set presentation metadata this.setPresentationMetadata(pptx, document, options); // Configure theme and layout this.configureTheme(pptx, options.theme || 'default'); // Process document blocks await this.generateSlides(pptx, document, options); const blob = await pptx.write(); const arrayBuffer = await blob.arrayBuffer(); const buffer = Buffer.from(arrayBuffer); return { buffer, mimeType: 'application/vnd.openxmlformats-officedocument.presentationml.presentation', extension: 'pptx' }; } setPresentationMetadata(pptx, document, options) { const meta = this.getMetadata(document); pptx.author = String(meta.author) || 'OmniScript OSF'; pptx.company = 'Generated by OmniScript'; pptx.title = String(meta.title) || 'OSF Presentation'; pptx.subject = 'Generated from OSF document'; } configureTheme(pptx, theme) { const themeConfig = this.getThemeConfiguration(theme); pptx.defineLayout({ name: 'OSF_LAYOUT', width: 10, height: 7.5 }); // Note: Master slides removed for compatibility with pptxgenjs v4 } async generateSlides(pptx, document, options) { let hasCreatedTitleSlide = false; for (const block of document.blocks) { switch (block.type) { case 'meta': if (!hasCreatedTitleSlide && options.includeMetadata !== false) { this.createTitleSlide(pptx, block, options); hasCreatedTitleSlide = true; } break; case 'doc': this.createDocSlides(pptx, block, options); break; case 'slide': this.createSlideFromBlock(pptx, block, options); break; case 'sheet': this.createSheetSlide(pptx, block, options); break; } } } createTitleSlide(pptx, meta, options) { const slide = pptx.addSlide(); const theme = this.getThemeConfiguration(options.theme || 'default'); if (meta.props.title) { slide.addText(String(meta.props.title), { x: 1, y: 2, w: 8, h: 1.5, align: 'center', fontSize: 44, bold: true, color: theme.primary, fontFace: theme.titleFont }); } const subtitle = []; if (meta.props.author) subtitle.push(`By: ${String(meta.props.author)}`); if (meta.props.date) subtitle.push(String(meta.props.date)); if (subtitle.length > 0) { slide.addText(subtitle.join(' | '), { x: 1, y: 4, w: 8, h: 0.8, align: 'center', fontSize: 20, color: theme.secondary, fontFace: theme.bodyFont }); } } createDocSlides(pptx, doc, options) { const content = doc.content || ''; const theme = this.getThemeConfiguration(options.theme || 'default'); // Split content into logical slides based on headings const sections = this.splitContentIntoSections(content); for (const section of sections) { const slide = pptx.addSlide(); if (section.title) { slide.addText(section.title, { x: 0.5, y: 0.5, w: 9, h: 1, fontSize: 32, bold: true, color: theme.primary, fontFace: theme.titleFont }); } if (section.content.length > 0) { const contentText = this.formatContentForSlide(section.content); slide.addText(contentText, { x: 0.5, y: section.title ? 1.8 : 0.5, w: 9, h: section.title ? 4.7 : 6.2, fontSize: 18, color: theme.text, fontFace: theme.bodyFont, valign: 'top' }); } } } createSlideFromBlock(pptx, slideBlock, options) { const slide = pptx.addSlide(); const theme = this.getThemeConfiguration(options.theme || 'default'); // Add slide title if (slideBlock.title) { slide.addText(slideBlock.title, { x: 0.5, y: 0.5, w: 9, h: 1, fontSize: 32, bold: true, color: theme.primary, fontFace: theme.titleFont }); } // Add slide content if (slideBlock.content) { let yPosition = slideBlock.title ? 1.8 : 0.5; for (const contentBlock of slideBlock.content) { if (contentBlock.type === 'unordered_list') { const bullets = contentBlock.items.map(item => { const itemText = item.content.map(this.extractText).join(''); return { text: itemText, options: { bullet: true } }; }); slide.addText(bullets, { x: 0.5, y: yPosition, w: 9, h: 4.5, fontSize: 20, color: theme.text, fontFace: theme.bodyFont, valign: 'top' }); yPosition += 4.5; } else if (contentBlock.type === 'paragraph') { const paragraphText = contentBlock.content.map(this.extractText).join(''); slide.addText(paragraphText, { x: 0.5, y: yPosition, w: 9, h: 1.5, fontSize: 18, color: theme.text, fontFace: theme.bodyFont, valign: 'top' }); yPosition += 1.8; } } } } createSheetSlide(pptx, sheet, options) { const slide = pptx.addSlide(); const theme = this.getThemeConfiguration(options.theme || 'default'); // Add sheet title if (sheet.name) { slide.addText(sheet.name, { x: 0.5, y: 0.5, w: 9, h: 1, fontSize: 28, bold: true, color: theme.primary, fontFace: theme.titleFont }); } if (sheet.data) { // Prepare table data const tableData = this.prepareTableData(sheet); if (tableData.length > 0) { slide.addTable(tableData, { x: 0.5, y: sheet.name ? 1.8 : 0.5, w: 9, h: sheet.name ? 4.7 : 6.2, fontSize: 14, color: theme.text, fontFace: theme.bodyFont, border: { pt: 1, color: theme.border }, fill: { color: theme.tableBackground } }); } } } prepareTableData(sheet) { const tableData = []; // Add header row if columns are defined if (sheet.cols) { const cols = Array.isArray(sheet.cols) ? sheet.cols : String(sheet.cols).replace(/[[\]]/g, '').split(',').map(s => s.trim()); const headerRow = cols.map(col => ({ text: col, options: { bold: true, fill: { color: 'E8E8E8' } } })); tableData.push(headerRow); } if (sheet.data) { // Calculate table dimensions const coords = Object.keys(sheet.data).map(k => k.split(',').map(Number)); const maxRow = Math.max(...coords.map(c => c[0])); const maxCol = Math.max(...coords.map(c => c[1])); // Add data rows for (let r = 1; r <= maxRow; r++) { const row = []; for (let c = 1; c <= maxCol; c++) { const key = `${r},${c}`; const value = sheet.data[key] || ''; row.push({ text: String(value) }); } tableData.push(row); } } return tableData; } splitContentIntoSections(content) { const lines = content.split('\n'); const sections = []; let currentSection = { content: [] }; for (const line of lines) { const trimmed = line.trim(); if (trimmed.startsWith('# ')) { // New section with heading if (currentSection.title || currentSection.content.length > 0) { sections.push(currentSection); } currentSection = { title: trimmed.substring(2), content: [] }; } else if (trimmed.startsWith('## ')) { // Subsection - also creates new slide if (currentSection.title || currentSection.content.length > 0) { sections.push(currentSection); } currentSection = { title: trimmed.substring(3), content: [] }; } else if (trimmed !== '') { currentSection.content.push(trimmed); } } // Add the last section if (currentSection.title || currentSection.content.length > 0) { sections.push(currentSection); } return sections.length > 0 ? sections : [{ content: [content] }]; } formatContentForSlide(contentLines) { const formattedContent = []; for (const line of contentLines) { if (line.startsWith('- ') || line.startsWith('* ')) { // Bullet point formattedContent.push({ text: line.substring(2), options: { bullet: true } }); } else { // Regular paragraph formattedContent.push({ text: line, options: { paragraph: true } }); } } return formattedContent; } extractText(run) { if (typeof run === 'string') return run; if (run.type === 'link') return run.text; if (run.type === 'image') return run.alt || ''; if (run.text) return run.text; return ''; } getMetadata(document) { for (const block of document.blocks) { if (block.type === 'meta') { const meta = block; return { title: meta.props.title ? String(meta.props.title) : undefined, author: meta.props.author ? String(meta.props.author) : undefined, date: meta.props.date ? String(meta.props.date) : undefined }; } } return {}; } getThemeConfiguration(theme) { const themes = { default: { primary: '2C3E50', secondary: '7F8C8D', accent: '3498DB', text: '2C3E50', background: 'FFFFFF', border: 'DDDDDD', tableBackground: 'F8F9FA', titleFont: 'Calibri', bodyFont: 'Calibri' }, corporate: { primary: '1A365D', secondary: '4A5568', accent: '2B6CB0', text: '2D3748', background: 'FFFFFF', border: '2B6CB0', tableBackground: 'EBF4FF', titleFont: 'Arial', bodyFont: 'Arial' }, academic: { primary: '2D3748', secondary: '4A5568', accent: '4A5568', text: '1A202C', background: 'FFFFFF', border: '4A5568', tableBackground: 'F7FAFC', titleFont: 'Times New Roman', bodyFont: 'Times New Roman' }, modern: { primary: '6366F1', secondary: '8B5CF6', accent: '06B6D4', text: '1F2937', background: 'FFFFFF', border: 'E5E7EB', tableBackground: 'F9FAFB', titleFont: 'Segoe UI', bodyFont: 'Segoe UI' } }; return themes[theme] || themes.default; } } exports.PPTXConverter = PPTXConverter; //# sourceMappingURL=pptx.js.map