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.
Files changed (125) hide show
  1. {dars_framework-1.1.8 → dars_framework-1.2.0}/MANIFEST.in +2 -1
  2. {dars_framework-1.1.8/dars_framework.egg-info → dars_framework-1.2.0}/PKG-INFO +2 -1
  3. {dars_framework-1.1.8 → dars_framework-1.2.0}/README.md +220 -165
  4. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/all.py +2 -0
  5. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/main.py +76 -50
  6. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/preview.py +12 -1
  7. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/checkbox.py +3 -2
  8. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/container.py +3 -2
  9. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/input.py +3 -2
  10. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/page.py +2 -2
  11. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/radiobutton.py +3 -2
  12. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/select.py +3 -2
  13. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/text.py +3 -2
  14. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/config.py +1 -1
  15. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/app.py +2 -2
  16. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/component.py +102 -0
  17. dars_framework-1.2.0/dars/core/state.py +255 -0
  18. dars_framework-1.2.0/dars/docs/state_management.md +57 -0
  19. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/html_css_js.py +265 -29
  20. dars_framework-1.2.0/dars/js_lib.py +133 -0
  21. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/scripts/dscript.py +2 -2
  22. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/scripts/script.py +6 -5
  23. dars_framework-1.2.0/dars/security.py +133 -0
  24. dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/index.html +72 -0
  25. dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/lib/dars.min.js +131 -0
  26. dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/runtime_css.css +676 -0
  27. dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/runtime_dars.js +349 -0
  28. dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/script.js +1 -0
  29. dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/snapshot.json +1 -0
  30. dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/vdom_tree.js +1 -0
  31. dars_framework-1.2.0/dars/templates/examples/advanced/dState/dars_preview/version.txt +1 -0
  32. dars_framework-1.2.0/dars/templates/examples/advanced/dState/state_mods_demo.py +71 -0
  33. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/HelloWorld/hello_world.py +1 -1
  34. dars_framework-1.2.0/dars/templates/html/__init__.py +0 -0
  35. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/version.py +2 -2
  36. {dars_framework-1.1.8 → dars_framework-1.2.0/dars_framework.egg-info}/PKG-INFO +2 -1
  37. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/SOURCES.txt +14 -0
  38. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/requires.txt +1 -0
  39. {dars_framework-1.1.8 → dars_framework-1.2.0}/pyproject.toml +9 -5
  40. {dars_framework-1.1.8 → dars_framework-1.2.0}/LICENSE +0 -0
  41. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/__init__.py +0 -0
  42. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/__init__.py +0 -0
  43. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/hot_reload.py +0 -0
  44. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/cli/translations.py +0 -0
  45. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/__init__.py +0 -0
  46. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/__init__.py +0 -0
  47. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/accordion.py +0 -0
  48. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/card.py +0 -0
  49. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/modal.py +0 -0
  50. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/navbar.py +0 -0
  51. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/table.py +0 -0
  52. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/advanced/tabs.py +0 -0
  53. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/__init__.py +0 -0
  54. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/button.py +0 -0
  55. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/datepicker.py +0 -0
  56. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/image.py +0 -0
  57. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/link.py +0 -0
  58. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/markdown.py +0 -0
  59. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/progressbar.py +0 -0
  60. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/slider.py +0 -0
  61. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/spinner.py +0 -0
  62. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/textarea.py +0 -0
  63. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/basic/tooltip.py +0 -0
  64. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/layout/__init__.py +0 -0
  65. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/layout/anchor.py +0 -0
  66. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/layout/flex.py +0 -0
  67. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/components/layout/grid.py +0 -0
  68. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/__init__.py +0 -0
  69. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/events.py +0 -0
  70. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/core/properties.py +0 -0
  71. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/apps_test/health_check.py +0 -0
  72. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/run_tests.py +0 -0
  73. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_advanced_components.py +0 -0
  74. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_basic_components.py +0 -0
  75. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_core_and_cli.py +0 -0
  76. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_layout_components.py +0 -0
  77. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/dars_tests/tests/test_version_check.py +0 -0
  78. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/__init__.py +0 -0
  79. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/app.md +0 -0
  80. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/cli.md +0 -0
  81. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/components.md +0 -0
  82. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/custom_components.md +0 -0
  83. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/events.md +0 -0
  84. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/exporters.md +0 -0
  85. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/getting_started.md +0 -0
  86. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/index.md +0 -0
  87. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/docs/scripts.md +0 -0
  88. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/__init__.py +0 -0
  89. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/base.py +0 -0
  90. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/OLD/html_css_js_OLD4.py +0 -0
  91. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/OLD/html_css_js_old.py +0 -0
  92. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/OLD/html_css_js_old2.py +0 -0
  93. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/__init__.py +0 -0
  94. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/exporters/web/vdom.py +0 -0
  95. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/scripts/__init__.py +0 -0
  96. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/__init__.py +0 -0
  97. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/__pycache__/__init__.cpython-311.pyc +0 -0
  98. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/README.md +0 -0
  99. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/__pycache__/dynamic_event_demo.cpython-311.pyc +0 -0
  100. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/Modal_Demo/advanced_modal_demo.py +0 -0
  101. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/SimpleDashboard/dashboard.py +0 -0
  102. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/SimpleModermWeb/modern_web_app.py +0 -0
  103. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/VariousComponents/all_components_demo.py +0 -0
  104. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/advanced/__init__.py +0 -0
  105. /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
  106. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Forms/form_components.py +0 -0
  107. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Forms/simple_form.py +0 -0
  108. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Layouts/flex_layout_responsive.py +0 -0
  109. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Layouts/grid_layout_responsive.py +0 -0
  110. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Layouts/layout_multipage_demo.py +0 -0
  111. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/Multipage/multipage_example.py +0 -0
  112. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/PWA/icon-192x192.png +0 -0
  113. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/PWA/icon-512x512.png +0 -0
  114. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/basic/PWA/pwa_custom_icons.py +0 -0
  115. {dars_framework-1.1.8/dars/templates/examples/markdown → dars_framework-1.2.0/dars/templates/examples/basic}/__init__.py +0 -0
  116. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/demo/__pycache__/complete_app.cpython-311.pyc +0 -0
  117. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/demo/complete_app.py +0 -0
  118. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/markdown/MarkdownTemplate/README.md +0 -0
  119. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/markdown/MarkdownTemplate/markdown_template.py +0 -0
  120. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars/templates/examples/markdown/MarkdownTemplate/other_docs.md +0 -0
  121. {dars_framework-1.1.8/dars/templates/html → dars_framework-1.2.0/dars/templates/examples/markdown}/__init__.py +0 -0
  122. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/dependency_links.txt +0 -0
  123. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/entry_points.txt +0 -0
  124. {dars_framework-1.1.8 → dars_framework-1.2.0}/dars_framework.egg-info/top_level.txt +0 -0
  125. {dars_framework-1.1.8 → dars_framework-1.2.0}/setup.cfg +0 -0
@@ -3,4 +3,5 @@ include LICENSE
3
3
  recursive-include dars/templates *
4
4
  recursive-include dars/docs *
5
5
  recursive-include dars *.json
6
- recursive-include dars *.md
6
+ recursive-include dars *.md
7
+ exclude LandingPage
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dars_framework
3
- Version: 1.1.8
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="160" />
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
- > Note: this is an single page example but you can build multipage apps with Page component see the [Components Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html#dars-components-documentation) to know more.
28
-
29
- ```python
30
- from dars.all import *
31
-
32
- app = App()
33
-
34
- # Crear aplicación con sintaxis nueva (v1.0.3)
35
- container = Container(
36
- Text(
37
- "Hola Dars",
38
- style={'font-size': '32px', 'color': '#333'}
39
- ),
40
- Button(
41
- "Hacer clic",
42
- style={'background-color': '#007bff', 'color': 'white'}
43
- ),
44
- style={
45
- 'display': 'flex',
46
- 'flex-direction': 'column',
47
- 'align-items': 'center',
48
- 'padding': '40px'
49
- }
50
- )
51
-
52
- # Script para interactividad
53
- script = InlineScript("""
54
- document.addEventListener('DOMContentLoaded', function() {
55
- const boton = document.querySelector('button');
56
- boton.addEventListener('click', function() {
57
- alert('Hola desde Dars.');
58
- });
59
- });
60
- """)
61
-
62
- # Ensamblar aplicación
63
- app.set_root(container)
64
- app.add_script(script)
65
-
66
- if __name__ == "__main__":
67
- app.rTimeCompile() # Live preview at http://localhost:8000
68
-
69
- ```
70
-
71
- ## CLI Usage
72
- | Command | What it does |
73
- |-----------------------------------------|--------------------------------------------|
74
- | `dars export my_app.py --format html` | Export app to HTML/CSS/JS in `./my_app_web` |
75
- | `dars preview ./my_app_web` | Preview exported app locally |
76
- | `dars init my_project` | Create a new Dars project (also creates dars.config.json) |
77
- | `dars init --update` | Create/Update dars.config.json in current dir |
78
- | `dars build` | Build using dars.config.json (entry/outdir/format) |
79
- | `dars config validate` | Validate dars.config.json and print report |
80
- | `dars info my_app.py` | Show info about your app |
81
- | `dars formats` | List supported export formats |
82
- | `dars --help` | Show help and all CLI options |
83
-
84
- ## More
85
-
86
- - Visit dars [official website](https://ztamdev.github.io/Dars-Framework/)
87
- - Visit the dars official [Documentation](https://ztamdev.github.io/Dars-Framework/documentation.html) now on separate website.
88
- - Try dars without installing nothing just visit the [Dars Playground](https://dars-playground.vercel.app/)
89
-
90
- ## Local Execution and Live Preview
91
-
92
- To test your app locally before exporting, use the hot-reload preview from any Python file that defines your app:
93
-
94
- ```python
95
- if __name__ == "__main__":
96
- app.rTimeCompile()
97
- ```
98
-
99
- Then run your file directly:
100
-
101
- ```bash
102
- python my_app.py
103
- ```
104
-
105
- 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:
106
-
107
- ```bash
108
- python my_app.py --port 8088
109
- ```
110
-
111
- ---
112
-
113
- You can also use the CLI preview command on an exported app:
114
-
115
- ```bash
116
- dars preview ./my_exported_app
117
- ```
118
-
119
- This will start a local server at http://localhost:8000 to view your exported app in the browser.
120
-
121
- ---
122
-
123
- ## Project Configuration (dars.config.json)
124
-
125
- 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`.
126
-
127
- Example default:
128
-
129
- ```json
130
- {
131
- "entry": "main.py",
132
- "format": "html",
133
- "outdir": "dist",
134
- "publicDir": null,
135
- "include": [],
136
- "exclude": ["**/__pycache__", ".git", ".venv", "node_modules"],
137
- "bundle": false
138
- }
139
- ```
140
-
141
- - `entry`: Python entry file. Used by `dars build` and `dars export config`.
142
- - `format`: Export format. Currently only `html` is supported.
143
- - `outdir`: Output directory. Used by `dars build` and default for `dars export` when not overridden.
144
- - `publicDir`: Folder (e.g., `public/` or `assets/`) copied into the output. If null, it is autodetected.
145
- - `include`/`exclude`: Basic filters for copying from `publicDir`.
146
- - `bundle`: Reserved for future use. CLI exports and build already bundle appropriately.
147
-
148
- Validate your config:
149
-
150
- ```bash
151
- dars config validate
152
- ```
153
-
154
- Build using config:
155
-
156
- ```bash
157
- dars build
158
- ```
159
-
160
- Export using the config entry and outdir:
161
-
162
- ```bash
163
- dars export config --format html
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=RichHelpFormatter,
531
- epilog="" # Remove epilog to avoid duplication
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
- # Add language parameter to the main parser
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
- # Add language option to all subparsers
604
- for subparser in [export_parser, info_parser, formats_parser, preview_parser, init_parser, build_parser, config_parser, cfg_validate]:
605
- subparser.add_argument('--lang', '-l', choices=['en', 'es'], default='en',
606
- help=translator.get('lang_help'))
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
- # Check for language parameter before parsing arguments
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
- # Show banner
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
- # Show banner for normal commands
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
- # Usar nuestro formateador personalizado en lugar del estándar
1018
- RichHelpFormatter.rich_print_help(parser)
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
- if path.endswith('sw.js'):
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