dars-framework 1.2.3__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.
- dars/__init__.py +0 -0
- dars/all.py +69 -0
- dars/cli/__init__.py +0 -0
- dars/cli/doctor/__init__.py +1 -0
- dars/cli/doctor/detect.py +154 -0
- dars/cli/doctor/doctor.py +176 -0
- dars/cli/doctor/installers.py +100 -0
- dars/cli/doctor/persist.py +62 -0
- dars/cli/doctor/preflight.py +33 -0
- dars/cli/doctor/ui.py +54 -0
- dars/cli/hot_reload.py +33 -0
- dars/cli/main.py +1107 -0
- dars/cli/preview.py +448 -0
- dars/cli/translations.py +531 -0
- dars/components/__init__.py +0 -0
- dars/components/advanced/__init__.py +8 -0
- dars/components/advanced/accordion.py +26 -0
- dars/components/advanced/card.py +33 -0
- dars/components/advanced/modal.py +45 -0
- dars/components/advanced/navbar.py +44 -0
- dars/components/advanced/table.py +25 -0
- dars/components/advanced/tabs.py +31 -0
- dars/components/basic/__init__.py +34 -0
- dars/components/basic/button.py +55 -0
- dars/components/basic/checkbox.py +35 -0
- dars/components/basic/container.py +29 -0
- dars/components/basic/datepicker.py +139 -0
- dars/components/basic/image.py +36 -0
- dars/components/basic/input.py +57 -0
- dars/components/basic/link.py +31 -0
- dars/components/basic/markdown.py +86 -0
- dars/components/basic/page.py +20 -0
- dars/components/basic/progressbar.py +18 -0
- dars/components/basic/radiobutton.py +35 -0
- dars/components/basic/select.py +82 -0
- dars/components/basic/slider.py +63 -0
- dars/components/basic/spinner.py +12 -0
- dars/components/basic/text.py +23 -0
- dars/components/basic/textarea.py +46 -0
- dars/components/basic/tooltip.py +19 -0
- dars/components/layout/__init__.py +0 -0
- dars/components/layout/anchor.py +13 -0
- dars/components/layout/flex.py +26 -0
- dars/components/layout/grid.py +45 -0
- dars/config.py +134 -0
- dars/core/__init__.py +0 -0
- dars/core/app.py +957 -0
- dars/core/component.py +284 -0
- dars/core/events.py +102 -0
- dars/core/js_bridge.py +99 -0
- dars/core/properties.py +127 -0
- dars/core/state.py +309 -0
- dars/dars_tests/apps_test/health_check.py +56 -0
- dars/dars_tests/run_tests.py +275 -0
- dars/dars_tests/tests/test_advanced_components.py +69 -0
- dars/dars_tests/tests/test_basic_components.py +88 -0
- dars/dars_tests/tests/test_core_and_cli.py +17 -0
- dars/dars_tests/tests/test_layout_components.py +58 -0
- dars/dars_tests/tests/test_version_check.py +21 -0
- dars/docs/__init__.py +0 -0
- dars/docs/app.md +290 -0
- dars/docs/cli.md +80 -0
- dars/docs/components.md +1679 -0
- dars/docs/custom_components.md +30 -0
- dars/docs/events.md +45 -0
- dars/docs/exporters.md +162 -0
- dars/docs/getting_started.md +79 -0
- dars/docs/index.md +18 -0
- dars/docs/scripts.md +593 -0
- dars/docs/state_management.md +57 -0
- dars/exporters/__init__.py +0 -0
- dars/exporters/base.py +96 -0
- dars/exporters/web/OLD/html_css_js_OLD4.py +1538 -0
- dars/exporters/web/OLD/html_css_js_old.py +1406 -0
- dars/exporters/web/OLD/html_css_js_old2.py +1406 -0
- dars/exporters/web/__init__.py +0 -0
- dars/exporters/web/html_css_js.py +2675 -0
- dars/exporters/web/vdom.py +251 -0
- dars/js_lib.py +206 -0
- dars/scripts/__init__.py +0 -0
- dars/scripts/dscript.py +26 -0
- dars/scripts/script.py +39 -0
- dars/security.py +195 -0
- dars/templates/__init__.py +0 -0
- dars/templates/__pycache__/__init__.cpython-311.pyc +0 -0
- dars/templates/examples/README.md +4 -0
- dars/templates/examples/__pycache__/dynamic_event_demo.cpython-311.pyc +0 -0
- dars/templates/examples/advanced/Modal_Demo/advanced_modal_demo.py +275 -0
- dars/templates/examples/advanced/SimpleDashboard/dashboard.py +437 -0
- dars/templates/examples/advanced/SimpleModermWeb/modern_web_app.py +452 -0
- dars/templates/examples/advanced/VariousComponents/all_components_demo.py +87 -0
- dars/templates/examples/advanced/__init__.py +0 -0
- dars/templates/examples/advanced/dState/state_mods_demo.py +68 -0
- dars/templates/examples/basic/Forms/form_components.py +516 -0
- dars/templates/examples/basic/Forms/simple_form.py +379 -0
- dars/templates/examples/basic/HelloWorld/hello_world.py +56 -0
- dars/templates/examples/basic/Layouts/flex_layout_responsive.py +13 -0
- dars/templates/examples/basic/Layouts/grid_layout_responsive.py +12 -0
- dars/templates/examples/basic/Layouts/layout_multipage_demo.py +23 -0
- dars/templates/examples/basic/Multipage/multipage_example.py +67 -0
- dars/templates/examples/basic/PWA/icon-192x192.png +0 -0
- dars/templates/examples/basic/PWA/icon-512x512.png +0 -0
- dars/templates/examples/basic/PWA/pwa_custom_icons.py +33 -0
- dars/templates/examples/basic/__init__.py +0 -0
- dars/templates/examples/demo/__pycache__/complete_app.cpython-311.pyc +0 -0
- dars/templates/examples/demo/complete_app.py +21 -0
- dars/templates/examples/markdown/MarkdownTemplate/README.md +159 -0
- dars/templates/examples/markdown/MarkdownTemplate/markdown_template.py +21 -0
- dars/templates/examples/markdown/MarkdownTemplate/other_docs.md +1 -0
- dars/templates/examples/markdown/__init__.py +0 -0
- dars/templates/html/__init__.py +0 -0
- dars/version.py +2 -0
- dars_framework-1.2.3.dist-info/METADATA +15 -0
- dars_framework-1.2.3.dist-info/RECORD +118 -0
- dars_framework-1.2.3.dist-info/WHEEL +5 -0
- dars_framework-1.2.3.dist-info/entry_points.txt +2 -0
- dars_framework-1.2.3.dist-info/licenses/LICENSE +21 -0
- dars_framework-1.2.3.dist-info/top_level.txt +1 -0
dars/cli/preview.py
ADDED
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Dars Preview - Preview system for exported applications
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import os
|
|
7
|
+
import sys
|
|
8
|
+
import webbrowser
|
|
9
|
+
import http.server
|
|
10
|
+
import mimetypes
|
|
11
|
+
import socketserver
|
|
12
|
+
import threading
|
|
13
|
+
import time
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
from rich.console import Console
|
|
17
|
+
from rich.panel import Panel
|
|
18
|
+
from rich.text import Text
|
|
19
|
+
from rich.table import Table
|
|
20
|
+
from rich import print as rprint
|
|
21
|
+
|
|
22
|
+
from dars.cli.translations import translator
|
|
23
|
+
|
|
24
|
+
console = Console()
|
|
25
|
+
|
|
26
|
+
class PreviewServer:
|
|
27
|
+
"""Preview server for Dars applications"""
|
|
28
|
+
|
|
29
|
+
class DarsRequestHandler(http.server.SimpleHTTPRequestHandler):
|
|
30
|
+
def end_headers(self):
|
|
31
|
+
# CORS para desarrollo PWA si es necesario
|
|
32
|
+
self.send_header('Access-Control-Allow-Origin', '*')
|
|
33
|
+
super().end_headers()
|
|
34
|
+
def guess_type(self, path):
|
|
35
|
+
# Ensure correct MIME types for JS modules and JSON
|
|
36
|
+
if path.endswith('.mjs') or path.endswith('.js'):
|
|
37
|
+
return 'application/javascript'
|
|
38
|
+
if path.endswith('.json'):
|
|
39
|
+
return 'application/json'
|
|
40
|
+
return super().guess_type(path)
|
|
41
|
+
def log_request(self, code='-', size='-'):
|
|
42
|
+
"""Silencia logs para peticiones frecuentes del hot-reload (version.txt)."""
|
|
43
|
+
try:
|
|
44
|
+
p = getattr(self, 'path', '') or ''
|
|
45
|
+
# Coincidir /version.txt o /version_<slug>.txt
|
|
46
|
+
if p.endswith('version.txt') or (p.startswith('/version_') and p.endswith('.txt')):
|
|
47
|
+
return # no loggear
|
|
48
|
+
except Exception:
|
|
49
|
+
pass
|
|
50
|
+
return super().log_request(code, size)
|
|
51
|
+
|
|
52
|
+
def __init__(self, directory: str, port: int = 8000):
|
|
53
|
+
self.directory = os.path.abspath(directory)
|
|
54
|
+
self.port = port
|
|
55
|
+
self.server = None
|
|
56
|
+
self.server_thread = None
|
|
57
|
+
|
|
58
|
+
def start(self):
|
|
59
|
+
"""Starts the preview server"""
|
|
60
|
+
try:
|
|
61
|
+
# Change to the application directory
|
|
62
|
+
os.chdir(self.directory)
|
|
63
|
+
|
|
64
|
+
# Create the server
|
|
65
|
+
# Register mimetypes for strict module loading
|
|
66
|
+
try:
|
|
67
|
+
mimetypes.add_type('application/javascript', '.js')
|
|
68
|
+
mimetypes.add_type('application/javascript', '.mjs')
|
|
69
|
+
mimetypes.add_type('application/json', '.json')
|
|
70
|
+
except Exception:
|
|
71
|
+
pass
|
|
72
|
+
handler = self.DarsRequestHandler
|
|
73
|
+
self.server = socketserver.TCPServer(("", self.port), handler)
|
|
74
|
+
|
|
75
|
+
# Start in a separate thread
|
|
76
|
+
self.server_thread = threading.Thread(target=self.server.serve_forever)
|
|
77
|
+
self.server_thread.daemon = True
|
|
78
|
+
self.server_thread.start()
|
|
79
|
+
|
|
80
|
+
return True
|
|
81
|
+
|
|
82
|
+
except Exception as e:
|
|
83
|
+
console.print(f"[red]{translator.get('server_start_error')}: {e}[/red]")
|
|
84
|
+
return False
|
|
85
|
+
|
|
86
|
+
def stop(self):
|
|
87
|
+
"""Stops the preview server"""
|
|
88
|
+
if self.server:
|
|
89
|
+
self.server.shutdown()
|
|
90
|
+
self.server.server_close()
|
|
91
|
+
|
|
92
|
+
def get_url(self) -> str:
|
|
93
|
+
"""Gets the server URL"""
|
|
94
|
+
return f"http://localhost:{self.port}"
|
|
95
|
+
|
|
96
|
+
def preview_html_app(directory: str, auto_open: bool = True, port: int = 8000):
|
|
97
|
+
"""Previews an exported HTML application"""
|
|
98
|
+
|
|
99
|
+
import signal
|
|
100
|
+
|
|
101
|
+
# Verify that index.html exists
|
|
102
|
+
index_path = os.path.join(directory, "index.html")
|
|
103
|
+
if not os.path.exists(index_path):
|
|
104
|
+
console.print(f"[red]{translator.get('index_html_missing')} {directory}[/red]")
|
|
105
|
+
return False
|
|
106
|
+
|
|
107
|
+
# Create and start the server
|
|
108
|
+
server = PreviewServer(directory, port)
|
|
109
|
+
|
|
110
|
+
if not server.start():
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
url = server.get_url()
|
|
114
|
+
|
|
115
|
+
# Show information
|
|
116
|
+
panel_content = f"""
|
|
117
|
+
[green]✓[/green] {translator.get('preview_server_started')}
|
|
118
|
+
|
|
119
|
+
[bold]URL:[/bold] {url}
|
|
120
|
+
[bold]{translator.get('directory')}:[/bold] {directory}
|
|
121
|
+
[bold]{translator.get('port')}:[/bold] {port}
|
|
122
|
+
|
|
123
|
+
[yellow]{translator.get('press_ctrl_c')}[/yellow]
|
|
124
|
+
"""
|
|
125
|
+
|
|
126
|
+
console.print(Panel(panel_content, title="Dars Preview", border_style="green"))
|
|
127
|
+
|
|
128
|
+
# Open in browser if requested
|
|
129
|
+
if auto_open:
|
|
130
|
+
try:
|
|
131
|
+
webbrowser.open(url)
|
|
132
|
+
console.print(f"[cyan]{translator.get('opening_in_browser').format(url=url)}[/cyan]")
|
|
133
|
+
except Exception as e:
|
|
134
|
+
console.print(f"[yellow]{translator.get('browser_open_error')}: {e}[/yellow]")
|
|
135
|
+
console.print(f"[cyan]{translator.get('open_manually')}: {url}[/cyan]")
|
|
136
|
+
|
|
137
|
+
import threading
|
|
138
|
+
import signal
|
|
139
|
+
|
|
140
|
+
shutdown_event = threading.Event()
|
|
141
|
+
|
|
142
|
+
try:
|
|
143
|
+
while not shutdown_event.is_set():
|
|
144
|
+
shutdown_event.wait(timeout=1) # Espera hasta que se pida cerrar, sin consumir CPU
|
|
145
|
+
except KeyboardInterrupt:
|
|
146
|
+
shutdown_event.set()
|
|
147
|
+
finally:
|
|
148
|
+
console.print(f"\n[yellow]{translator.get('stopping_server')}[/yellow]")
|
|
149
|
+
server.stop()
|
|
150
|
+
console.print(f"[green]{translator.get('server_stopped')}[/green]")
|
|
151
|
+
|
|
152
|
+
return True
|
|
153
|
+
|
|
154
|
+
def preview_react_app(directory: str):
|
|
155
|
+
"""Previews an exported React application"""
|
|
156
|
+
|
|
157
|
+
# Verify that package.json exists
|
|
158
|
+
package_path = os.path.join(directory, "package.json")
|
|
159
|
+
if not os.path.exists(package_path):
|
|
160
|
+
console.print(f"[red]{translator.get('package_json_not_found')} {directory}[/red]")
|
|
161
|
+
return False
|
|
162
|
+
|
|
163
|
+
console.print(Panel(
|
|
164
|
+
f"""
|
|
165
|
+
{translator.get('preview_react_instructions')}:
|
|
166
|
+
|
|
167
|
+
1. {translator.get('navigate_to_directory')}:
|
|
168
|
+
[cyan]cd {directory}[/cyan]
|
|
169
|
+
|
|
170
|
+
2. {translator.get('install_dependencies')}:
|
|
171
|
+
[cyan]npm install[/cyan]
|
|
172
|
+
|
|
173
|
+
3. {translator.get('start_dev_server')}:
|
|
174
|
+
[cyan]npm start[/cyan]
|
|
175
|
+
|
|
176
|
+
{translator.get('app_will_open')} http://localhost:3000
|
|
177
|
+
""",
|
|
178
|
+
title=translator.get('react_preview'),
|
|
179
|
+
border_style="blue"
|
|
180
|
+
))
|
|
181
|
+
|
|
182
|
+
return True
|
|
183
|
+
|
|
184
|
+
def preview_react_native_app(directory: str):
|
|
185
|
+
"""Previews an exported React Native application"""
|
|
186
|
+
|
|
187
|
+
# Verify that package.json exists
|
|
188
|
+
package_path = os.path.join(directory, "package.json")
|
|
189
|
+
if not os.path.exists(package_path):
|
|
190
|
+
console.print(f"[red]{translator.get('package_json_not_found')} {directory}[/red]")
|
|
191
|
+
return False
|
|
192
|
+
|
|
193
|
+
console.print(Panel(
|
|
194
|
+
f"""
|
|
195
|
+
{translator.get('preview_react_native_instructions')}:
|
|
196
|
+
|
|
197
|
+
1. {translator.get('navigate_to_directory')}:
|
|
198
|
+
[cyan]cd {directory}[/cyan]
|
|
199
|
+
|
|
200
|
+
2. {translator.get('install_dependencies')}:
|
|
201
|
+
[cyan]npm install[/cyan]
|
|
202
|
+
|
|
203
|
+
3. {translator.get('for_android')}:
|
|
204
|
+
[cyan]npm run android[/cyan]
|
|
205
|
+
|
|
206
|
+
4. {translator.get('for_ios')}:
|
|
207
|
+
[cyan]npm run ios[/cyan]
|
|
208
|
+
|
|
209
|
+
5. {translator.get('start_metro')}:
|
|
210
|
+
[cyan]npm start[/cyan]
|
|
211
|
+
|
|
212
|
+
[yellow]{translator.get('react_native_note')}[/yellow]
|
|
213
|
+
""",
|
|
214
|
+
title=translator.get('react_native_preview'),
|
|
215
|
+
border_style="green"
|
|
216
|
+
))
|
|
217
|
+
|
|
218
|
+
return True
|
|
219
|
+
|
|
220
|
+
def preview_pyside6_app(directory: str):
|
|
221
|
+
"""Previews an exported PySide6 application"""
|
|
222
|
+
|
|
223
|
+
# Verify that main.py exists
|
|
224
|
+
main_path = os.path.join(directory, "main.py")
|
|
225
|
+
if not os.path.exists(main_path):
|
|
226
|
+
console.print(f"[red]{translator.get('main_py_not_found')} {directory}[/red]")
|
|
227
|
+
return False
|
|
228
|
+
|
|
229
|
+
console.print(Panel(
|
|
230
|
+
f"""
|
|
231
|
+
{translator.get('run_pyside6_app')}:
|
|
232
|
+
|
|
233
|
+
1. {translator.get('navigate_to_directory')}:
|
|
234
|
+
[cyan]cd {directory}[/cyan]
|
|
235
|
+
|
|
236
|
+
2. {translator.get('install_dependencies')}:
|
|
237
|
+
[cyan]pip install -r requirements.txt[/cyan]
|
|
238
|
+
|
|
239
|
+
3. {translator.get('run_application')}:
|
|
240
|
+
[cyan]python main.py[/cyan]
|
|
241
|
+
|
|
242
|
+
[yellow]{translator.get('pyside6_note')}[/yellow]
|
|
243
|
+
""",
|
|
244
|
+
title=translator.get('pyside6_preview'),
|
|
245
|
+
border_style="magenta"
|
|
246
|
+
))
|
|
247
|
+
|
|
248
|
+
return True
|
|
249
|
+
|
|
250
|
+
def preview_csharp_app(directory: str):
|
|
251
|
+
"""Previews an exported C# application"""
|
|
252
|
+
|
|
253
|
+
# Search for .csproj file
|
|
254
|
+
csproj_files = list(Path(directory).glob("*.csproj"))
|
|
255
|
+
if not csproj_files:
|
|
256
|
+
console.print(f"[red]{translator.get('csproj_not_found')} {directory}[/red]")
|
|
257
|
+
return False
|
|
258
|
+
|
|
259
|
+
csproj_file = csproj_files[0].name
|
|
260
|
+
|
|
261
|
+
console.print(Panel(
|
|
262
|
+
f"""
|
|
263
|
+
{translator.get('run_csharp_app')}:
|
|
264
|
+
|
|
265
|
+
1. {translator.get('navigate_to_directory')}:
|
|
266
|
+
[cyan]cd {directory}[/cyan]
|
|
267
|
+
|
|
268
|
+
2. {translator.get('restore_dependencies')}:
|
|
269
|
+
[cyan]dotnet restore[/cyan]
|
|
270
|
+
|
|
271
|
+
3. {translator.get('build_application')}:
|
|
272
|
+
[cyan]dotnet build[/cyan]
|
|
273
|
+
|
|
274
|
+
4. {translator.get('run_application')}:
|
|
275
|
+
[cyan]dotnet run[/cyan]
|
|
276
|
+
|
|
277
|
+
[yellow]{translator.get('dotnet_note')}[/yellow]
|
|
278
|
+
""",
|
|
279
|
+
title=translator.get('csharp_preview'),
|
|
280
|
+
border_style="red"
|
|
281
|
+
))
|
|
282
|
+
|
|
283
|
+
return True
|
|
284
|
+
|
|
285
|
+
def preview_kotlin_app(directory: str):
|
|
286
|
+
"""Previews an exported Kotlin application"""
|
|
287
|
+
|
|
288
|
+
# Verify that build.gradle.kts exists
|
|
289
|
+
gradle_path = os.path.join(directory, "build.gradle.kts")
|
|
290
|
+
if not os.path.exists(gradle_path):
|
|
291
|
+
console.print(f"[red]{translator.get('gradle_not_found')} {directory}[/red]")
|
|
292
|
+
return False
|
|
293
|
+
|
|
294
|
+
console.print(Panel(
|
|
295
|
+
f"""
|
|
296
|
+
{translator.get('run_kotlin_app')}:
|
|
297
|
+
|
|
298
|
+
1. {translator.get('navigate_to_directory')}:
|
|
299
|
+
[cyan]cd {directory}[/cyan]
|
|
300
|
+
|
|
301
|
+
2. {translator.get('for_desktop')}:
|
|
302
|
+
[cyan]./gradlew run[/cyan]
|
|
303
|
+
|
|
304
|
+
3. {translator.get('for_android')}:
|
|
305
|
+
[cyan]./gradlew installDebug[/cyan]
|
|
306
|
+
|
|
307
|
+
4. {translator.get('build_all_platforms')}:
|
|
308
|
+
[cyan]./gradlew build[/cyan]
|
|
309
|
+
|
|
310
|
+
[yellow]{translator.get('kotlin_note')}[/yellow]
|
|
311
|
+
""",
|
|
312
|
+
title=translator.get('kotlin_preview'),
|
|
313
|
+
border_style="yellow"
|
|
314
|
+
))
|
|
315
|
+
|
|
316
|
+
return True
|
|
317
|
+
|
|
318
|
+
def auto_detect_format(directory: str) -> str:
|
|
319
|
+
"""Automatically detects the format of the exported application"""
|
|
320
|
+
|
|
321
|
+
if os.path.exists(os.path.join(directory, "index.html")):
|
|
322
|
+
return "html"
|
|
323
|
+
elif os.path.exists(os.path.join(directory, "package.json")):
|
|
324
|
+
# Read package.json to distinguish between React and React Native
|
|
325
|
+
try:
|
|
326
|
+
import json
|
|
327
|
+
with open(os.path.join(directory, "package.json"), 'r') as f:
|
|
328
|
+
package_data = json.load(f)
|
|
329
|
+
|
|
330
|
+
if "react-native" in package_data.get("dependencies", {}):
|
|
331
|
+
return "react-native"
|
|
332
|
+
else:
|
|
333
|
+
return "react"
|
|
334
|
+
except:
|
|
335
|
+
return "react"
|
|
336
|
+
elif os.path.exists(os.path.join(directory, "main.py")):
|
|
337
|
+
return "pyside6"
|
|
338
|
+
elif list(Path(directory).glob("*.csproj")):
|
|
339
|
+
return "csharp"
|
|
340
|
+
elif os.path.exists(os.path.join(directory, "build.gradle.kts")):
|
|
341
|
+
return "kotlin"
|
|
342
|
+
else:
|
|
343
|
+
return "unknown"
|
|
344
|
+
|
|
345
|
+
def preview_app(directory: str, format_name: str = None, auto_open: bool = True, port: int = 8000):
|
|
346
|
+
"""Previews an exported application"""
|
|
347
|
+
|
|
348
|
+
if not os.path.exists(directory):
|
|
349
|
+
console.print(f"[red]{translator.get('directory_not_exists').format(directory=directory)}[/red]")
|
|
350
|
+
return False
|
|
351
|
+
|
|
352
|
+
# Automatically detect format if not specified
|
|
353
|
+
if format_name is None:
|
|
354
|
+
format_name = auto_detect_format(directory)
|
|
355
|
+
|
|
356
|
+
if format_name == "unknown":
|
|
357
|
+
console.print(f"[red]{translator.get('format_not_detected').format(directory=directory)}[/red]")
|
|
358
|
+
return False
|
|
359
|
+
|
|
360
|
+
console.print(f"[cyan]{translator.get('detected_format')}: {format_name}[/cyan]")
|
|
361
|
+
|
|
362
|
+
# Call the corresponding previewer
|
|
363
|
+
preview_functions = {
|
|
364
|
+
"html": lambda: preview_html_app(directory, auto_open, port),
|
|
365
|
+
"react": lambda: preview_react_app(directory),
|
|
366
|
+
"react-native": lambda: preview_react_native_app(directory),
|
|
367
|
+
"pyside6": lambda: preview_pyside6_app(directory),
|
|
368
|
+
"csharp": lambda: preview_csharp_app(directory),
|
|
369
|
+
"kotlin": lambda: preview_kotlin_app(directory)
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
preview_function = preview_functions.get(format_name)
|
|
373
|
+
if preview_function:
|
|
374
|
+
return preview_function()
|
|
375
|
+
else:
|
|
376
|
+
console.print(f"[red]{translator.get('format_not_supported').format(format=format_name)}[/red]")
|
|
377
|
+
return False
|
|
378
|
+
|
|
379
|
+
if __name__ == "__main__":
|
|
380
|
+
import argparse
|
|
381
|
+
import sys
|
|
382
|
+
|
|
383
|
+
# First, create a simple parser just to extract the language
|
|
384
|
+
pre_parser = argparse.ArgumentParser(add_help=False)
|
|
385
|
+
pre_parser.add_argument("--lang", "-l", choices=["en", "es"], default="en")
|
|
386
|
+
|
|
387
|
+
# Parse known args to get language without triggering errors on other args
|
|
388
|
+
pre_args, _ = pre_parser.parse_known_args()
|
|
389
|
+
|
|
390
|
+
# Set language before creating the main parser and save preference if specified
|
|
391
|
+
# If --lang is in sys.argv, it means the user explicitly specified it
|
|
392
|
+
save_preference = "--lang" in sys.argv or "-l" in sys.argv
|
|
393
|
+
translator.set_language(pre_args.lang, save=save_preference)
|
|
394
|
+
|
|
395
|
+
# Check for help before parsing arguments to show Rich-styled help
|
|
396
|
+
if '-h' in sys.argv or '--help' in sys.argv:
|
|
397
|
+
# Show banner
|
|
398
|
+
console.print(Panel(
|
|
399
|
+
Text("Dars Preview", style="bold cyan", justify="center"),
|
|
400
|
+
subtitle=translator.get('preview_description'),
|
|
401
|
+
border_style="cyan"
|
|
402
|
+
))
|
|
403
|
+
|
|
404
|
+
# Show usage
|
|
405
|
+
console.print(f"\n[bold cyan]{translator.get('usage')}:[/bold cyan]")
|
|
406
|
+
console.print("preview.py [-h] [--format FORMAT] [--no-open] [--port PORT] [--lang {en,es}] directory")
|
|
407
|
+
|
|
408
|
+
# Show positional arguments
|
|
409
|
+
console.print(f"\n[bold cyan]{translator.get('positional_arguments')}:[/bold cyan]")
|
|
410
|
+
pos_table = Table(show_header=False, box=None, padding=(0, 2, 0, 0), expand=True)
|
|
411
|
+
pos_table.add_column("Argument", style="bold green", width=20, no_wrap=True)
|
|
412
|
+
pos_table.add_column("Description", style="dim white", overflow="fold")
|
|
413
|
+
pos_table.add_row("directory", translator.get('directory_help'))
|
|
414
|
+
console.print(pos_table)
|
|
415
|
+
|
|
416
|
+
# Show options
|
|
417
|
+
console.print(f"\n[bold cyan]{translator.get('options')}:[/bold cyan]")
|
|
418
|
+
opt_table = Table(show_header=False, box=None, padding=(0, 2, 0, 0), expand=True)
|
|
419
|
+
opt_table.add_column("Option", style="bold green", width=30, no_wrap=True)
|
|
420
|
+
opt_table.add_column("Description", style="dim white", overflow="fold")
|
|
421
|
+
opt_table.add_row("-h, --help", "show this help message and exit")
|
|
422
|
+
opt_table.add_row("--format FORMAT, -f FORMAT", translator.get('format_help'))
|
|
423
|
+
opt_table.add_row("--no-open", translator.get('no_open_help'))
|
|
424
|
+
opt_table.add_row("--port PORT, -p PORT", translator.get('port_help'))
|
|
425
|
+
opt_table.add_row("--lang {en,es}, -l {en,es}", translator.get('lang_help'))
|
|
426
|
+
console.print(opt_table)
|
|
427
|
+
|
|
428
|
+
sys.exit(0)
|
|
429
|
+
|
|
430
|
+
# Now create the full parser with translated help text
|
|
431
|
+
parser = argparse.ArgumentParser(description=translator.get('preview_description'))
|
|
432
|
+
parser.add_argument("directory", help=translator.get('directory_help'))
|
|
433
|
+
parser.add_argument("--format", "-f", help=translator.get('format_help'))
|
|
434
|
+
parser.add_argument("--no-open", action="store_true", help=translator.get('no_open_help'))
|
|
435
|
+
parser.add_argument("--port", "-p", type=int, default=8000, help=translator.get('port_help'))
|
|
436
|
+
parser.add_argument("--lang", "-l", choices=["en", "es"], default="en", help=translator.get('lang_help'))
|
|
437
|
+
|
|
438
|
+
args = parser.parse_args()
|
|
439
|
+
|
|
440
|
+
success = preview_app(
|
|
441
|
+
args.directory,
|
|
442
|
+
args.format,
|
|
443
|
+
not args.no_open,
|
|
444
|
+
args.port
|
|
445
|
+
)
|
|
446
|
+
|
|
447
|
+
sys.exit(0 if success else 1)
|
|
448
|
+
|