返回 ppt-master
generate_examples_index.py
根目录 / skills / ppt-master / scripts / generate_examples_index.py
1 #!/usr/bin/env python3
2 """
3 PPT Master - Examples Index Generator
4
5 Automatically scans the examples directory and generates a README.md index file.
6
7 Usage:
8 python3 scripts/generate_examples_index.py
9 python3 scripts/generate_examples_index.py examples
10 """
11
12 import argparse
13 import os
14 import sys
15 from collections import defaultdict
16 from datetime import datetime
17 from pathlib import Path
18
19 from console_encoding import configure_utf8_stdio
20
21 try:
22 from project_utils import find_all_projects, get_project_info, CANVAS_FORMATS
23 except ImportError:
24 print("Error: Cannot import the project_utils module")
25 print("Please ensure project_utils.py is in the same directory")
26 sys.exit(1)
27
28
29 def generate_examples_index(examples_dir: str = 'examples') -> str:
30 """
31 Generate a README.md index for the examples directory
32
33 Args:
34 examples_dir: Path to the examples directory
35
36 Returns:
37 Generated README.md content
38 """
39 examples_path = Path(examples_dir)
40 skill_dir = Path(__file__).resolve().parent.parent
41
42 if not examples_path.exists():
43 print(f"[ERROR] Directory not found: {examples_dir}")
44 return ""
45
46 def skill_link(target: Path) -> str:
47 """Return a link from the generated index to a packaged Skill resource."""
48 return Path(
49 os.path.relpath(target, start=examples_path.resolve())
50 ).as_posix()
51
52 print(f"[SCAN] Scanning directory: {examples_dir}")
53
54 # Find all projects
55 projects = find_all_projects(examples_dir)
56
57 if not projects:
58 print("[WARN] No projects found")
59 return ""
60
61 print(f"Found {len(projects)} project(s)")
62
63 # Collect project information
64 projects_info = []
65 for project_path in projects:
66 info = get_project_info(str(project_path))
67 projects_info.append(info)
68
69 # Sort by date (newest first)
70 projects_info.sort(key=lambda x: x['date'], reverse=True)
71
72 # Group by format
73 by_format = defaultdict(list)
74 for info in projects_info:
75 by_format[info['format']].append(info)
76
77 # Generate README content
78 content = []
79 content.append("# PPT Master Example Projects Index\n")
80 content.append("> This file is auto-generated by the packaged `scripts/generate_examples_index.py`\n")
81 content.append(f"> Last updated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n")
82
83 # Overview statistics
84 content.append("## [Stats] Overview\n")
85 content.append(f"- **Total projects**: {len(projects_info)}")
86 content.append(f"- **Canvas formats**: {len(by_format)} type(s)")
87
88 total_svgs = sum(info['svg_count'] for info in projects_info)
89 content.append(f"- **SVG files**: {total_svgs}")
90
91 # Statistics by format
92 content.append("\n### Format Distribution\n")
93 for fmt_key in sorted(by_format.keys(), key=lambda x: len(by_format[x]), reverse=True):
94 count = len(by_format[fmt_key])
95 fmt_name = CANVAS_FORMATS.get(fmt_key, {}).get('name', fmt_key)
96 content.append(f"- **{fmt_name}**: {count} project(s)")
97
98 # Recently updated
99 content.append("\n## [New] Recently Updated\n")
100 for info in projects_info[:5]:
101 content.append(
102 f"- **{info['name']}** ({info['format_name']}) - {info['date_formatted']}")
103
104 # Project list by format
105 content.append("\n## [List] Project List\n")
106
107 # Define format display order
108 format_order = ['ppt169', 'ppt43', 'wechat',
109 'xiaohongshu', 'moments', 'story', 'banner', 'a4']
110
111 for fmt_key in format_order:
112 if fmt_key not in by_format:
113 continue
114
115 fmt_info = CANVAS_FORMATS.get(fmt_key, {})
116 fmt_name = fmt_info.get('name', fmt_key)
117 dimensions = fmt_info.get('dimensions', '')
118
119 content.append(f"\n### {fmt_name} ({dimensions})\n")
120
121 projects_list = by_format[fmt_key]
122 # Sort by date
123 projects_list.sort(key=lambda x: x['date'], reverse=True)
124
125 for info in projects_list:
126 # Project name and link
127 project_link = f"./{info['dir_name']}"
128
129 # Build project entry
130 line = f"- **[{info['name']}]({project_link})**"
131
132 # Add date
133 line += f" - {info['date_formatted']}"
134
135 # Add SVG count
136 line += f" - {info['svg_count']} page(s)"
137
138 content.append(line)
139
140 # Other uncategorized formats
141 other_formats = set(by_format.keys()) - set(format_order)
142 if other_formats:
143 content.append("\n### Other Formats\n")
144 for fmt_key in sorted(other_formats):
145 projects_list = by_format[fmt_key]
146 for info in projects_list:
147 project_link = f"./{info['dir_name']}"
148 line = f"- **[{info['name']}]({project_link})**"
149 line += f" ({info['format_name']}) - {info['date_formatted']}"
150 line += f" - {info['svg_count']} page(s)"
151 content.append(line)
152
153 # Usage instructions
154 content.append("\n## [Docs] Usage Instructions\n")
155 content.append("### Preview Projects\n")
156 content.append("Each project contains the following files:\n")
157 content.append("- `README.md` - Project documentation")
158 content.append("- `Design Spec & Content Outline.md` - Full design specification")
159 content.append("- `svg_output/` - SVG output files\n")
160
161 content.append("**Method 1: Using an HTTP server (recommended)**\n")
162 content.append("```bash")
163 content.append(
164 "python3 -m http.server --directory examples/<project_name>/svg_output 8000")
165 content.append("# Visit http://localhost:8000")
166 content.append("```\n")
167
168 content.append("**Method 2: Open SVG directly**\n")
169 content.append("```bash")
170 content.append(
171 "open examples/<project_name>/svg_output/slide_01_cover.svg")
172 content.append("```\n")
173
174 # Create new project
175 content.append("### Create a New Project\n")
176 content.append("Refer to existing project structures, or use the project management tool:\n")
177 content.append("```bash")
178 content.append(
179 "python3 scripts/project_manager.py init my_project --format ppt169")
180 content.append("```\n")
181
182 # Contribution guidelines
183 content.append("## [Contribute] Contributing Example Projects\n")
184 content.append("We welcome you to share your projects in the examples directory!\n")
185 content.append("### Project Requirements\n")
186 content.append("1. Follow the standard project structure")
187 content.append("2. Include a complete README.md and design specification")
188 content.append("3. SVG files must comply with technical specifications")
189 content.append("4. Directory naming format: `{project_name}_{format}_{YYYYMMDD}`\n")
190
191 content.append("### Submission Process\n")
192 content.append("1. Create a project under the `examples/` directory")
193 content.append(
194 "2. Validate the project: `python3 scripts/project_manager.py validate examples/<project>`")
195 content.append("3. Update the index: `python3 scripts/generate_examples_index.py`")
196 content.append("4. Submit a Pull Request\n")
197
198 # Related resources
199 content.append("## [Resources] Related Resources\n")
200 content.append(f"- [Workflow]({skill_link(skill_dir / 'SKILL.md')})")
201 content.append(
202 f"- [Canvas Formats]({skill_link(skill_dir / 'references' / 'canvas-formats.md')})")
203 content.append(
204 f"- [Role Definitions]({skill_link(skill_dir / 'references')})")
205 content.append(
206 f"- [Visualization Templates]({skill_link(skill_dir / 'templates' / 'README.md')})\n")
207
208 # Footer
209 content.append("---\n")
210 content.append(
211 f"*Auto-generated on {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} by PPT Master*")
212
213 return "\n".join(content)
214
215
216 def build_parser() -> argparse.ArgumentParser:
217 """Build the examples-index CLI parser."""
218 parser = argparse.ArgumentParser(
219 description="Generate the PPT Master examples README index.",
220 )
221 parser.add_argument(
222 "examples_dir",
223 nargs="?",
224 default="examples",
225 help="Examples directory (default: examples)",
226 )
227 return parser
228
229
230 def main(argv: list[str] | None = None) -> int:
231 """Run the CLI entry point."""
232 parser = build_parser()
233 raw_argv = list(sys.argv[1:] if argv is None else argv)
234 if raw_argv == ["help"]:
235 parser.print_help()
236 return 0
237 args = parser.parse_args(raw_argv)
238 configure_utf8_stdio()
239 examples_dir = args.examples_dir
240
241 print("=" * 80)
242 print("PPT Master - Examples Index Generator")
243 print("=" * 80 + "\n")
244
245 # Generate index content
246 content = generate_examples_index(examples_dir)
247
248 if not content:
249 print("\n[ERROR] Generation failed")
250 return 1
251
252 # Write to file
253 output_file = Path(examples_dir) / 'README.md'
254
255 try:
256 with open(output_file, 'w', encoding='utf-8') as f:
257 f.write(content)
258
259 print(f"\n[OK] Index file generated: {output_file}")
260 print(f" Contains {len(content.splitlines())} lines")
261
262 # Display statistics
263 projects_count = content.count('- **[')
264 print(f" Indexed {projects_count} project(s)")
265
266 except Exception as e:
267 print(f"\n[ERROR] Failed to write file: {e}")
268 return 1
269
270 return 0
271
272
273 if __name__ == '__main__':
274 raise SystemExit(main())
275
275 lines PYTHON