skills/elite-powerpoint-designer/scripts/analyze_content.py

262 lines
8.9 KiB
Python
Executable File

#!/usr/bin/env python3
"""
Elite PowerPoint Designer - Content Analyzer
Analyzes markdown content and recommends brand style and template mapping.
"""
import sys
import json
import re
from typing import Dict, List, Tuple
class ContentAnalyzer:
def __init__(self):
self.keywords = {
'tech-keynote': ['product', 'launch', 'innovation', 'demo', 'revolutionary', 'future', 'transform'],
'corporate-professional': ['business', 'strategy', 'report', 'proposal', 'enterprise', 'quarter', 'results'],
'creative-bold': ['brand', 'marketing', 'campaign', 'creative', 'design', 'experience', 'engage'],
'financial-elite': ['investment', 'financial', 'investor', 'portfolio', 'capital', 'returns', 'valuation'],
'startup-pitch': ['startup', 'funding', 'traction', 'growth', 'market', 'team', 'vision', 'problem', 'solution']
}
self.slide_patterns = {
'title_slide': r'^#\s+(.+)$',
'chapter_intro': r'^##\s+(.+)$',
'key_message': r'^###\s+(.+)$',
'bullet_list': r'^\*\s+(.+)$|^-\s+(.+)$',
'quote': r'^>\s+(.+)$',
'image': r'!\[.*?\]\((.+?)\)',
'table': r'^\|.+\|.+\|$',
'metrics': r'(\d+\.?\d*[%$€£¥M-Z]*)',
'section_break': r'^===+$'
}
def analyze(self, content: str) -> Dict:
"""Analyze content and return recommendations."""
lines = content.split('\n')
# Extract frontmatter if present
frontmatter = self._extract_frontmatter(content)
# Analyze content for style recommendation
style = frontmatter.get('style') or self._recommend_style(content)
# Map slides
slides = self._map_slides(lines)
# Detect metrics and key data
metrics = self._extract_metrics(content)
# Count slide types
slide_stats = self._calculate_stats(slides)
return {
'recommended_style': style,
'frontmatter': frontmatter,
'total_slides': len(slides),
'slide_structure': slides,
'key_metrics': metrics,
'statistics': slide_stats,
'estimated_duration': len(slides) # 1 slide per minute rule
}
def _extract_frontmatter(self, content: str) -> Dict:
"""Extract YAML frontmatter from markdown."""
match = re.match(r'^---\s*\n(.*?)\n---\s*\n', content, re.DOTALL)
if not match:
return {}
frontmatter = {}
yaml_content = match.group(1)
# Simple YAML parser (only handles key: value pairs)
for line in yaml_content.split('\n'):
if ':' in line:
key, value = line.split(':', 1)
frontmatter[key.strip()] = value.strip().strip('"\'')
return frontmatter
def _recommend_style(self, content: str) -> str:
"""Recommend brand style based on content analysis."""
content_lower = content.lower()
scores = {}
for style, keywords in self.keywords.items():
score = sum(content_lower.count(keyword) for keyword in keywords)
scores[style] = score
# Return style with highest score
recommended = max(scores.items(), key=lambda x: x[1])
# Default to corporate-professional if no clear winner
if recommended[1] == 0:
return 'corporate-professional'
return recommended[0]
def _map_slides(self, lines: List[str]) -> List[Dict]:
"""Map markdown lines to slide templates."""
slides = []
current_slide = None
for i, line in enumerate(lines):
line = line.strip()
if not line:
continue
# Title slide (# Header)
if re.match(r'^#\s+[^#]', line):
if current_slide:
slides.append(current_slide)
current_slide = {
'type': 'title_slide',
'template': 'title_slide',
'content': {
'title': re.sub(r'^#\s+', '', line)
},
'line_number': i + 1
}
# Section/Chapter (## Header)
elif re.match(r'^##\s+[^#]', line):
if current_slide:
slides.append(current_slide)
current_slide = {
'type': 'section',
'template': 'chapter_intro',
'content': {
'title': re.sub(r'^##\s+', '', line)
},
'line_number': i + 1
}
# Key message (### Header)
elif re.match(r'^###\s+', line):
if current_slide:
slides.append(current_slide)
current_slide = {
'type': 'key_message',
'template': 'key_metrics_dashboard',
'content': {
'title': re.sub(r'^###\s+', '', line),
'bullets': []
},
'line_number': i + 1
}
# Bullets
elif re.match(r'^[\*\-]\s+', line):
if current_slide and 'bullets' in current_slide['content']:
bullet_text = re.sub(r'^[\*\-]\s+', '', line)
current_slide['content']['bullets'].append(bullet_text)
else:
if current_slide:
slides.append(current_slide)
current_slide = {
'type': 'bullets',
'template': 'two_column_text',
'content': {
'bullets': [re.sub(r'^[\*\-]\s+', '', line)]
},
'line_number': i + 1
}
# Quote
elif re.match(r'^>\s+', line):
if current_slide:
slides.append(current_slide)
current_slide = {
'type': 'quote',
'template': 'quote_testimonial',
'content': {
'quote': re.sub(r'^>\s+', '', line)
},
'line_number': i + 1
}
# Image
elif re.search(r'!\[.*?\]\((.+?)\)', line):
images = re.findall(r'!\[.*?\]\((.+?)\)', line)
if current_slide:
slides.append(current_slide)
current_slide = {
'type': 'image',
'template': 'full_image_slide' if len(images) == 1 else 'two_column_text',
'content': {
'images': images
},
'line_number': i + 1
}
# Section break
elif re.match(r'^===+$', line):
# Mark next slide as section intro
if current_slide:
slides.append(current_slide)
current_slide = None
if current_slide:
slides.append(current_slide)
return slides
def _extract_metrics(self, content: str) -> List[Dict]:
"""Extract key metrics and numbers from content."""
metrics = []
# Find numbers with units/symbols
pattern = r'(\d+\.?\d*)\s*([%$€£¥MKB]?)'
matches = re.finditer(pattern, content)
for match in matches:
value = match.group(1)
unit = match.group(2)
# Only include significant numbers (> 10 or with units)
if float(value) > 10 or unit:
metrics.append({
'value': value,
'unit': unit,
'context': content[max(0, match.start()-50):min(len(content), match.end()+50)]
})
return metrics[:10] # Top 10 metrics
def _calculate_stats(self, slides: List[Dict]) -> Dict:
"""Calculate statistics about slide composition."""
types = {}
for slide in slides:
slide_type = slide['type']
types[slide_type] = types.get(slide_type, 0) + 1
return {
'slide_types': types,
'has_images': any(s['type'] == 'image' for s in slides),
'has_metrics': any('metrics' in str(s) for s in slides),
'has_quotes': any(s['type'] == 'quote' for s in slides)
}
def main():
if len(sys.argv) < 2:
print("Usage: python analyze_content.py input.md")
sys.exit(1)
input_file = sys.argv[1]
try:
with open(input_file, 'r', encoding='utf-8') as f:
content = f.read()
except FileNotFoundError:
print(f"Error: File '{input_file}' not found")
sys.exit(1)
analyzer = ContentAnalyzer()
result = analyzer.analyze(content)
print(json.dumps(result, indent=2))
if __name__ == '__main__':
main()