import type { SlideLayout, SlotConfig } from '../types/theme';
/**
* Creates a simple SVG pattern for image slots
*/
const createImageSVG = (slotName: string, width: number = 400, height: number = 300): string => {
const encodedSVG = encodeURIComponent(`
`);
return `data:image/svg+xml,${encodedSVG}`;
};
/**
* Sample content templates for more realistic previews
*/
const SAMPLE_CONTENT = {
title: [
'Quarterly Sales Review',
'Project Roadmap 2024',
'Market Analysis Report',
'New Product Launch',
'Team Performance Update'
],
subtitle: [
'Q4 Results and Future Outlook',
'Strategic Planning and Key Milestones',
'Customer Insights and Trends',
'Innovation and Growth Strategy',
'Achievements and Next Steps'
],
heading: [
'Key Findings',
'Next Steps',
'Executive Summary',
'Strategic Goals',
'Market Opportunities'
],
text: [
'This comprehensive analysis provides insights into market trends and customer behavior patterns that will shape our strategic decisions moving forward.',
'Our team has achieved significant milestones this quarter, demonstrating strong execution and commitment to delivering exceptional results.',
'The data shows promising growth opportunities in emerging markets, with particular strength in the technology and healthcare sectors.',
'Customer feedback indicates high satisfaction levels with our current offerings, while highlighting areas for continued innovation.',
'Looking ahead, we will focus on expanding our market presence while maintaining our commitment to quality and customer excellence.'
],
list: [
'• Increase market share by 15%\n• Launch 3 new products\n• Expand to 5 new regions',
'• Improve customer satisfaction\n• Reduce operational costs\n• Enhance digital capabilities',
'• Strengthen brand recognition\n• Optimize supply chain\n• Invest in talent development'
]
};
/**
* Generates sample data for a slot based on its configuration
*/
export const generateSampleDataForSlot = (slot: SlotConfig): string => {
const { id, type, defaultContent } = slot;
// Use default content if available
if (defaultContent && defaultContent.trim()) {
return defaultContent;
}
// Clean up slot name for display
const slotDisplayName = id.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
// Generate sample data based on slot type
switch (type) {
case 'image':
return createImageSVG(slotDisplayName);
case 'title': {
const titleSamples = SAMPLE_CONTENT.title;
return titleSamples[Math.floor(Math.random() * titleSamples.length)];
}
case 'subtitle': {
const subtitleSamples = SAMPLE_CONTENT.subtitle;
return subtitleSamples[Math.floor(Math.random() * subtitleSamples.length)];
}
case 'heading': {
const headingSamples = SAMPLE_CONTENT.heading;
return headingSamples[Math.floor(Math.random() * headingSamples.length)];
}
case 'text': {
const textSamples = SAMPLE_CONTENT.text;
return textSamples[Math.floor(Math.random() * textSamples.length)];
}
case 'video':
return createImageSVG(`${slotDisplayName} (Video)`, 640, 360);
case 'audio':
return `[${slotDisplayName} Audio]`;
case 'list': {
const listSamples = SAMPLE_CONTENT.list;
return listSamples[Math.floor(Math.random() * listSamples.length)];
}
case 'code':
return `// ${slotDisplayName}\nfunction ${id.replace(/-/g, '')}() {\n return "${slotDisplayName}";\n}`;
case 'table':
return `${slotDisplayName} Col 1 | ${slotDisplayName} Col 2\n--- | ---\nRow 1 Data | Row 1 Data\nRow 2 Data | Row 2 Data`;
default:
return slotDisplayName;
}
};
/**
* Generates a complete sample data object for all slots in a layout
*/
export const generateSampleDataForLayout = (layout: SlideLayout): Record => {
const sampleData: Record = {};
layout.slots.forEach(slot => {
sampleData[slot.id] = generateSampleDataForSlot(slot);
// Add related data for image slots
if (slot.type === 'image') {
sampleData[`${slot.id}Alt`] = `Sample ${slot.id} description`;
}
});
// Add common template variables that might be used
sampleData.footerText = 'Sample Footer Text';
sampleData.author = 'Sample Author';
sampleData.date = new Date().toLocaleDateString();
// Add layout metadata for templates that might use it
sampleData['layout-description'] = layout.description || `This is the ${layout.name} layout`;
sampleData['layout-name'] = layout.name;
return sampleData;
};
/**
* Renders an HTML template with sample data using simple string replacement
*/
export const renderTemplateWithSampleData = (
htmlTemplate: string,
layout: SlideLayout
): string => {
const sampleData = generateSampleDataForLayout(layout);
let rendered = htmlTemplate;
// Handle Handlebars-style templates: {{variable}}
Object.entries(sampleData).forEach(([key, value]) => {
const simpleRegex = new RegExp(`\\{\\{${key}\\}\\}`, 'g');
rendered = rendered.replace(simpleRegex, value);
});
// Handle conditional blocks: {{#variable}}...{{/variable}}
Object.entries(sampleData).forEach(([key, value]) => {
const conditionalRegex = new RegExp(`\\{\\{#${key}\\}\\}([\\s\\S]*?)\\{\\{/${key}\\}\\}`, 'g');
if (value && value.trim()) {
// Replace conditional block with content, substituting variables within
rendered = rendered.replace(conditionalRegex, (_match, content) => {
// Replace variables within the conditional block
let blockContent = content;
Object.entries(sampleData).forEach(([innerKey, innerValue]) => {
const innerRegex = new RegExp(`\\{\\{${innerKey}\\}\\}`, 'g');
blockContent = blockContent.replace(innerRegex, innerValue);
});
return blockContent;
});
} else {
// Remove conditional block if no data
rendered = rendered.replace(conditionalRegex, '');
}
});
// Clean up any remaining template variables
rendered = rendered.replace(/\{\{[^}]+\}\}/g, '');
return rendered;
};
/**
* Creates a preview-ready HTML document with theme CSS applied
*/
export const createPreviewDocument = (
renderedTemplate: string,
themeCssUrl: string
): string => {
return `
${renderedTemplate}
`;
};