quantum-framework 0.9.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (262) hide show
  1. quantum/__init__.py +1 -0
  2. quantum/cli/__init__.py +2 -0
  3. quantum/cli/commands/__init__.py +15 -0
  4. quantum/cli/commands/build.py +417 -0
  5. quantum/cli/commands/dev.py +185 -0
  6. quantum/cli/commands/docs.py +329 -0
  7. quantum/cli/commands/lint.py +523 -0
  8. quantum/cli/commands/migrate.py +527 -0
  9. quantum/cli/commands/new.py +622 -0
  10. quantum/cli/commands/serve.py +190 -0
  11. quantum/cli/commands/test.py +193 -0
  12. quantum/cli/deploy.py +810 -0
  13. quantum/cli/hot_reload.py +951 -0
  14. quantum/cli/jobs.py +356 -0
  15. quantum/cli/mq.py +582 -0
  16. quantum/cli/pkg.py +390 -0
  17. quantum/cli/runner.py +547 -0
  18. quantum/cli/server_process.py +159 -0
  19. quantum/cli/utils.py +334 -0
  20. quantum/compiler/__init__.py +30 -0
  21. quantum/compiler/base_generator.py +367 -0
  22. quantum/compiler/cli.py +295 -0
  23. quantum/compiler/expression_transformer.py +444 -0
  24. quantum/compiler/javascript/__init__.py +10 -0
  25. quantum/compiler/javascript/generator.py +659 -0
  26. quantum/compiler/optimizer.py +270 -0
  27. quantum/compiler/python/__init__.py +10 -0
  28. quantum/compiler/python/generator.py +883 -0
  29. quantum/compiler/python/runtime.py +863 -0
  30. quantum/compiler/transpiler.py +330 -0
  31. quantum/core/__init__.py +3 -0
  32. quantum/core/ast_nodes.py +2611 -0
  33. quantum/core/expression_diagnostics.py +87 -0
  34. quantum/core/expression_stdlib.py +148 -0
  35. quantum/core/expressions.py +591 -0
  36. quantum/core/features/agents/src/__init__.py +30 -0
  37. quantum/core/features/agents/src/ast_node.py +540 -0
  38. quantum/core/features/conditionals/src/__init__.py +8 -0
  39. quantum/core/features/conditionals/src/ast_node.py +68 -0
  40. quantum/core/features/data_fetching/src/__init__.py +21 -0
  41. quantum/core/features/data_fetching/src/ast_node.py +312 -0
  42. quantum/core/features/data_fetching/src/desktop_adapter.py +351 -0
  43. quantum/core/features/data_fetching/src/html_adapter.py +474 -0
  44. quantum/core/features/data_fetching/src/parser.py +225 -0
  45. quantum/core/features/data_import/src/__init__.py +0 -0
  46. quantum/core/features/data_import/src/ast_node.py +291 -0
  47. quantum/core/features/data_import/src/runtime.py +538 -0
  48. quantum/core/features/dump/src/__init__.py +12 -0
  49. quantum/core/features/dump/src/ast_node.py +106 -0
  50. quantum/core/features/dump/src/parser.py +61 -0
  51. quantum/core/features/dump/src/runtime.py +246 -0
  52. quantum/core/features/functions/src/__init__.py +8 -0
  53. quantum/core/features/functions/src/ast_node.py +149 -0
  54. quantum/core/features/game_engine_2d/src/__init__.py +19 -0
  55. quantum/core/features/game_engine_2d/src/ast_nodes.py +1719 -0
  56. quantum/core/features/game_engine_2d/src/parser.py +983 -0
  57. quantum/core/features/invocation/src/__init__.py +0 -0
  58. quantum/core/features/invocation/src/ast_node.py +146 -0
  59. quantum/core/features/invocation/src/runtime.py +327 -0
  60. quantum/core/features/knowledge_base/src/__init__.py +6 -0
  61. quantum/core/features/knowledge_base/src/ast_node.py +113 -0
  62. quantum/core/features/knowledge_base/src/parser.py +82 -0
  63. quantum/core/features/logging/src/__init__.py +12 -0
  64. quantum/core/features/logging/src/ast_node.py +111 -0
  65. quantum/core/features/logging/src/parser.py +50 -0
  66. quantum/core/features/logging/src/runtime.py +190 -0
  67. quantum/core/features/loops/src/__init__.py +8 -0
  68. quantum/core/features/loops/src/ast_node.py +60 -0
  69. quantum/core/features/query/src/__init__.py +0 -0
  70. quantum/core/features/query/src/database_service.py +322 -0
  71. quantum/core/features/query/src/query_validators.py +20 -0
  72. quantum/core/features/state_management/src/__init__.py +11 -0
  73. quantum/core/features/state_management/src/ast_node.py +228 -0
  74. quantum/core/features/terminal_engine/src/__init__.py +21 -0
  75. quantum/core/features/terminal_engine/src/ast_nodes.py +560 -0
  76. quantum/core/features/terminal_engine/src/parser.py +361 -0
  77. quantum/core/features/testing_engine/src/__init__.py +41 -0
  78. quantum/core/features/testing_engine/src/ast_nodes.py +1212 -0
  79. quantum/core/features/testing_engine/src/parser.py +604 -0
  80. quantum/core/features/theming/src/__init__.py +48 -0
  81. quantum/core/features/theming/src/ast_node.py +137 -0
  82. quantum/core/features/theming/src/presets.py +405 -0
  83. quantum/core/features/ui_engine/src/__init__.py +20 -0
  84. quantum/core/features/ui_engine/src/ast_nodes.py +1854 -0
  85. quantum/core/features/ui_engine/src/parser.py +1106 -0
  86. quantum/core/features/websocket/src/__init__.py +24 -0
  87. quantum/core/features/websocket/src/ast_node.py +247 -0
  88. quantum/core/html_compat.py +299 -0
  89. quantum/core/parser.py +1235 -0
  90. quantum/core/parser_registry.py +213 -0
  91. quantum/core/parsers/__init__.py +76 -0
  92. quantum/core/parsers/ai/__init__.py +12 -0
  93. quantum/core/parsers/ai/agent_parser.py +106 -0
  94. quantum/core/parsers/ai/knowledge_parser.py +86 -0
  95. quantum/core/parsers/ai/llm_parser.py +78 -0
  96. quantum/core/parsers/ai/team_parser.py +88 -0
  97. quantum/core/parsers/base.py +322 -0
  98. quantum/core/parsers/composition/__init__.py +10 -0
  99. quantum/core/parsers/composition/import_parser.py +50 -0
  100. quantum/core/parsers/composition/slot_parser.py +48 -0
  101. quantum/core/parsers/control_flow/__init__.py +11 -0
  102. quantum/core/parsers/control_flow/if_parser.py +68 -0
  103. quantum/core/parsers/control_flow/loop_parser.py +105 -0
  104. quantum/core/parsers/control_flow/set_parser.py +89 -0
  105. quantum/core/parsers/data/__init__.py +12 -0
  106. quantum/core/parsers/data/data_parser.py +217 -0
  107. quantum/core/parsers/data/invoke_parser.py +116 -0
  108. quantum/core/parsers/data/query_parser.py +188 -0
  109. quantum/core/parsers/data/transaction_parser.py +77 -0
  110. quantum/core/parsers/events/__init__.py +9 -0
  111. quantum/core/parsers/events/dispatch_event_parser.py +44 -0
  112. quantum/core/parsers/forms/__init__.py +11 -0
  113. quantum/core/parsers/forms/action_parser.py +54 -0
  114. quantum/core/parsers/forms/flash_parser.py +34 -0
  115. quantum/core/parsers/forms/redirect_parser.py +33 -0
  116. quantum/core/parsers/functions/__init__.py +11 -0
  117. quantum/core/parsers/functions/function_parser.py +137 -0
  118. quantum/core/parsers/functions/param_parser.py +66 -0
  119. quantum/core/parsers/functions/return_parser.py +31 -0
  120. quantum/core/parsers/html/__init__.py +10 -0
  121. quantum/core/parsers/html/component_call_parser.py +130 -0
  122. quantum/core/parsers/html/html_parser.py +115 -0
  123. quantum/core/parsers/jobs/__init__.py +11 -0
  124. quantum/core/parsers/jobs/job_parser.py +71 -0
  125. quantum/core/parsers/jobs/schedule_parser.py +62 -0
  126. quantum/core/parsers/jobs/thread_parser.py +57 -0
  127. quantum/core/parsers/messaging/__init__.py +17 -0
  128. quantum/core/parsers/messaging/message_ack_parser.py +30 -0
  129. quantum/core/parsers/messaging/message_nack_parser.py +30 -0
  130. quantum/core/parsers/messaging/message_parser.py +114 -0
  131. quantum/core/parsers/messaging/queue_parser.py +61 -0
  132. quantum/core/parsers/messaging/websocket_parser.py +121 -0
  133. quantum/core/parsers/persistence/__init__.py +9 -0
  134. quantum/core/parsers/persistence/persist_parser.py +64 -0
  135. quantum/core/parsers/routing/__init__.py +9 -0
  136. quantum/core/parsers/routing/route_parser.py +41 -0
  137. quantum/core/parsers/scripting/__init__.py +12 -0
  138. quantum/core/parsers/scripting/pyclass_parser.py +62 -0
  139. quantum/core/parsers/scripting/pydecorator_parser.py +68 -0
  140. quantum/core/parsers/scripting/pyimport_parser.py +52 -0
  141. quantum/core/parsers/scripting/python_parser.py +49 -0
  142. quantum/core/parsers/services/__init__.py +12 -0
  143. quantum/core/parsers/services/dump_parser.py +52 -0
  144. quantum/core/parsers/services/file_parser.py +48 -0
  145. quantum/core/parsers/services/log_parser.py +46 -0
  146. quantum/core/parsers/services/mail_parser.py +65 -0
  147. quantum/core/tiers.py +82 -0
  148. quantum/packages/__init__.py +28 -0
  149. quantum/packages/manager.py +413 -0
  150. quantum/packages/manifest.py +351 -0
  151. quantum/packages/registry.py +399 -0
  152. quantum/packages/resolver.py +336 -0
  153. quantum/plugins/__init__.py +33 -0
  154. quantum/plugins/hooks.py +329 -0
  155. quantum/plugins/loader.py +479 -0
  156. quantum/plugins/manifest.py +336 -0
  157. quantum/plugins/registry.py +371 -0
  158. quantum/runtime/__init__.py +28 -0
  159. quantum/runtime/action_handler.py +443 -0
  160. quantum/runtime/adapters/__init__.py +88 -0
  161. quantum/runtime/adapters/memory_adapter.py +690 -0
  162. quantum/runtime/adapters/rabbitmq_adapter.py +715 -0
  163. quantum/runtime/adapters/redis_adapter.py +582 -0
  164. quantum/runtime/adapters/sqlite_adapter.py +414 -0
  165. quantum/runtime/agent_service.py +1133 -0
  166. quantum/runtime/api_server.py +86 -0
  167. quantum/runtime/ast_cache.py +506 -0
  168. quantum/runtime/auth_service.py +267 -0
  169. quantum/runtime/component.py +990 -0
  170. quantum/runtime/component_composer.py +319 -0
  171. quantum/runtime/component_resolver.py +174 -0
  172. quantum/runtime/database_service.py +598 -0
  173. quantum/runtime/email_service.py +162 -0
  174. quantum/runtime/error_handler.py +295 -0
  175. quantum/runtime/execution_context.py +286 -0
  176. quantum/runtime/executor_registry.py +171 -0
  177. quantum/runtime/executors/__init__.py +71 -0
  178. quantum/runtime/executors/ai/__init__.py +12 -0
  179. quantum/runtime/executors/ai/agent_executor.py +217 -0
  180. quantum/runtime/executors/ai/knowledge_executor.py +114 -0
  181. quantum/runtime/executors/ai/llm_executor.py +153 -0
  182. quantum/runtime/executors/ai/team_executor.py +171 -0
  183. quantum/runtime/executors/base.py +262 -0
  184. quantum/runtime/executors/control_flow/__init__.py +11 -0
  185. quantum/runtime/executors/control_flow/if_executor.py +93 -0
  186. quantum/runtime/executors/control_flow/loop_executor.py +307 -0
  187. quantum/runtime/executors/control_flow/set_executor.py +412 -0
  188. quantum/runtime/executors/data/__init__.py +12 -0
  189. quantum/runtime/executors/data/data_executor.py +145 -0
  190. quantum/runtime/executors/data/invoke_executor.py +176 -0
  191. quantum/runtime/executors/data/query_executor.py +256 -0
  192. quantum/runtime/executors/data/transaction_executor.py +91 -0
  193. quantum/runtime/executors/jobs/__init__.py +11 -0
  194. quantum/runtime/executors/jobs/job_executor.py +190 -0
  195. quantum/runtime/executors/jobs/schedule_executor.py +132 -0
  196. quantum/runtime/executors/jobs/thread_executor.py +127 -0
  197. quantum/runtime/executors/messaging/__init__.py +17 -0
  198. quantum/runtime/executors/messaging/message_ack_executor.py +51 -0
  199. quantum/runtime/executors/messaging/message_executor.py +174 -0
  200. quantum/runtime/executors/messaging/queue_executor.py +103 -0
  201. quantum/runtime/executors/messaging/websocket_executor.py +197 -0
  202. quantum/runtime/executors/scripting/__init__.py +11 -0
  203. quantum/runtime/executors/scripting/pyclass_executor.py +90 -0
  204. quantum/runtime/executors/scripting/pyimport_executor.py +81 -0
  205. quantum/runtime/executors/scripting/python_executor.py +249 -0
  206. quantum/runtime/executors/services/__init__.py +12 -0
  207. quantum/runtime/executors/services/dump_executor.py +72 -0
  208. quantum/runtime/executors/services/file_executor.py +89 -0
  209. quantum/runtime/executors/services/log_executor.py +77 -0
  210. quantum/runtime/executors/services/mail_executor.py +81 -0
  211. quantum/runtime/expression_cache.py +498 -0
  212. quantum/runtime/file_upload_service.py +326 -0
  213. quantum/runtime/function_registry.py +118 -0
  214. quantum/runtime/game_builder.py +166 -0
  215. quantum/runtime/game_code_generator.py +2371 -0
  216. quantum/runtime/game_templates.py +2006 -0
  217. quantum/runtime/godot_code_generator.py +4681 -0
  218. quantum/runtime/godot_templates.py +1449 -0
  219. quantum/runtime/job_executor.py +1599 -0
  220. quantum/runtime/knowledge_service.py +500 -0
  221. quantum/runtime/llm_cache.py +100 -0
  222. quantum/runtime/llm_providers.py +704 -0
  223. quantum/runtime/llm_service.py +287 -0
  224. quantum/runtime/logging_setup.py +140 -0
  225. quantum/runtime/message_broker.py +364 -0
  226. quantum/runtime/message_queue_service.py +571 -0
  227. quantum/runtime/param_validation.py +184 -0
  228. quantum/runtime/pypy_compat.py +315 -0
  229. quantum/runtime/python_bridge.py +698 -0
  230. quantum/runtime/query_validators.py +304 -0
  231. quantum/runtime/renderer.py +733 -0
  232. quantum/runtime/service_container.py +444 -0
  233. quantum/runtime/terminal_builder.py +76 -0
  234. quantum/runtime/terminal_code_generator.py +607 -0
  235. quantum/runtime/terminal_templates.py +243 -0
  236. quantum/runtime/testing_builder.py +77 -0
  237. quantum/runtime/testing_code_generator.py +833 -0
  238. quantum/runtime/testing_templates.py +85 -0
  239. quantum/runtime/ui_builder.py +188 -0
  240. quantum/runtime/ui_desktop_adapter.py +1730 -0
  241. quantum/runtime/ui_desktop_templates.py +307 -0
  242. quantum/runtime/ui_html_adapter.py +2691 -0
  243. quantum/runtime/ui_html_templates.py +2297 -0
  244. quantum/runtime/ui_mobile_adapter.py +1832 -0
  245. quantum/runtime/ui_mobile_templates.py +1003 -0
  246. quantum/runtime/ui_textual_adapter.py +1866 -0
  247. quantum/runtime/ui_textual_templates.py +45 -0
  248. quantum/runtime/ui_tokens.py +465 -0
  249. quantum/runtime/ui_validator.py +365 -0
  250. quantum/runtime/validators.py +256 -0
  251. quantum/runtime/web_server.py +1766 -0
  252. quantum/runtime/websocket_adapter.py +501 -0
  253. quantum/runtime/websocket_service.py +585 -0
  254. quantum/runtime/websocket_transport.py +289 -0
  255. quantum/runtime/wsgi.py +101 -0
  256. quantum/utils/__init__.py +1 -0
  257. quantum_framework-0.9.0.dist-info/METADATA +244 -0
  258. quantum_framework-0.9.0.dist-info/RECORD +262 -0
  259. quantum_framework-0.9.0.dist-info/WHEEL +5 -0
  260. quantum_framework-0.9.0.dist-info/entry_points.txt +2 -0
  261. quantum_framework-0.9.0.dist-info/licenses/LICENSE +21 -0
  262. quantum_framework-0.9.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,329 @@
1
+ """
2
+ Quantum CLI - Docs Command
3
+
4
+ Generate documentation from components.
5
+ """
6
+
7
+ import sys
8
+ from pathlib import Path
9
+ from typing import Optional, List
10
+
11
+ import click
12
+
13
+ from quantum.cli.utils import get_console, find_project_root, find_q_files
14
+
15
+
16
+ @click.command('docs')
17
+ @click.argument('path', required=False, type=click.Path())
18
+ @click.option('--output', '-o', type=click.Path(), default='docs/api',
19
+ help='Output directory for generated docs')
20
+ @click.option('--format', '-f', type=click.Choice(['markdown', 'html', 'json']), default='markdown',
21
+ help='Output format')
22
+ @click.option('--serve', '-s', is_flag=True, help='Start docs server after generation')
23
+ @click.option('--port', '-p', type=int, default=5173, help='Port for docs server')
24
+ @click.option('--quiet', '-q', is_flag=True, help='Quiet mode')
25
+ def docs(
26
+ path: Optional[str],
27
+ output: str,
28
+ format: str,
29
+ serve: bool,
30
+ port: int,
31
+ quiet: bool
32
+ ):
33
+ """Generate documentation from Quantum components.
34
+
35
+ Extracts component metadata, props, slots, and examples to create
36
+ API documentation.
37
+
38
+ Examples:
39
+
40
+ quantum docs
41
+
42
+ quantum docs ./components
43
+
44
+ quantum docs --output ./api-docs --format html
45
+
46
+ quantum docs --serve
47
+ """
48
+ console = get_console(quiet=quiet)
49
+
50
+ # Find project root
51
+ project_root = find_project_root()
52
+ if not project_root:
53
+ project_root = Path.cwd()
54
+
55
+ # Determine source path
56
+ if path:
57
+ source_path = Path(path)
58
+ if not source_path.is_absolute():
59
+ source_path = project_root / path
60
+ else:
61
+ # Default locations for components
62
+ for default_path in ['components', 'src/components', 'src']:
63
+ candidate = project_root / default_path
64
+ if candidate.exists():
65
+ source_path = candidate
66
+ break
67
+ else:
68
+ source_path = project_root
69
+
70
+ if not source_path.exists():
71
+ console.error(f"Source path not found: {source_path}")
72
+ raise click.Abort()
73
+
74
+ # Output directory
75
+ output_path = Path(output)
76
+ if not output_path.is_absolute():
77
+ output_path = project_root / output
78
+
79
+ console.header(
80
+ "Quantum Docs Generator",
81
+ f"Source: {source_path}\nOutput: {output_path}"
82
+ )
83
+
84
+ # Find .q files
85
+ q_files = find_q_files(source_path, recursive=True)
86
+ console.info(f"Found {len(q_files)} component(s)")
87
+
88
+ if not q_files:
89
+ console.warning("No .q files found")
90
+ return
91
+
92
+ # Generate documentation
93
+ output_path.mkdir(parents=True, exist_ok=True)
94
+ generated = []
95
+
96
+ with console.progress("Generating documentation...") as progress:
97
+ task = progress.add_task("Processing", total=len(q_files))
98
+
99
+ for q_file in q_files:
100
+ try:
101
+ doc = _generate_component_doc(q_file, format)
102
+ if doc:
103
+ # Write doc file
104
+ rel_path = q_file.relative_to(source_path) if q_file.is_relative_to(source_path) else q_file.name
105
+ ext = {'markdown': '.md', 'html': '.html', 'json': '.json'}[format]
106
+ doc_file = output_path / str(rel_path).replace('.q', ext)
107
+ doc_file.parent.mkdir(parents=True, exist_ok=True)
108
+ doc_file.write_text(doc, encoding='utf-8')
109
+ generated.append(doc_file)
110
+ except Exception as e:
111
+ console.warning(f"Failed to process {q_file.name}: {e}")
112
+
113
+ progress.update(task, advance=1)
114
+
115
+ # Generate index
116
+ if generated and format == 'markdown':
117
+ index_content = _generate_index(generated, output_path)
118
+ index_file = output_path / 'index.md'
119
+ index_file.write_text(index_content, encoding='utf-8')
120
+ generated.append(index_file)
121
+
122
+ console.success(f"Generated {len(generated)} documentation file(s)")
123
+
124
+ # Start server if requested
125
+ if serve:
126
+ console.info(f"Starting docs server on http://localhost:{port}")
127
+ _serve_docs(output_path, port)
128
+
129
+
130
+ def _generate_component_doc(file_path: Path, format: str) -> Optional[str]:
131
+ """Generate documentation for a single component."""
132
+ import re
133
+
134
+ content = file_path.read_text(encoding='utf-8')
135
+
136
+ # Extract component metadata
137
+ component_match = re.search(r'<q:component\s+name="([^"]+)"', content)
138
+ if not component_match:
139
+ return None
140
+
141
+ component_name = component_match.group(1)
142
+
143
+ # Extract description from comment
144
+ desc_match = re.search(r'<!--\s*@description\s+(.*?)\s*-->', content, re.DOTALL)
145
+ description = desc_match.group(1).strip() if desc_match else "No description available."
146
+
147
+ # Extract params
148
+ params = []
149
+ for match in re.finditer(
150
+ r'<q:param\s+name="([^"]+)"(?:\s+type="([^"]+)")?(?:\s+default="([^"]+)")?(?:\s+required="([^"]+)")?[^>]*/?>',
151
+ content
152
+ ):
153
+ params.append({
154
+ 'name': match.group(1),
155
+ 'type': match.group(2) or 'any',
156
+ 'default': match.group(3),
157
+ 'required': match.group(4) == 'true',
158
+ })
159
+
160
+ # Extract slots
161
+ slots = []
162
+ for match in re.finditer(r'<q:slot(?:\s+name="([^"]+)")?[^>]*/>', content):
163
+ slot_name = match.group(1) or 'default'
164
+ slots.append({'name': slot_name})
165
+
166
+ # Extract example from comment
167
+ example_match = re.search(r'<!--\s*@example\s+(.*?)\s*-->', content, re.DOTALL)
168
+ example = example_match.group(1).strip() if example_match else None
169
+
170
+ # Generate output
171
+ if format == 'markdown':
172
+ return _format_markdown(component_name, description, params, slots, example, file_path)
173
+ elif format == 'html':
174
+ return _format_html(component_name, description, params, slots, example, file_path)
175
+ elif format == 'json':
176
+ import json
177
+ return json.dumps({
178
+ 'name': component_name,
179
+ 'description': description,
180
+ 'params': params,
181
+ 'slots': slots,
182
+ 'example': example,
183
+ 'file': str(file_path),
184
+ }, indent=2)
185
+
186
+ return None
187
+
188
+
189
+ def _format_markdown(name: str, description: str, params: List, slots: List, example: Optional[str], file_path: Path) -> str:
190
+ """Format component documentation as Markdown."""
191
+ lines = [
192
+ f"# {name}",
193
+ "",
194
+ description,
195
+ "",
196
+ ]
197
+
198
+ if params:
199
+ lines.extend([
200
+ "## Props",
201
+ "",
202
+ "| Name | Type | Default | Required |",
203
+ "|------|------|---------|----------|",
204
+ ])
205
+ for p in params:
206
+ default = f"`{p['default']}`" if p['default'] else "-"
207
+ required = "Yes" if p['required'] else "No"
208
+ lines.append(f"| `{p['name']}` | `{p['type']}` | {default} | {required} |")
209
+ lines.append("")
210
+
211
+ if slots:
212
+ lines.extend([
213
+ "## Slots",
214
+ "",
215
+ ])
216
+ for s in slots:
217
+ lines.append(f"- `{s['name']}`")
218
+ lines.append("")
219
+
220
+ if example:
221
+ lines.extend([
222
+ "## Example",
223
+ "",
224
+ "```xml",
225
+ example,
226
+ "```",
227
+ "",
228
+ ])
229
+
230
+ lines.extend([
231
+ "---",
232
+ f"*Source: `{file_path.name}`*",
233
+ ])
234
+
235
+ return '\n'.join(lines)
236
+
237
+
238
+ def _format_html(name: str, description: str, params: List, slots: List, example: Optional[str], file_path: Path) -> str:
239
+ """Format component documentation as HTML."""
240
+ import html
241
+
242
+ parts = [
243
+ "<!DOCTYPE html>",
244
+ "<html>",
245
+ "<head>",
246
+ f"<title>{html.escape(name)} - Quantum Component</title>",
247
+ "<style>",
248
+ "body { font-family: system-ui, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }",
249
+ "h1 { color: #333; }",
250
+ "table { border-collapse: collapse; width: 100%; }",
251
+ "th, td { border: 1px solid #ddd; padding: 8px; text-align: left; }",
252
+ "th { background: #f5f5f5; }",
253
+ "code { background: #f5f5f5; padding: 2px 6px; border-radius: 3px; }",
254
+ "pre { background: #1e1e1e; color: #d4d4d4; padding: 16px; border-radius: 6px; overflow-x: auto; }",
255
+ "</style>",
256
+ "</head>",
257
+ "<body>",
258
+ f"<h1>{html.escape(name)}</h1>",
259
+ f"<p>{html.escape(description)}</p>",
260
+ ]
261
+
262
+ if params:
263
+ parts.extend([
264
+ "<h2>Props</h2>",
265
+ "<table>",
266
+ "<tr><th>Name</th><th>Type</th><th>Default</th><th>Required</th></tr>",
267
+ ])
268
+ for p in params:
269
+ default = f"<code>{html.escape(p['default'])}</code>" if p['default'] else "-"
270
+ required = "Yes" if p['required'] else "No"
271
+ parts.append(f"<tr><td><code>{html.escape(p['name'])}</code></td><td><code>{html.escape(p['type'])}</code></td><td>{default}</td><td>{required}</td></tr>")
272
+ parts.append("</table>")
273
+
274
+ if slots:
275
+ parts.append("<h2>Slots</h2><ul>")
276
+ for s in slots:
277
+ parts.append(f"<li><code>{html.escape(s['name'])}</code></li>")
278
+ parts.append("</ul>")
279
+
280
+ if example:
281
+ parts.extend([
282
+ "<h2>Example</h2>",
283
+ f"<pre><code>{html.escape(example)}</code></pre>",
284
+ ])
285
+
286
+ parts.extend([
287
+ f"<hr><p><em>Source: <code>{html.escape(file_path.name)}</code></em></p>",
288
+ "</body>",
289
+ "</html>",
290
+ ])
291
+
292
+ return '\n'.join(parts)
293
+
294
+
295
+ def _generate_index(generated: List[Path], output_path: Path) -> str:
296
+ """Generate index file for documentation."""
297
+ lines = [
298
+ "# Quantum Component API",
299
+ "",
300
+ "## Components",
301
+ "",
302
+ ]
303
+
304
+ for doc_file in sorted(generated):
305
+ if doc_file.name == 'index.md':
306
+ continue
307
+ rel_path = doc_file.relative_to(output_path)
308
+ name = doc_file.stem
309
+ lines.append(f"- [{name}](./{rel_path})")
310
+
311
+ return '\n'.join(lines)
312
+
313
+
314
+ def _serve_docs(output_path: Path, port: int):
315
+ """Start a simple HTTP server for documentation."""
316
+ import http.server
317
+ import socketserver
318
+ import os
319
+
320
+ os.chdir(output_path)
321
+
322
+ handler = http.server.SimpleHTTPRequestHandler
323
+ with socketserver.TCPServer(("", port), handler) as httpd:
324
+ print(f"Serving docs at http://localhost:{port}")
325
+ print("Press Ctrl+C to stop")
326
+ try:
327
+ httpd.serve_forever()
328
+ except KeyboardInterrupt:
329
+ print("\nServer stopped")