dars-framework 1.1.8__tar.gz → 1.2.0__tar.gz
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_framework-1.1.8 → dars_framework-1.2.0}/MANIFEST.in +2 -1
- {dars_framework-1.1.8/dars_framework.egg-info → dars_framework-1.2.0}/PKG-INFO +2 -1
- {dars_framework-1.1.8 → dars_framework-1.2.0}/README.md +220 -165
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/all.py +2 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/main.py +76 -50
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/preview.py +12 -1
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/checkbox.py +3 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/container.py +3 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/input.py +3 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/page.py +2 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/radiobutton.py +3 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/select.py +3 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/text.py +3 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/config.py +1 -1
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/app.py +2 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/component.py +102 -0
- dars_framework-1.2.0/dars/core/state.py +255 -0
- dars_framework-1.2.0/dars/docs/state_management.md +57 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/html_css_js.py +265 -29
- dars_framework-1.2.0/dars/js_lib.py +133 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/scripts/dscript.py +2 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/scripts/script.py +6 -5
- dars_framework-1.2.0/dars/security.py +133 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/index.html +72 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/lib/dars.min.js +131 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/runtime_css.css +676 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/runtime_dars.js +349 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/script.js +1 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/snapshot.json +1 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/vdom_tree.js +1 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/version.txt +1 -0
- dars_framework-1.2.0/dars/templates/examples/advanced/dState/state_mods_demo.py +71 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/HelloWorld/hello_world.py +1 -1
- dars_framework-1.2.0/dars/templates/html/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/version.py +2 -2
- {dars_framework-1.1.8 → dars_framework-1.2.0/dars_framework.egg-info}/PKG-INFO +2 -1
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/SOURCES.txt +14 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/requires.txt +1 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/pyproject.toml +9 -5
- {dars_framework-1.1.8 → dars_framework-1.2.0}/LICENSE +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/hot_reload.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/translations.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/accordion.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/card.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/modal.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/navbar.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/table.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/tabs.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/button.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/datepicker.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/image.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/link.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/markdown.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/progressbar.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/slider.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/spinner.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/textarea.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/tooltip.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/layout/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/layout/anchor.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/layout/flex.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/layout/grid.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/events.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/properties.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/apps_test/health_check.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/run_tests.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_advanced_components.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_basic_components.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_core_and_cli.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_layout_components.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_version_check.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/app.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/cli.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/components.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/custom_components.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/events.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/exporters.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/getting_started.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/index.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/scripts.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/base.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/OLD/html_css_js_OLD4.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/OLD/html_css_js_old.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/OLD/html_css_js_old2.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/vdom.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/scripts/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/__pycache__/__init__.cpython-311.pyc +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/README.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/__pycache__/dynamic_event_demo.cpython-311.pyc +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/Modal_Demo/advanced_modal_demo.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/SimpleDashboard/dashboard.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/SimpleModermWeb/modern_web_app.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/VariousComponents/all_components_demo.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/__init__.py +0 -0
- /dars_framework-1.1.8/dars/templates/examples/basic/__init__.py → /dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/styles.css +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Forms/form_components.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Forms/simple_form.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Layouts/flex_layout_responsive.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Layouts/grid_layout_responsive.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Layouts/layout_multipage_demo.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Multipage/multipage_example.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/PWA/icon-192x192.png +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/PWA/icon-512x512.png +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/PWA/pwa_custom_icons.py +0 -0
- {dars_framework-1.1.8/dars/templates/examples/markdown → dars_framework-1.2.0/dars/templates/examples/basic}/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/demo/__pycache__/complete_app.cpython-311.pyc +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/demo/complete_app.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/markdown/MarkdownTemplate/README.md +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/markdown/MarkdownTemplate/markdown_template.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/markdown/MarkdownTemplate/other_docs.md +0 -0
- {dars_framework-1.1.8/dars/templates/html → dars_framework-1.2.0/dars/templates/examples/markdown}/__init__.py +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/dependency_links.txt +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/entry_points.txt +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/top_level.txt +0 -0
- {dars_framework-1.1.8 → dars_framework-1.2.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: dars_framework
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.2.0
|
|
4
4
|
Summary: Dars is a Python UI framework for building modern, interactive web apps with only Python code. Write your interface in Python, export it to static HTML/CSS/JS, and deploy anywhere.
|
|
5
5
|
Author-email: ztamdev <zondax2009@gmail.com>
|
|
6
6
|
License: MIT
|
|
@@ -11,4 +11,5 @@ Requires-Dist: uvicorn==0.35.0
|
|
|
11
11
|
Requires-Dist: fastapi==0.116.1
|
|
12
12
|
Requires-Dist: markdown2==2.5.4
|
|
13
13
|
Requires-Dist: requests==2.32.5
|
|
14
|
+
Requires-Dist: rjsmin==1.2.5
|
|
14
15
|
Dynamic: license-file
|
|
@@ -1,165 +1,220 @@
|
|
|
1
|
-
<h1 align="center">Dars Framework</h1>
|
|
2
|
-
|
|
3
|
-
<p align="center">
|
|
4
|
-
<img src="./Dars-logo.png" alt="Dars Framework Logo" width="
|
|
5
|
-
</p>
|
|
6
|
-
|
|
7
|
-
<p align="center">
|
|
8
|
-
<em>Dars is a Python UI framework for building modern, interactive web apps with Python code. Write your interface in Python, export it to static HTML/CSS/JS, and deploy anywhere.</em>
|
|
9
|
-
</p>
|
|
10
|
-
|
|
11
|
-
```bash
|
|
12
|
-
pip install dars-framework
|
|
13
|
-
```
|
|
14
|
-
|
|
15
|
-
> Some Javascript or frontend stack required.
|
|
16
|
-
|
|
17
|
-
Try dars without installing nothing just visit the [Dars Playground](https://dars-playground.vercel.app/)
|
|
18
|
-
|
|
19
|
-
## How It Works
|
|
20
|
-
- Build your UI using Python classes and components (like Text, Button, Container, Page, etc).
|
|
21
|
-
- Preview instantly with hot-reload using `app.rTimeCompile()`.
|
|
22
|
-
- Export your app to static web files with a single CLI command.
|
|
23
|
-
- Use multipage, layouts, scripts, and more—see docs for advanced features.
|
|
24
|
-
- For mor information visit the [Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html)
|
|
25
|
-
|
|
26
|
-
## Quick Example: Your First App
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
-
|
|
142
|
-
-
|
|
143
|
-
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
```
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
```bash
|
|
157
|
-
|
|
158
|
-
```
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
```bash
|
|
163
|
-
|
|
164
|
-
```
|
|
165
|
-
|
|
1
|
+
<h1 align="center">Dars Framework</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<img src="./Dars-logo.png" alt="Dars Framework Logo" width="200" />
|
|
5
|
+
</p>
|
|
6
|
+
|
|
7
|
+
<p align="center">
|
|
8
|
+
<em>Dars is a Python UI framework for building modern, interactive web apps with Python code. Write your interface in Python, export it to static HTML/CSS/JS, and deploy anywhere.</em>
|
|
9
|
+
</p>
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install dars-framework
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
> Some Javascript or frontend stack required.
|
|
16
|
+
|
|
17
|
+
Try dars without installing nothing just visit the [Dars Playground](https://dars-playground.vercel.app/)
|
|
18
|
+
|
|
19
|
+
## How It Works
|
|
20
|
+
- Build your UI using Python classes and components (like Text, Button, Container, Page, etc).
|
|
21
|
+
- Preview instantly with hot-reload using `app.rTimeCompile()`.
|
|
22
|
+
- Export your app to static web files with a single CLI command.
|
|
23
|
+
- Use multipage, layouts, scripts, and more—see docs for advanced features.
|
|
24
|
+
- For mor information visit the [Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html)
|
|
25
|
+
|
|
26
|
+
## Quick Example: Your First App
|
|
27
|
+
```python
|
|
28
|
+
from dars.all import *
|
|
29
|
+
|
|
30
|
+
app = App(title="Hello World", theme="dark")
|
|
31
|
+
# Crear componentes
|
|
32
|
+
index = Page(
|
|
33
|
+
Text(
|
|
34
|
+
text="Hello World",
|
|
35
|
+
style={
|
|
36
|
+
'font-size': '48px',
|
|
37
|
+
'color': '#2c3e50',
|
|
38
|
+
'margin-bottom': '20px',
|
|
39
|
+
'font-weight': 'bold',
|
|
40
|
+
'text-align': 'center'
|
|
41
|
+
}
|
|
42
|
+
),
|
|
43
|
+
Text(
|
|
44
|
+
text="Hello World",
|
|
45
|
+
style={
|
|
46
|
+
'font-size': '20px',
|
|
47
|
+
'color': '#7f8c8d',
|
|
48
|
+
'margin-bottom': '40px',
|
|
49
|
+
'text-align': 'center'
|
|
50
|
+
}
|
|
51
|
+
),
|
|
52
|
+
|
|
53
|
+
Button(
|
|
54
|
+
text="Click Me!",
|
|
55
|
+
on_click= dScript("alert('Hello World')"),
|
|
56
|
+
on_mouse_enter=dScript("this.style.backgroundColor = '#2980b9';"),
|
|
57
|
+
on_mouse_leave=dScript("this.style.backgroundColor = '#3498db';"),
|
|
58
|
+
style={
|
|
59
|
+
'background-color': '#3498db',
|
|
60
|
+
'color': 'white',
|
|
61
|
+
'padding': '15px 30px',
|
|
62
|
+
'border': 'none',
|
|
63
|
+
'border-radius': '8px',
|
|
64
|
+
'font-size': '18px',
|
|
65
|
+
'cursor': 'pointer',
|
|
66
|
+
'transition': 'background-color 0.3s'
|
|
67
|
+
}
|
|
68
|
+
),
|
|
69
|
+
style={
|
|
70
|
+
'display': 'flex',
|
|
71
|
+
'flex-direction': 'column',
|
|
72
|
+
'align-items': 'center',
|
|
73
|
+
'justify-content': 'center',
|
|
74
|
+
'min-height': '100vh',
|
|
75
|
+
'background-color': '#f0f2f5',
|
|
76
|
+
'font-family': 'Arial, sans-serif'
|
|
77
|
+
}
|
|
78
|
+
)
|
|
79
|
+
index.attr()
|
|
80
|
+
app.add_page("index", index, title="Hello World", index=True)
|
|
81
|
+
|
|
82
|
+
if __name__ == "__main__":
|
|
83
|
+
app.rTimeCompile()
|
|
84
|
+
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Reactivity and State System
|
|
90
|
+
|
|
91
|
+
**Dars Framework** includes a built-in **reactive state system** (`dState` / `cState`) that allows dynamic and modular DOM updates directly from Python.
|
|
92
|
+
It enables fully event-driven interfaces without requiring manual JavaScript.
|
|
93
|
+
|
|
94
|
+
### Key Concepts
|
|
95
|
+
|
|
96
|
+
* **`dState(name, component, states)`**
|
|
97
|
+
Creates a reactive state controller bound to a specific component and a list of possible states.
|
|
98
|
+
|
|
99
|
+
* **`cState(idx, mods=[...])`**
|
|
100
|
+
Defines rules (modifications) that are automatically applied when entering a specific state.
|
|
101
|
+
|
|
102
|
+
* **`Mod` Helpers**
|
|
103
|
+
A compact way to modify DOM elements on state changes: `inc`, `dec`, `set`, `toggle_class`, `append_text`, `prepend_text`, `goto`, and more.
|
|
104
|
+
|
|
105
|
+
* **Deferred Mutations**
|
|
106
|
+
Using `component.attr(..., defer=True)` or `component.mod(...)` inside a `cComp=True` state defers HTML updates until an event occurs, preventing authoring-time mutations.
|
|
107
|
+
|
|
108
|
+
### Example Template
|
|
109
|
+
|
|
110
|
+
A complete example demonstrating `dState`, `cState`, `Mod`, and deferred updates is available [here](https://github.com/ZtaMDev/Dars-Framework/blob/CrystalMain/dars/templates/examples/advanced/dState/state_mods_demo.py)
|
|
111
|
+
|
|
112
|
+
<img width="384" height="187" alt="imagen" src="https://github.com/user-attachments/assets/7750ee7f-768f-48da-94df-2fa00339a99c" /> <img width="361" height="215" alt="imagen" src="https://github.com/user-attachments/assets/9b8a3e67-2424-49b4-aee0-9f1c0f747d66" />
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
### Features
|
|
117
|
+
|
|
118
|
+
* Reactive Mod system with compact `Mod` helpers
|
|
119
|
+
* Unified event model — any component can use `on_*` props (`on_click`, `on_input`, `on_change`, etc.)
|
|
120
|
+
* Deferred rendering for safer, predictable state transitions (`cComp=True`)
|
|
121
|
+
* Navigation between states using `goto`, including relative moves (`'+1'`, `'-1'`)
|
|
122
|
+
* Consistent, event-time mutation flow for reliable behavior
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## CLI Usage
|
|
127
|
+
| Command | What it does |
|
|
128
|
+
|-----------------------------------------|--------------------------------------------|
|
|
129
|
+
| `dars export my_app.py --format html` | Export app to HTML/CSS/JS in `./my_app_web` |
|
|
130
|
+
| `dars preview ./my_app_web` | Preview exported app locally |
|
|
131
|
+
| `dars init my_project` | Create a new Dars project (also creates dars.config.json) |
|
|
132
|
+
| `dars init --update` | Create/Update dars.config.json in current dir |
|
|
133
|
+
| `dars build` | Build using dars.config.json (entry/outdir/format) |
|
|
134
|
+
| `dars config validate` | Validate dars.config.json and print report |
|
|
135
|
+
| `dars info my_app.py` | Show info about your app |
|
|
136
|
+
| `dars formats` | List supported export formats |
|
|
137
|
+
| `dars --help` | Show help and all CLI options |
|
|
138
|
+
|
|
139
|
+
## More
|
|
140
|
+
|
|
141
|
+
- Visit dars [official website](https://ztamdev.github.io/Dars-Framework/)
|
|
142
|
+
- Visit the dars official [Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html) now on separate website.
|
|
143
|
+
- Try dars without installing nothing just visit the [Dars Playground](https://dars-playground.vercel.app/)
|
|
144
|
+
|
|
145
|
+
## Local Execution and Live Preview
|
|
146
|
+
|
|
147
|
+
To test your app locally before exporting, use the hot-reload preview from any Python file that defines your app:
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
if __name__ == "__main__":
|
|
151
|
+
app.rTimeCompile()
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Then run your file directly:
|
|
155
|
+
|
|
156
|
+
```bash
|
|
157
|
+
python my_app.py
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
This will start a local server at http://localhost:8000 so you can view your app in the browser—no manual export needed. You can change the port with:
|
|
161
|
+
|
|
162
|
+
```bash
|
|
163
|
+
python my_app.py --port 8088
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
You can also use the CLI preview command on an exported app:
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
dars preview ./my_exported_app
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
This will start a local server at http://localhost:8000 to view your exported app in the browser.
|
|
175
|
+
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
## Project Configuration (dars.config.json)
|
|
179
|
+
|
|
180
|
+
Dars can read build/export settings from a `dars.config.json` at your project root. It is created automatically by `dars init`, and you can add it to existing projects with `dars init --update`.
|
|
181
|
+
|
|
182
|
+
Example default:
|
|
183
|
+
|
|
184
|
+
```json
|
|
185
|
+
{
|
|
186
|
+
"entry": "main.py",
|
|
187
|
+
"format": "html",
|
|
188
|
+
"outdir": "dist",
|
|
189
|
+
"publicDir": null,
|
|
190
|
+
"include": [],
|
|
191
|
+
"exclude": ["**/__pycache__", ".git", ".venv", "node_modules"],
|
|
192
|
+
"bundle": false
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
- `entry`: Python entry file. Used by `dars build` and `dars export config`.
|
|
197
|
+
- `format`: Export format. Currently only `html` is supported.
|
|
198
|
+
- `outdir`: Output directory. Used by `dars build` and default for `dars export` when not overridden.
|
|
199
|
+
- `publicDir`: Folder (e.g., `public/` or `assets/`) copied into the output. If null, it is autodetected.
|
|
200
|
+
- `include`/`exclude`: Basic filters for copying from `publicDir`.
|
|
201
|
+
- `bundle`: Reserved for future use. CLI exports and build already bundle appropriately.
|
|
202
|
+
|
|
203
|
+
Validate your config:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
dars config validate
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
Build using config:
|
|
210
|
+
|
|
211
|
+
```bash
|
|
212
|
+
dars build
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
Export using the config entry and outdir:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
dars export config --format html
|
|
219
|
+
```
|
|
220
|
+
|
|
@@ -53,6 +53,7 @@ from dars.dars_tests import *
|
|
|
53
53
|
from dars.dars_tests.run_tests import run_app_tests, run_unit_tests, main
|
|
54
54
|
# CLI (optional, for advanced usage)
|
|
55
55
|
# from dars.cli.main import main as dars_cli_main
|
|
56
|
+
from dars.core.state import dState, Mod
|
|
56
57
|
|
|
57
58
|
__all__ = [
|
|
58
59
|
'App', 'Component', 'EventManager',
|
|
@@ -64,4 +65,5 @@ __all__ = [
|
|
|
64
65
|
'EventTypes', 'EventHandler', 'EventEmitter', 'EventManager', 'Markdown',
|
|
65
66
|
'__version__',
|
|
66
67
|
'run_app_tests', 'run_unit_tests', 'main',
|
|
68
|
+
'dState', 'Mod',
|
|
67
69
|
]
|
|
@@ -291,6 +291,16 @@ class DarsExporter:
|
|
|
291
291
|
progress.update(task2, advance=80)
|
|
292
292
|
|
|
293
293
|
if success:
|
|
294
|
+
# Minification step for bundle
|
|
295
|
+
try:
|
|
296
|
+
from dars.security import minify_output_dir
|
|
297
|
+
task3 = progress.add_task("Applying minification (bundle)", total=100)
|
|
298
|
+
# Run minification
|
|
299
|
+
count = minify_output_dir(output_path)
|
|
300
|
+
progress.update(task3, completed=100)
|
|
301
|
+
except Exception:
|
|
302
|
+
# Do not fail export on minification errors
|
|
303
|
+
pass
|
|
294
304
|
progress.update(task1, completed=100)
|
|
295
305
|
progress.update(task2, completed=100)
|
|
296
306
|
|
|
@@ -527,14 +537,12 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
527
537
|
"""Creates the command line argument parser"""
|
|
528
538
|
parser = argparse.ArgumentParser(
|
|
529
539
|
description=translator.get('main_description'),
|
|
530
|
-
formatter_class=
|
|
531
|
-
epilog=""
|
|
540
|
+
formatter_class=argparse.HelpFormatter,
|
|
541
|
+
epilog=""
|
|
532
542
|
)
|
|
533
543
|
parser.add_argument('-v', '--version', action='store_true', help='Show Dars version and release link')
|
|
534
544
|
|
|
535
|
-
#
|
|
536
|
-
parser.add_argument('--lang', '-l', choices=['en', 'es'], default='en',
|
|
537
|
-
help=translator.get('lang_help'))
|
|
545
|
+
# English-only: no language flag
|
|
538
546
|
|
|
539
547
|
subparsers = parser.add_subparsers(dest='command', help=translator.get('available_commands'))
|
|
540
548
|
|
|
@@ -600,10 +608,11 @@ def create_parser() -> argparse.ArgumentParser:
|
|
|
600
608
|
cfg_subparsers = config_parser.add_subparsers(dest='config_command')
|
|
601
609
|
cfg_validate = cfg_subparsers.add_parser('validate', help='Validate dars.config.json in a project')
|
|
602
610
|
cfg_validate.add_argument('--project', '-p', default='.', help='Project root (default: .)')
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
611
|
+
|
|
612
|
+
# Dev command (run entry in dev mode)
|
|
613
|
+
dev_parser = subparsers.add_parser('dev', help='Run the configured entry file in development mode')
|
|
614
|
+
dev_parser.add_argument('--project', '-p', default='.', help='Project root where dars.config.json resides (default: .)')
|
|
615
|
+
# English-only: no language option on subparsers
|
|
607
616
|
|
|
608
617
|
return parser
|
|
609
618
|
|
|
@@ -725,42 +734,13 @@ def list_templates_detailed():
|
|
|
725
734
|
console.print(table)
|
|
726
735
|
def main():
|
|
727
736
|
"""Main CLI function"""
|
|
728
|
-
#
|
|
729
|
-
# If --lang is not specified, it will use the saved preference or default to English
|
|
730
|
-
for i, arg in enumerate(sys.argv):
|
|
731
|
-
if arg in ['--lang', '-l'] and i + 1 < len(sys.argv):
|
|
732
|
-
lang = sys.argv[i + 1]
|
|
733
|
-
if lang in ['en', 'es']:
|
|
734
|
-
# Save the language preference when explicitly specified
|
|
735
|
-
translator.set_language(lang, save=True)
|
|
737
|
+
# English-only: no language parameter pre-scan
|
|
736
738
|
|
|
737
|
-
# Intercept help before parsing arguments
|
|
739
|
+
# Intercept help before parsing arguments - print simple help without panels
|
|
738
740
|
if len(sys.argv) == 1 or '-h' in sys.argv or '--help' in sys.argv:
|
|
739
741
|
parser = create_parser()
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
console.print(Panel(
|
|
743
|
-
Text("Dars Exporter", style="bold cyan", justify="center"),
|
|
744
|
-
subtitle=translator.get('main_description'),
|
|
745
|
-
border_style="cyan"
|
|
746
|
-
))
|
|
747
|
-
|
|
748
|
-
# If it's general help
|
|
749
|
-
if len(sys.argv) == 1 or (len(sys.argv) == 2 and (sys.argv[1] == '-h' or sys.argv[1] == '--help')):
|
|
750
|
-
RichHelpFormatter.rich_print_help(parser)
|
|
751
|
-
return
|
|
752
|
-
|
|
753
|
-
# If it's help for a subcommand
|
|
754
|
-
if len(sys.argv) > 2 and (sys.argv[2] == '-h' or sys.argv[2] == '--help'):
|
|
755
|
-
subcommand = sys.argv[1]
|
|
756
|
-
# Get the corresponding subparser
|
|
757
|
-
subparsers_actions = [action for action in parser._actions
|
|
758
|
-
if isinstance(action, argparse._SubParsersAction)]
|
|
759
|
-
for subparsers_action in subparsers_actions:
|
|
760
|
-
for choice, subparser in subparsers_action.choices.items():
|
|
761
|
-
if choice == subcommand:
|
|
762
|
-
RichHelpFormatter.rich_print_help(subparser)
|
|
763
|
-
return
|
|
742
|
+
parser.print_help()
|
|
743
|
+
return
|
|
764
744
|
|
|
765
745
|
# Continue with normal flow if not help
|
|
766
746
|
parser = create_parser()
|
|
@@ -775,12 +755,7 @@ def main():
|
|
|
775
755
|
print_version_info()
|
|
776
756
|
sys.exit(0)
|
|
777
757
|
|
|
778
|
-
#
|
|
779
|
-
console.print(Panel(
|
|
780
|
-
Text("Dars Exporter", style="bold cyan", justify="center"),
|
|
781
|
-
subtitle=translator.get('cli_subtitle'),
|
|
782
|
-
border_style="cyan"
|
|
783
|
-
))
|
|
758
|
+
# No banner for normal commands; keep output minimal
|
|
784
759
|
|
|
785
760
|
exporter = DarsExporter()
|
|
786
761
|
|
|
@@ -825,6 +800,7 @@ def main():
|
|
|
825
800
|
console.print(f"[red]{translator.get('error_output_create')}: {outdir} -> {e}[/red]")
|
|
826
801
|
sys.exit(1)
|
|
827
802
|
|
|
803
|
+
ensure_dars_lib(project_root)
|
|
828
804
|
success = exporter.export_app(app, args.format, outdir, args.preview)
|
|
829
805
|
sys.exit(0 if success else 1)
|
|
830
806
|
|
|
@@ -849,6 +825,7 @@ def main():
|
|
|
849
825
|
project_root = os.path.abspath(target_dir)
|
|
850
826
|
os.makedirs(project_root, exist_ok=True)
|
|
851
827
|
write_default_config(project_root, overwrite=False)
|
|
828
|
+
ensure_dars_lib(project_root)
|
|
852
829
|
console.print("[green]✔ dars.config.json created/updated[/green]")
|
|
853
830
|
elif not args.name:
|
|
854
831
|
console.print("[red]Error: Project name is required[/red]")
|
|
@@ -885,6 +862,7 @@ def main():
|
|
|
885
862
|
console.print(f"[red]{translator.get('error_output_create')}: {outdir} -> {e}[/red]")
|
|
886
863
|
sys.exit(1)
|
|
887
864
|
|
|
865
|
+
ensure_dars_lib(project_root)
|
|
888
866
|
app = exporter.load_app_from_file(entry)
|
|
889
867
|
if app is None:
|
|
890
868
|
sys.exit(1)
|
|
@@ -1013,9 +991,57 @@ def main():
|
|
|
1013
991
|
RichHelpFormatter.rich_print_help(subparsers_action.choices['config'])
|
|
1014
992
|
return
|
|
1015
993
|
|
|
994
|
+
elif args.command == 'dev':
|
|
995
|
+
# Resolve project and config
|
|
996
|
+
project_root = os.path.abspath(getattr(args, 'project', '.'))
|
|
997
|
+
cfg, found = load_config(project_root)
|
|
998
|
+
if not found:
|
|
999
|
+
console.print("[yellow][Dars] Warning: dars.config.json not found. Run 'dars init --update' to create it.[/yellow]")
|
|
1000
|
+
resolved = resolve_paths(cfg, project_root)
|
|
1001
|
+
entry = resolved.get('entry_abs') or os.path.join(project_root, cfg.get('entry', 'main.py'))
|
|
1002
|
+
|
|
1003
|
+
if not os.path.exists(entry):
|
|
1004
|
+
console.print(f"[red]{translator.get('error_entry_not_found_in_config')}: {entry}[/red]")
|
|
1005
|
+
console.print(f"[yellow]{translator.get('edit_config_hint')}[/yellow]")
|
|
1006
|
+
sys.exit(1)
|
|
1007
|
+
|
|
1008
|
+
# Ensure dars.min.js exists in project
|
|
1009
|
+
ensure_dars_lib(project_root)
|
|
1010
|
+
# Run entry in development mode (the entry typically calls app.rTimeCompile())
|
|
1011
|
+
import subprocess
|
|
1012
|
+
process = None
|
|
1013
|
+
try:
|
|
1014
|
+
console.print(f"[cyan]Running dev: {entry}[/cyan]")
|
|
1015
|
+
process = subprocess.Popen([sys.executable, entry], cwd=os.path.dirname(entry))
|
|
1016
|
+
process.wait()
|
|
1017
|
+
sys.exit(process.returncode or 0)
|
|
1018
|
+
except KeyboardInterrupt:
|
|
1019
|
+
if process:
|
|
1020
|
+
process.terminate()
|
|
1021
|
+
process.wait()
|
|
1022
|
+
sys.exit(0)
|
|
1023
|
+
except Exception as e:
|
|
1024
|
+
console.print(f"[red]Failed to start dev process: {e}[/red]")
|
|
1025
|
+
sys.exit(1)
|
|
1026
|
+
|
|
1016
1027
|
else:
|
|
1017
|
-
#
|
|
1018
|
-
|
|
1028
|
+
# Fallback: print plain help
|
|
1029
|
+
parser.print_help()
|
|
1030
|
+
|
|
1031
|
+
# Utility: ensure lib/dars.min.js exists at project root (no overwrite)
|
|
1032
|
+
def ensure_dars_lib(project_root: str):
|
|
1033
|
+
try:
|
|
1034
|
+
os.makedirs(os.path.join(project_root, 'lib'), exist_ok=True)
|
|
1035
|
+
dest = os.path.join(project_root, 'lib', 'dars.min.js')
|
|
1036
|
+
if not os.path.exists(dest):
|
|
1037
|
+
try:
|
|
1038
|
+
from dars.js_lib import DARS_MIN_JS
|
|
1039
|
+
with open(dest, 'w', encoding='utf-8') as fdst:
|
|
1040
|
+
fdst.write(DARS_MIN_JS)
|
|
1041
|
+
except Exception:
|
|
1042
|
+
pass
|
|
1043
|
+
except Exception:
|
|
1044
|
+
pass
|
|
1019
1045
|
|
|
1020
1046
|
if __name__ == "__main__":
|
|
1021
1047
|
main()
|
|
@@ -7,6 +7,7 @@ import os
|
|
|
7
7
|
import sys
|
|
8
8
|
import webbrowser
|
|
9
9
|
import http.server
|
|
10
|
+
import mimetypes
|
|
10
11
|
import socketserver
|
|
11
12
|
import threading
|
|
12
13
|
import time
|
|
@@ -31,8 +32,11 @@ class PreviewServer:
|
|
|
31
32
|
self.send_header('Access-Control-Allow-Origin', '*')
|
|
32
33
|
super().end_headers()
|
|
33
34
|
def guess_type(self, path):
|
|
34
|
-
|
|
35
|
+
# Ensure correct MIME types for JS modules and JSON
|
|
36
|
+
if path.endswith('.mjs') or path.endswith('.js'):
|
|
35
37
|
return 'application/javascript'
|
|
38
|
+
if path.endswith('.json'):
|
|
39
|
+
return 'application/json'
|
|
36
40
|
return super().guess_type(path)
|
|
37
41
|
def log_request(self, code='-', size='-'):
|
|
38
42
|
"""Silencia logs para peticiones frecuentes del hot-reload (version.txt)."""
|
|
@@ -58,6 +62,13 @@ class PreviewServer:
|
|
|
58
62
|
os.chdir(self.directory)
|
|
59
63
|
|
|
60
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
|
|
61
72
|
handler = self.DarsRequestHandler
|
|
62
73
|
self.server = socketserver.TCPServer(("", self.port), handler)
|
|
63
74
|
|