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