UNPKG

omniscript-converters

Version:

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

448 lines 18 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 () { var ownKeys = function(o) { ownKeys = Object.getOwnPropertyNames || function (o) { var ar = []; for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k; return ar; }; return ownKeys(o); }; return function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]); __setModuleDefault(result, mod); return result; }; })(); Object.defineProperty(exports, "__esModule", { value: true }); exports.XLSXConverter = void 0; const ExcelJS = __importStar(require("exceljs")); class XLSXConverter { getSupportedFormats() { return ['xlsx']; } async convert(document, options = {}) { const workbook = new ExcelJS.Workbook(); // Set workbook metadata this.setWorkbookMetadata(workbook, document); // Process document blocks await this.generateWorksheets(workbook, document, options); // Ensure at least one worksheet exists if (workbook.worksheets.length === 0) { this.createSummaryWorksheet(workbook, document, options); } const buffer = await workbook.xlsx.writeBuffer(); return { buffer: Buffer.from(buffer), mimeType: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', extension: 'xlsx' }; } setWorkbookMetadata(workbook, document) { const meta = this.getMetadata(document); workbook.creator = meta.author || 'OmniScript OSF'; workbook.created = meta.date ? new Date(meta.date) : new Date(); workbook.modified = new Date(); workbook.company = 'Generated by OmniScript'; workbook.title = meta.title || 'OSF Workbook'; workbook.description = 'Generated from OSF document'; } async generateWorksheets(workbook, document, options) { let worksheetIndex = 1; let hasSheets = false; for (const block of document.blocks) { switch (block.type) { case 'sheet': this.createSheetWorksheet(workbook, block, options); hasSheets = true; break; case 'doc': case 'slide': this.createContentWorksheet(workbook, block, options, `Content_${worksheetIndex}`); worksheetIndex++; break; case 'meta': // Metadata will be included in summary if no sheets exist break; } } // If no dedicated sheets exist, create a summary worksheet if (!hasSheets) { this.createSummaryWorksheet(workbook, document, options); } } createSheetWorksheet(workbook, sheet, options) { const worksheetName = this.sanitizeWorksheetName(sheet.name || 'Sheet'); const worksheet = workbook.addWorksheet(worksheetName); // Configure worksheet styling this.applyWorksheetStyling(worksheet, options); let currentRow = 1; // Add sheet title if (sheet.name) { const titleCell = worksheet.getCell(currentRow, 1); titleCell.value = sheet.name; titleCell.font = { bold: true, size: 16, color: { argb: 'FF2C3E50' } }; titleCell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF8F9FA' } }; // Merge cells for title if we have multiple columns const colCount = this.getColumnCount(sheet); if (colCount > 1) { worksheet.mergeCells(currentRow, 1, currentRow, colCount); } currentRow += 2; } // Add column headers if (sheet.cols) { const cols = Array.isArray(sheet.cols) ? sheet.cols : String(sheet.cols).replace(/[[\]]/g, '').split(',').map(s => s.trim()); cols.forEach((col, index) => { const cell = worksheet.getCell(currentRow, index + 1); cell.value = col; cell.font = { bold: true, color: { argb: 'FFFFFFFF' } }; cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FF3498DB' } }; cell.border = { top: { style: 'thin' }, left: { style: 'thin' }, bottom: { style: 'thin' }, right: { style: 'thin' } }; }); currentRow++; } // Add data rows if (sheet.data) { this.populateSheetData(worksheet, sheet, currentRow, options); } // Apply formulas if any if (sheet.formulas && sheet.formulas.length > 0) { this.applyFormulas(worksheet, sheet.formulas); } // Auto-size columns this.autoSizeColumns(worksheet); } createContentWorksheet(workbook, block, options, name) { const worksheet = workbook.addWorksheet(name); this.applyWorksheetStyling(worksheet, options); let currentRow = 1; if (block.type === 'doc') { const docBlock = block; currentRow = this.addDocContentToWorksheet(worksheet, docBlock, currentRow); } else if (block.type === 'slide') { const slideBlock = block; currentRow = this.addSlideContentToWorksheet(worksheet, slideBlock, currentRow); } this.autoSizeColumns(worksheet); } createSummaryWorksheet(workbook, document, options) { const worksheet = workbook.addWorksheet('Summary'); this.applyWorksheetStyling(worksheet, options); let currentRow = 1; // Add document metadata const meta = this.getMetadata(document); if (meta.title || meta.author || meta.date) { const titleCell = worksheet.getCell(currentRow, 1); titleCell.value = 'Document Information'; titleCell.font = { bold: true, size: 16, color: { argb: 'FF2C3E50' } }; currentRow += 2; if (meta.title) { worksheet.getCell(currentRow, 1).value = 'Title:'; worksheet.getCell(currentRow, 1).font = { bold: true }; worksheet.getCell(currentRow, 2).value = meta.title; currentRow++; } if (meta.author) { worksheet.getCell(currentRow, 1).value = 'Author:'; worksheet.getCell(currentRow, 1).font = { bold: true }; worksheet.getCell(currentRow, 2).value = meta.author; currentRow++; } if (meta.date) { worksheet.getCell(currentRow, 1).value = 'Date:'; worksheet.getCell(currentRow, 1).font = { bold: true }; worksheet.getCell(currentRow, 2).value = meta.date; currentRow++; } currentRow += 2; } // Add content summary const contentBlocks = document.blocks.filter(b => b.type === 'doc' || b.type === 'slide'); if (contentBlocks.length > 0) { const summaryTitleCell = worksheet.getCell(currentRow, 1); summaryTitleCell.value = 'Content Summary'; summaryTitleCell.font = { bold: true, size: 14, color: { argb: 'FF2C3E50' } }; currentRow += 2; // Add headers worksheet.getCell(currentRow, 1).value = 'Type'; worksheet.getCell(currentRow, 2).value = 'Title/Content Preview'; worksheet.getRow(currentRow).font = { bold: true }; currentRow++; for (const block of contentBlocks) { worksheet.getCell(currentRow, 1).value = block.type.toUpperCase(); if (block.type === 'slide') { const slide = block; worksheet.getCell(currentRow, 2).value = slide.title || 'Untitled Slide'; } else if (block.type === 'doc') { const doc = block; const preview = this.getContentPreview(doc.content || ''); worksheet.getCell(currentRow, 2).value = preview; } currentRow++; } } this.autoSizeColumns(worksheet); } populateSheetData(worksheet, sheet, startRow, options) { if (!sheet.data) return; 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])); // Populate data cells for (let r = 1; r <= maxRow; r++) { for (let c = 1; c <= maxCol; c++) { const key = `${r},${c}`; const value = sheet.data[key]; if (value !== undefined) { const cell = worksheet.getCell(startRow + r - 1, c); // Handle different data types if (typeof value === 'number') { cell.value = value; cell.numFmt = '#,##0.00'; } else if (typeof value === 'boolean') { cell.value = value; } else { cell.value = String(value); } // Apply basic styling cell.border = { top: { style: 'thin' }, left: { style: 'thin' }, bottom: { style: 'thin' }, right: { style: 'thin' } }; } } } } applyFormulas(worksheet, formulas) { for (const formula of formulas) { const [row, col] = formula.cell; const cell = worksheet.getCell(row, col); // Convert OSF formula to Excel formula let excelFormula = formula.expr; if (!excelFormula.startsWith('=')) { excelFormula = '=' + excelFormula; } // Convert cell references if needed (basic conversion) excelFormula = this.convertToExcelFormula(excelFormula); cell.value = { formula: excelFormula }; // Style formula cells cell.fill = { type: 'pattern', pattern: 'solid', fgColor: { argb: 'FFF0F8FF' } }; cell.font = { italic: true }; } } addDocContentToWorksheet(worksheet, doc, startRow) { let currentRow = startRow; const content = doc.content || ''; // Add title const titleCell = worksheet.getCell(currentRow, 1); titleCell.value = 'Document Content'; titleCell.font = { bold: true, size: 14, color: { argb: 'FF2C3E50' } }; currentRow += 2; // Split content into paragraphs and add to cells const paragraphs = content.split('\n\n'); for (const paragraph of paragraphs) { if (paragraph.trim()) { const cell = worksheet.getCell(currentRow, 1); cell.value = paragraph.trim(); cell.alignment = { wrapText: true, vertical: 'top' }; worksheet.getRow(currentRow).height = Math.max(15, Math.min(100, paragraph.length / 10)); currentRow++; } } return currentRow + 1; } addSlideContentToWorksheet(worksheet, slide, startRow) { let currentRow = startRow; // Add slide title if (slide.title) { const titleCell = worksheet.getCell(currentRow, 1); titleCell.value = slide.title; titleCell.font = { bold: true, size: 14, color: { argb: 'FF2C3E50' } }; currentRow += 2; } // Add slide content if (slide.content) { for (const contentBlock of slide.content) { if (contentBlock.type === 'unordered_list') { for (const item of contentBlock.items) { const itemText = item.content.map(this.extractText).join(''); const cell = worksheet.getCell(currentRow, 1); cell.value = `• ${itemText}`; currentRow++; } } else if (contentBlock.type === 'paragraph') { const paragraphText = contentBlock.content.map(this.extractText).join(''); const cell = worksheet.getCell(currentRow, 1); cell.value = paragraphText; cell.alignment = { wrapText: true }; currentRow++; } } } return currentRow + 1; } applyWorksheetStyling(worksheet, options) { // Set default column width worksheet.columns = [ { width: 20 }, { width: 30 }, { width: 15 }, { width: 15 } ]; // Apply theme-based styling if specified const theme = options.theme || 'default'; const themeColors = this.getThemeColors(theme); // Set worksheet tab color based on theme worksheet.properties.tabColor = { argb: themeColors.accent }; } autoSizeColumns(worksheet) { worksheet.columns.forEach((column, index) => { let maxLength = 10; // Minimum width worksheet.eachRow({ includeEmpty: false }, (row) => { const cell = row.getCell(index + 1); if (cell.value) { const length = String(cell.value).length; maxLength = Math.max(maxLength, Math.min(50, length + 2)); } }); column.width = maxLength; }); } getColumnCount(sheet) { if (sheet.cols) { const cols = Array.isArray(sheet.cols) ? sheet.cols : String(sheet.cols).replace(/[[\]]/g, '').split(',').map(s => s.trim()); return cols.length; } if (sheet.data) { const coords = Object.keys(sheet.data).map(k => k.split(',').map(Number)); return Math.max(...coords.map(c => c[1])); } return 1; } convertToExcelFormula(formula) { // Basic conversion from OSF formula format to Excel format // This is a simplified conversion - you might want to enhance this return formula .replace(/\(\s*(\d+),\s*(\d+)\s*\)/g, (match, row, col) => { // Convert (row,col) to Excel cell reference const colLetter = this.numberToColumnLetter(parseInt(col)); return `${colLetter}${row}`; }); } numberToColumnLetter(num) { let result = ''; while (num > 0) { num--; result = String.fromCharCode(65 + (num % 26)) + result; num = Math.floor(num / 26); } return result; } sanitizeWorksheetName(name) { // Excel worksheet names have restrictions return name .replace(/[\\\/\*\?\[\]:]/g, '_') .substring(0, 31); // Max 31 characters } getContentPreview(content) { const preview = content .replace(/[#*`]/g, '') .replace(/\n+/g, ' ') .trim(); return preview.length > 50 ? preview.substring(0, 47) + '...' : preview; } 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 {}; } getThemeColors(theme) { const themes = { default: { primary: 'FF2C3E50', accent: 'FF3498DB', background: 'FFFFFFFF' }, corporate: { primary: 'FF1A365D', accent: 'FF2B6CB0', background: 'FFFFFFFF' }, academic: { primary: 'FF2D3748', accent: 'FF4A5568', background: 'FFFFFFFF' } }; return themes[theme] || themes.default; } } exports.XLSXConverter = XLSXConverter; //# sourceMappingURL=xlsx.js.map