Files
wehub-resource-sync 8ef9db2513
Deploy to GitHub Pages / deploy (push) Has been cancelled
Deploy to GitHub Pages / build (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:56:49 +08:00

250 lines
8.3 KiB
Python

#!/usr/bin/env python3
"""
PPT Master - Examples Index Generator
Automatically scans the examples directory and generates a README.md index file.
Usage:
python3 scripts/generate_examples_index.py
python3 scripts/generate_examples_index.py examples
"""
import sys
from pathlib import Path
from datetime import datetime
from collections import defaultdict
from console_encoding import configure_utf8_stdio
configure_utf8_stdio()
try:
from project_utils import find_all_projects, get_project_info, CANVAS_FORMATS
except ImportError:
print("Error: Cannot import the project_utils module")
print("Please ensure project_utils.py is in the same directory")
sys.exit(1)
def generate_examples_index(examples_dir: str = 'examples') -> str:
"""
Generate a README.md index for the examples directory
Args:
examples_dir: Path to the examples directory
Returns:
Generated README.md content
"""
examples_path = Path(examples_dir)
if not examples_path.exists():
print(f"[ERROR] Directory not found: {examples_dir}")
return ""
print(f"[SCAN] Scanning directory: {examples_dir}")
# Find all projects
projects = find_all_projects(examples_dir)
if not projects:
print("[WARN] No projects found")
return ""
print(f"Found {len(projects)} project(s)")
# Collect project information
projects_info = []
for project_path in projects:
info = get_project_info(str(project_path))
projects_info.append(info)
# Sort by date (newest first)
projects_info.sort(key=lambda x: x['date'], reverse=True)
# Group by format
by_format = defaultdict(list)
for info in projects_info:
by_format[info['format']].append(info)
# Generate README content
content = []
content.append("# PPT Master Example Projects Index\n")
content.append("> This file is auto-generated by `skills/ppt-master/scripts/generate_examples_index.py`\n")
content.append(f"> Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
# Overview statistics
content.append("## [Stats] Overview\n")
content.append(f"- **Total projects**: {len(projects_info)}")
content.append(f"- **Canvas formats**: {len(by_format)} type(s)")
total_svgs = sum(info['svg_count'] for info in projects_info)
content.append(f"- **SVG files**: {total_svgs}")
# Statistics by format
content.append("\n### Format Distribution\n")
for fmt_key in sorted(by_format.keys(), key=lambda x: len(by_format[x]), reverse=True):
count = len(by_format[fmt_key])
fmt_name = CANVAS_FORMATS.get(fmt_key, {}).get('name', fmt_key)
content.append(f"- **{fmt_name}**: {count} project(s)")
# Recently updated
content.append("\n## [New] Recently Updated\n")
for info in projects_info[:5]:
content.append(
f"- **{info['name']}** ({info['format_name']}) - {info['date_formatted']}")
# Project list by format
content.append("\n## [List] Project List\n")
# Define format display order
format_order = ['ppt169', 'ppt43', 'wechat',
'xiaohongshu', 'moments', 'story', 'banner', 'a4']
for fmt_key in format_order:
if fmt_key not in by_format:
continue
fmt_info = CANVAS_FORMATS.get(fmt_key, {})
fmt_name = fmt_info.get('name', fmt_key)
dimensions = fmt_info.get('dimensions', '')
content.append(f"\n### {fmt_name} ({dimensions})\n")
projects_list = by_format[fmt_key]
# Sort by date
projects_list.sort(key=lambda x: x['date'], reverse=True)
for info in projects_list:
# Project name and link
project_link = f"./{info['dir_name']}"
# Build project entry
line = f"- **[{info['name']}]({project_link})**"
# Add date
line += f" - {info['date_formatted']}"
# Add SVG count
line += f" - {info['svg_count']} page(s)"
content.append(line)
# Other uncategorized formats
other_formats = set(by_format.keys()) - set(format_order)
if other_formats:
content.append("\n### Other Formats\n")
for fmt_key in sorted(other_formats):
projects_list = by_format[fmt_key]
for info in projects_list:
project_link = f"./{info['dir_name']}"
line = f"- **[{info['name']}]({project_link})**"
line += f" ({info['format_name']}) - {info['date_formatted']}"
line += f" - {info['svg_count']} page(s)"
content.append(line)
# Usage instructions
content.append("\n## [Docs] Usage Instructions\n")
content.append("### Preview Projects\n")
content.append("Each project contains the following files:\n")
content.append("- `README.md` - Project documentation")
content.append("- `Design Spec & Content Outline.md` - Full design specification")
content.append("- `svg_output/` - SVG output files\n")
content.append("**Method 1: Using an HTTP server (recommended)**\n")
content.append("```bash")
content.append(
"python3 -m http.server --directory examples/<project_name>/svg_output 8000")
content.append("# Visit http://localhost:8000")
content.append("```\n")
content.append("**Method 2: Open SVG directly**\n")
content.append("```bash")
content.append(
"open examples/<project_name>/svg_output/slide_01_cover.svg")
content.append("```\n")
# Create new project
content.append("### Create a New Project\n")
content.append("Refer to existing project structures, or use the project management tool:\n")
content.append("```bash")
content.append(
"python3 scripts/project_manager.py init my_project --format ppt169")
content.append("```\n")
# Contribution guidelines
content.append("## [Contribute] Contributing Example Projects\n")
content.append("We welcome you to share your projects in the examples directory!\n")
content.append("### Project Requirements\n")
content.append("1. Follow the standard project structure")
content.append("2. Include a complete README.md and design specification")
content.append("3. SVG files must comply with technical specifications")
content.append("4. Directory naming format: `{project_name}_{format}_{YYYYMMDD}`\n")
content.append("### Submission Process\n")
content.append("1. Create a project under the `examples/` directory")
content.append(
"2. Validate the project: `python3 scripts/project_manager.py validate examples/<project>`")
content.append("3. Update the index: `python3 scripts/generate_examples_index.py`")
content.append("4. Submit a Pull Request\n")
# Related resources
content.append("## [Resources] Related Resources\n")
content.append("- [Quick Start](../README.md)")
content.append("- [Workflow Tutorial](../../AGENTS.md)")
content.append("- [Canvas Formats](../references/canvas-formats.md)")
content.append("- [Role Definitions](../references/)")
content.append("- [Chart Templates](../templates/charts/README.md)\n")
# Footer
content.append("---\n")
content.append(
f"*Auto-generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} by PPT Master*")
return "\n".join(content)
def main() -> None:
"""Run the CLI entry point."""
examples_dir = 'examples'
if len(sys.argv) > 1:
if sys.argv[1] in {'-h', '--help', 'help'}:
print(__doc__)
sys.exit(0)
examples_dir = sys.argv[1]
print("=" * 80)
print("PPT Master - Examples Index Generator")
print("=" * 80 + "\n")
# Generate index content
content = generate_examples_index(examples_dir)
if not content:
print("\n[ERROR] Generation failed")
sys.exit(1)
# Write to file
output_file = Path(examples_dir) / 'README.md'
try:
with open(output_file, 'w', encoding='utf-8') as f:
f.write(content)
print(f"\n[OK] Index file generated: {output_file}")
print(f" Contains {len(content.splitlines())} lines")
# Display statistics
projects_count = content.count('- **[')
print(f" Indexed {projects_count} project(s)")
except Exception as e:
print(f"\n[ERROR] Failed to write file: {e}")
sys.exit(1)
if __name__ == '__main__':
main()