scitex 2.10.3__py3-none-any.whl → 2.13.0__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 (504) hide show
  1. scitex/__init__.py +1 -4
  2. scitex/__main__.py +24 -5
  3. scitex/__version__.py +1 -1
  4. scitex/_install_guide.py +14 -2
  5. scitex/_optional_deps.py +33 -0
  6. scitex/ai/classification/reporters/_ClassificationReporter.py +1 -1
  7. scitex/ai/classification/timeseries/_TimeSeriesBlockingSplit.py +2 -2
  8. scitex/ai/classification/timeseries/_TimeSeriesCalendarSplit.py +2 -2
  9. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit.py +2 -2
  10. scitex/ai/classification/timeseries/_TimeSeriesSlidingWindowSplit_v01-not-using-n_splits.py +2 -2
  11. scitex/ai/classification/timeseries/_TimeSeriesStratifiedSplit.py +2 -2
  12. scitex/ai/classification/timeseries/_normalize_timestamp.py +1 -1
  13. scitex/ai/metrics/_calc_seizure_prediction_metrics.py +1 -1
  14. scitex/ai/plt/_plot_feature_importance.py +1 -1
  15. scitex/ai/plt/_plot_learning_curve.py +1 -1
  16. scitex/ai/plt/_plot_optuna_study.py +1 -1
  17. scitex/ai/plt/_plot_pre_rec_curve.py +1 -1
  18. scitex/ai/plt/_plot_roc_curve.py +1 -1
  19. scitex/ai/plt/_stx_conf_mat.py +1 -1
  20. scitex/ai/training/_LearningCurveLogger.py +1 -1
  21. scitex/audio/mcp_server.py +38 -8
  22. scitex/bridge/_figrecipe.py +1 -1
  23. scitex/bridge/_helpers.py +1 -1
  24. scitex/bridge/_plt_vis.py +1 -1
  25. scitex/bridge/_stats_plt.py +1 -1
  26. scitex/bridge/_stats_vis.py +2 -2
  27. scitex/browser/automation/CookieHandler.py +1 -1
  28. scitex/browser/core/BrowserMixin.py +1 -1
  29. scitex/browser/core/ChromeProfileManager.py +1 -1
  30. scitex/browser/debugging/_browser_logger.py +1 -1
  31. scitex/browser/debugging/_highlight_element.py +1 -1
  32. scitex/browser/debugging/_show_grid.py +1 -1
  33. scitex/browser/interaction/click_center.py +1 -1
  34. scitex/browser/interaction/click_with_fallbacks.py +1 -1
  35. scitex/browser/interaction/close_popups.py +1 -1
  36. scitex/browser/interaction/fill_with_fallbacks.py +1 -1
  37. scitex/browser/pdf/click_download_for_chrome_pdf_viewer.py +1 -1
  38. scitex/browser/pdf/detect_chrome_pdf_viewer.py +1 -1
  39. scitex/browser/stealth/HumanBehavior.py +1 -1
  40. scitex/browser/stealth/StealthManager.py +1 -1
  41. scitex/{fig → canvas}/__init__.py +84 -96
  42. scitex/canvas/_mcp_handlers.py +372 -0
  43. scitex/canvas/_mcp_tool_schemas.py +219 -0
  44. scitex/{fig → canvas}/backend/_parser.py +1 -1
  45. scitex/{fig → canvas}/canvas.py +13 -14
  46. scitex/{fts/_fig/_editor → canvas/editor}/_defaults.py +2 -2
  47. scitex/{fig → canvas}/editor/edit/__init__.py +11 -14
  48. scitex/{fig → canvas}/editor/edit/bundle_resolver.py +56 -48
  49. scitex/{fig → canvas}/editor/edit/editor_launcher.py +79 -26
  50. scitex/{fts/_fig/_editor/_cui/_panel_loader.py → canvas/editor/edit/panel_loader.py} +8 -8
  51. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_bbox.py +2 -1
  52. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_core.py +84 -84
  53. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/_renderer.py +7 -6
  54. scitex/{fts/_fig/_editor/_gui/_flask_editor → canvas/editor/flask_editor}/static/css/features/canvas.css +2 -2
  55. scitex/{fig → canvas}/editor/flask_editor/static/css/features/panel-grid.css +1 -1
  56. scitex/{fig → canvas}/editor/flask_editor/static/js/core/api.js +3 -4
  57. scitex/{fig → canvas}/editor/flask_editor/static/js/editor/preview.js +5 -5
  58. scitex/{fig → canvas}/editor/flask_editor/templates/_html.py +3 -3
  59. scitex/{fig → canvas}/editor/flask_editor/templates/_scripts.py +10 -10
  60. scitex/{fig → canvas}/editor/flask_editor/templates/_styles.py +3 -3
  61. scitex/{fig → canvas}/io/__init__.py +32 -38
  62. scitex/{fig → canvas}/io/_bundle.py +217 -154
  63. scitex/{fig → canvas}/io/_canvas.py +1 -1
  64. scitex/{fig → canvas}/io/_data.py +1 -1
  65. scitex/{fig → canvas}/io/_export.py +1 -1
  66. scitex/{fig → canvas}/io/_load.py +1 -1
  67. scitex/{fig → canvas}/io/_panel.py +1 -1
  68. scitex/{fig → canvas}/io/_save.py +1 -1
  69. scitex/canvas/mcp_server.py +151 -0
  70. scitex/{fig → canvas}/model/__init__.py +1 -1
  71. scitex/{fig → canvas}/model/_annotations.py +1 -1
  72. scitex/{fig → canvas}/model/_axes.py +1 -1
  73. scitex/{fig → canvas}/model/_figure.py +1 -1
  74. scitex/{fig → canvas}/model/_guides.py +1 -1
  75. scitex/{fig → canvas}/model/_plot.py +1 -1
  76. scitex/{fig → canvas}/model/_styles.py +1 -1
  77. scitex/{fig → canvas}/utils/__init__.py +1 -1
  78. scitex/capture/mcp_server.py +41 -12
  79. scitex/cli/audio.py +233 -0
  80. scitex/cli/capture.py +307 -0
  81. scitex/cli/convert.py +10 -6
  82. scitex/cli/main.py +27 -4
  83. scitex/cli/repro.py +233 -0
  84. scitex/cli/resource.py +240 -0
  85. scitex/cli/stats.py +325 -0
  86. scitex/cli/template.py +236 -0
  87. scitex/cli/tex.py +286 -0
  88. scitex/cli/web.py +11 -12
  89. scitex/dev/__init__.py +3 -0
  90. scitex/dev/_pyproject.py +405 -0
  91. scitex/dev/plt/__init__.py +2 -2
  92. scitex/dev/plt/mpl/get_dir_ax.py +1 -1
  93. scitex/dev/plt/mpl/get_signatures.py +1 -1
  94. scitex/dev/plt/mpl/get_signatures_details.py +1 -1
  95. scitex/diagram/README.md +7 -7
  96. scitex/diagram/_mcp_handlers.py +400 -0
  97. scitex/diagram/_mcp_tool_schemas.py +157 -0
  98. scitex/diagram/mcp_server.py +151 -0
  99. scitex/dsp/_demo_sig.py +51 -5
  100. scitex/dsp/_mne.py +13 -2
  101. scitex/dsp/_modulation_index.py +15 -3
  102. scitex/dsp/_pac.py +23 -5
  103. scitex/dsp/_psd.py +16 -4
  104. scitex/dsp/_resample.py +24 -4
  105. scitex/dsp/_transform.py +16 -3
  106. scitex/dsp/add_noise.py +15 -1
  107. scitex/dsp/norm.py +17 -2
  108. scitex/dsp/reference.py +17 -1
  109. scitex/dsp/utils/_differential_bandpass_filters.py +20 -2
  110. scitex/dsp/utils/_zero_pad.py +18 -4
  111. scitex/dt/_normalize_timestamp.py +1 -1
  112. scitex/git/_session.py +1 -1
  113. scitex/io/__init__.py +7 -19
  114. scitex/io/_load.py +15 -19
  115. scitex/io/_load_modules/_canvas.py +2 -2
  116. scitex/io/_load_modules/_con.py +17 -6
  117. scitex/io/_load_modules/_eeg.py +28 -13
  118. scitex/io/_load_modules/_optuna.py +21 -63
  119. scitex/io/_load_modules/_torch.py +11 -3
  120. scitex/io/_save.py +11 -16
  121. scitex/io/_save_modules/__init__.py +6 -10
  122. scitex/io/_save_modules/_canvas.py +3 -3
  123. scitex/io/_save_modules/_optuna_study_as_csv_and_pngs.py +13 -2
  124. scitex/io/_save_modules/_plot_bundle.py +112 -0
  125. scitex/io/_save_modules/{_pltz_stx.py → _plot_scitex.py} +7 -7
  126. scitex/io/_save_modules/_stx_bundle.py +16 -16
  127. scitex/io/_save_modules/_torch.py +11 -3
  128. scitex/io/bundle/README.md +89 -80
  129. scitex/{fts/_bundle/_FTS.py → io/bundle/_Bundle.py} +197 -95
  130. scitex/io/bundle/__init__.py +67 -35
  131. scitex/{fts/_bundle → io/bundle}/_children.py +32 -40
  132. scitex/io/bundle/_core.py +184 -97
  133. scitex/{fts/_bundle/_dataclasses/_Node.py → io/bundle/_dataclasses/_Spec.py} +29 -23
  134. scitex/{fts/_bundle/_dataclasses/_NodeRefs.py → io/bundle/_dataclasses/_SpecRefs.py} +6 -6
  135. scitex/{fts/_bundle → io/bundle}/_dataclasses/__init__.py +4 -4
  136. scitex/{fts/_bundle → io/bundle}/_loader.py +19 -19
  137. scitex/io/bundle/_manifest.py +99 -0
  138. scitex/{fts/_bundle → io/bundle}/_mpl_helpers.py +119 -28
  139. scitex/io/bundle/_nested.py +113 -100
  140. scitex/{fts/_bundle → io/bundle}/_saver.py +13 -14
  141. scitex/{fts/_bundle → io/bundle}/_storage.py +3 -3
  142. scitex/io/bundle/_types.py +41 -16
  143. scitex/{fts/_bundle → io/bundle}/_validation.py +20 -18
  144. scitex/io/bundle/_zip.py +21 -31
  145. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_backend/_parser.py +1 -1
  146. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Annotations.py +1 -1
  147. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Axes.py +1 -1
  148. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Figure.py +1 -1
  149. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Guides.py +1 -1
  150. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_models/_Plot.py +1 -1
  151. scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_Styles.py +1 -1
  152. scitex/{fts/_kinds → io/bundle/kinds}/_plot/_utils/_plot_layout.py +1 -1
  153. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/__init__.py +1 -1
  154. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/_app.py +1 -1
  155. scitex/{fts/_tables → io/bundle/kinds/_table}/_latex/_export.py +1 -1
  156. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_figure_exporter.py +1 -1
  157. scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_table_exporter.py +1 -1
  158. scitex/io/bundle/schemas/__init__.py +30 -0
  159. scitex/mcp_server.py +159 -0
  160. scitex/parallel/_run.py +5 -4
  161. scitex/path/_find.py +60 -83
  162. scitex/path/_get_module_path.py +23 -21
  163. scitex/path/_get_spath.py +6 -27
  164. scitex/path/_getsize.py +23 -9
  165. scitex/path/_increment_version.py +31 -38
  166. scitex/path/_mk_spath.py +26 -29
  167. scitex/path/_path.py +5 -12
  168. scitex/path/_split.py +27 -15
  169. scitex/path/_this_path.py +23 -9
  170. scitex/plt/_mcp_handlers.py +361 -0
  171. scitex/plt/_mcp_tool_schemas.py +169 -0
  172. scitex/plt/_subplots/_AxisWrapperMixins/_MatplotlibPlotMixin/__init__.py +2 -1
  173. scitex/plt/_subplots/_AxisWrapperMixins/__init__.py +2 -2
  174. scitex/plt/gallery/_generate.py +76 -50
  175. scitex/plt/io/__init__.py +17 -19
  176. scitex/plt/io/_bundle.py +99 -52
  177. scitex/plt/io/_layered_bundle.py +303 -168
  178. scitex/plt/mcp_server.py +205 -0
  179. scitex/plt/utils/_csv_column_naming.py +250 -118
  180. scitex/repro/README_RandomStateManager.md +3 -3
  181. scitex/repro/_RandomStateManager.py +14 -14
  182. scitex/repro/_gen_ID.py +1 -1
  183. scitex/repro/_gen_timestamp.py +1 -1
  184. scitex/repro/_hash_array.py +4 -4
  185. scitex/schema/__init__.py +69 -73
  186. scitex/schema/_canvas.py +1 -1
  187. scitex/schema/_stats.py +2 -2
  188. scitex/scholar/__main__.py +24 -2
  189. scitex/scholar/_mcp_handlers.py +685 -0
  190. scitex/scholar/_mcp_tool_schemas.py +339 -0
  191. scitex/scholar/docs/template.py +1 -1
  192. scitex/scholar/examples/07_storage_integration.py +1 -1
  193. scitex/scholar/impact_factor/jcr/ImpactFactorJCREngine.py +1 -1
  194. scitex/scholar/impact_factor/jcr/build_database.py +1 -1
  195. scitex/scholar/mcp_server.py +315 -0
  196. scitex/scholar/pdf_download/ScholarPDFDownloader.py +1 -1
  197. scitex/scholar/pipelines/ScholarPipelineBibTeX.py +1 -1
  198. scitex/scholar/pipelines/ScholarPipelineParallel.py +1 -1
  199. scitex/scholar/pipelines/ScholarPipelineSingle.py +1 -1
  200. scitex/scholar/storage/PaperIO.py +1 -1
  201. scitex/session/README.md +4 -4
  202. scitex/session/__init__.py +1 -1
  203. scitex/session/_decorator.py +9 -9
  204. scitex/session/_lifecycle.py +5 -5
  205. scitex/session/template.py +1 -1
  206. scitex/stats/__init__.py +30 -33
  207. scitex/stats/__main__.py +281 -0
  208. scitex/stats/_mcp_handlers.py +1191 -0
  209. scitex/stats/_mcp_tool_schemas.py +384 -0
  210. scitex/stats/_schema.py +1 -1
  211. scitex/stats/correct/_correct_bonferroni.py +1 -1
  212. scitex/stats/correct/_correct_fdr.py +1 -1
  213. scitex/stats/correct/_correct_fdr_.py +1 -1
  214. scitex/stats/correct/_correct_holm.py +1 -1
  215. scitex/stats/correct/_correct_sidak.py +1 -1
  216. scitex/stats/effect_sizes/_cliffs_delta.py +1 -1
  217. scitex/stats/effect_sizes/_cohens_d.py +1 -1
  218. scitex/stats/effect_sizes/_epsilon_squared.py +1 -1
  219. scitex/stats/effect_sizes/_eta_squared.py +1 -1
  220. scitex/stats/effect_sizes/_prob_superiority.py +1 -1
  221. scitex/stats/io/__init__.py +10 -11
  222. scitex/stats/io/_bundle.py +16 -16
  223. scitex/stats/mcp_server.py +405 -0
  224. scitex/stats/posthoc/_dunnett.py +1 -1
  225. scitex/stats/posthoc/_games_howell.py +1 -1
  226. scitex/stats/posthoc/_tukey_hsd.py +1 -1
  227. scitex/stats/power/_power.py +1 -1
  228. scitex/stats/utils/_effect_size.py +1 -1
  229. scitex/stats/utils/_formatters.py +1 -1
  230. scitex/stats/utils/_power.py +1 -1
  231. scitex/template/_mcp_handlers.py +259 -0
  232. scitex/template/_mcp_tool_schemas.py +112 -0
  233. scitex/template/mcp_server.py +186 -0
  234. scitex/utils/_verify_scitex_format.py +2 -2
  235. scitex/utils/template.py +1 -1
  236. scitex/web/__init__.py +12 -11
  237. scitex/web/_scraping.py +26 -265
  238. scitex/web/download_images.py +316 -0
  239. scitex/writer/Writer.py +1 -1
  240. scitex/writer/_clone_writer_project.py +1 -1
  241. scitex/writer/_validate_tree_structures.py +1 -1
  242. scitex/writer/dataclasses/config/_WriterConfig.py +1 -1
  243. scitex/writer/dataclasses/contents/_ManuscriptContents.py +1 -1
  244. scitex/writer/dataclasses/core/_Document.py +1 -1
  245. scitex/writer/dataclasses/core/_DocumentSection.py +1 -1
  246. scitex/writer/dataclasses/results/_CompilationResult.py +1 -1
  247. scitex/writer/dataclasses/results/_LaTeXIssue.py +1 -1
  248. scitex/writer/utils/.legacy_git_retry.py +7 -5
  249. scitex/writer/utils/_parse_latex_logs.py +1 -1
  250. scitex-2.13.0.dist-info/METADATA +1231 -0
  251. {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/RECORD +376 -470
  252. scitex-2.13.0.dist-info/entry_points.txt +11 -0
  253. scitex/fig/editor/_defaults.py +0 -300
  254. scitex/fig/editor/edit/panel_loader.py +0 -232
  255. scitex/fig/editor/flask_editor/_bbox.py +0 -1299
  256. scitex/fig/editor/flask_editor/_core.py +0 -1429
  257. scitex/fig/editor/flask_editor/_renderer.py +0 -813
  258. scitex/fig/editor/flask_editor/static/css/features/canvas.css +0 -176
  259. scitex/fts/README.md +0 -262
  260. scitex/fts/TODO.md +0 -66
  261. scitex/fts/__init__.py +0 -90
  262. scitex/fts/_bundle/README_IN_BUNDLE.md +0 -102
  263. scitex/fts/_bundle/__init__.py +0 -38
  264. scitex/fts/_bundle/_utils/__init__.py +0 -55
  265. scitex/fts/_bundle/_utils/_const.py +0 -26
  266. scitex/fts/_bundle/_utils/_errors.py +0 -73
  267. scitex/fts/_bundle/_utils/_generate.py +0 -21
  268. scitex/fts/_bundle/_utils/_types.py +0 -76
  269. scitex/fts/_bundle/_zipbundle.py +0 -165
  270. scitex/fts/_fig/__init__.py +0 -22
  271. scitex/fts/_fig/_backend/_parser.py +0 -188
  272. scitex/fts/_fig/_editor/__init__.py +0 -14
  273. scitex/fts/_fig/_editor/_cui/__init__.py +0 -33
  274. scitex/fts/_fig/_editor/_cui/_backend_detector.py +0 -39
  275. scitex/fts/_fig/_editor/_cui/_bundle_resolver.py +0 -366
  276. scitex/fts/_fig/_editor/_cui/_editor_launcher.py +0 -175
  277. scitex/fts/_fig/_editor/_cui/_manual_handler.py +0 -52
  278. scitex/fts/_fig/_editor/_cui/_path_resolver.py +0 -66
  279. scitex/fts/_fig/_editor/_gui/__init__.py +0 -11
  280. scitex/fts/_fig/_editor/_gui/_flask_editor/__init__.py +0 -20
  281. scitex/fts/_fig/_editor/_gui/_flask_editor/_plotter.py +0 -664
  282. scitex/fts/_fig/_editor/_gui/_flask_editor/_utils.py +0 -79
  283. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/reset.css +0 -41
  284. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/typography.css +0 -16
  285. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/base/variables.css +0 -85
  286. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/buttons.css +0 -217
  287. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/context-menu.css +0 -93
  288. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/dropdown.css +0 -57
  289. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/forms.css +0 -112
  290. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/modal.css +0 -59
  291. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/components/sections.css +0 -212
  292. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/element-inspector.css +0 -190
  293. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/loading.css +0 -59
  294. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/overlay.css +0 -45
  295. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/panel-grid.css +0 -95
  296. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/selection.css +0 -101
  297. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/features/statistics.css +0 -138
  298. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/index.css +0 -31
  299. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/container.css +0 -7
  300. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/controls.css +0 -56
  301. scitex/fts/_fig/_editor/_gui/_flask_editor/static/css/layout/preview.css +0 -78
  302. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/axis.js +0 -314
  303. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/basic.js +0 -107
  304. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/alignment/distribute.js +0 -54
  305. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/canvas.js +0 -172
  306. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/dragging.js +0 -258
  307. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/resize.js +0 -48
  308. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/canvas/selection.js +0 -71
  309. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/api.js +0 -288
  310. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/state.js +0 -143
  311. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/core/utils.js +0 -245
  312. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/dev/element-inspector.js +0 -992
  313. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/bbox.js +0 -339
  314. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/element-drag.js +0 -286
  315. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/overlay.js +0 -371
  316. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/editor/preview.js +0 -293
  317. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/main.js +0 -426
  318. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/context-menu.js +0 -152
  319. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/shortcuts/keyboard.js +0 -265
  320. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/controls.js +0 -184
  321. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/download.js +0 -57
  322. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/help.js +0 -100
  323. scitex/fts/_fig/_editor/_gui/_flask_editor/static/js/ui/theme.js +0 -34
  324. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/__init__.py +0 -124
  325. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_html.py +0 -851
  326. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_scripts.py +0 -4932
  327. scitex/fts/_fig/_editor/_gui/_flask_editor/templates/_styles.py +0 -1657
  328. scitex/fts/_fig/_editor/_gui/_flask_editor.py +0 -36
  329. scitex/fts/_fig/_models/_Annotations.py +0 -115
  330. scitex/fts/_fig/_models/_Axes.py +0 -152
  331. scitex/fts/_fig/_models/_Figure.py +0 -138
  332. scitex/fts/_fig/_models/_Plot.py +0 -123
  333. scitex/fts/_fig/_utils/_plot_layout.py +0 -397
  334. scitex/fts/_kinds/_figure/_composite.py +0 -345
  335. scitex/fts/_kinds/_plot/_backend/__init__.py +0 -53
  336. scitex/fts/_kinds/_plot/_backend/_export.py +0 -165
  337. scitex/fts/_kinds/_plot/_backend/_render.py +0 -538
  338. scitex/fts/_kinds/_plot/_dataclasses/_ChannelEncoding.py +0 -46
  339. scitex/fts/_kinds/_plot/_dataclasses/_Encoding.py +0 -82
  340. scitex/fts/_kinds/_plot/_dataclasses/_Theme.py +0 -441
  341. scitex/fts/_kinds/_plot/_dataclasses/_TraceEncoding.py +0 -52
  342. scitex/fts/_kinds/_plot/_dataclasses/__init__.py +0 -47
  343. scitex/fts/_kinds/_plot/_models/_Guides.py +0 -104
  344. scitex/fts/_kinds/_plot/_models/_Styles.py +0 -245
  345. scitex/fts/_kinds/_plot/_models/__init__.py +0 -80
  346. scitex/fts/_kinds/_plot/_models/_plot_types/__init__.py +0 -156
  347. scitex/fts/_kinds/_plot/_models/_plot_types/_bar.py +0 -43
  348. scitex/fts/_kinds/_plot/_models/_plot_types/_box.py +0 -38
  349. scitex/fts/_kinds/_plot/_models/_plot_types/_distribution.py +0 -36
  350. scitex/fts/_kinds/_plot/_models/_plot_types/_errorbar.py +0 -60
  351. scitex/fts/_kinds/_plot/_models/_plot_types/_histogram.py +0 -30
  352. scitex/fts/_kinds/_plot/_models/_plot_types/_image.py +0 -61
  353. scitex/fts/_kinds/_plot/_models/_plot_types/_line.py +0 -57
  354. scitex/fts/_kinds/_plot/_models/_plot_types/_scatter.py +0 -30
  355. scitex/fts/_kinds/_plot/_models/_plot_types/_seaborn.py +0 -121
  356. scitex/fts/_kinds/_plot/_models/_plot_types/_violin.py +0 -36
  357. scitex/fts/_kinds/_plot/_utils/__init__.py +0 -129
  358. scitex/fts/_kinds/_plot/_utils/_auto_layout.py +0 -127
  359. scitex/fts/_kinds/_plot/_utils/_calc_bounds.py +0 -111
  360. scitex/fts/_kinds/_plot/_utils/_const_sizes.py +0 -48
  361. scitex/fts/_kinds/_plot/_utils/_convert_coords.py +0 -77
  362. scitex/fts/_kinds/_plot/_utils/_get_template.py +0 -178
  363. scitex/fts/_kinds/_plot/_utils/_normalize.py +0 -73
  364. scitex/fts/_kinds/_plot/_utils/_validate.py +0 -197
  365. scitex/fts/_kinds/_table/_latex/_export.py +0 -279
  366. scitex/fts/_stats/__init__.py +0 -48
  367. scitex/fts/_stats/_dataclasses/_Stats.py +0 -423
  368. scitex/fts/_stats/_dataclasses/__init__.py +0 -48
  369. scitex/fts/_tables/__init__.py +0 -65
  370. scitex/fts/_tables/_latex/__init__.py +0 -93
  371. scitex/fts/_tables/_latex/_editor/__init__.py +0 -11
  372. scitex/fts/_tables/_latex/_editor/_app.py +0 -725
  373. scitex/fts/_tables/_latex/_figure_exporter.py +0 -153
  374. scitex/fts/_tables/_latex/_stats_formatter.py +0 -274
  375. scitex/fts/_tables/_latex/_table_exporter.py +0 -362
  376. scitex/fts/_tables/_latex/_utils.py +0 -369
  377. scitex/fts/_tables/_latex/_validator.py +0 -445
  378. scitex/io/_save_modules/_pltz_bundle.py +0 -356
  379. scitex-2.10.3.dist-info/METADATA +0 -952
  380. scitex-2.10.3.dist-info/entry_points.txt +0 -2
  381. /scitex/{fig → canvas}/README.md +0 -0
  382. /scitex/{fig → canvas}/backend/__init__.py +0 -0
  383. /scitex/{fig → canvas}/backend/_export.py +0 -0
  384. /scitex/{fig → canvas}/backend/_render.py +0 -0
  385. /scitex/{fig → canvas}/docs/CANVAS_ARCHITECTURE.md +0 -0
  386. /scitex/{fig → canvas}/editor/__init__.py +0 -0
  387. /scitex/{fig → canvas}/editor/_dearpygui_editor.py +0 -0
  388. /scitex/{fig → canvas}/editor/_flask_editor.py +0 -0
  389. /scitex/{fig → canvas}/editor/_mpl_editor.py +0 -0
  390. /scitex/{fig → canvas}/editor/_qt_editor.py +0 -0
  391. /scitex/{fig → canvas}/editor/_tkinter_editor.py +0 -0
  392. /scitex/{fig → canvas}/editor/edit/backend_detector.py +0 -0
  393. /scitex/{fig → canvas}/editor/edit/manual_handler.py +0 -0
  394. /scitex/{fig → canvas}/editor/edit/path_resolver.py +0 -0
  395. /scitex/{fig → canvas}/editor/flask_editor/__init__.py +0 -0
  396. /scitex/{fig → canvas}/editor/flask_editor/_plotter.py +0 -0
  397. /scitex/{fig → canvas}/editor/flask_editor/_utils.py +0 -0
  398. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/reset.css +0 -0
  399. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/typography.css +0 -0
  400. /scitex/{fig → canvas}/editor/flask_editor/static/css/base/variables.css +0 -0
  401. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/buttons.css +0 -0
  402. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/context-menu.css +0 -0
  403. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/dropdown.css +0 -0
  404. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/forms.css +0 -0
  405. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/modal.css +0 -0
  406. /scitex/{fig → canvas}/editor/flask_editor/static/css/components/sections.css +0 -0
  407. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/element-inspector.css +0 -0
  408. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/loading.css +0 -0
  409. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/overlay.css +0 -0
  410. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/selection.css +0 -0
  411. /scitex/{fig → canvas}/editor/flask_editor/static/css/features/statistics.css +0 -0
  412. /scitex/{fig → canvas}/editor/flask_editor/static/css/index.css +0 -0
  413. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/container.css +0 -0
  414. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/controls.css +0 -0
  415. /scitex/{fig → canvas}/editor/flask_editor/static/css/layout/preview.css +0 -0
  416. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/axis.js +0 -0
  417. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/basic.js +0 -0
  418. /scitex/{fig → canvas}/editor/flask_editor/static/js/alignment/distribute.js +0 -0
  419. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/canvas.js +0 -0
  420. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/dragging.js +0 -0
  421. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/resize.js +0 -0
  422. /scitex/{fig → canvas}/editor/flask_editor/static/js/canvas/selection.js +0 -0
  423. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/state.js +0 -0
  424. /scitex/{fig → canvas}/editor/flask_editor/static/js/core/utils.js +0 -0
  425. /scitex/{fig → canvas}/editor/flask_editor/static/js/dev/element-inspector.js +0 -0
  426. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/bbox.js +0 -0
  427. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/element-drag.js +0 -0
  428. /scitex/{fig → canvas}/editor/flask_editor/static/js/editor/overlay.js +0 -0
  429. /scitex/{fig → canvas}/editor/flask_editor/static/js/main.js +0 -0
  430. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/context-menu.js +0 -0
  431. /scitex/{fig → canvas}/editor/flask_editor/static/js/shortcuts/keyboard.js +0 -0
  432. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/controls.js +0 -0
  433. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/download.js +0 -0
  434. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/help.js +0 -0
  435. /scitex/{fig → canvas}/editor/flask_editor/static/js/ui/theme.js +0 -0
  436. /scitex/{fig → canvas}/editor/flask_editor/templates/__init__.py +0 -0
  437. /scitex/{fig → canvas}/io/_directory.py +0 -0
  438. /scitex/{fig → canvas}/model/_plot_types.py +0 -0
  439. /scitex/{fig → canvas}/utils/_defaults.py +0 -0
  440. /scitex/{fig → canvas}/utils/_validate.py +0 -0
  441. /scitex/{fts/_bundle → io/bundle}/_conversion/__init__.py +0 -0
  442. /scitex/{fts/_bundle → io/bundle}/_conversion/_bundle2dict.py +0 -0
  443. /scitex/{fts/_bundle → io/bundle}/_conversion/_dict2bundle.py +0 -0
  444. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_Axes.py +0 -0
  445. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_BBox.py +0 -0
  446. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_ColumnDef.py +0 -0
  447. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataFormat.py +0 -0
  448. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataInfo.py +0 -0
  449. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_DataSource.py +0 -0
  450. /scitex/{fts/_bundle → io/bundle}/_dataclasses/_SizeMM.py +0 -0
  451. /scitex/{fts/_bundle → io/bundle}/_extractors/__init__.py +0 -0
  452. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_bar.py +0 -0
  453. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_line.py +0 -0
  454. /scitex/{fts/_bundle → io/bundle}/_extractors/_extract_scatter.py +0 -0
  455. /scitex/{fts/_kinds → io/bundle/kinds}/__init__.py +0 -0
  456. /scitex/{fts/_kinds → io/bundle/kinds}/_figure/__init__.py +0 -0
  457. /scitex/{fts/_fig → io/bundle/kinds/_figure}/_composite.py +0 -0
  458. /scitex/{fts/_kinds → io/bundle/kinds}/_plot/__init__.py +0 -0
  459. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/__init__.py +0 -0
  460. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_export.py +0 -0
  461. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_backend/_render.py +0 -0
  462. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_ChannelEncoding.py +0 -0
  463. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Encoding.py +0 -0
  464. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_Theme.py +0 -0
  465. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/_TraceEncoding.py +0 -0
  466. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_dataclasses/__init__.py +0 -0
  467. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/__init__.py +0 -0
  468. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/__init__.py +0 -0
  469. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_bar.py +0 -0
  470. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_box.py +0 -0
  471. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_distribution.py +0 -0
  472. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_errorbar.py +0 -0
  473. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_histogram.py +0 -0
  474. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_image.py +0 -0
  475. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_line.py +0 -0
  476. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_scatter.py +0 -0
  477. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_seaborn.py +0 -0
  478. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_models/_plot_types/_violin.py +0 -0
  479. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/__init__.py +0 -0
  480. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_auto_layout.py +0 -0
  481. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_calc_bounds.py +0 -0
  482. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_const_sizes.py +0 -0
  483. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_convert_coords.py +0 -0
  484. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_get_template.py +0 -0
  485. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_normalize.py +0 -0
  486. /scitex/{fts/_fig → io/bundle/kinds/_plot}/_utils/_validate.py +0 -0
  487. /scitex/{fts/_kinds → io/bundle/kinds}/_shape/__init__.py +0 -0
  488. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/__init__.py +0 -0
  489. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/_Stats.py +0 -0
  490. /scitex/{fts/_kinds → io/bundle/kinds}/_stats/_dataclasses/__init__.py +0 -0
  491. /scitex/{fts/_kinds → io/bundle/kinds}/_table/__init__.py +0 -0
  492. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_editor/__init__.py +0 -0
  493. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_stats_formatter.py +0 -0
  494. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_utils.py +0 -0
  495. /scitex/{fts/_kinds → io/bundle/kinds}/_table/_latex/_validator.py +0 -0
  496. /scitex/{fts/_kinds → io/bundle/kinds}/_text/__init__.py +0 -0
  497. /scitex/{fts/_schemas → io/bundle/schemas}/data_info.schema.json +0 -0
  498. /scitex/{fts/_schemas → io/bundle/schemas}/encoding.schema.json +0 -0
  499. /scitex/{fts/_schemas → io/bundle/schemas}/node.schema.json +0 -0
  500. /scitex/{fts/_schemas → io/bundle/schemas}/render_manifest.schema.json +0 -0
  501. /scitex/{fts/_schemas → io/bundle/schemas}/stats.schema.json +0 -0
  502. /scitex/{fts/_schemas → io/bundle/schemas}/theme.schema.json +0 -0
  503. {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/WHEEL +0 -0
  504. {scitex-2.10.3.dist-info → scitex-2.13.0.dist-info}/licenses/LICENSE +0 -0
@@ -1,992 +0,0 @@
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
- })();