dars-framework 1.9.2__tar.gz → 1.9.3__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 (183) hide show
  1. {dars_framework-1.9.2/dars_framework.egg-info → dars_framework-1.9.3}/PKG-INFO +5 -2
  2. {dars_framework-1.9.2 → dars_framework-1.9.3}/README.md +4 -1
  3. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/main.py +11 -1
  4. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/page.py +67 -0
  5. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/config.py +1 -0
  6. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/app.py +143 -15
  7. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/exporters/web/html_css_js.py +51 -88
  8. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/security.py +1 -1
  9. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/version.py +2 -2
  10. {dars_framework-1.9.2 → dars_framework-1.9.3/dars_framework.egg-info}/PKG-INFO +5 -2
  11. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars_framework.egg-info/SOURCES.txt +0 -1
  12. {dars_framework-1.9.2 → dars_framework-1.9.3}/pyproject.toml +1 -1
  13. dars_framework-1.9.2/dars/js_lib.py +0 -2049
  14. {dars_framework-1.9.2 → dars_framework-1.9.3}/Dars-logo.png +0 -0
  15. {dars_framework-1.9.2 → dars_framework-1.9.3}/LICENSE +0 -0
  16. {dars_framework-1.9.2 → dars_framework-1.9.3}/MANIFEST.in +0 -0
  17. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/__init__.py +0 -0
  18. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/actionProtocol.py +0 -0
  19. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/all.py +0 -0
  20. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/backend/__init__.py +0 -0
  21. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/backend/components.py +0 -0
  22. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/backend/data.py +0 -0
  23. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/backend/http.py +0 -0
  24. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/backend/json_utils.py +0 -0
  25. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/backend/route_loader.py +0 -0
  26. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/backend/ssr.py +0 -0
  27. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/__init__.py +0 -0
  28. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/doctor/__init__.py +0 -0
  29. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/doctor/detect.py +0 -0
  30. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/doctor/doctor.py +0 -0
  31. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/doctor/installers.py +0 -0
  32. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/doctor/persist.py +0 -0
  33. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/doctor/preflight.py +0 -0
  34. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/doctor/ui.py +0 -0
  35. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/dpm.py +0 -0
  36. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/hot_reload.py +0 -0
  37. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/preview.py +0 -0
  38. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/cli/translations.py +0 -0
  39. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/__init__.py +0 -0
  40. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/__init__.py +0 -0
  41. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/accordion.py +0 -0
  42. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/card.py +0 -0
  43. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/file_upload.py +0 -0
  44. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/head.py +0 -0
  45. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/modal.py +0 -0
  46. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/navbar.py +0 -0
  47. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/outlet.py +0 -0
  48. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/table.py +0 -0
  49. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/advanced/tabs.py +0 -0
  50. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/__init__.py +0 -0
  51. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/audio.py +0 -0
  52. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/button.py +0 -0
  53. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/checkbox.py +0 -0
  54. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/container.py +0 -0
  55. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/datepicker.py +0 -0
  56. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/image.py +0 -0
  57. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/input.py +0 -0
  58. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/link.py +0 -0
  59. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/markdown.py +0 -0
  60. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/progressbar.py +0 -0
  61. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/radiobutton.py +0 -0
  62. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/section.py +0 -0
  63. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/select.py +0 -0
  64. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/slider.py +0 -0
  65. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/spinner.py +0 -0
  66. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/text.py +0 -0
  67. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/textarea.py +0 -0
  68. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/tooltip.py +0 -0
  69. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/basic/video.py +0 -0
  70. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/layout/__init__.py +0 -0
  71. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/layout/anchor.py +0 -0
  72. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/layout/flex.py +0 -0
  73. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/layout/grid.py +0 -0
  74. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/visualization/__init__.py +0 -0
  75. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/visualization/chart.py +0 -0
  76. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/components/visualization/table.py +0 -0
  77. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/__init__.py +0 -0
  78. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/component.py +0 -0
  79. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/events.py +0 -0
  80. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/js_bridge.py +0 -0
  81. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/properties.py +0 -0
  82. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/route_types.py +0 -0
  83. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/routing.py +0 -0
  84. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/state.py +0 -0
  85. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/state_v2.py +0 -0
  86. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/core/utilities.py +0 -0
  87. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/dars_tests/apps_test/health_check.py +0 -0
  88. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/dars_tests/run_tests.py +0 -0
  89. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/dars_tests/tests/test_advanced_components.py +0 -0
  90. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/dars_tests/tests/test_basic_components.py +0 -0
  91. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/dars_tests/tests/test_core_and_cli.py +0 -0
  92. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/dars_tests/tests/test_layout_components.py +0 -0
  93. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/dars_tests/tests/test_version_check.py +0 -0
  94. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/desktop/__init__.py +0 -0
  95. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/desktop/api.py +0 -0
  96. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/desktop/js_generator.py +0 -0
  97. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/INSTALL.md +0 -0
  98. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/KeyEvents.md +0 -0
  99. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/__init__.py +0 -0
  100. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/animations.md +0 -0
  101. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/app.md +0 -0
  102. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/backend_api.md +0 -0
  103. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/cli.md +0 -0
  104. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/components.md +0 -0
  105. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/config.md +0 -0
  106. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/custom_components.md +0 -0
  107. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/env.md +0 -0
  108. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/events.md +0 -0
  109. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/exporters.md +0 -0
  110. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/getting_started.md +0 -0
  111. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/hooks.md +0 -0
  112. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/index.md +0 -0
  113. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/operations.md +0 -0
  114. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/routing.md +0 -0
  115. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/scripts.md +0 -0
  116. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/ssr.md +0 -0
  117. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/state_management.md +0 -0
  118. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/docs/styling.md +0 -0
  119. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/env.py +0 -0
  120. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/exporters/__init__.py +0 -0
  121. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/exporters/base.py +0 -0
  122. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/exporters/desktop/electron.py +0 -0
  123. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/exporters/web/__init__.py +0 -0
  124. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/exporters/web/vdom.py +0 -0
  125. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/__init__.py +0 -0
  126. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/form_helpers.py +0 -0
  127. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/set_vref.py +0 -0
  128. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/update_vref.py +0 -0
  129. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/use_dynamic.py +0 -0
  130. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/use_value.py +0 -0
  131. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/use_vref.py +0 -0
  132. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/use_watch.py +0 -0
  133. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/hooks/value_helpers.py +0 -0
  134. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/scripts/__init__.py +0 -0
  135. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/scripts/animations.py +0 -0
  136. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/scripts/dscript.py +0 -0
  137. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/scripts/keycode.py +0 -0
  138. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/scripts/script.py +0 -0
  139. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/scripts/utils_ds.py +0 -0
  140. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/__init__.py +0 -0
  141. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/icon.png +0 -0
  142. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/backend/icons/icon.png +0 -0
  143. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/backend/main.js +0 -0
  144. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/backend/package.json +0 -0
  145. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/backend/preload.js +0 -0
  146. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/dars.config.json +0 -0
  147. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/icons/icon.png +0 -0
  148. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/main.py +0 -0
  149. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/public/electron-icon.png +0 -0
  150. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/desktop/template/public/icon.png +0 -0
  151. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/README.md +0 -0
  152. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/CustomComp/main.py +0 -0
  153. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/Modal_Demo/advanced_modal_demo.py +0 -0
  154. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/StateV2/README.md +0 -0
  155. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/StateV2/animation_component.py +0 -0
  156. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/StateV2/counter_component.py +0 -0
  157. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/StateV2/hero_component.py +0 -0
  158. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/StateV2/main.py +0 -0
  159. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/StateV2/styles.css +0 -0
  160. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/StateV2/timer_component.py +0 -0
  161. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/VariousComponents/all_components_demo.py +0 -0
  162. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/__init__.py +0 -0
  163. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/dState/state_mods_demo.py +0 -0
  164. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/hooks/useDynamic.py +0 -0
  165. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/hooks/useValue.py +0 -0
  166. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/advanced/hooks/useWatch.py +0 -0
  167. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/basic/HelloWorld/hello_world.py +0 -0
  168. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/basic/Layouts/flex_layout_responsive.py +0 -0
  169. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/basic/Layouts/grid_layout_responsive.py +0 -0
  170. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/basic/Layouts/layout_multipage_demo.py +0 -0
  171. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/basic/PWA/icon-192x192.png +0 -0
  172. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/basic/PWA/icon-512x512.png +0 -0
  173. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/basic/PWA/pwa_custom_icons.py +0 -0
  174. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/basic/__init__.py +0 -0
  175. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/markdown/MarkdownTemplate/README.md +0 -0
  176. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/markdown/MarkdownTemplate/markdown_template.py +0 -0
  177. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/markdown/MarkdownTemplate/other_docs.md +0 -0
  178. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars/templates/examples/markdown/__init__.py +0 -0
  179. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars_framework.egg-info/dependency_links.txt +0 -0
  180. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars_framework.egg-info/entry_points.txt +0 -0
  181. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars_framework.egg-info/requires.txt +0 -0
  182. {dars_framework-1.9.2 → dars_framework-1.9.3}/dars_framework.egg-info/top_level.txt +0 -0
  183. {dars_framework-1.9.2 → dars_framework-1.9.3}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dars-framework
3
- Version: 1.9.2
3
+ Version: 1.9.3
4
4
  Summary: Dars is a Full-Stack multiplatform Python UI framework for building modern, interactive web and desktop apps with Python code. Seamlessly integrated with FastAPI, it allows you to build complete applications with Server-Side Rendering (SSR) and reactive SPA capabilities also classic multipage html and desktop apps in a single codebase.
5
5
  Author-email: ztamdev <ztadevs@gmail.com>
6
6
  Maintainer-email: ztamdev <ztadevs@gmail.com>
@@ -483,6 +483,7 @@ For complete documentation, see the [Backend API Guide](https://ztamdev.github.i
483
483
  | `dars info my_app.py` | Show info about your app |
484
484
  | `dars formats` | List supported export formats |
485
485
  | `dars dev` | Run the configured entry file with hot preview (app.rTimeCompile) |
486
+ | `dars dev --port 9000` | Run dev server on a custom port (overrides config) |
486
487
  | `dars dev --backend` | Run only the configured backendEntry (FastAPI/SSR backend) |
487
488
  | `dars --help` | Show help and all CLI options |
488
489
 
@@ -516,7 +517,7 @@ Then run your file directly:
516
517
  python my_app.py
517
518
  ```
518
519
 
519
- 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:
520
+ This will start a local server at the port specified in your `dars.config.json` (defaults to http://localhost:8000) so you can view your app in the browser—no manual export needed. You can override the port with:
520
521
 
521
522
  ```bash
522
523
  python my_app.py --port 8088
@@ -554,6 +555,7 @@ Example default:
554
555
  "utility_styles": {},
555
556
  "markdownHighlight": true,
556
557
  "markdownHighlightTheme": "auto",
558
+ "port": 8000,
557
559
  "backendEntry": "backend.api:app"
558
560
  }
559
561
  ```
@@ -569,6 +571,7 @@ Example default:
569
571
  - `utility_styles`: Dictionary defining custom utility classes. Keys are class names, values are lists of utility strings or raw CSS properties.
570
572
  - `markdownHighlight`: Auto-inject a client-side syntax highlighter for fenced code blocks in Markdown. Default `true`.
571
573
  - `backendEntry`: Python import path for your SSR/backend app (e.g. `"backend.api:app"`). Required when your app uses `RouteType.SSR` routes. Used by `dars dev --backend`.
574
+ - `port`: The port for the development preview server. Default `8000`.
572
575
 
573
576
  Validate your config:
574
577
 
@@ -442,6 +442,7 @@ For complete documentation, see the [Backend API Guide](https://ztamdev.github.i
442
442
  | `dars info my_app.py` | Show info about your app |
443
443
  | `dars formats` | List supported export formats |
444
444
  | `dars dev` | Run the configured entry file with hot preview (app.rTimeCompile) |
445
+ | `dars dev --port 9000` | Run dev server on a custom port (overrides config) |
445
446
  | `dars dev --backend` | Run only the configured backendEntry (FastAPI/SSR backend) |
446
447
  | `dars --help` | Show help and all CLI options |
447
448
 
@@ -475,7 +476,7 @@ Then run your file directly:
475
476
  python my_app.py
476
477
  ```
477
478
 
478
- 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:
479
+ This will start a local server at the port specified in your `dars.config.json` (defaults to http://localhost:8000) so you can view your app in the browser—no manual export needed. You can override the port with:
479
480
 
480
481
  ```bash
481
482
  python my_app.py --port 8088
@@ -513,6 +514,7 @@ Example default:
513
514
  "utility_styles": {},
514
515
  "markdownHighlight": true,
515
516
  "markdownHighlightTheme": "auto",
517
+ "port": 8000,
516
518
  "backendEntry": "backend.api:app"
517
519
  }
518
520
  ```
@@ -528,6 +530,7 @@ Example default:
528
530
  - `utility_styles`: Dictionary defining custom utility classes. Keys are class names, values are lists of utility strings or raw CSS properties.
529
531
  - `markdownHighlight`: Auto-inject a client-side syntax highlighter for fenced code blocks in Markdown. Default `true`.
530
532
  - `backendEntry`: Python import path for your SSR/backend app (e.g. `"backend.api:app"`). Required when your app uses `RouteType.SSR` routes. Used by `dars dev --backend`.
533
+ - `port`: The port for the development preview server. Default `8000`.
531
534
 
532
535
  Validate your config:
533
536
 
@@ -1206,6 +1206,7 @@ def create_parser(include_hidden: bool = True) -> argparse.ArgumentParser:
1206
1206
  # Dev command (run entry in dev mode)
1207
1207
  dev_parser = subparsers.add_parser('dev', help='Run the configured entry file in development mode')
1208
1208
  dev_parser.add_argument('--project', '-p', default='.', help='Project root where dars.config.json resides (default: .)')
1209
+ dev_parser.add_argument('--port', '-P', type=int, help='Port to run the dev server on (overrides config)')
1209
1210
  dev_parser.add_argument('--backend', action='store_true', help='Run only the configured backendEntry (SSR/API) instead of the frontend entry')
1210
1211
  # English-only: no language option on subparsers
1211
1212
 
@@ -2296,7 +2297,16 @@ def main():
2296
2297
  # Backend/SSR server can be started in a separate terminal with `dars dev --backend` if needed.
2297
2298
  process = None
2298
2299
  try:
2299
- process = subprocess.Popen([sys.executable, entry], cwd=os.path.dirname(entry))
2300
+ cmd = [sys.executable, entry]
2301
+ # Prioritize CLI arg, then config, then fallback to 8000
2302
+ port_to_pass = getattr(args, 'port', None)
2303
+ if port_to_pass is None and found and "port" in cfg:
2304
+ port_to_pass = cfg["port"]
2305
+
2306
+ if port_to_pass:
2307
+ cmd.extend(['--port', str(port_to_pass)])
2308
+
2309
+ process = subprocess.Popen(cmd, cwd=os.path.dirname(entry))
2300
2310
  process.wait()
2301
2311
  sys.exit(process.returncode or 0)
2302
2312
  except KeyboardInterrupt:
@@ -39,6 +39,73 @@ class Page(Component):
39
39
  self.add_child(child)
40
40
 
41
41
  def add_script(self, script):
42
+ """
43
+ Adds a script to this page.
44
+
45
+ Supports multiple script types:
46
+
47
+ - **DScript**: Direct Python function compilation to JavaScript
48
+ - **String**: Inline JavaScript code
49
+ - **Dictionary**: Raw script object (fallback)
50
+ - **Utility Chains**: DAP utility functions with promise-based chaining
51
+
52
+ **Script Types:**
53
+
54
+ 1. **DScript** - Compile Python to JavaScript:
55
+ ```python
56
+ page.add_script(dScript(file_path="script.js"))
57
+ ```
58
+
59
+ 2. **Inline JavaScript**:
60
+ ```python
61
+ page.add_script("console.log('Page loaded');")
62
+ ```
63
+
64
+ 3. **Utility Functions** - Chain DAP commands:
65
+ ```python
66
+ from dars.scripts.utils_ds import setTimeout, addClass, log
67
+
68
+ # Sequential animations with promise chaining
69
+ page.add_script(
70
+ setTimeout(5, addClass("logo", "show"))
71
+ .then(setTimeout(350, addClass("title", "show")))
72
+ .then(setTimeout(650, addClass("description", "show")))
73
+ )
74
+ ```
75
+
76
+ 4. **useWatch** - React to state changes:
77
+ ```python
78
+ page.add_script(
79
+ useWatch("user.name", log("Name changed!"))
80
+ )
81
+ ```
82
+
83
+ **Common Utilities:**
84
+
85
+ - **setTimeout(ms, action)**: Execute action after delay (returns Promise)
86
+ - **addClass(id, class)**: Add CSS class to element
87
+ - **removeClass(id, class)**: Remove CSS class
88
+ - **toggleClass(id, class)**: Toggle CSS class
89
+ - **log(msg)**: Log to console
90
+ - **navigate(url)**: Navigate to URL
91
+ - **createComp(target, root)**: Dynamically create components
92
+ - **updateComp(id, props)**: Update component properties
93
+ - **deleteComp(id)**: Remove component from DOM
94
+
95
+ **Promise Chaining:**
96
+
97
+ All timeout/async utilities return Promises, allowing sequential execution:
98
+
99
+ ```python
100
+ page.add_script(
101
+ setTimeout(100, log("Step 1"))
102
+ .then(setTimeout(200, log("Step 2")))
103
+ .then(setTimeout(300, log("Step 3")))
104
+ )
105
+ ```
106
+
107
+ Returns self to allow method chaining.
108
+ """
42
109
  self.scripts.append(script)
43
110
 
44
111
  def useWatch(self, state_path: str, *js_helpers):
@@ -22,6 +22,7 @@ DEFAULT_CONFIG = {
22
22
  "markdownHighlight": True,
23
23
  "markdownHighlightTheme": "auto",
24
24
  "targetPlatform": "auto", # Desktop-only option: platform target for Electron build (auto|windows|linux|macos)
25
+ "port": 8000,
25
26
  # Optional: backend entry for SSR projects (module or file path). Disabled by default.
26
27
  "backendEntry": None,
27
28
  # Optional: custom utility styles map consumed by register_custom_utilities
@@ -46,11 +46,73 @@ class Page:
46
46
  # Métodos para manejar scripts
47
47
  # -----------------------------
48
48
  def add_script(self, script: Any):
49
- """Adds a script to this page.
50
- - If 'script' is an instance (e.g., InlineScript/FileScript/DScript), it is added as is.
51
- - If 'script' is a string, it is interpreted as an InlineScript (code).
52
- - If 'script' is a dict, it is added as is (fallback).
53
- Returns self to allow call chaining."""
49
+ """
50
+ Adds a script to this page.
51
+
52
+ Supports multiple script types:
53
+
54
+ - **DScript**: Direct Python function compilation to JavaScript
55
+ - **String**: Inline JavaScript code
56
+ - **Dictionary**: Raw script object (fallback)
57
+ - **Utility Chains**: DAP utility functions with promise-based chaining
58
+
59
+ **Script Types:**
60
+
61
+ 1. **DScript** - Compile Python to JavaScript:
62
+ ```python
63
+ page.add_script(dScript(file_path="script.js"))
64
+ ```
65
+
66
+ 2. **Inline JavaScript**:
67
+ ```python
68
+ page.add_script("console.log('Page loaded');")
69
+ ```
70
+
71
+ 3. **Utility Functions** - Chain DAP commands:
72
+ ```python
73
+ from dars.scripts.utils_ds import setTimeout, addClass, log
74
+
75
+ # Sequential animations with promise chaining
76
+ page.add_script(
77
+ setTimeout(5, addClass("logo", "show"))
78
+ .then(setTimeout(350, addClass("title", "show")))
79
+ .then(setTimeout(650, addClass("description", "show")))
80
+ )
81
+ ```
82
+
83
+ 4. **useWatch** - React to state changes:
84
+ ```python
85
+ page.add_script(
86
+ useWatch("user.name", log("Name changed!"))
87
+ )
88
+ ```
89
+
90
+ **Common Utilities:**
91
+
92
+ - **setTimeout(ms, action)**: Execute action after delay (returns Promise)
93
+ - **addClass(id, class)**: Add CSS class to element
94
+ - **removeClass(id, class)**: Remove CSS class
95
+ - **toggleClass(id, class)**: Toggle CSS class
96
+ - **log(msg)**: Log to console
97
+ - **navigate(url)**: Navigate to URL
98
+ - **createComp(target, root)**: Dynamically create components
99
+ - **updateComp(id, props)**: Update component properties
100
+ - **deleteComp(id)**: Remove component from DOM
101
+
102
+ **Promise Chaining:**
103
+
104
+ All timeout/async utilities return Promises, allowing sequential execution:
105
+
106
+ ```python
107
+ page.add_script(
108
+ setTimeout(100, log("Step 1"))
109
+ .then(setTimeout(200, log("Step 2")))
110
+ .then(setTimeout(300, log("Step 3")))
111
+ )
112
+ ```
113
+
114
+ Returns self to allow method chaining.
115
+ """
54
116
 
55
117
  # si es str => interpretarlo como inline
56
118
  if isinstance(script, str):
@@ -614,15 +676,6 @@ class App:
614
676
  except Exception:
615
677
  console = None
616
678
 
617
- # ---- PORT ----
618
- if port is None:
619
- port = 8000
620
- for i, arg in enumerate(sys.argv):
621
- if arg in ('--port', '-p') and i + 1 < len(sys.argv):
622
- try:
623
- port = int(sys.argv[i + 1])
624
- except:
625
- pass
626
679
 
627
680
  # ---- NORMALIZE EXTENSIONS ----
628
681
  def _normalize_exts(exts):
@@ -777,6 +830,27 @@ class App:
777
830
  # Fix logic: Use self.desktop attribute if available, regardless of config
778
831
  is_desktop = bool(getattr(self, 'desktop', False) or fmt == 'desktop')
779
832
 
833
+ # ---- PORT (CONFIG DRIVEN) ----
834
+ if port is None:
835
+ # 1. Try to get port from config
836
+ if cfg_found and "port" in cfg:
837
+ try:
838
+ port = int(cfg["port"])
839
+ except:
840
+ pass
841
+
842
+ # 2. Default if not in config
843
+ if port is None:
844
+ port = 8000
845
+
846
+ # 3. CLI override always takes precedence
847
+ for i, arg in enumerate(sys.argv):
848
+ if arg in ('--port', '-p') and i + 1 < len(sys.argv):
849
+ try:
850
+ port = int(sys.argv[i + 1])
851
+ except:
852
+ pass
853
+
780
854
  # ---- STARTUP SPINNER ----
781
855
  startup_status = None
782
856
  if console:
@@ -1674,7 +1748,61 @@ class App:
1674
1748
  self._spa_error_page = onErrorComp
1675
1749
 
1676
1750
  def add_script(self, script: 'Script'):
1677
- """Adds a script to the app"""
1751
+ """
1752
+ Adds a global script to the application (runs on every page).
1753
+
1754
+ Global scripts are injected into every page of your application and can be used for:
1755
+ - Global utilities and helpers
1756
+ - Application-wide event listeners
1757
+ - Initialization code
1758
+ - Analytics and tracking
1759
+ - Feature detection
1760
+
1761
+ **Supported Script Types:**
1762
+
1763
+ 1. **DScript** - Compiled Python functions:
1764
+ ```python
1765
+ app.add_script(dScript(file_path="global.js"))
1766
+ ```
1767
+
1768
+ 2. **Inline JavaScript**:
1769
+ ```python
1770
+ app.add_script("window.appVersion = '1.0.0';")
1771
+ ```
1772
+
1773
+ 3. **Utility Chains** - Global DAP utilities:
1774
+ ```python
1775
+ from dars.scripts.utils_ds import setTimeout, addClass, log
1776
+
1777
+ # Global theme initialization with animations
1778
+ app.add_script(
1779
+ setTimeout(100, addClass("app-container", "initialized"))
1780
+ .then(setTimeout(500, log("App ready!")))
1781
+ )
1782
+ ```
1783
+
1784
+ 4. **useWatch** - Global state monitoring:
1785
+ ```python
1786
+ app.add_script(
1787
+ useWatch("theme", log("Theme changed!"))
1788
+ )
1789
+ ```
1790
+
1791
+ **Example: Global animations on page load**
1792
+
1793
+ ```python
1794
+ from dars.scripts.utils_ds import setTimeout, addClass
1795
+
1796
+ # Add fade-in animation for all pages
1797
+ app.add_script(
1798
+ setTimeout(5, addClass("app-content", "fade-in"))
1799
+ .then(setTimeout(500, addClass("app-content", "show")))
1800
+ )
1801
+ ```
1802
+
1803
+ **Note:** Global scripts are included in every page and should be lightweight.
1804
+ For page-specific scripts, use `page.add_script()` instead.
1805
+ """
1678
1806
  self.scripts.append(script)
1679
1807
 
1680
1808
  def useWatch(self, state_path: str, *js_helpers):
@@ -44,6 +44,8 @@ from bs4 import BeautifulSoup
44
44
  from dars.exporters.web.vdom import VDomBuilder
45
45
  from dars.config import load_config, resolve_paths, copy_public_dir
46
46
  import json
47
+ import shutil
48
+ import inspect
47
49
 
48
50
  class DarsJSONEncoder(json.JSONEncoder):
49
51
  def default(self, obj):
@@ -113,38 +115,7 @@ class HTMLCSSJSExporter(Exporter):
113
115
  # Initialize style registry for this export (Phase 1 of style optimization)
114
116
  # Maps generated class name -> dict(style)
115
117
  self._style_registry: Dict[str, Dict[str, Any]] = {}
116
- self._global_css_blocks: List[str] = ["""
117
- /* Dars Markdown Copy Button Styles */
118
- .dars-code-copy {
119
- position: absolute;
120
- top: 8px;
121
- right: 8px;
122
- background: rgba(0,0,0,0.6);
123
- color: #fff;
124
- border: none;
125
- border-radius: 6px;
126
- padding: 5px 10px;
127
- font-size: 12px;
128
- font-weight: 500;
129
- cursor: pointer;
130
- opacity: 0;
131
- transition: all 0.2s ease;
132
- z-index: 10;
133
- backdrop-filter: blur(4px);
134
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
135
- }
136
- pre:hover .dars-code-copy {
137
- opacity: 1;
138
- }
139
- .dars-code-copy:hover {
140
- background: rgba(0,0,0,0.8);
141
- transform: translateY(-1px);
142
- }
143
- .dars-code-copy.copied {
144
- background: #16a34a !important;
145
- opacity: 1 !important;
146
- }
147
- """]
118
+ self._global_css_blocks: List[str] = []
148
119
  self._markdown_html_assets = {} # route_name -> list of html strings
149
120
  # Separate registries for hover/active variants (class -> dict(style))
150
121
  self._hover_style_registry: Dict[str, Dict[str, Any]] = {}
@@ -178,30 +149,25 @@ pre:hover .dars-code-copy {
178
149
  pass
179
150
 
180
151
  # --- Escribir librería de reactividad (dars.min.js) embebida ---
181
- # Optimization: Skip if file exists and content is identical (hot reload)
152
+ # --- Runtime Assets (lib/) ---
182
153
  try:
183
154
  lib_dir = os.path.join(output_path, 'lib')
184
155
  os.makedirs(lib_dir, exist_ok=True)
185
- dest_js = os.path.join(lib_dir, 'dars.min.js')
186
156
 
187
- # Check if file exists and content matches
188
- should_write = True
189
- if os.path.exists(dest_js):
190
- try:
191
- with open(dest_js, 'r', encoding='utf-8') as f:
192
- existing_content = f.read()
193
- from dars.js_lib import DARS_MIN_JS
194
- if existing_content == DARS_MIN_JS:
195
- should_write = False # Skip write, already up to date
196
- except Exception:
197
- pass # If read fails, write anyway
157
+ # Copy all resources from dars/exporters/web/resources/
158
+ # This includes dars.min.js, dap.js, router.js, ssr.js, dompurify.js
159
+ exporter_dir = os.path.dirname(os.path.abspath(inspect.getfile(self.__class__)))
160
+ resources_dir = os.path.join(exporter_dir, 'resources')
198
161
 
199
- if should_write:
200
- from dars.js_lib import DARS_MIN_JS
201
- with open(dest_js, 'w', encoding='utf-8') as f:
202
- f.write(DARS_MIN_JS)
203
- except Exception:
204
- pass
162
+ if os.path.exists(resources_dir):
163
+ for filename in os.listdir(resources_dir):
164
+ if filename.endswith('.js') or filename.endswith('.js.map'):
165
+ src = os.path.join(resources_dir, filename)
166
+ dst = os.path.join(lib_dir, filename)
167
+ # Copy fresh every time to ensure updates are reflected
168
+ shutil.copy2(src, dst)
169
+ except Exception as e:
170
+ print(f"[Dars] Error copying runtime resources: {e}")
205
171
 
206
172
  # --- Cargar configuración si existe y copiar public/assets ---
207
173
  try:
@@ -1279,7 +1245,7 @@ self.addEventListener('fetch', event => {
1279
1245
 
1280
1246
  def generate_custom_css(self, app: App) -> str:
1281
1247
  """Genera solo los estilos personalizados de la aplicación"""
1282
- css_content = self._generate_style_registry_css() + "\n\n"
1248
+ css_content = ""
1283
1249
 
1284
1250
  # Generar estilos hover PRIMERO para que tengan prioridad
1285
1251
  css_content += self._generate_hover_styles(app)
@@ -2236,6 +2202,37 @@ body {
2236
2202
  }
2237
2203
 
2238
2204
  /* Markdown */
2205
+ /* Dars Markdown Copy Button Styles */
2206
+ .dars-code-copy {
2207
+ position: absolute;
2208
+ top: 8px;
2209
+ right: 8px;
2210
+ background: rgba(0,0,0,0.6);
2211
+ color: #fff;
2212
+ border: none;
2213
+ border-radius: 6px;
2214
+ padding: 5px 10px;
2215
+ font-size: 12px;
2216
+ font-weight: 500;
2217
+ cursor: pointer;
2218
+ opacity: 0;
2219
+ transition: all 0.2s ease;
2220
+ z-index: 10;
2221
+ backdrop-filter: blur(4px);
2222
+ box-shadow: 0 2px 4px rgba(0,0,0,0.2);
2223
+ }
2224
+ pre:hover .dars-code-copy {
2225
+ opacity: 1;
2226
+ }
2227
+ .dars-code-copy:hover {
2228
+ background: rgba(0,0,0,0.8);
2229
+ transform: translateY(-1px);
2230
+ }
2231
+ .dars-code-copy.copied {
2232
+ background: #16a34a !important;
2233
+ opacity: 1 !important;
2234
+ }
2235
+
2239
2236
  .dars-markdown {
2240
2237
  font-family: var(--dars-font-family);
2241
2238
  line-height: 1.6;
@@ -5365,42 +5362,8 @@ audio.dars-audio {
5365
5362
  '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.29.0/themes/prism-okaidia.min.css" media="(prefers-color-scheme: dark)">\n'
5366
5363
  )
5367
5364
 
5368
- # Register Global CSS for Copy Button (if not already registered)
5369
- if not hasattr(self, '_markdown_styles_registered'):
5370
- self._markdown_styles_registered = True
5371
- if not hasattr(self, '_global_css_blocks'):
5372
- self._global_css_blocks = []
5373
- self._global_css_blocks.append("""
5374
- .dars-code-copy {
5375
- position: absolute;
5376
- top: 8px;
5377
- right: 8px;
5378
- background: rgba(0,0,0,0.6);
5379
- color: #fff;
5380
- border: none;
5381
- border-radius: 6px;
5382
- padding: 5px 10px;
5383
- font-size: 12px;
5384
- font-weight: 500;
5385
- cursor: pointer;
5386
- opacity: 0;
5387
- transition: all 0.2s ease;
5388
- z-index: 10;
5389
- backdrop-filter: blur(4px);
5390
- box-shadow: 0 2px 4px rgba(0,0,0,0.2);
5391
- }
5392
- pre:hover .dars-code-copy {
5393
- opacity: 1;
5394
- }
5395
- .dars-code-copy:hover {
5396
- background: rgba(0,0,0,0.8);
5397
- transform: translateY(-1px);
5398
- }
5399
- .dars-code-copy.copied {
5400
- background: #16a34a;
5401
- opacity: 1;
5402
- }
5403
- """)
5365
+ # Copy Button styles are now in runtime_css.css
5366
+ pass
5404
5367
 
5405
5368
  parts = []
5406
5369
  parts.append(css_links)
@@ -275,7 +275,7 @@ def minify_output_dir(output_dir: str, extra_skip: Iterable[str] = None, progres
275
275
  # It is already minified and toolchains can corrupt it (e.g. emit ESM exports).
276
276
  # If you still want to re-minify it, do it with Python-only rjsmin.
277
277
  base0 = os.path.basename(full_path)
278
- if ext0 in SAFE_JS_EXT and base0 == 'dars.min.js':
278
+ if ext0 in SAFE_JS_EXT and (base0 in ('dars.min.js', 'dompurify.js') or 'lib' in full_path.split(os.sep)):
279
279
  # Fall back to Python-only rjsmin (never run Vite on this file)
280
280
  try:
281
281
  with open(full_path, 'r', encoding='utf-8') as f:
@@ -6,5 +6,5 @@
6
6
  #
7
7
  # Copyright (c) 2025 ZtaDev
8
8
 
9
- __version__ = "1.9.2"
10
- __release_url__ = "https://github.com/ZtaMDev/Dars-Framework/releases/tag/1.9.2"
9
+ __version__ = "1.9.3"
10
+ __release_url__ = "https://github.com/ZtaMDev/Dars-Framework/releases/tag/1.9.3"
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dars-framework
3
- Version: 1.9.2
3
+ Version: 1.9.3
4
4
  Summary: Dars is a Full-Stack multiplatform Python UI framework for building modern, interactive web and desktop apps with Python code. Seamlessly integrated with FastAPI, it allows you to build complete applications with Server-Side Rendering (SSR) and reactive SPA capabilities also classic multipage html and desktop apps in a single codebase.
5
5
  Author-email: ztamdev <ztadevs@gmail.com>
6
6
  Maintainer-email: ztamdev <ztadevs@gmail.com>
@@ -483,6 +483,7 @@ For complete documentation, see the [Backend API Guide](https://ztamdev.github.i
483
483
  | `dars info my_app.py` | Show info about your app |
484
484
  | `dars formats` | List supported export formats |
485
485
  | `dars dev` | Run the configured entry file with hot preview (app.rTimeCompile) |
486
+ | `dars dev --port 9000` | Run dev server on a custom port (overrides config) |
486
487
  | `dars dev --backend` | Run only the configured backendEntry (FastAPI/SSR backend) |
487
488
  | `dars --help` | Show help and all CLI options |
488
489
 
@@ -516,7 +517,7 @@ Then run your file directly:
516
517
  python my_app.py
517
518
  ```
518
519
 
519
- 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:
520
+ This will start a local server at the port specified in your `dars.config.json` (defaults to http://localhost:8000) so you can view your app in the browser—no manual export needed. You can override the port with:
520
521
 
521
522
  ```bash
522
523
  python my_app.py --port 8088
@@ -554,6 +555,7 @@ Example default:
554
555
  "utility_styles": {},
555
556
  "markdownHighlight": true,
556
557
  "markdownHighlightTheme": "auto",
558
+ "port": 8000,
557
559
  "backendEntry": "backend.api:app"
558
560
  }
559
561
  ```
@@ -569,6 +571,7 @@ Example default:
569
571
  - `utility_styles`: Dictionary defining custom utility classes. Keys are class names, values are lists of utility strings or raw CSS properties.
570
572
  - `markdownHighlight`: Auto-inject a client-side syntax highlighter for fenced code blocks in Markdown. Default `true`.
571
573
  - `backendEntry`: Python import path for your SSR/backend app (e.g. `"backend.api:app"`). Required when your app uses `RouteType.SSR` routes. Used by `dars dev --backend`.
574
+ - `port`: The port for the development preview server. Default `8000`.
572
575
 
573
576
  Validate your config:
574
577
 
@@ -8,7 +8,6 @@ dars/actionProtocol.py
8
8
  dars/all.py
9
9
  dars/config.py
10
10
  dars/env.py
11
- dars/js_lib.py
12
11
  dars/security.py
13
12
  dars/version.py
14
13
  dars/backend/__init__.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "dars-framework"
7
- version = "1.9.2"
7
+ version = "1.9.3"
8
8
  description = "Dars is a Full-Stack multiplatform Python UI framework for building modern, interactive web and desktop apps with Python code. Seamlessly integrated with FastAPI, it allows you to build complete applications with Server-Side Rendering (SSR) and reactive SPA capabilities also classic multipage html and desktop apps in a single codebase."
9
9
  dependencies = [ "rich==15.0.0", "bs4==0.0.2", "uvicorn==0.46.0", "markdown2==2.5.5", "requests==2.33.1", "plotly==6.7.0", "fastapi==0.136.1", "rjsmin==1.2.5", "rcssmin==1.2.2",]
10
10
  license = "MPL-2.0"