srcly 0.1.24__tar.gz → 0.1.27__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (316) hide show
  1. {srcly-0.1.24 → srcly-0.1.27}/PKG-INFO +1 -1
  2. {srcly-0.1.24 → srcly-0.1.27}/app/models.py +5 -0
  3. {srcly-0.1.24 → srcly-0.1.27}/app/services/focus_overlay.py +295 -77
  4. srcly-0.1.27/app/services/python/python_analysis.py +313 -0
  5. srcly-0.1.27/app/services/typescript/typescript_analysis.py +948 -0
  6. srcly-0.1.27/app/static/assets/index-BD7BxeQJ.js +66 -0
  7. srcly-0.1.27/app/static/assets/index-BDq2TMkJ.css +1 -0
  8. {srcly-0.1.24 → srcly-0.1.27}/app/static/index.html +2 -2
  9. {srcly-0.1.24 → srcly-0.1.27}/pyproject.toml +1 -1
  10. srcly-0.1.24/app/services/python/python_analysis.py +0 -317
  11. srcly-0.1.24/app/services/typescript/typescript_analysis.py +0 -1353
  12. srcly-0.1.24/app/static/assets/index-VtJb58No.js +0 -66
  13. srcly-0.1.24/app/static/assets/index-enroYfNN.css +0 -1
  14. {srcly-0.1.24 → srcly-0.1.27}/.gitignore +0 -0
  15. {srcly-0.1.24 → srcly-0.1.27}/README.md +0 -0
  16. {srcly-0.1.24 → srcly-0.1.27}/app/.gitignore +0 -0
  17. {srcly-0.1.24 → srcly-0.1.27}/app/__init__.py +0 -0
  18. {srcly-0.1.24 → srcly-0.1.27}/app/config.py +0 -0
  19. {srcly-0.1.24 → srcly-0.1.27}/app/main.py +0 -0
  20. {srcly-0.1.24 → srcly-0.1.27}/app/routers/analysis.py +0 -0
  21. {srcly-0.1.24 → srcly-0.1.27}/app/routers/files.py +0 -0
  22. {srcly-0.1.24 → srcly-0.1.27}/app/run.py +0 -0
  23. {srcly-0.1.24 → srcly-0.1.27}/app/services/analysis.py +0 -0
  24. {srcly-0.1.24 → srcly-0.1.27}/app/services/analysis_types.py +0 -0
  25. {srcly-0.1.24 → srcly-0.1.27}/app/services/cache.py +0 -0
  26. {srcly-0.1.24 → srcly-0.1.27}/app/services/css/css_analysis.py +0 -0
  27. {srcly-0.1.24 → srcly-0.1.27}/app/services/data_flow_analysis.py +0 -0
  28. {srcly-0.1.24 → srcly-0.1.27}/app/services/ipynb/ipynb_analysis.py +0 -0
  29. {srcly-0.1.24 → srcly-0.1.27}/app/services/markdown/markdown_analysis.py +0 -0
  30. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/abap-BdImnpbu.js +0 -0
  31. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/actionscript-3-CfeIJUat.js +0 -0
  32. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ada-bCR0ucgS.js +0 -0
  33. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/andromeeda-C-Jbm3Hp.js +0 -0
  34. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/angular-html-CU67Zn6k.js +0 -0
  35. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/angular-ts-BwZT4LLn.js +0 -0
  36. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/apache-Pmp26Uib.js +0 -0
  37. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/apex-DhZLUxFE.js +0 -0
  38. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/apl-dKokRX4l.js +0 -0
  39. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/applescript-Co6uUVPk.js +0 -0
  40. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ara-BRHolxvo.js +0 -0
  41. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/asciidoc-Dv7Oe6Be.js +0 -0
  42. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/asm-D_Q5rh1f.js +0 -0
  43. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/astro-CbQHKStN.js +0 -0
  44. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/aurora-x-D-2ljcwZ.js +0 -0
  45. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/awk-DMzUqQB5.js +0 -0
  46. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ayu-dark-Cv9koXgw.js +0 -0
  47. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ballerina-BFfxhgS-.js +0 -0
  48. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/bat-BkioyH1T.js +0 -0
  49. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/beancount-k_qm7-4y.js +0 -0
  50. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/berry-D08WgyRC.js +0 -0
  51. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/bibtex-CHM0blh-.js +0 -0
  52. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/bicep-Bmn6On1c.js +0 -0
  53. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/blade-DVc8C-J4.js +0 -0
  54. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/bsl-BO_Y6i37.js +0 -0
  55. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/c-BIGW1oBm.js +0 -0
  56. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/cadence-Bv_4Rxtq.js +0 -0
  57. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/cairo-KRGpt6FW.js +0 -0
  58. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/catppuccin-frappe-DFWUc33u.js +0 -0
  59. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/catppuccin-latte-C9dUb6Cb.js +0 -0
  60. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/catppuccin-macchiato-DQyhUUbL.js +0 -0
  61. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/catppuccin-mocha-D87Tk5Gz.js +0 -0
  62. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/clarity-D53aC0YG.js +0 -0
  63. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/clojure-P80f7IUj.js +0 -0
  64. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/cmake-D1j8_8rp.js +0 -0
  65. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/cobol-nwyudZeR.js +0 -0
  66. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/codeowners-Bp6g37R7.js +0 -0
  67. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/codeql-DsOJ9woJ.js +0 -0
  68. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/coffee-Ch7k5sss.js +0 -0
  69. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/common-lisp-Cg-RD9OK.js +0 -0
  70. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/coq-DkFqJrB1.js +0 -0
  71. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/cpp-CofmeUqb.js +0 -0
  72. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/crystal-tKQVLTB8.js +0 -0
  73. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/csharp-CX12Zw3r.js +0 -0
  74. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/css-DPfMkruS.js +0 -0
  75. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/csv-fuZLfV_i.js +0 -0
  76. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/cue-D82EKSYY.js +0 -0
  77. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/cypher-COkxafJQ.js +0 -0
  78. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/d-85-TOEBH.js +0 -0
  79. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/dark-plus-eOWES_5F.js +0 -0
  80. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/dart-CF10PKvl.js +0 -0
  81. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/dax-CEL-wOlO.js +0 -0
  82. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/desktop-BmXAJ9_W.js +0 -0
  83. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/diff-D97Zzqfu.js +0 -0
  84. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/docker-BcOcwvcX.js +0 -0
  85. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/dotenv-Da5cRb03.js +0 -0
  86. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/dracula-BzJJZx-M.js +0 -0
  87. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/dracula-soft-BXkSAIEj.js +0 -0
  88. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/dream-maker-BtqSS_iP.js +0 -0
  89. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/edge-BkV0erSs.js +0 -0
  90. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/elixir-CDX3lj18.js +0 -0
  91. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/elm-DbKCFpqz.js +0 -0
  92. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/emacs-lisp-C9XAeP06.js +0 -0
  93. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/erb-BOJIQeun.js +0 -0
  94. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/erlang-DsQrWhSR.js +0 -0
  95. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/everforest-dark-BgDCqdQA.js +0 -0
  96. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/everforest-light-C8M2exoo.js +0 -0
  97. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/fennel-BYunw83y.js +0 -0
  98. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/fish-BvzEVeQv.js +0 -0
  99. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/fluent-C4IJs8-o.js +0 -0
  100. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/fortran-fixed-form-BZjJHVRy.js +0 -0
  101. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/fortran-free-form-D22FLkUw.js +0 -0
  102. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/fsharp-CXgrBDvD.js +0 -0
  103. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gdresource-B7Tvp0Sc.js +0 -0
  104. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gdscript-DTMYz4Jt.js +0 -0
  105. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gdshader-DkwncUOv.js +0 -0
  106. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/genie-D0YGMca9.js +0 -0
  107. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gherkin-DyxjwDmM.js +0 -0
  108. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/git-commit-F4YmCXRG.js +0 -0
  109. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/git-rebase-r7XF79zn.js +0 -0
  110. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/github-dark-DHJKELXO.js +0 -0
  111. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/github-dark-default-Cuk6v7N8.js +0 -0
  112. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/github-dark-dimmed-DH5Ifo-i.js +0 -0
  113. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/github-dark-high-contrast-E3gJ1_iC.js +0 -0
  114. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/github-light-DAi9KRSo.js +0 -0
  115. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/github-light-default-D7oLnXFd.js +0 -0
  116. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/github-light-high-contrast-BfjtVDDH.js +0 -0
  117. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gleam-BspZqrRM.js +0 -0
  118. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/glimmer-js-Rg0-pVw9.js +0 -0
  119. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/glimmer-ts-U6CK756n.js +0 -0
  120. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/glsl-DplSGwfg.js +0 -0
  121. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gnuplot-DdkO51Og.js +0 -0
  122. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/go-Dn2_MT6a.js +0 -0
  123. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/graphql-ChdNCCLP.js +0 -0
  124. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/groovy-gcz8RCvz.js +0 -0
  125. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gruvbox-dark-hard-CFHQjOhq.js +0 -0
  126. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gruvbox-dark-medium-GsRaNv29.js +0 -0
  127. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gruvbox-dark-soft-CVdnzihN.js +0 -0
  128. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gruvbox-light-hard-CH1njM8p.js +0 -0
  129. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gruvbox-light-medium-DRw_LuNl.js +0 -0
  130. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/gruvbox-light-soft-hJgmCMqR.js +0 -0
  131. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/hack-CaT9iCJl.js +0 -0
  132. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/haml-B8DHNrY2.js +0 -0
  133. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/handlebars-BL8al0AC.js +0 -0
  134. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/haskell-Df6bDoY_.js +0 -0
  135. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/haxe-CzTSHFRz.js +0 -0
  136. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/hcl-BWvSN4gD.js +0 -0
  137. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/hjson-D5-asLiD.js +0 -0
  138. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/hlsl-D3lLCCz7.js +0 -0
  139. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/houston-DnULxvSX.js +0 -0
  140. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/html-GMplVEZG.js +0 -0
  141. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/html-derivative-BFtXZ54Q.js +0 -0
  142. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/http-jrhK8wxY.js +0 -0
  143. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/hurl-irOxFIW8.js +0 -0
  144. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/hxml-Bvhsp5Yf.js +0 -0
  145. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/hy-DFXneXwc.js +0 -0
  146. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/imba-DGztddWO.js +0 -0
  147. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ini-BEwlwnbL.js +0 -0
  148. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/java-CylS5w8V.js +0 -0
  149. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/javascript-wDzz0qaB.js +0 -0
  150. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/jinja-4LBKfQ-Z.js +0 -0
  151. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/jison-wvAkD_A8.js +0 -0
  152. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/json-Cp-IABpG.js +0 -0
  153. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/json5-C9tS-k6U.js +0 -0
  154. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/jsonc-Des-eS-w.js +0 -0
  155. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/jsonl-DcaNXYhu.js +0 -0
  156. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/jsonnet-DFQXde-d.js +0 -0
  157. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/jssm-C2t-YnRu.js +0 -0
  158. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/jsx-g9-lgVsj.js +0 -0
  159. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/julia-C8NyazO9.js +0 -0
  160. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/kanagawa-dragon-CkXjmgJE.js +0 -0
  161. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/kanagawa-lotus-CfQXZHmo.js +0 -0
  162. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/kanagawa-wave-DWedfzmr.js +0 -0
  163. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/kdl-DV7GczEv.js +0 -0
  164. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/kotlin-BdnUsdx6.js +0 -0
  165. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/kusto-BvAqAH-y.js +0 -0
  166. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/laserwave-DUszq2jm.js +0 -0
  167. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/latex-BUKiar2Z.js +0 -0
  168. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/lean-DP1Csr6i.js +0 -0
  169. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/less-B1dDrJ26.js +0 -0
  170. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/light-plus-B7mTdjB0.js +0 -0
  171. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/liquid-DYVedYrR.js +0 -0
  172. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/llvm-BtvRca6l.js +0 -0
  173. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/log-2UxHyX5q.js +0 -0
  174. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/logo-BtOb2qkB.js +0 -0
  175. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/lua-BbnMAYS6.js +0 -0
  176. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/luau-CXu1NL6O.js +0 -0
  177. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/make-CHLpvVh8.js +0 -0
  178. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/markdown-Cvjx9yec.js +0 -0
  179. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/marko-CPi9NSCl.js +0 -0
  180. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/material-theme-D5KoaKCx.js +0 -0
  181. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/material-theme-darker-BfHTSMKl.js +0 -0
  182. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/material-theme-lighter-B0m2ddpp.js +0 -0
  183. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/material-theme-ocean-CyktbL80.js +0 -0
  184. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/material-theme-palenight-Csfq5Kiy.js +0 -0
  185. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/matlab-D7o27uSR.js +0 -0
  186. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/mdc-DUICxH0z.js +0 -0
  187. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/mdx-Cmh6b_Ma.js +0 -0
  188. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/mermaid-DKYwYmdq.js +0 -0
  189. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/min-dark-CafNBF8u.js +0 -0
  190. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/min-light-CTRr51gU.js +0 -0
  191. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/mipsasm-CKIfxQSi.js +0 -0
  192. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/mojo-1DNp92w6.js +0 -0
  193. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/monokai-D4h5O-jR.js +0 -0
  194. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/move-Bu9oaDYs.js +0 -0
  195. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/narrat-DRg8JJMk.js +0 -0
  196. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/nextflow-CUEJCptM.js +0 -0
  197. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/nginx-DknmC5AR.js +0 -0
  198. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/night-owl-C39BiMTA.js +0 -0
  199. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/nim-CVrawwO9.js +0 -0
  200. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/nix-BbRYJGeE.js +0 -0
  201. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/nord-Ddv68eIx.js +0 -0
  202. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/nushell-C-sUppwS.js +0 -0
  203. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/objective-c-DXmwc3jG.js +0 -0
  204. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/objective-cpp-CLxacb5B.js +0 -0
  205. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ocaml-C0hk2d4L.js +0 -0
  206. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/one-dark-pro-DVMEJ2y_.js +0 -0
  207. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/one-light-PoHY5YXO.js +0 -0
  208. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/pascal-D93ZcfNL.js +0 -0
  209. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/perl-C0TMdlhV.js +0 -0
  210. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/php-CDn_0X-4.js +0 -0
  211. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/pkl-u5AG7uiY.js +0 -0
  212. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/plastic-3e1v2bzS.js +0 -0
  213. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/plsql-ChMvpjG-.js +0 -0
  214. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/po-BTJTHyun.js +0 -0
  215. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/poimandres-CS3Unz2-.js +0 -0
  216. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/polar-C0HS_06l.js +0 -0
  217. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/postcss-CXtECtnM.js +0 -0
  218. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/powerquery-CEu0bR-o.js +0 -0
  219. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/powershell-Dpen1YoG.js +0 -0
  220. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/prisma-Dd19v3D-.js +0 -0
  221. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/prolog-CbFg5uaA.js +0 -0
  222. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/proto-DyJlTyXw.js +0 -0
  223. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/pug-CGlum2m_.js +0 -0
  224. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/puppet-BMWR74SV.js +0 -0
  225. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/purescript-CklMAg4u.js +0 -0
  226. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/python-B6aJPvgy.js +0 -0
  227. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/qml-3beO22l8.js +0 -0
  228. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/qmldir-C8lEn-DE.js +0 -0
  229. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/qss-IeuSbFQv.js +0 -0
  230. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/r-DiinP2Uv.js +0 -0
  231. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/racket-BqYA7rlc.js +0 -0
  232. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/raku-DXvB9xmW.js +0 -0
  233. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/razor-WgofotgN.js +0 -0
  234. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/red-bN70gL4F.js +0 -0
  235. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/reg-C-SQnVFl.js +0 -0
  236. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/regexp-CDVJQ6XC.js +0 -0
  237. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/rel-C3B-1QV4.js +0 -0
  238. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/riscv-BM1_JUlF.js +0 -0
  239. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/rose-pine-BHrmToEH.js +0 -0
  240. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/rose-pine-dawn-CnK8MTSM.js +0 -0
  241. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/rose-pine-moon-NleAzG8P.js +0 -0
  242. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/rosmsg-BJDFO7_C.js +0 -0
  243. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/rst-B0xPkSld.js +0 -0
  244. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ruby-BvKwtOVI.js +0 -0
  245. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/rust-B1yitclQ.js +0 -0
  246. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/sas-cz2c8ADy.js +0 -0
  247. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/sass-Cj5Yp3dK.js +0 -0
  248. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/scala-C151Ov-r.js +0 -0
  249. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/scheme-C98Dy4si.js +0 -0
  250. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/scss-OYdSNvt2.js +0 -0
  251. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/sdbl-DVxCFoDh.js +0 -0
  252. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/shaderlab-Dg9Lc6iA.js +0 -0
  253. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/shellscript-Yzrsuije.js +0 -0
  254. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/shellsession-BADoaaVG.js +0 -0
  255. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/slack-dark-BthQWCQV.js +0 -0
  256. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/slack-ochin-DqwNpetd.js +0 -0
  257. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/smalltalk-BERRCDM3.js +0 -0
  258. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/snazzy-light-Bw305WKR.js +0 -0
  259. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/solarized-dark-DXbdFlpD.js +0 -0
  260. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/solarized-light-L9t79GZl.js +0 -0
  261. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/solidity-BbcW6ACK.js +0 -0
  262. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/soy-Brmx7dQM.js +0 -0
  263. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/sparql-rVzFXLq3.js +0 -0
  264. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/splunk-BtCnVYZw.js +0 -0
  265. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/sql-BLtJtn59.js +0 -0
  266. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ssh-config-_ykCGR6B.js +0 -0
  267. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/stata-BH5u7GGu.js +0 -0
  268. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/stylus-BEDo0Tqx.js +0 -0
  269. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/svelte-3Dk4HxPD.js +0 -0
  270. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/swift-Dg5xB15N.js +0 -0
  271. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/synthwave-84-CbfX1IO0.js +0 -0
  272. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/system-verilog-CnnmHF94.js +0 -0
  273. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/systemd-4A_iFExJ.js +0 -0
  274. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/talonscript-CkByrt1z.js +0 -0
  275. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/tasl-QIJgUcNo.js +0 -0
  276. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/tcl-dwOrl1Do.js +0 -0
  277. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/templ-W15q3VgB.js +0 -0
  278. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/terraform-BETggiCN.js +0 -0
  279. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/tex-Cppo0RY3.js +0 -0
  280. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/tokyo-night-hegEt444.js +0 -0
  281. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/toml-vGWfd6FD.js +0 -0
  282. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/ts-tags-zn1MmPIZ.js +0 -0
  283. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/tsv-B_m7g4N7.js +0 -0
  284. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/tsx-COt5Ahok.js +0 -0
  285. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/turtle-BsS91CYL.js +0 -0
  286. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/twig-CO9l9SDP.js +0 -0
  287. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/typescript-BPQ3VLAy.js +0 -0
  288. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/typespec-Df68jz8_.js +0 -0
  289. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/typst-DHCkPAjA.js +0 -0
  290. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/v-BcVCzyr7.js +0 -0
  291. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vala-CsfeWuGM.js +0 -0
  292. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vb-D17OF-Vu.js +0 -0
  293. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/verilog-BQ8w6xss.js +0 -0
  294. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vesper-DU1UobuO.js +0 -0
  295. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vhdl-CeAyd5Ju.js +0 -0
  296. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/viml-CJc9bBzg.js +0 -0
  297. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vitesse-black-Bkuqu6BP.js +0 -0
  298. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vitesse-dark-D0r3Knsf.js +0 -0
  299. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vitesse-light-CVO1_9PV.js +0 -0
  300. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vue-CCoi5OLL.js +0 -0
  301. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vue-html-DAAvJJDi.js +0 -0
  302. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vue-vine-_Ih-lPRR.js +0 -0
  303. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/vyper-CDx5xZoG.js +0 -0
  304. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/wasm-CG6Dc4jp.js +0 -0
  305. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/wasm-MzD3tlZU.js +0 -0
  306. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/wenyan-BV7otONQ.js +0 -0
  307. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/wgsl-Dx-B1_4e.js +0 -0
  308. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/wikitext-BhOHFoWU.js +0 -0
  309. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/wit-5i3qLPDT.js +0 -0
  310. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/wolfram-lXgVvXCa.js +0 -0
  311. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/xml-sdJ4AIDG.js +0 -0
  312. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/xsl-CtQFsRM5.js +0 -0
  313. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/yaml-Buea-lGh.js +0 -0
  314. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/zenscript-DVFEvuxE.js +0 -0
  315. {srcly-0.1.24 → srcly-0.1.27}/app/static/assets/zig-VOosw3JB.js +0 -0
  316. {srcly-0.1.24 → srcly-0.1.27}/app/static/vite.svg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: srcly
3
- Version: 0.1.24
3
+ Version: 0.1.27
4
4
  Summary: Interactive codebase treemap and metrics viewer.
5
5
  Requires-Python: >=3.13
6
6
  Requires-Dist: fastapi>=0.121.3
@@ -90,6 +90,11 @@ class OverlayToken(BaseModel):
90
90
  category: str
91
91
  symbolId: str
92
92
  tooltip: str
93
+ definitionSnippet: str | None = None
94
+ definitionLine: int | None = None
95
+ scopeSnippet: str | None = None
96
+ scopeLine: int | None = None
97
+ scopeEndLine: int | None = None
93
98
 
94
99
 
95
100
  class FocusOverlayResponse(BaseModel):
@@ -1,5 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
+ import logging
3
4
  from dataclasses import dataclass
4
5
  from pathlib import Path
5
6
  from typing import Dict, List, Optional, Tuple
@@ -14,6 +15,8 @@ from app.models import FocusOverlayResponse, OverlayToken
14
15
  TYPESCRIPT_LANGUAGE = Language(tstypescript.language_typescript())
15
16
  TSX_LANGUAGE = Language(tstypescript.language_tsx())
16
17
 
18
+ logger = logging.getLogger(__name__)
19
+
17
20
  _SUPPORTED_TYPESCRIPT_SUFFIXES: set[str] = {
18
21
  ".ts",
19
22
  ".tsx",
@@ -53,10 +56,11 @@ class _Def:
53
56
  @dataclass
54
57
  class _Scope:
55
58
  id: str
56
- type: str # "global" | "function" | "block"
59
+ type: str # "global" | "function" | "block" | "catch"
57
60
  parent_id: str | None
58
61
  start_line: int
59
62
  end_line: int
63
+ def_line: int # Line of the node that created the scope
60
64
  vars: Dict[str, _Def]
61
65
 
62
66
 
@@ -67,10 +71,11 @@ class _Usage:
67
71
  start_col: int # 0-based
68
72
  end_col: int # exclusive
69
73
  resolved: _Def | None
74
+ containing_fn_scope_id: str # Added to track where this usage occurs
70
75
 
71
76
 
72
77
  _BUILTINS: set[str] = {
73
- # JS/TS builtins (small Phase 1 heuristic set)
78
+ # JS/TS builtins
74
79
  "console",
75
80
  "Math",
76
81
  "JSON",
@@ -93,17 +98,96 @@ _BUILTINS: set[str] = {
93
98
  "URIError",
94
99
  "Symbol",
95
100
  "BigInt",
101
+ "Intl",
102
+ "Proxy",
103
+ "Reflect",
104
+ "Atomics",
105
+ "DataView",
106
+ "ArrayBuffer",
107
+ "SharedArrayBuffer",
108
+ "AggregateError",
109
+ "FinalizationRegistry",
110
+ "WeakRef",
111
+ # Typed Arrays
112
+ "Int8Array",
113
+ "Uint8Array",
114
+ "Uint8ClampedArray",
115
+ "Int16Array",
116
+ "Uint16Array",
117
+ "Int32Array",
118
+ "Uint32Array",
119
+ "Float32Array",
120
+ "Float64Array",
121
+ "BigInt64Array",
122
+ "BigUint64Array",
123
+ # Fetch / Streams
96
124
  "fetch",
97
125
  "Request",
98
126
  "Response",
99
127
  "Headers",
100
128
  "URL",
101
129
  "URLSearchParams",
130
+ "ReadableStream",
131
+ "WritableStream",
132
+ "TransformStream",
133
+ "TextEncoder",
134
+ "TextDecoder",
135
+ # Environment / Global
102
136
  "window",
103
137
  "document",
104
138
  "globalThis",
105
139
  "process",
106
140
  "Buffer",
141
+ "navigator",
142
+ "location",
143
+ "history",
144
+ "screen",
145
+ "frames",
146
+ "performance",
147
+ "structuredClone",
148
+ "queueMicrotask",
149
+ "requestIdleCallback",
150
+ "cancelIdleCallback",
151
+ # Common DOM / Web APIs
152
+ "Object",
153
+ "requestAnimationFrame",
154
+ "cancelAnimationFrame",
155
+ "localStorage",
156
+ "sessionStorage",
157
+ "confirm",
158
+ "alert",
159
+ "prompt",
160
+ "Node",
161
+ "NodeFilter",
162
+ "HTMLElement",
163
+ "Element",
164
+ "Event",
165
+ "CustomEvent",
166
+ "CSS",
167
+ "IntersectionObserver",
168
+ "ResizeObserver",
169
+ "MutationObserver",
170
+ "AbortController",
171
+ "AbortSignal",
172
+ "Crypto",
173
+ "crypto",
174
+ "indexedDB",
175
+ "ShadowRoot",
176
+ "DocumentFragment",
177
+ "setTimeout",
178
+ "clearTimeout",
179
+ "setInterval",
180
+ "clearInterval",
181
+ # Node.js legacy/common
182
+ "require",
183
+ "module",
184
+ "exports",
185
+ "__dirname",
186
+ "__filename",
187
+ # Constants
188
+ "undefined",
189
+ "NaN",
190
+ "Infinity",
107
191
  }
108
192
 
109
193
 
@@ -305,6 +389,8 @@ def _resolve_to_existing_ts_module(candidate: Path) -> Optional[Path]:
305
389
  ".webp",
306
390
  ".bmp",
307
391
  ".avif",
392
+ ".md",
393
+ ".txt",
308
394
  }
309
395
  if resolved.suffix and resolved.suffix in asset_exts:
310
396
  return None
@@ -364,6 +450,7 @@ def compute_focus_overlay(
364
450
  focus_end_line = max(focus_start_line, int(focus_end_line))
365
451
 
366
452
  content = path.read_bytes()
453
+ source_lines = content.decode("utf-8", errors="replace").splitlines()
367
454
  is_tsx = path.suffix.lower() == ".tsx" or path.name.endswith(".tsx")
368
455
  parser = Parser(TSX_LANGUAGE if is_tsx else TYPESCRIPT_LANGUAGE)
369
456
  tree = parser.parse(content)
@@ -375,8 +462,7 @@ def compute_focus_overlay(
375
462
  slice_end_line = min(slice_end_line, file_total_lines)
376
463
 
377
464
  scopes: Dict[str, _Scope] = {}
378
- scope_stack: List[_Scope] = []
379
-
465
+
380
466
  # Deterministic scope IDs based on start/end lines + a monotonic counter for collisions.
381
467
  scope_counter = 0
382
468
 
@@ -396,13 +482,13 @@ def compute_focus_overlay(
396
482
  parent_id=parent.id if parent else None,
397
483
  start_line=start_line,
398
484
  end_line=end_line,
485
+ def_line=start_line,
399
486
  vars={},
400
487
  )
401
488
  scopes[scope.id] = scope
402
489
  return scope
403
490
 
404
491
  global_scope = new_scope("global", tree.root_node, None)
405
- scope_stack.append(global_scope)
406
492
 
407
493
  # --- Helpers ---
408
494
  def _is_function_node(n: Node) -> bool:
@@ -414,21 +500,29 @@ def compute_focus_overlay(
414
500
  "generator_function",
415
501
  "generator_function_declaration",
416
502
  }
503
+
504
+ def _is_catch_clause(n: Node) -> bool:
505
+ return n.type == "catch_clause"
417
506
 
418
507
  def _is_scope_boundary(n: Node) -> bool:
419
508
  # Mirror the data-flow analyzer behavior: don't create a redundant block
420
509
  # scope for function bodies.
421
510
  if n.type in {"block", "statement_block"}:
422
511
  parent = n.parent
423
- if parent and _is_function_node(parent):
512
+ if parent and (_is_function_node(parent) or _is_catch_clause(parent)):
424
513
  return False
425
514
  return True
515
+
516
+ if _is_catch_clause(n):
517
+ return True
426
518
 
427
519
  return _is_function_node(n)
428
520
 
429
521
  def _scope_type(n: Node) -> str:
430
522
  if _is_function_node(n):
431
523
  return "function"
524
+ if _is_catch_clause(n):
525
+ return "catch"
432
526
  if n.type in {"block", "statement_block"}:
433
527
  return "block"
434
528
  return "block"
@@ -506,10 +600,15 @@ def compute_focus_overlay(
506
600
  )
507
601
  scope.vars[name] = d
508
602
 
509
- def _resolve(name: str) -> _Def | None:
510
- for s in reversed(scope_stack):
511
- if name in s.vars:
512
- return s.vars[name]
603
+ def _resolve(name: str, start_scope: _Scope) -> _Def | None:
604
+ curr = start_scope
605
+ while curr:
606
+ if name in curr.vars:
607
+ return curr.vars[name]
608
+ if curr.parent_id:
609
+ curr = scopes[curr.parent_id]
610
+ else:
611
+ break
513
612
  return None
514
613
 
515
614
  def _ancestor_chain(scope_id: str) -> List[str]:
@@ -522,16 +621,20 @@ def compute_focus_overlay(
522
621
  curr = scopes.get(curr.parent_id)
523
622
  return chain
524
623
 
525
- # --- Traverse: create scopes + record defs/usages ---
526
- usages: List[_Usage] = []
527
-
528
- def traverse(n: Node) -> None:
529
- scope_created = False
624
+ # --- Phase 1: Create scopes and record definitions ---
625
+
626
+ # We maintain a mapping of node_id -> created_scope so we can look them up in Phase 2
627
+ # `scope_boundary_map[id(node)] = scope`
628
+ scope_boundary_map: Dict[int, _Scope] = {}
629
+
630
+ def phase1_traverse(n: Node, current_scope: _Scope) -> None:
631
+ next_scope = current_scope
530
632
  if _is_scope_boundary(n):
531
- parent = scope_stack[-1] if scope_stack else None
532
- scope = new_scope(_scope_type(n), n, parent)
533
- scope_stack.append(scope)
534
- scope_created = True
633
+ # If we are effectively creating a new scope
634
+ # Ensure we don't recreate global scope if n is root
635
+ if n != tree.root_node:
636
+ next_scope = new_scope(_scope_type(n), n, current_scope)
637
+ scope_boundary_map[n.id] = next_scope
535
638
 
536
639
  # Definitions
537
640
  if n.type == "import_statement":
@@ -617,62 +720,86 @@ def compute_focus_overlay(
617
720
  import_is_internal=is_internal,
618
721
  )
619
722
 
620
- if n.type == "variable_declarator":
723
+ elif n.type == "variable_declarator":
621
724
  name_node = n.child_by_field_name("name")
622
725
  if name_node is not None:
623
726
  if name_node.type == "identifier":
624
727
  _add_def(
625
728
  name_node=name_node,
626
729
  kind="local",
627
- scope=scope_stack[-1],
628
- scope_type=scope_stack[-1].type,
730
+ scope=next_scope,
731
+ scope_type=next_scope.type,
629
732
  )
630
733
  else:
631
734
  for ident in _collect_pattern_identifiers(name_node):
632
735
  _add_def(
633
736
  name_node=ident,
634
737
  kind="local",
635
- scope=scope_stack[-1],
636
- scope_type=scope_stack[-1].type,
738
+ scope=next_scope,
739
+ scope_type=next_scope.type,
637
740
  )
638
741
 
639
- if n.type in {"required_parameter", "optional_parameter", "rest_parameter"}:
742
+ elif n.type in {"required_parameter", "optional_parameter", "rest_parameter"}:
640
743
  for ident in _collect_pattern_identifiers(n):
641
744
  _add_def(
642
745
  name_node=ident,
643
746
  kind="param",
644
- scope=scope_stack[-1],
645
- scope_type=scope_stack[-1].type,
747
+ scope=next_scope,
748
+ scope_type=next_scope.type,
646
749
  )
750
+
751
+ elif n.type == "identifier" and n.parent and n.parent.type == "arrow_function":
752
+ # In arrow functions like `tile => { ... }`, the parameter `tile`
753
+ # is a direct identifier child of the arrow_function node.
754
+ _add_def(
755
+ name_node=n,
756
+ kind="param",
757
+ scope=next_scope,
758
+ scope_type=next_scope.type,
759
+ )
760
+
761
+ elif n.type == "catch_clause":
762
+ # catch (err) ...
763
+ param = n.child_by_field_name("parameter")
764
+ if param:
765
+ # The parameter node might be an identifier or a pattern (destructuring)
766
+ # But it is physically outside the 'body' block.
767
+ # Since we created a 'catch' scope for this catch_clause node, we can add it there.
768
+
769
+ # In tree-sitter-typescript, the parameter field of catch_clause serves as the binding.
770
+ if param.type == "identifier":
771
+ _add_def(name_node=param, kind="param", scope=next_scope, scope_type="catch")
772
+ else:
773
+ for ident in _collect_pattern_identifiers(param):
774
+ _add_def(name_node=ident, kind="param", scope=next_scope, scope_type="catch")
647
775
 
648
- if n.type == "function_declaration":
776
+
777
+ elif n.type == "function_declaration":
649
778
  name_node = n.child_by_field_name("name")
650
779
  if name_node is not None:
651
780
  # Define function name in parent scope (if any).
652
- parent_scope = scope_stack[-2] if len(scope_stack) >= 2 else scope_stack[-1]
781
+ # `next_scope` IS the function scope.
782
+ # So we want the scope enclosing `n`, which is `current_scope`.
783
+
653
784
  _add_def(
654
785
  name_node=name_node,
655
- kind="local" if parent_scope.type != "global" else "module",
656
- scope=parent_scope,
657
- scope_type=parent_scope.type,
786
+ kind="local" if current_scope.type != "global" else "module",
787
+ scope=current_scope,
788
+ scope_type=current_scope.type,
658
789
  )
659
790
 
660
- if n.type == "class_declaration":
791
+ elif n.type == "class_declaration":
661
792
  name_node = n.child_by_field_name("name")
662
793
  if name_node is not None:
663
- parent_scope = scope_stack[-2] if len(scope_stack) >= 2 else scope_stack[-1]
664
794
  _add_def(
665
795
  name_node=name_node,
666
- kind="local" if parent_scope.type != "global" else "module",
667
- scope=parent_scope,
668
- scope_type=parent_scope.type,
796
+ kind="local" if current_scope.type != "global" else "module",
797
+ scope=current_scope,
798
+ scope_type=current_scope.type,
669
799
  )
670
800
 
671
801
  # Loop introductions:
672
- # In our tree-sitter-typescript version, `for (const x of xs) { ... }`
673
- # parses as `for_in_statement` with children including `const`, `of`,
674
- # and `left` as a bare identifier (not a variable_declarator).
675
- if n.type == "for_in_statement":
802
+ elif n.type == "for_in_statement":
676
803
  # Only treat as an introduction when it's a declaration (const/let/var).
677
804
  is_decl = any(c.type in {"const", "let", "var"} for c in n.children)
678
805
  if is_decl:
@@ -682,20 +809,35 @@ def compute_focus_overlay(
682
809
  _add_def(
683
810
  name_node=left,
684
811
  kind="local",
685
- scope=scope_stack[-1],
686
- scope_type=scope_stack[-1].type,
812
+ scope=next_scope,
813
+ scope_type=next_scope.type,
687
814
  )
688
815
  else:
689
816
  for ident in _collect_pattern_identifiers(left):
690
817
  _add_def(
691
818
  name_node=ident,
692
819
  kind="local",
693
- scope=scope_stack[-1],
694
- scope_type=scope_stack[-1].type,
820
+ scope=next_scope,
821
+ scope_type=next_scope.type,
695
822
  )
696
823
 
697
- # Usages: resolve identifiers while we still have the right scope stack.
698
- if n.type == "identifier":
824
+ for c in n.children:
825
+ phase1_traverse(c, next_scope)
826
+
827
+ phase1_traverse(tree.root_node, global_scope)
828
+
829
+ # --- Phase 2: Record usages ---
830
+ usages: List[_Usage] = []
831
+
832
+ unresolved_counts: Dict[str, int] = {}
833
+
834
+ def phase2_traverse(n: Node, current_scope: _Scope) -> None:
835
+ next_scope = current_scope
836
+ if n.id in scope_boundary_map:
837
+ next_scope = scope_boundary_map[n.id]
838
+
839
+ # Usages: resolve identifiers
840
+ if n.type in {"identifier", "jsx_identifier"}:
699
841
  parent = n.parent
700
842
  if parent is not None:
701
843
  # Skip identifier occurrences that are themselves definitions.
@@ -707,36 +849,77 @@ def compute_focus_overlay(
707
849
  pass
708
850
  elif parent.type in {"required_parameter", "optional_parameter", "rest_parameter"}:
709
851
  pass
852
+ elif parent.type == "catch_clause" and parent.child_by_field_name("parameter") == n:
853
+ pass
710
854
  elif (
711
855
  parent.type == "for_in_statement"
712
856
  and parent.child_by_field_name("left") == n
713
857
  and any(c.type in {"const", "let", "var"} for c in parent.children)
714
858
  ):
715
- # `for (const x of xs)` introduces `x` as a binding.
716
859
  pass
717
860
  elif parent.type == "property_identifier":
718
861
  pass
862
+
863
+ # SPECIAL HANDLING FOR JSX
864
+ # 1. Skip if it is an attribute name
865
+ elif (n.type in {"identifier", "jsx_identifier"}) and parent.type == "jsx_attribute" and parent.child_by_field_name("name") == n:
866
+ pass
867
+ # 2. Skip intrinsic elements (lowercase tag names)
868
+ # If text is uppercase, the condition below fails, so we fall through to 'else'
869
+ # and process it as a component usage.
870
+ elif (
871
+ n.type in {"identifier", "jsx_identifier"}
872
+ and parent.type in {"jsx_opening_element", "jsx_closing_element", "jsx_self_closing_element"}
873
+ and parent.child_by_field_name("name") == n
874
+ and n.text.decode("utf-8", errors="ignore")[0].islower()
875
+ ):
876
+ pass
877
+
719
878
  else:
720
879
  # Skip identifiers inside binding patterns (destructuring LHS / params)
880
+ # Skip identifiers inside binding patterns (destructuring LHS / params)
881
+ # We need to be careful not to skip usages on the RHS.
882
+ # e.g. `const { x: y } = z` -> x is prop (skipped), y is def (skipped), z is usage.
721
883
  curr = n
884
+ is_definition_part = False
885
+
722
886
  while curr is not None:
723
887
  p = curr.parent
724
888
  if p is None:
725
889
  break
890
+
891
+ # Variable declarator: `name` field is the pattern/identifier being defined.
726
892
  if p.type == "variable_declarator":
727
893
  name_node = p.child_by_field_name("name")
728
894
  if name_node is not None:
729
895
  check = n
896
+ # Walk up from n to p. If we hit name_node, we are inside the definition side.
730
897
  while check is not None and check is not p:
731
- if check is name_node:
898
+ if check == name_node:
899
+ is_definition_part = True
732
900
  break
733
901
  check = check.parent
734
- if check is name_node:
735
- curr = None
902
+ if is_definition_part:
736
903
  break
904
+
737
905
  if p.type in {"required_parameter", "optional_parameter", "rest_parameter"}:
738
- curr = None
906
+ is_definition_part = True
739
907
  break
908
+
909
+ if p.type == "catch_clause":
910
+ param = p.child_by_field_name("parameter")
911
+ # If we are inside the parameter node
912
+ if param:
913
+ check = n
914
+ while check is not None and check is not p:
915
+ if check is param:
916
+ is_definition_part = True
917
+ break
918
+ check = check.parent
919
+ if is_definition_part:
920
+ break
921
+
922
+ # Boundaries where definition context definitely ends
740
923
  if p.type in {
741
924
  "program",
742
925
  "statement_block",
@@ -747,11 +930,24 @@ def compute_focus_overlay(
747
930
  "class_declaration",
748
931
  }:
749
932
  break
933
+
750
934
  curr = p
751
- if curr is not None:
935
+ if is_definition_part:
936
+ break
937
+
938
+ if not is_definition_part:
752
939
  name = n.text.decode("utf-8", errors="ignore")
753
940
  if name:
754
- resolved = _resolve(name)
941
+ resolved = _resolve(name, next_scope)
942
+ if resolved is None and name not in _BUILTINS:
943
+ unresolved_counts[name] = unresolved_counts.get(name, 0) + 1
944
+
945
+ # Find the immediate containing function scope for this usage.
946
+ # This is crucial for per-token "capture" vs "local" classification.
947
+ usage_fn_scope = next_scope
948
+ while usage_fn_scope and usage_fn_scope.type != "function" and usage_fn_scope.parent_id:
949
+ usage_fn_scope = scopes[usage_fn_scope.parent_id]
950
+
755
951
  usages.append(
756
952
  _Usage(
757
953
  name=name,
@@ -759,31 +955,19 @@ def compute_focus_overlay(
759
955
  start_col=n.start_point.column,
760
956
  end_col=n.end_point.column,
761
957
  resolved=resolved,
958
+ containing_fn_scope_id=usage_fn_scope.id if usage_fn_scope else global_scope.id,
762
959
  )
763
960
  )
764
961
 
765
962
  for c in n.children:
766
- traverse(c)
767
-
768
- if scope_created:
769
- scope_stack.pop()
963
+ phase2_traverse(c, next_scope)
770
964
 
771
- traverse(tree.root_node)
965
+ phase2_traverse(tree.root_node, global_scope)
772
966
 
773
- # --- Find focus function scope (preferred boundary for param/local/capture semantics) ---
774
- def smallest_containing_function_scope() -> _Scope:
775
- candidates: List[_Scope] = []
776
- for s in scopes.values():
777
- if s.type != "function":
778
- continue
779
- if s.start_line <= focus_start_line and s.end_line >= focus_end_line:
780
- candidates.append(s)
781
- if not candidates:
782
- return global_scope
783
- return min(candidates, key=lambda s: (s.end_line - s.start_line, s.start_line))
784
-
785
- focus_fn_scope = smallest_containing_function_scope()
786
- focus_fn_chain = set(_ancestor_chain(focus_fn_scope.id)) # includes global
967
+ if unresolved_counts:
968
+ # Log top unresolved identifiers to help identify missing builtins/globals
969
+ sorted_unresolved = sorted(unresolved_counts.items(), key=lambda x: x[1], reverse=True)
970
+ logger.info(f"Focus overlay unresolved symbols for {path.name}: {sorted_unresolved[:20]}")
787
971
 
788
972
  # --- Build tokens ---
789
973
  tokens: List[OverlayToken] = []
@@ -846,17 +1030,48 @@ def compute_focus_overlay(
846
1030
  category = "module"
847
1031
  tooltip = f"Module scope (line {d.def_line})"
848
1032
  else:
1033
+ # Classify relative to the token's immediate containing function scope
1034
+ usage_fn_scope_id = u.containing_fn_scope_id
1035
+ usage_fn_chain = set(_ancestor_chain(usage_fn_scope_id))
1036
+
1037
+
849
1038
  def_chain = set(_ancestor_chain(def_scope.id))
850
- if focus_fn_scope.id in def_chain:
1039
+
1040
+ # START FIX: If the definition is within the current focus range, treat as local.
1041
+ definition_in_focus = (focus_start_line <= d.def_line <= focus_end_line)
1042
+
1043
+ if definition_in_focus:
851
1044
  category = "local"
852
1045
  tooltip = f"Local declaration (line {d.def_line})"
853
- elif def_scope.id in focus_fn_chain and def_scope.id != global_scope.id:
1046
+ elif usage_fn_scope_id in def_chain:
1047
+ category = "local"
1048
+ tooltip = f"Local declaration (line {d.def_line})"
1049
+ elif def_scope.id in usage_fn_chain and def_scope.id != global_scope.id:
854
1050
  category = "capture"
855
1051
  tooltip = f"Captured from outer scope (line {d.def_line})"
856
1052
  else:
857
1053
  category = "local"
858
1054
  tooltip = f"Local declaration (line {d.def_line})"
859
1055
 
1056
+ definition_snippet: str | None = None
1057
+ definition_line: int | None = None
1058
+ if d:
1059
+ definition_line = d.def_line
1060
+ if 0 <= d.def_line - 1 < len(source_lines):
1061
+ definition_snippet = source_lines[d.def_line - 1].strip()
1062
+
1063
+ scope_snippet: str | None = None
1064
+ scope_line: int | None = None
1065
+ scope_end_line: int | None = None
1066
+
1067
+ if category == "capture" and d:
1068
+ def_scope = scopes.get(d.scope_id)
1069
+ if def_scope:
1070
+ scope_line = def_scope.def_line
1071
+ scope_end_line = def_scope.end_line
1072
+ if 0 <= scope_line - 1 < len(source_lines):
1073
+ scope_snippet = source_lines[scope_line - 1].strip()
1074
+
860
1075
  tokens.append(
861
1076
  OverlayToken(
862
1077
  fileLine=u_line,
@@ -865,9 +1080,12 @@ def compute_focus_overlay(
865
1080
  category=category,
866
1081
  symbolId=symbol_id,
867
1082
  tooltip=tooltip,
1083
+ definitionSnippet=definition_snippet,
1084
+ definitionLine=definition_line,
1085
+ scopeSnippet=scope_snippet,
1086
+ scopeLine=scope_line,
1087
+ scopeEndLine=scope_end_line,
868
1088
  )
869
1089
  )
870
1090
 
871
1091
  return FocusOverlayResponse(tokens=tokens)
872
-
873
-