scitex 2.7.0__py3-none-any.whl → 2.8.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (355) hide show
  1. scitex/__init__.py +6 -2
  2. scitex/__version__.py +1 -1
  3. scitex/audio/README.md +52 -0
  4. scitex/audio/__init__.py +384 -0
  5. scitex/audio/__main__.py +129 -0
  6. scitex/audio/_tts.py +334 -0
  7. scitex/audio/engines/__init__.py +44 -0
  8. scitex/audio/engines/base.py +275 -0
  9. scitex/audio/engines/elevenlabs_engine.py +143 -0
  10. scitex/audio/engines/gtts_engine.py +162 -0
  11. scitex/audio/engines/pyttsx3_engine.py +131 -0
  12. scitex/audio/mcp_server.py +757 -0
  13. scitex/bridge/_helpers.py +1 -1
  14. scitex/bridge/_plt_vis.py +1 -1
  15. scitex/bridge/_stats_vis.py +1 -1
  16. scitex/dev/plt/__init__.py +272 -0
  17. scitex/dev/plt/plot_mpl_axhline.py +28 -0
  18. scitex/dev/plt/plot_mpl_axhspan.py +28 -0
  19. scitex/dev/plt/plot_mpl_axvline.py +28 -0
  20. scitex/dev/plt/plot_mpl_axvspan.py +28 -0
  21. scitex/dev/plt/plot_mpl_bar.py +29 -0
  22. scitex/dev/plt/plot_mpl_barh.py +29 -0
  23. scitex/dev/plt/plot_mpl_boxplot.py +28 -0
  24. scitex/dev/plt/plot_mpl_contour.py +31 -0
  25. scitex/dev/plt/plot_mpl_contourf.py +31 -0
  26. scitex/dev/plt/plot_mpl_errorbar.py +30 -0
  27. scitex/dev/plt/plot_mpl_eventplot.py +28 -0
  28. scitex/dev/plt/plot_mpl_fill.py +30 -0
  29. scitex/dev/plt/plot_mpl_fill_between.py +31 -0
  30. scitex/dev/plt/plot_mpl_hexbin.py +28 -0
  31. scitex/dev/plt/plot_mpl_hist.py +28 -0
  32. scitex/dev/plt/plot_mpl_hist2d.py +28 -0
  33. scitex/dev/plt/plot_mpl_imshow.py +29 -0
  34. scitex/dev/plt/plot_mpl_pcolormesh.py +31 -0
  35. scitex/dev/plt/plot_mpl_pie.py +29 -0
  36. scitex/dev/plt/plot_mpl_plot.py +29 -0
  37. scitex/dev/plt/plot_mpl_quiver.py +31 -0
  38. scitex/dev/plt/plot_mpl_scatter.py +28 -0
  39. scitex/dev/plt/plot_mpl_stackplot.py +31 -0
  40. scitex/dev/plt/plot_mpl_stem.py +29 -0
  41. scitex/dev/plt/plot_mpl_step.py +29 -0
  42. scitex/dev/plt/plot_mpl_violinplot.py +28 -0
  43. scitex/dev/plt/plot_sns_barplot.py +29 -0
  44. scitex/dev/plt/plot_sns_boxplot.py +29 -0
  45. scitex/dev/plt/plot_sns_heatmap.py +28 -0
  46. scitex/dev/plt/plot_sns_histplot.py +29 -0
  47. scitex/dev/plt/plot_sns_kdeplot.py +29 -0
  48. scitex/dev/plt/plot_sns_lineplot.py +31 -0
  49. scitex/dev/plt/plot_sns_scatterplot.py +29 -0
  50. scitex/dev/plt/plot_sns_stripplot.py +29 -0
  51. scitex/dev/plt/plot_sns_swarmplot.py +29 -0
  52. scitex/dev/plt/plot_sns_violinplot.py +29 -0
  53. scitex/dev/plt/plot_stx_bar.py +29 -0
  54. scitex/dev/plt/plot_stx_barh.py +29 -0
  55. scitex/dev/plt/plot_stx_box.py +28 -0
  56. scitex/dev/plt/plot_stx_boxplot.py +28 -0
  57. scitex/dev/plt/plot_stx_conf_mat.py +28 -0
  58. scitex/dev/plt/plot_stx_contour.py +31 -0
  59. scitex/dev/plt/plot_stx_ecdf.py +28 -0
  60. scitex/dev/plt/plot_stx_errorbar.py +30 -0
  61. scitex/dev/plt/plot_stx_fill_between.py +31 -0
  62. scitex/dev/plt/plot_stx_fillv.py +28 -0
  63. scitex/dev/plt/plot_stx_heatmap.py +28 -0
  64. scitex/dev/plt/plot_stx_image.py +28 -0
  65. scitex/dev/plt/plot_stx_imshow.py +28 -0
  66. scitex/dev/plt/plot_stx_joyplot.py +28 -0
  67. scitex/dev/plt/plot_stx_kde.py +28 -0
  68. scitex/dev/plt/plot_stx_line.py +28 -0
  69. scitex/dev/plt/plot_stx_mean_ci.py +28 -0
  70. scitex/dev/plt/plot_stx_mean_std.py +28 -0
  71. scitex/dev/plt/plot_stx_median_iqr.py +28 -0
  72. scitex/dev/plt/plot_stx_raster.py +28 -0
  73. scitex/dev/plt/plot_stx_rectangle.py +28 -0
  74. scitex/dev/plt/plot_stx_scatter.py +29 -0
  75. scitex/dev/plt/plot_stx_shaded_line.py +29 -0
  76. scitex/dev/plt/plot_stx_violin.py +28 -0
  77. scitex/dev/plt/plot_stx_violinplot.py +28 -0
  78. scitex/diagram/README.md +197 -0
  79. scitex/diagram/__init__.py +48 -0
  80. scitex/diagram/_compile.py +312 -0
  81. scitex/diagram/_diagram.py +355 -0
  82. scitex/diagram/_presets.py +173 -0
  83. scitex/diagram/_schema.py +182 -0
  84. scitex/diagram/_split.py +278 -0
  85. scitex/fig/__init__.py +352 -0
  86. scitex/{vis → fig}/backend/_parser.py +1 -1
  87. scitex/{vis → fig}/canvas.py +1 -1
  88. scitex/{vis → fig}/editor/__init__.py +5 -2
  89. scitex/{vis → fig}/editor/_dearpygui_editor.py +1 -1
  90. scitex/{vis → fig}/editor/_defaults.py +70 -5
  91. scitex/{vis → fig}/editor/_mpl_editor.py +1 -1
  92. scitex/{vis → fig}/editor/_qt_editor.py +182 -2
  93. scitex/{vis → fig}/editor/_tkinter_editor.py +1 -1
  94. scitex/fig/editor/edit/__init__.py +50 -0
  95. scitex/fig/editor/edit/backend_detector.py +109 -0
  96. scitex/fig/editor/edit/bundle_resolver.py +240 -0
  97. scitex/fig/editor/edit/editor_launcher.py +239 -0
  98. scitex/fig/editor/edit/manual_handler.py +53 -0
  99. scitex/fig/editor/edit/panel_loader.py +232 -0
  100. scitex/fig/editor/edit/path_resolver.py +67 -0
  101. scitex/fig/editor/flask_editor/_bbox.py +1299 -0
  102. scitex/fig/editor/flask_editor/_core.py +1429 -0
  103. scitex/{vis → fig}/editor/flask_editor/_plotter.py +38 -4
  104. scitex/fig/editor/flask_editor/_renderer.py +813 -0
  105. scitex/fig/editor/flask_editor/static/css/base/reset.css +41 -0
  106. scitex/fig/editor/flask_editor/static/css/base/typography.css +16 -0
  107. scitex/fig/editor/flask_editor/static/css/base/variables.css +85 -0
  108. scitex/fig/editor/flask_editor/static/css/components/buttons.css +217 -0
  109. scitex/fig/editor/flask_editor/static/css/components/context-menu.css +93 -0
  110. scitex/fig/editor/flask_editor/static/css/components/dropdown.css +57 -0
  111. scitex/fig/editor/flask_editor/static/css/components/forms.css +112 -0
  112. scitex/fig/editor/flask_editor/static/css/components/modal.css +59 -0
  113. scitex/fig/editor/flask_editor/static/css/components/sections.css +212 -0
  114. scitex/fig/editor/flask_editor/static/css/features/canvas.css +176 -0
  115. scitex/fig/editor/flask_editor/static/css/features/element-inspector.css +190 -0
  116. scitex/fig/editor/flask_editor/static/css/features/loading.css +59 -0
  117. scitex/fig/editor/flask_editor/static/css/features/overlay.css +45 -0
  118. scitex/fig/editor/flask_editor/static/css/features/panel-grid.css +95 -0
  119. scitex/fig/editor/flask_editor/static/css/features/selection.css +101 -0
  120. scitex/fig/editor/flask_editor/static/css/features/statistics.css +138 -0
  121. scitex/fig/editor/flask_editor/static/css/index.css +31 -0
  122. scitex/fig/editor/flask_editor/static/css/layout/container.css +7 -0
  123. scitex/fig/editor/flask_editor/static/css/layout/controls.css +56 -0
  124. scitex/fig/editor/flask_editor/static/css/layout/preview.css +78 -0
  125. scitex/fig/editor/flask_editor/static/js/alignment/axis.js +314 -0
  126. scitex/fig/editor/flask_editor/static/js/alignment/basic.js +107 -0
  127. scitex/fig/editor/flask_editor/static/js/alignment/distribute.js +54 -0
  128. scitex/fig/editor/flask_editor/static/js/canvas/canvas.js +172 -0
  129. scitex/fig/editor/flask_editor/static/js/canvas/dragging.js +258 -0
  130. scitex/fig/editor/flask_editor/static/js/canvas/resize.js +48 -0
  131. scitex/fig/editor/flask_editor/static/js/canvas/selection.js +71 -0
  132. scitex/fig/editor/flask_editor/static/js/core/api.js +288 -0
  133. scitex/fig/editor/flask_editor/static/js/core/state.js +143 -0
  134. scitex/fig/editor/flask_editor/static/js/core/utils.js +245 -0
  135. scitex/fig/editor/flask_editor/static/js/dev/element-inspector.js +992 -0
  136. scitex/fig/editor/flask_editor/static/js/editor/bbox.js +339 -0
  137. scitex/fig/editor/flask_editor/static/js/editor/element-drag.js +286 -0
  138. scitex/fig/editor/flask_editor/static/js/editor/overlay.js +371 -0
  139. scitex/fig/editor/flask_editor/static/js/editor/preview.js +293 -0
  140. scitex/fig/editor/flask_editor/static/js/main.js +426 -0
  141. scitex/fig/editor/flask_editor/static/js/shortcuts/context-menu.js +152 -0
  142. scitex/fig/editor/flask_editor/static/js/shortcuts/keyboard.js +265 -0
  143. scitex/fig/editor/flask_editor/static/js/ui/controls.js +184 -0
  144. scitex/fig/editor/flask_editor/static/js/ui/download.js +57 -0
  145. scitex/fig/editor/flask_editor/static/js/ui/help.js +100 -0
  146. scitex/fig/editor/flask_editor/static/js/ui/theme.js +34 -0
  147. scitex/fig/editor/flask_editor/templates/__init__.py +123 -0
  148. scitex/fig/editor/flask_editor/templates/_html.py +852 -0
  149. scitex/fig/editor/flask_editor/templates/_scripts.py +4933 -0
  150. scitex/fig/editor/flask_editor/templates/_styles.py +1658 -0
  151. scitex/{vis → fig}/io/__init__.py +13 -1
  152. scitex/fig/io/_bundle.py +1058 -0
  153. scitex/{vis → fig}/io/_canvas.py +1 -1
  154. scitex/{vis → fig}/io/_data.py +1 -1
  155. scitex/{vis → fig}/io/_export.py +1 -1
  156. scitex/{vis → fig}/io/_load.py +1 -1
  157. scitex/{vis → fig}/io/_panel.py +1 -1
  158. scitex/{vis → fig}/io/_save.py +1 -1
  159. scitex/{vis → fig}/model/__init__.py +1 -1
  160. scitex/{vis → fig}/model/_annotations.py +1 -1
  161. scitex/{vis → fig}/model/_axes.py +1 -1
  162. scitex/{vis → fig}/model/_figure.py +1 -1
  163. scitex/{vis → fig}/model/_guides.py +1 -1
  164. scitex/{vis → fig}/model/_plot.py +1 -1
  165. scitex/{vis → fig}/model/_styles.py +1 -1
  166. scitex/{vis → fig}/utils/__init__.py +1 -1
  167. scitex/io/__init__.py +22 -26
  168. scitex/io/_bundle.py +493 -0
  169. scitex/io/_flush.py +5 -2
  170. scitex/io/_load.py +98 -0
  171. scitex/io/_load_modules/_H5Explorer.py +5 -2
  172. scitex/io/_load_modules/_canvas.py +2 -2
  173. scitex/io/_load_modules/_image.py +3 -4
  174. scitex/io/_load_modules/_txt.py +4 -2
  175. scitex/io/_metadata.py +34 -324
  176. scitex/io/_metadata_modules/__init__.py +46 -0
  177. scitex/io/_metadata_modules/_embed.py +70 -0
  178. scitex/io/_metadata_modules/_read.py +64 -0
  179. scitex/io/_metadata_modules/_utils.py +79 -0
  180. scitex/io/_metadata_modules/embed_metadata_jpeg.py +74 -0
  181. scitex/io/_metadata_modules/embed_metadata_pdf.py +53 -0
  182. scitex/io/_metadata_modules/embed_metadata_png.py +26 -0
  183. scitex/io/_metadata_modules/embed_metadata_svg.py +62 -0
  184. scitex/io/_metadata_modules/read_metadata_jpeg.py +57 -0
  185. scitex/io/_metadata_modules/read_metadata_pdf.py +51 -0
  186. scitex/io/_metadata_modules/read_metadata_png.py +39 -0
  187. scitex/io/_metadata_modules/read_metadata_svg.py +44 -0
  188. scitex/io/_qr_utils.py +5 -3
  189. scitex/io/_save.py +548 -30
  190. scitex/io/_save_modules/_canvas.py +3 -3
  191. scitex/io/_save_modules/_image.py +5 -9
  192. scitex/io/_save_modules/_tex.py +7 -4
  193. scitex/io/_zip_bundle.py +439 -0
  194. scitex/io/utils/h5_to_zarr.py +11 -9
  195. scitex/msword/__init__.py +255 -0
  196. scitex/msword/profiles.py +357 -0
  197. scitex/msword/reader.py +753 -0
  198. scitex/msword/utils.py +289 -0
  199. scitex/msword/writer.py +362 -0
  200. scitex/plt/__init__.py +5 -2
  201. scitex/plt/_subplots/_AxesWrapper.py +6 -6
  202. scitex/plt/_subplots/_AxisWrapper.py +15 -9
  203. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/__init__.py +36 -0
  204. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_labels.py +264 -0
  205. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_metadata.py +213 -0
  206. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin/_visual.py +128 -0
  207. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +59 -0
  208. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_base.py +34 -0
  209. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_scientific.py +593 -0
  210. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_statistical.py +654 -0
  211. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/_stx_aliases.py +527 -0
  212. scitex/plt/_subplots/_AxisWrapperMixins/_RawMatplotlibMixin.py +321 -0
  213. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/__init__.py +33 -0
  214. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_base.py +152 -0
  215. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin/_wrappers.py +600 -0
  216. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +79 -5
  217. scitex/plt/_subplots/_FigWrapper.py +6 -6
  218. scitex/plt/_subplots/_SubplotsWrapper.py +28 -18
  219. scitex/plt/_subplots/_export_as_csv.py +35 -5
  220. scitex/plt/_subplots/_export_as_csv_formatters/__init__.py +8 -0
  221. scitex/plt/_subplots/_export_as_csv_formatters/_format_annotate.py +10 -21
  222. scitex/plt/_subplots/_export_as_csv_formatters/_format_eventplot.py +18 -7
  223. scitex/plt/_subplots/_export_as_csv_formatters/_format_imshow2d.py +28 -12
  224. scitex/plt/_subplots/_export_as_csv_formatters/_format_matshow.py +10 -4
  225. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_imshow.py +13 -1
  226. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_kde.py +12 -2
  227. scitex/plt/_subplots/_export_as_csv_formatters/_format_plot_scatter.py +10 -3
  228. scitex/plt/_subplots/_export_as_csv_formatters/_format_quiver.py +10 -4
  229. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_jointplot.py +18 -3
  230. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_lineplot.py +44 -36
  231. scitex/plt/_subplots/_export_as_csv_formatters/_format_sns_pairplot.py +14 -2
  232. scitex/plt/_subplots/_export_as_csv_formatters/_format_streamplot.py +11 -5
  233. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_bar.py +84 -0
  234. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_barh.py +85 -0
  235. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_conf_mat.py +14 -3
  236. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_contour.py +54 -0
  237. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_ecdf.py +14 -2
  238. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_errorbar.py +120 -0
  239. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_heatmap.py +16 -6
  240. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_image.py +29 -19
  241. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_imshow.py +63 -0
  242. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_joyplot.py +22 -5
  243. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_mean_ci.py +18 -14
  244. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_mean_std.py +18 -14
  245. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_median_iqr.py +18 -14
  246. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_raster.py +10 -2
  247. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter.py +51 -0
  248. scitex/plt/_subplots/_export_as_csv_formatters/_format_stx_scatter_hist.py +18 -9
  249. scitex/plt/ax/_plot/_stx_ecdf.py +4 -2
  250. scitex/plt/gallery/_generate.py +421 -14
  251. scitex/plt/io/__init__.py +53 -0
  252. scitex/plt/io/_bundle.py +490 -0
  253. scitex/plt/io/_layered_bundle.py +1343 -0
  254. scitex/plt/styles/SCITEX_STYLE.yaml +26 -0
  255. scitex/plt/styles/__init__.py +14 -0
  256. scitex/plt/styles/presets.py +78 -0
  257. scitex/plt/utils/__init__.py +13 -1
  258. scitex/plt/utils/_collect_figure_metadata.py +10 -14
  259. scitex/plt/utils/_configure_mpl.py +6 -18
  260. scitex/plt/utils/_crop.py +32 -14
  261. scitex/plt/utils/_csv_column_naming.py +54 -0
  262. scitex/plt/utils/_figure_mm.py +116 -1
  263. scitex/plt/utils/_hitmap.py +1643 -0
  264. scitex/plt/utils/metadata/__init__.py +25 -0
  265. scitex/plt/utils/metadata/_core.py +9 -10
  266. scitex/plt/utils/metadata/_dimensions.py +6 -3
  267. scitex/plt/utils/metadata/_editable_export.py +405 -0
  268. scitex/plt/utils/metadata/_geometry_extraction.py +570 -0
  269. scitex/schema/__init__.py +109 -16
  270. scitex/schema/_canvas.py +1 -1
  271. scitex/schema/_plot.py +1015 -0
  272. scitex/schema/_stats.py +2 -2
  273. scitex/stats/__init__.py +117 -0
  274. scitex/stats/io/__init__.py +29 -0
  275. scitex/stats/io/_bundle.py +156 -0
  276. scitex/tex/__init__.py +4 -0
  277. scitex/tex/_export.py +890 -0
  278. {scitex-2.7.0.dist-info → scitex-2.8.1.dist-info}/METADATA +11 -1
  279. {scitex-2.7.0.dist-info → scitex-2.8.1.dist-info}/RECORD +294 -170
  280. scitex/io/memo.md +0 -2827
  281. scitex/plt/REQUESTS.md +0 -191
  282. scitex/plt/_subplots/TODO.md +0 -53
  283. scitex/plt/_subplots/_AxisWrapperMixins/_AdjustmentMixin.py +0 -559
  284. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin.py +0 -1609
  285. scitex/plt/_subplots/_AxisWrapperMixins/_SeabornMixin.py +0 -447
  286. scitex/plt/templates/research-master/scitex/vis/gallery/area/fill_between.json +0 -110
  287. scitex/plt/templates/research-master/scitex/vis/gallery/area/fill_betweenx.json +0 -88
  288. scitex/plt/templates/research-master/scitex/vis/gallery/area/stx_fill_between.json +0 -103
  289. scitex/plt/templates/research-master/scitex/vis/gallery/area/stx_fillv.json +0 -106
  290. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/bar.json +0 -92
  291. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/barh.json +0 -92
  292. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/boxplot.json +0 -92
  293. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_bar.json +0 -84
  294. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_barh.json +0 -84
  295. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_box.json +0 -83
  296. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_boxplot.json +0 -93
  297. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_violin.json +0 -91
  298. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/stx_violinplot.json +0 -91
  299. scitex/plt/templates/research-master/scitex/vis/gallery/categorical/violinplot.json +0 -91
  300. scitex/plt/templates/research-master/scitex/vis/gallery/contour/contour.json +0 -97
  301. scitex/plt/templates/research-master/scitex/vis/gallery/contour/contourf.json +0 -98
  302. scitex/plt/templates/research-master/scitex/vis/gallery/contour/stx_contour.json +0 -84
  303. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/hist.json +0 -101
  304. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/hist2d.json +0 -96
  305. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_ecdf.json +0 -95
  306. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_joyplot.json +0 -95
  307. scitex/plt/templates/research-master/scitex/vis/gallery/distribution/stx_kde.json +0 -93
  308. scitex/plt/templates/research-master/scitex/vis/gallery/grid/imshow.json +0 -95
  309. scitex/plt/templates/research-master/scitex/vis/gallery/grid/matshow.json +0 -95
  310. scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_conf_mat.json +0 -83
  311. scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_heatmap.json +0 -92
  312. scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_image.json +0 -121
  313. scitex/plt/templates/research-master/scitex/vis/gallery/grid/stx_imshow.json +0 -84
  314. scitex/plt/templates/research-master/scitex/vis/gallery/line/plot.json +0 -110
  315. scitex/plt/templates/research-master/scitex/vis/gallery/line/step.json +0 -92
  316. scitex/plt/templates/research-master/scitex/vis/gallery/line/stx_line.json +0 -95
  317. scitex/plt/templates/research-master/scitex/vis/gallery/line/stx_shaded_line.json +0 -96
  318. scitex/plt/templates/research-master/scitex/vis/gallery/scatter/hexbin.json +0 -95
  319. scitex/plt/templates/research-master/scitex/vis/gallery/scatter/scatter.json +0 -95
  320. scitex/plt/templates/research-master/scitex/vis/gallery/scatter/stem.json +0 -92
  321. scitex/plt/templates/research-master/scitex/vis/gallery/scatter/stx_scatter.json +0 -84
  322. scitex/plt/templates/research-master/scitex/vis/gallery/special/pie.json +0 -94
  323. scitex/plt/templates/research-master/scitex/vis/gallery/special/stx_raster.json +0 -109
  324. scitex/plt/templates/research-master/scitex/vis/gallery/special/stx_rectangle.json +0 -108
  325. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/errorbar.json +0 -93
  326. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_errorbar.json +0 -84
  327. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_mean_ci.json +0 -96
  328. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_mean_std.json +0 -96
  329. scitex/plt/templates/research-master/scitex/vis/gallery/statistical/stx_median_iqr.json +0 -96
  330. scitex/plt/templates/research-master/scitex/vis/gallery/vector/quiver.json +0 -99
  331. scitex/plt/templates/research-master/scitex/vis/gallery/vector/streamplot.json +0 -100
  332. scitex/vis/__init__.py +0 -177
  333. scitex/vis/editor/_edit.py +0 -390
  334. scitex/vis/editor/flask_editor/_bbox.py +0 -529
  335. scitex/vis/editor/flask_editor/_core.py +0 -168
  336. scitex/vis/editor/flask_editor/_renderer.py +0 -393
  337. scitex/vis/editor/flask_editor/templates/__init__.py +0 -33
  338. scitex/vis/editor/flask_editor/templates/_html.py +0 -513
  339. scitex/vis/editor/flask_editor/templates/_scripts.py +0 -1261
  340. scitex/vis/editor/flask_editor/templates/_styles.py +0 -739
  341. /scitex/{vis → fig}/README.md +0 -0
  342. /scitex/{vis → fig}/backend/__init__.py +0 -0
  343. /scitex/{vis → fig}/backend/_export.py +0 -0
  344. /scitex/{vis → fig}/backend/_render.py +0 -0
  345. /scitex/{vis → fig}/docs/CANVAS_ARCHITECTURE.md +0 -0
  346. /scitex/{vis → fig}/editor/_flask_editor.py +0 -0
  347. /scitex/{vis → fig}/editor/flask_editor/__init__.py +0 -0
  348. /scitex/{vis → fig}/editor/flask_editor/_utils.py +0 -0
  349. /scitex/{vis → fig}/io/_directory.py +0 -0
  350. /scitex/{vis → fig}/model/_plot_types.py +0 -0
  351. /scitex/{vis → fig}/utils/_defaults.py +0 -0
  352. /scitex/{vis → fig}/utils/_validate.py +0 -0
  353. {scitex-2.7.0.dist-info → scitex-2.8.1.dist-info}/WHEEL +0 -0
  354. {scitex-2.7.0.dist-info → scitex-2.8.1.dist-info}/entry_points.txt +0 -0
  355. {scitex-2.7.0.dist-info → scitex-2.8.1.dist-info}/licenses/LICENSE +0 -0
@@ -0,0 +1,992 @@
1
+ /**
2
+ * Element Inspector - Visual Debugging Tool
3
+ * Shows all HTML elements with colored rectangles and labels.
4
+ *
5
+ * Shortcuts:
6
+ * Alt+I: Toggle inspector overlay
7
+ * Ctrl+Alt+I: Rectangle selection mode
8
+ * Ctrl+Shift+I: Debug snapshot (console logs + page info)
9
+ * Escape: Deactivate inspector / Cancel selection
10
+ */
11
+
12
+ (function() {
13
+ 'use strict';
14
+
15
+ // ============================================================================
16
+ // State
17
+ // ============================================================================
18
+ var isActive = false;
19
+ var overlayContainer = null;
20
+ var elementBoxMap = new Map();
21
+ var currentlyHoveredBox = null;
22
+ var currentlyHoveredElement = null;
23
+ var consoleLogs = [];
24
+ var maxLogs = 500;
25
+ var onCopyCallback = null;
26
+
27
+ // Selection mode state
28
+ var selectionMode = false;
29
+ var selectionStart = null;
30
+ var selectionRect = null;
31
+ var selectionOverlay = null;
32
+ var currentlySelectedElements = new Set();
33
+
34
+ // ============================================================================
35
+ // Console Capture (start immediately)
36
+ // ============================================================================
37
+ var originalConsole = {
38
+ log: console.log.bind(console),
39
+ warn: console.warn.bind(console),
40
+ error: console.error.bind(console),
41
+ info: console.info.bind(console)
42
+ };
43
+
44
+ function captureLog(type, args) {
45
+ var entry = {
46
+ type: type,
47
+ timestamp: new Date().toISOString(),
48
+ args: args.map(function(arg) { return stringify(arg); }),
49
+ source: getCallSource()
50
+ };
51
+ consoleLogs.push(entry);
52
+ if (consoleLogs.length > maxLogs) {
53
+ consoleLogs.shift();
54
+ }
55
+ }
56
+
57
+ function getCallSource() {
58
+ try {
59
+ var stack = new Error().stack;
60
+ if (!stack) return '';
61
+ var lines = stack.split('\n');
62
+ for (var i = 4; i < lines.length; i++) {
63
+ var line = lines[i];
64
+ var match = line.match(/(?:at\s+)?(?:.*?\s+\()?([^\s()]+):(\d+):(\d+)\)?$/);
65
+ if (match) {
66
+ var file = match[1];
67
+ var lineNum = match[2];
68
+ var fileName = file.split('/').pop() || file;
69
+ if (fileName.includes('element-inspector')) continue;
70
+ return fileName + ':' + lineNum;
71
+ }
72
+ }
73
+ } catch (e) {}
74
+ return '';
75
+ }
76
+
77
+ function stringify(obj) {
78
+ if (obj === null) return 'null';
79
+ if (obj === undefined) return 'undefined';
80
+ if (typeof obj === 'string') return obj;
81
+ if (typeof obj === 'number' || typeof obj === 'boolean') return String(obj);
82
+ if (obj instanceof Error) {
83
+ return obj.name + ': ' + obj.message + '\n' + (obj.stack || '');
84
+ }
85
+ try {
86
+ return JSON.stringify(obj, null, 2);
87
+ } catch (e) {
88
+ return String(obj);
89
+ }
90
+ }
91
+
92
+ // Override console methods
93
+ console.log = function() {
94
+ captureLog('log', Array.from(arguments));
95
+ originalConsole.log.apply(console, arguments);
96
+ };
97
+ console.warn = function() {
98
+ captureLog('warn', Array.from(arguments));
99
+ originalConsole.warn.apply(console, arguments);
100
+ };
101
+ console.error = function() {
102
+ captureLog('error', Array.from(arguments));
103
+ originalConsole.error.apply(console, arguments);
104
+ };
105
+ console.info = function() {
106
+ captureLog('info', Array.from(arguments));
107
+ originalConsole.info.apply(console, arguments);
108
+ };
109
+
110
+ // ============================================================================
111
+ // Notification Manager
112
+ // ============================================================================
113
+ function showNotification(message, type) {
114
+ var notification = document.createElement('div');
115
+ notification.className = 'element-inspector-notification ' + type;
116
+ notification.textContent = message;
117
+ document.body.appendChild(notification);
118
+
119
+ requestAnimationFrame(function() {
120
+ notification.classList.add('visible');
121
+ });
122
+
123
+ setTimeout(function() {
124
+ notification.classList.remove('visible');
125
+ setTimeout(function() { notification.remove(); }, 200);
126
+ }, 1000);
127
+ }
128
+
129
+ function showCameraFlash() {
130
+ var flash = document.createElement('div');
131
+ flash.className = 'camera-flash';
132
+ document.body.appendChild(flash);
133
+ setTimeout(function() { flash.remove(); }, 300);
134
+ }
135
+
136
+ function triggerCopyCallback() {
137
+ if (onCopyCallback) {
138
+ setTimeout(function() {
139
+ onCopyCallback();
140
+ }, 400);
141
+ }
142
+ }
143
+
144
+ // ============================================================================
145
+ // Debug Info Collector
146
+ // ============================================================================
147
+ function buildCSSSelector(element) {
148
+ var tag = element.tagName.toLowerCase();
149
+ var id = element.id;
150
+ var classes = element.className;
151
+
152
+ var selector = tag;
153
+ if (id) selector += '#' + id;
154
+ if (classes && typeof classes === 'string') {
155
+ var classList = classes.split(/\s+/).filter(function(c) { return c; });
156
+ if (classList.length > 0) {
157
+ selector += '.' + classList.join('.');
158
+ }
159
+ }
160
+ return selector;
161
+ }
162
+
163
+ function getXPath(element) {
164
+ if (element.id) {
165
+ return '//*[@id="' + element.id + '"]';
166
+ }
167
+
168
+ var parts = [];
169
+ var current = element;
170
+
171
+ while (current && current.nodeType === Node.ELEMENT_NODE) {
172
+ var index = 0;
173
+ var sibling = current.previousSibling;
174
+
175
+ while (sibling) {
176
+ if (sibling.nodeType === Node.ELEMENT_NODE && sibling.nodeName === current.nodeName) {
177
+ index++;
178
+ }
179
+ sibling = sibling.previousSibling;
180
+ }
181
+
182
+ var tagName = current.nodeName.toLowerCase();
183
+ var pathIndex = index > 0 ? '[' + (index + 1) + ']' : '';
184
+ parts.unshift(tagName + pathIndex);
185
+ current = current.parentElement;
186
+ }
187
+
188
+ return '/' + parts.join('/');
189
+ }
190
+
191
+ function getParentChain(element) {
192
+ var chain = [];
193
+ var current = element.parentElement;
194
+ var depth = 0;
195
+
196
+ while (current && depth < 5) {
197
+ chain.push(buildCSSSelector(current));
198
+ current = current.parentElement;
199
+ depth++;
200
+ }
201
+
202
+ return chain;
203
+ }
204
+
205
+ function gatherElementDebugInfo(element) {
206
+ var info = {};
207
+
208
+ info.url = window.location.href;
209
+ info.timestamp = new Date().toISOString();
210
+
211
+ var className = typeof element.className === 'string' ? element.className : '';
212
+ info.element = {
213
+ tag: element.tagName.toLowerCase(),
214
+ id: element.id || null,
215
+ classes: className ? className.split(/\s+/).filter(function(c) { return c; }) : [],
216
+ selector: buildCSSSelector(element),
217
+ xpath: getXPath(element)
218
+ };
219
+
220
+ info.attributes = {};
221
+ for (var i = 0; i < element.attributes.length; i++) {
222
+ var attr = element.attributes[i];
223
+ info.attributes[attr.name] = attr.value;
224
+ }
225
+
226
+ if (element instanceof HTMLElement) {
227
+ var computed = window.getComputedStyle(element);
228
+ info.styles = {
229
+ display: computed.display,
230
+ position: computed.position,
231
+ width: computed.width,
232
+ height: computed.height,
233
+ backgroundColor: computed.backgroundColor,
234
+ color: computed.color,
235
+ fontSize: computed.fontSize
236
+ };
237
+
238
+ var rect = element.getBoundingClientRect();
239
+ info.dimensions = {
240
+ width: rect.width,
241
+ height: rect.height,
242
+ top: rect.top,
243
+ left: rect.left
244
+ };
245
+
246
+ info.content = {
247
+ textContent: (element.textContent || '').substring(0, 200)
248
+ };
249
+ }
250
+
251
+ info.parentChain = getParentChain(element);
252
+
253
+ return formatDebugInfoForAI(info);
254
+ }
255
+
256
+ function formatDebugInfoForAI(info) {
257
+ return '# Element Debug Information\n\n' +
258
+ '## Page Context\n' +
259
+ '- URL: ' + info.url + '\n' +
260
+ '- Timestamp: ' + info.timestamp + '\n\n' +
261
+ '## Element Identification\n' +
262
+ '- Tag: <' + info.element.tag + '>\n' +
263
+ '- ID: ' + (info.element.id || 'none') + '\n' +
264
+ '- Classes: ' + (info.element.classes.join(', ') || 'none') + '\n' +
265
+ '- CSS Selector: ' + info.element.selector + '\n' +
266
+ '- XPath: ' + info.element.xpath + '\n\n' +
267
+ '## Attributes\n' +
268
+ Object.entries(info.attributes).map(function(entry) {
269
+ return '- ' + entry[0] + ': ' + entry[1];
270
+ }).join('\n') + '\n\n' +
271
+ '## Computed Styles\n' +
272
+ Object.entries(info.styles || {}).map(function(entry) {
273
+ return '- ' + entry[0] + ': ' + entry[1];
274
+ }).join('\n') + '\n\n' +
275
+ '## Dimensions & Position\n' +
276
+ '- Width: ' + (info.dimensions ? info.dimensions.width : 0) + 'px\n' +
277
+ '- Height: ' + (info.dimensions ? info.dimensions.height : 0) + 'px\n' +
278
+ '- Top: ' + (info.dimensions ? info.dimensions.top : 0) + 'px\n' +
279
+ '- Left: ' + (info.dimensions ? info.dimensions.left : 0) + 'px\n\n' +
280
+ '## Content (truncated)\n' +
281
+ (info.content ? info.content.textContent : 'none') + '\n\n' +
282
+ '## Parent Chain\n' +
283
+ info.parentChain.map(function(p, i) { return (i + 1) + '. ' + p; }).join('\n') + '\n\n' +
284
+ '---\nGenerated by Element Inspector';
285
+ }
286
+
287
+ // ============================================================================
288
+ // Element Scanner
289
+ // ============================================================================
290
+ function getDepth(element) {
291
+ var depth = 0;
292
+ var current = element;
293
+
294
+ while (current && current !== document.body) {
295
+ depth++;
296
+ current = current.parentElement;
297
+ }
298
+
299
+ return depth;
300
+ }
301
+
302
+ function getColorForDepth(depth) {
303
+ var colors = [
304
+ '#3B82F6', // Blue (depth 0-2)
305
+ '#10B981', // Green (depth 3-5)
306
+ '#F59E0B', // Yellow (depth 6-8)
307
+ '#EF4444', // Red (depth 9-11)
308
+ '#EC4899' // Pink (depth 12+)
309
+ ];
310
+
311
+ var index = Math.min(Math.floor(depth / 3), colors.length - 1);
312
+ return colors[index];
313
+ }
314
+
315
+ function shouldShowLabel(element, rect, depth) {
316
+ if (element.id) {
317
+ return rect.width > 20 && rect.height > 20;
318
+ }
319
+ if (rect.width > 100 || rect.height > 100) {
320
+ return true;
321
+ }
322
+ var importantTags = ['header', 'nav', 'main', 'section', 'article', 'aside', 'footer', 'form', 'table'];
323
+ if (importantTags.indexOf(element.tagName.toLowerCase()) !== -1 && (rect.width > 50 || rect.height > 50)) {
324
+ return true;
325
+ }
326
+ var interactiveTags = ['button', 'a', 'input', 'select', 'textarea'];
327
+ if (interactiveTags.indexOf(element.tagName.toLowerCase()) !== -1 && (rect.width > 30 || rect.height > 30)) {
328
+ return true;
329
+ }
330
+ if (depth > 8 && rect.width < 100 && rect.height < 100) {
331
+ return false;
332
+ }
333
+ return false;
334
+ }
335
+
336
+ function scanElements(container) {
337
+ var allElements = document.querySelectorAll('*');
338
+ var count = 0;
339
+ var occupiedPositions = [];
340
+
341
+ allElements.forEach(function(element) {
342
+ if (element.closest('#element-inspector-overlay')) return;
343
+
344
+ if (element instanceof HTMLElement) {
345
+ var computed = window.getComputedStyle(element);
346
+ if (computed.display === 'none' || computed.visibility === 'hidden') return;
347
+ }
348
+
349
+ var depth = getDepth(element);
350
+ var color = getColorForDepth(depth);
351
+
352
+ var rect = element.getBoundingClientRect();
353
+ if (rect.width === 0 || rect.height === 0) return;
354
+
355
+ var box = document.createElement('div');
356
+ box.className = 'element-inspector-box';
357
+ box.style.cssText =
358
+ 'top: ' + (rect.top + window.scrollY) + 'px;' +
359
+ 'left: ' + (rect.left + window.scrollX) + 'px;' +
360
+ 'width: ' + rect.width + 'px;' +
361
+ 'height: ' + rect.height + 'px;' +
362
+ 'border-color: ' + color + ';';
363
+
364
+ var tag = element.tagName.toLowerCase();
365
+ var id = element.id ? '#' + element.id : '';
366
+ box.title = 'Click to copy debug info: ' + tag + id;
367
+
368
+ elementBoxMap.set(box, element);
369
+
370
+ box.addEventListener('mouseenter', function() {
371
+ currentlyHoveredBox = box;
372
+ currentlyHoveredElement = element;
373
+ });
374
+
375
+ box.addEventListener('mouseleave', function() {
376
+ if (currentlyHoveredBox === box) {
377
+ currentlyHoveredBox = null;
378
+ currentlyHoveredElement = null;
379
+ }
380
+ });
381
+
382
+ box.addEventListener('click', function(e) {
383
+ e.preventDefault();
384
+ e.stopPropagation();
385
+
386
+ var selectedElement = currentlyHoveredElement || element;
387
+ var selectedBox = currentlyHoveredBox || box;
388
+
389
+ selectedBox.classList.add('highlighted');
390
+
391
+ var debugInfo = gatherElementDebugInfo(selectedElement);
392
+ navigator.clipboard.writeText(debugInfo).then(function() {
393
+ showNotification('✓ Copied!', 'success');
394
+ console.log('[ElementInspector] Copied:', debugInfo);
395
+ triggerCopyCallback();
396
+ }).catch(function(err) {
397
+ console.error('[ElementInspector] Copy failed:', err);
398
+ showNotification('✗ Copy Failed', 'error');
399
+ selectedBox.classList.remove('highlighted');
400
+ });
401
+ });
402
+
403
+ if (shouldShowLabel(element, rect, depth)) {
404
+ var label = createLabel(element, depth);
405
+ if (label) {
406
+ var labelPos = findLabelPosition(rect, occupiedPositions);
407
+ if (labelPos.isValid) {
408
+ label.style.top = labelPos.top + 'px';
409
+ label.style.left = labelPos.left + 'px';
410
+ addCopyToClipboard(label, element);
411
+ addHoverHighlight(label, box, element);
412
+
413
+ occupiedPositions.push({
414
+ top: labelPos.top - 8,
415
+ left: labelPos.left - 8,
416
+ bottom: labelPos.top + 20 + 8,
417
+ right: labelPos.left + 250 + 8
418
+ });
419
+
420
+ container.appendChild(label);
421
+ }
422
+ }
423
+ }
424
+
425
+ container.appendChild(box);
426
+ count++;
427
+ });
428
+
429
+ console.log('[ElementInspector] Visualized ' + count + ' elements');
430
+ }
431
+
432
+ function createLabel(element, depth) {
433
+ var tag = element.tagName.toLowerCase();
434
+ var id = element.id;
435
+ var classes = element.className;
436
+
437
+ var labelText = '<span class="element-inspector-label-tag">' + tag + '</span>';
438
+
439
+ if (id) {
440
+ labelText += ' <span class="element-inspector-label-id">#' + id + '</span>';
441
+ }
442
+
443
+ if (classes && typeof classes === 'string') {
444
+ var classList = classes.split(/\s+/).filter(function(c) { return c.length > 0; });
445
+ if (classList.length > 0) {
446
+ var classPreview = classList.slice(0, 2).join('.');
447
+ labelText += ' <span class="element-inspector-label-class">.' + classPreview + '</span>';
448
+ if (classList.length > 2) {
449
+ labelText += '<span class="element-inspector-label-class">+' + (classList.length - 2) + '</span>';
450
+ }
451
+ }
452
+ }
453
+
454
+ if (depth > 5) {
455
+ labelText += ' <span style="color: #999; font-size: 9px;">d' + depth + '</span>';
456
+ }
457
+
458
+ var label = document.createElement('div');
459
+ label.className = 'element-inspector-label';
460
+ label.innerHTML = labelText;
461
+ label.title = 'Click to copy comprehensive debug info for AI';
462
+
463
+ return label;
464
+ }
465
+
466
+ function findLabelPosition(rect, occupiedPositions) {
467
+ var scrollY = window.scrollY;
468
+ var scrollX = window.scrollX;
469
+
470
+ var positions = [
471
+ { top: rect.top + scrollY - 24, left: rect.left + scrollX },
472
+ { top: rect.top + scrollY - 24, left: rect.right + scrollX - 200 },
473
+ { top: rect.top + scrollY + 4, left: rect.left + scrollX + 4 },
474
+ { top: rect.bottom + scrollY + 4, left: rect.left + scrollX }
475
+ ];
476
+
477
+ for (var i = 0; i < positions.length; i++) {
478
+ if (!isPositionOccupied(positions[i], occupiedPositions)) {
479
+ return { top: positions[i].top, left: positions[i].left, isValid: true };
480
+ }
481
+ }
482
+
483
+ return { top: 0, left: 0, isValid: false };
484
+ }
485
+
486
+ function isPositionOccupied(pos, occupiedPositions) {
487
+ var labelWidth = 250;
488
+ var labelHeight = 20;
489
+
490
+ for (var i = 0; i < occupiedPositions.length; i++) {
491
+ var occupied = occupiedPositions[i];
492
+ if (!(pos.left + labelWidth < occupied.left ||
493
+ pos.left > occupied.right ||
494
+ pos.top + labelHeight < occupied.top ||
495
+ pos.top > occupied.bottom)) {
496
+ return true;
497
+ }
498
+ }
499
+ return false;
500
+ }
501
+
502
+ function addHoverHighlight(label, box, element) {
503
+ label.addEventListener('mouseenter', function() {
504
+ currentlyHoveredBox = box;
505
+ currentlyHoveredElement = element;
506
+ box.classList.add('highlighted');
507
+ if (element instanceof HTMLElement) {
508
+ element.style.outline = '3px solid rgba(59, 130, 246, 0.8)';
509
+ element.style.outlineOffset = '2px';
510
+ }
511
+ });
512
+
513
+ label.addEventListener('mouseleave', function() {
514
+ currentlyHoveredBox = null;
515
+ currentlyHoveredElement = null;
516
+ box.classList.remove('highlighted');
517
+ if (element instanceof HTMLElement) {
518
+ element.style.outline = '';
519
+ element.style.outlineOffset = '';
520
+ }
521
+ });
522
+ }
523
+
524
+ function addCopyToClipboard(label, element) {
525
+ label.addEventListener('click', function(e) {
526
+ e.stopPropagation();
527
+ e.preventDefault();
528
+
529
+ var debugInfo = gatherElementDebugInfo(element);
530
+
531
+ navigator.clipboard.writeText(debugInfo).then(function() {
532
+ showNotification('✓ Copied!', 'success');
533
+ console.log('[ElementInspector] Copied debug info to clipboard');
534
+ triggerCopyCallback();
535
+ }).catch(function(err) {
536
+ console.error('[ElementInspector] Failed to copy:', err);
537
+ showNotification('✗ Copy Failed', 'error');
538
+ });
539
+ });
540
+ }
541
+
542
+ // ============================================================================
543
+ // Selection Mode
544
+ // ============================================================================
545
+ function startSelectionMode() {
546
+ if (!isActive) {
547
+ activate();
548
+ }
549
+
550
+ selectionMode = true;
551
+ document.body.classList.add('element-inspector-selection-mode');
552
+
553
+ selectionOverlay = document.createElement('div');
554
+ selectionOverlay.className = 'selection-overlay';
555
+ document.body.appendChild(selectionOverlay);
556
+
557
+ showNotification('Drag to select area', 'success');
558
+
559
+ document.addEventListener('mousedown', onSelectionMouseDown);
560
+ document.addEventListener('mousemove', onSelectionMouseMove);
561
+ document.addEventListener('mouseup', onSelectionMouseUp);
562
+ }
563
+
564
+ function cancelSelectionMode() {
565
+ selectionMode = false;
566
+ document.body.classList.remove('element-inspector-selection-mode');
567
+
568
+ if (selectionOverlay) {
569
+ selectionOverlay.remove();
570
+ selectionOverlay = null;
571
+ }
572
+
573
+ if (selectionRect) {
574
+ selectionRect.remove();
575
+ selectionRect = null;
576
+ }
577
+
578
+ document.removeEventListener('mousedown', onSelectionMouseDown);
579
+ document.removeEventListener('mousemove', onSelectionMouseMove);
580
+ document.removeEventListener('mouseup', onSelectionMouseUp);
581
+
582
+ selectionStart = null;
583
+ currentlySelectedElements.clear();
584
+ }
585
+
586
+ function onSelectionMouseDown(e) {
587
+ if (!selectionMode) return;
588
+
589
+ e.preventDefault();
590
+ selectionStart = { x: e.clientX, y: e.clientY };
591
+
592
+ selectionRect = document.createElement('div');
593
+ selectionRect.className = 'selection-rectangle';
594
+ selectionRect.style.left = e.clientX + 'px';
595
+ selectionRect.style.top = e.clientY + 'px';
596
+ selectionRect.style.width = '0px';
597
+ selectionRect.style.height = '0px';
598
+
599
+ document.body.appendChild(selectionRect);
600
+ }
601
+
602
+ function onSelectionMouseMove(e) {
603
+ if (!selectionMode || !selectionStart || !selectionRect) return;
604
+
605
+ e.preventDefault();
606
+
607
+ var left = Math.min(selectionStart.x, e.clientX);
608
+ var top = Math.min(selectionStart.y, e.clientY);
609
+ var width = Math.abs(e.clientX - selectionStart.x);
610
+ var height = Math.abs(e.clientY - selectionStart.y);
611
+
612
+ selectionRect.style.left = left + 'px';
613
+ selectionRect.style.top = top + 'px';
614
+ selectionRect.style.width = width + 'px';
615
+ selectionRect.style.height = height + 'px';
616
+ }
617
+
618
+ function onSelectionMouseUp(e) {
619
+ if (!selectionMode || !selectionStart || !selectionRect) return;
620
+
621
+ e.preventDefault();
622
+
623
+ var left = Math.min(selectionStart.x, e.clientX);
624
+ var top = Math.min(selectionStart.y, e.clientY);
625
+ var width = Math.abs(e.clientX - selectionStart.x);
626
+ var height = Math.abs(e.clientY - selectionStart.y);
627
+
628
+ if (width < 5 || height < 5) {
629
+ cancelSelectionMode();
630
+ showNotification('Selection too small', 'error');
631
+ return;
632
+ }
633
+
634
+ var selectedElements = findElementsInRect({ left: left, top: top, width: width, height: height });
635
+
636
+ console.log('[ElementInspector] Found ' + selectedElements.length + ' elements in selection');
637
+
638
+ var selectionInfo = gatherSelectionInfo(selectedElements, { left: left, top: top, width: width, height: height });
639
+
640
+ navigator.clipboard.writeText(selectionInfo).then(function() {
641
+ showNotification('✓ ' + selectedElements.length + ' elements copied!', 'success');
642
+ triggerCopyCallback();
643
+ }).catch(function(err) {
644
+ console.error('[ElementInspector] Failed to copy:', err);
645
+ showNotification('✗ Copy Failed', 'error');
646
+ });
647
+
648
+ cancelSelectionMode();
649
+ }
650
+
651
+ function findElementsInRect(rect) {
652
+ var selectedElements = [];
653
+ var allElements = document.querySelectorAll('*');
654
+
655
+ var selectionRect = {
656
+ left: rect.left,
657
+ top: rect.top,
658
+ right: rect.left + rect.width,
659
+ bottom: rect.top + rect.height
660
+ };
661
+
662
+ allElements.forEach(function(element) {
663
+ if (element.closest('#element-inspector-overlay') ||
664
+ element.classList.contains('selection-rectangle') ||
665
+ element.classList.contains('selection-overlay')) {
666
+ return;
667
+ }
668
+
669
+ if (element instanceof HTMLElement) {
670
+ var computed = window.getComputedStyle(element);
671
+ if (computed.display === 'none' || computed.visibility === 'hidden') return;
672
+ }
673
+
674
+ var elementRect = element.getBoundingClientRect();
675
+ var intersects = !(
676
+ elementRect.right < selectionRect.left ||
677
+ elementRect.left > selectionRect.right ||
678
+ elementRect.bottom < selectionRect.top ||
679
+ elementRect.top > selectionRect.bottom
680
+ );
681
+
682
+ if (intersects) {
683
+ selectedElements.push(element);
684
+ }
685
+ });
686
+
687
+ return selectedElements;
688
+ }
689
+
690
+ function gatherSelectionInfo(elements, rect) {
691
+ var info = '# Rectangle Selection Debug Information\n\n' +
692
+ '## Selection Area\n' +
693
+ '- Position: (' + Math.round(rect.left) + ', ' + Math.round(rect.top) + ')\n' +
694
+ '- Size: ' + Math.round(rect.width) + 'x' + Math.round(rect.height) + 'px\n' +
695
+ '- URL: ' + window.location.href + '\n' +
696
+ '- Elements Found: ' + elements.length + '\n\n---\n\n';
697
+
698
+ var elementTypes = {};
699
+ elements.forEach(function(el) {
700
+ var tag = el.tagName.toLowerCase();
701
+ elementTypes[tag] = (elementTypes[tag] || 0) + 1;
702
+ });
703
+
704
+ info += '## Element Type Summary\n';
705
+ Object.entries(elementTypes)
706
+ .sort(function(a, b) { return b[1] - a[1]; })
707
+ .forEach(function(entry) {
708
+ info += '- ' + entry[0] + ': ' + entry[1] + '\n';
709
+ });
710
+
711
+ info += '\n---\n\n## Detailed Element Information (first 10 elements)\n\n';
712
+
713
+ elements.slice(0, 10).forEach(function(element, index) {
714
+ info += '### Element ' + (index + 1) + '\n';
715
+ info += gatherElementDebugInfo(element);
716
+ info += '\n---\n\n';
717
+ });
718
+
719
+ return info;
720
+ }
721
+
722
+ // ============================================================================
723
+ // Debug Snapshot (Screenshot + Console Logs)
724
+ // ============================================================================
725
+ function captureDebugSnapshot() {
726
+ showCameraFlash();
727
+
728
+ // Run screenshot and console log capture in parallel
729
+ Promise.all([
730
+ captureScreenshot(),
731
+ captureConsoleLogs()
732
+ ]).then(function(results) {
733
+ var screenshotOk = results[0];
734
+ var logsOk = results[1];
735
+
736
+ if (screenshotOk && logsOk) {
737
+ showNotification('✓ Screenshot + logs copied', 'success');
738
+ } else if (screenshotOk) {
739
+ showNotification('✓ Screenshot copied', 'success');
740
+ } else if (logsOk) {
741
+ showNotification('✓ Console logs copied', 'success');
742
+ } else {
743
+ showNotification('✗ Capture failed', 'error');
744
+ }
745
+ });
746
+ }
747
+
748
+ function captureScreenshot() {
749
+ return navigator.mediaDevices.getDisplayMedia({
750
+ video: {
751
+ displaySurface: 'browser'
752
+ },
753
+ preferCurrentTab: true,
754
+ selfBrowserSurface: 'include',
755
+ systemAudio: 'exclude'
756
+ }).then(function(stream) {
757
+ var video = document.createElement('video');
758
+ video.srcObject = stream;
759
+ video.muted = true;
760
+
761
+ return new Promise(function(resolve) {
762
+ video.onloadedmetadata = function() {
763
+ video.play().then(function() {
764
+ // Small delay to ensure frame is rendered
765
+ setTimeout(function() {
766
+ var canvas = document.createElement('canvas');
767
+ canvas.width = video.videoWidth;
768
+ canvas.height = video.videoHeight;
769
+ var ctx = canvas.getContext('2d');
770
+
771
+ if (!ctx) {
772
+ stream.getTracks().forEach(function(t) { t.stop(); });
773
+ resolve(false);
774
+ return;
775
+ }
776
+
777
+ ctx.drawImage(video, 0, 0);
778
+ stream.getTracks().forEach(function(t) { t.stop(); });
779
+
780
+ // Convert to blob and copy to clipboard
781
+ canvas.toBlob(function(blob) {
782
+ if (!blob) {
783
+ resolve(false);
784
+ return;
785
+ }
786
+
787
+ navigator.clipboard.write([
788
+ new ClipboardItem({ 'image/png': blob })
789
+ ]).then(function() {
790
+ console.log('[ElementInspector] Screenshot copied to clipboard');
791
+ resolve(true);
792
+ }).catch(function(err) {
793
+ console.error('[ElementInspector] Screenshot clipboard write failed:', err);
794
+ resolve(false);
795
+ });
796
+ }, 'image/png');
797
+ }, 100);
798
+ }).catch(function() {
799
+ stream.getTracks().forEach(function(t) { t.stop(); });
800
+ resolve(false);
801
+ });
802
+ };
803
+
804
+ video.onerror = function() {
805
+ stream.getTracks().forEach(function(t) { t.stop(); });
806
+ resolve(false);
807
+ };
808
+
809
+ // Timeout fallback
810
+ setTimeout(function() {
811
+ stream.getTracks().forEach(function(t) { t.stop(); });
812
+ resolve(false);
813
+ }, 5000);
814
+ });
815
+ }).catch(function(err) {
816
+ // User cancelled or permission denied - this is normal
817
+ if (err.name !== 'NotAllowedError') {
818
+ console.error('[ElementInspector] Screenshot capture failed:', err);
819
+ }
820
+ return false;
821
+ });
822
+ }
823
+
824
+ function captureConsoleLogs() {
825
+ var logs = getConsoleLogs();
826
+ return navigator.clipboard.writeText(logs).then(function() {
827
+ console.log('[ElementInspector] Console logs copied to clipboard');
828
+ return true;
829
+ }).catch(function(err) {
830
+ console.error('[ElementInspector] Failed to copy logs:', err);
831
+ return false;
832
+ });
833
+ }
834
+
835
+ function getConsoleLogs() {
836
+ if (consoleLogs.length === 0) {
837
+ return 'No console logs captured.';
838
+ }
839
+
840
+ var output = '# Console Logs\n\n';
841
+ output += 'URL: ' + window.location.href + '\n';
842
+ output += 'Timestamp: ' + new Date().toISOString() + '\n';
843
+ output += 'Total Logs: ' + consoleLogs.length + '\n\n---\n\n';
844
+
845
+ consoleLogs.forEach(function(entry) {
846
+ var icon = entry.type === 'error' ? '❌' : entry.type === 'warn' ? '⚠️' : '📝';
847
+ var source = entry.source ? entry.source + ' ' : '';
848
+ output += icon + ' ' + source + entry.args.join(' ') + '\n';
849
+ });
850
+
851
+ return output;
852
+ }
853
+
854
+ // ============================================================================
855
+ // Main Functions
856
+ // ============================================================================
857
+ function activate() {
858
+ console.log('[ElementInspector] Activating...');
859
+ isActive = true;
860
+
861
+ // Create overlay container
862
+ overlayContainer = document.createElement('div');
863
+ overlayContainer.id = 'element-inspector-overlay';
864
+
865
+ var docHeight = Math.max(
866
+ document.body.scrollHeight,
867
+ document.documentElement.scrollHeight,
868
+ document.body.offsetHeight,
869
+ document.documentElement.offsetHeight
870
+ );
871
+
872
+ overlayContainer.style.cssText =
873
+ 'position: absolute;' +
874
+ 'top: 0;' +
875
+ 'left: 0;' +
876
+ 'width: 100%;' +
877
+ 'height: ' + docHeight + 'px;' +
878
+ 'pointer-events: none;' +
879
+ 'z-index: 999999;';
880
+
881
+ document.body.appendChild(overlayContainer);
882
+
883
+ // Scan all elements
884
+ scanElements(overlayContainer);
885
+
886
+ console.log('[ElementInspector] Active - Press Alt+I to deactivate');
887
+ }
888
+
889
+ function deactivate() {
890
+ console.log('[ElementInspector] Deactivating...');
891
+ isActive = false;
892
+
893
+ elementBoxMap.clear();
894
+ currentlyHoveredBox = null;
895
+ currentlyHoveredElement = null;
896
+
897
+ if (overlayContainer) {
898
+ overlayContainer.remove();
899
+ overlayContainer = null;
900
+ }
901
+ }
902
+
903
+ function toggle() {
904
+ if (isActive) {
905
+ deactivate();
906
+ } else {
907
+ activate();
908
+ }
909
+ }
910
+
911
+ function refresh() {
912
+ if (isActive) {
913
+ deactivate();
914
+ activate();
915
+ }
916
+ }
917
+
918
+ // ============================================================================
919
+ // Keyboard Shortcuts
920
+ // ============================================================================
921
+ document.addEventListener('keydown', function(e) {
922
+ var key = e.key.toLowerCase();
923
+
924
+ // Ctrl+Shift+I: Debug snapshot
925
+ if (e.ctrlKey && e.shiftKey && !e.altKey && key === 'i') {
926
+ e.preventDefault();
927
+ e.stopPropagation();
928
+ console.log('[ElementInspector] Ctrl+Shift+I pressed - capturing debug snapshot');
929
+ captureDebugSnapshot();
930
+ return;
931
+ }
932
+
933
+ // Ctrl+Alt+I: Start rectangle selection mode
934
+ if (e.ctrlKey && e.altKey && !e.shiftKey && key === 'i') {
935
+ e.preventDefault();
936
+ startSelectionMode();
937
+ return;
938
+ }
939
+
940
+ // Alt+I: Toggle inspector
941
+ if (e.altKey && !e.shiftKey && !e.ctrlKey && key === 'i') {
942
+ e.preventDefault();
943
+ toggle();
944
+ return;
945
+ }
946
+
947
+ // Escape: Deactivate
948
+ if (e.key === 'Escape') {
949
+ e.preventDefault();
950
+ if (selectionMode) {
951
+ cancelSelectionMode();
952
+ deactivate();
953
+ } else if (isActive) {
954
+ deactivate();
955
+ }
956
+ return;
957
+ }
958
+ });
959
+
960
+ // Set up auto-dismiss callback
961
+ onCopyCallback = function() {
962
+ deactivate();
963
+ };
964
+
965
+ // Auto-refresh on window resize
966
+ var resizeTimeout;
967
+ window.addEventListener('resize', function() {
968
+ clearTimeout(resizeTimeout);
969
+ resizeTimeout = setTimeout(function() {
970
+ if (isActive) {
971
+ refresh();
972
+ }
973
+ }, 500);
974
+ });
975
+
976
+ // Export to window for manual control
977
+ window.elementInspector = {
978
+ toggle: toggle,
979
+ activate: activate,
980
+ deactivate: deactivate,
981
+ refresh: refresh,
982
+ captureDebugSnapshot: captureDebugSnapshot,
983
+ getConsoleLogs: getConsoleLogs
984
+ };
985
+
986
+ console.log('[ElementInspector] Initialized');
987
+ console.log(' Alt+I: Toggle inspector overlay');
988
+ console.log(' Ctrl+Alt+I: Rectangle selection mode');
989
+ console.log(' Ctrl+Shift+I: Debug snapshot (console logs)');
990
+ console.log(' Escape: Deactivate inspector');
991
+
992
+ })();