@fairyhunter13/opentui-core 0.1.88 → 0.1.90

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 (570) hide show
  1. package/dev/keypress-debug-renderer.ts +148 -0
  2. package/dev/keypress-debug.ts +43 -0
  3. package/dev/print-env-vars.ts +32 -0
  4. package/dev/test-tmux-graphics-334.sh +68 -0
  5. package/dev/thai-debug-test.ts +68 -0
  6. package/docs/development.md +141 -0
  7. package/docs/env-vars.md +140 -0
  8. package/docs/getting-started.md +353 -0
  9. package/docs/renderables-vs-constructs.md +159 -0
  10. package/docs/tree-sitter.md +311 -0
  11. package/package.json +61 -52
  12. package/scripts/build.ts +400 -0
  13. package/scripts/publish.ts +60 -0
  14. package/src/3d/SpriteResourceManager.ts +286 -0
  15. package/src/3d/SpriteUtils.ts +71 -0
  16. package/src/3d/TextureUtils.ts +196 -0
  17. package/src/3d/ThreeRenderable.ts +197 -0
  18. package/src/3d/WGPURenderer.ts +294 -0
  19. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  20. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  21. package/src/3d/animation/SpriteAnimator.ts +633 -0
  22. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  23. package/src/3d/canvas.ts +464 -0
  24. package/src/3d/index.ts +12 -0
  25. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  26. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  27. package/src/3d/physics/physics-interface.ts +31 -0
  28. package/src/3d/shaders/supersampling.wgsl +201 -0
  29. package/src/3d.ts +3 -0
  30. package/src/NativeSpanFeed.ts +300 -0
  31. package/src/Renderable.ts +1698 -0
  32. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  33. package/src/animation/Timeline.test.ts +2709 -0
  34. package/src/animation/Timeline.ts +598 -0
  35. package/src/ansi.ts +18 -0
  36. package/src/benchmark/latest-all-bench-run.json +707 -0
  37. package/src/benchmark/latest-async-bench-run.json +336 -0
  38. package/src/benchmark/latest-default-bench-run.json +657 -0
  39. package/src/benchmark/latest-large-bench-run.json +707 -0
  40. package/src/benchmark/latest-quick-bench-run.json +207 -0
  41. package/src/benchmark/markdown-benchmark.ts +1804 -0
  42. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  43. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  44. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  45. package/src/benchmark/native-span-feed-compare.ts +280 -0
  46. package/src/benchmark/renderer-benchmark.ts +754 -0
  47. package/src/benchmark/text-table-benchmark.ts +947 -0
  48. package/src/buffer.test.ts +291 -0
  49. package/src/buffer.ts +519 -0
  50. package/src/console.test.ts +612 -0
  51. package/src/console.ts +1255 -0
  52. package/src/edit-buffer.test.ts +1769 -0
  53. package/src/edit-buffer.ts +411 -0
  54. package/src/editor-view.test.ts +1032 -0
  55. package/src/editor-view.ts +284 -0
  56. package/src/examples/ascii-font-selection-demo.ts +245 -0
  57. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  58. package/src/examples/assets/concrete.png +0 -0
  59. package/src/examples/assets/crate.png +0 -0
  60. package/src/examples/assets/crate_emissive.png +0 -0
  61. package/src/examples/assets/forrest_background.png +0 -0
  62. package/src/examples/assets/hast-example.json +1018 -0
  63. package/src/examples/assets/heart.png +0 -0
  64. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  65. package/src/examples/assets/main_char_idle.png +0 -0
  66. package/src/examples/assets/main_char_jump_end.png +0 -0
  67. package/src/examples/assets/main_char_jump_landing.png +0 -0
  68. package/src/examples/assets/main_char_jump_start.png +0 -0
  69. package/src/examples/assets/main_char_run_loop.png +0 -0
  70. package/src/examples/assets/roughness_map.jpg +0 -0
  71. package/src/examples/build.ts +115 -0
  72. package/src/examples/code-demo.ts +584 -0
  73. package/src/examples/console-demo.ts +358 -0
  74. package/src/examples/core-plugin-slots-demo.ts +759 -0
  75. package/src/examples/diff-demo.ts +699 -0
  76. package/src/examples/draggable-three-demo.ts +259 -0
  77. package/src/examples/editor-demo.ts +322 -0
  78. package/src/examples/extmarks-demo.ts +204 -0
  79. package/src/examples/focus-restore-demo.ts +310 -0
  80. package/src/examples/fonts.ts +245 -0
  81. package/src/examples/fractal-shader-demo.ts +268 -0
  82. package/src/examples/framebuffer-demo.ts +674 -0
  83. package/src/examples/full-unicode-demo.ts +181 -0
  84. package/src/examples/golden-star-demo.ts +933 -0
  85. package/src/examples/grayscale-buffer-demo.ts +249 -0
  86. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  87. package/src/examples/index.ts +925 -0
  88. package/src/examples/input-demo.ts +377 -0
  89. package/src/examples/input-select-layout-demo.ts +425 -0
  90. package/src/examples/install.sh +143 -0
  91. package/src/examples/keypress-debug-demo.ts +452 -0
  92. package/src/examples/lib/HexList.ts +122 -0
  93. package/src/examples/lib/PaletteGrid.ts +125 -0
  94. package/src/examples/lib/standalone-keys.ts +25 -0
  95. package/src/examples/lib/tab-controller.ts +243 -0
  96. package/src/examples/lights-phong-demo.ts +290 -0
  97. package/src/examples/link-demo.ts +220 -0
  98. package/src/examples/live-state-demo.ts +480 -0
  99. package/src/examples/markdown-demo.ts +620 -0
  100. package/src/examples/mouse-interaction-demo.ts +428 -0
  101. package/src/examples/nested-zindex-demo.ts +357 -0
  102. package/src/examples/opacity-example.ts +235 -0
  103. package/src/examples/opentui-demo.ts +1057 -0
  104. package/src/examples/physx-planck-2d-demo.ts +507 -0
  105. package/src/examples/physx-rapier-2d-demo.ts +526 -0
  106. package/src/examples/relative-positioning-demo.ts +323 -0
  107. package/src/examples/scroll-example.ts +214 -0
  108. package/src/examples/scrollbox-mouse-test.ts +112 -0
  109. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  110. package/src/examples/select-demo.ts +237 -0
  111. package/src/examples/shader-cube-demo.ts +772 -0
  112. package/src/examples/simple-layout-example.ts +591 -0
  113. package/src/examples/slider-demo.ts +617 -0
  114. package/src/examples/split-mode-demo.ts +445 -0
  115. package/src/examples/sprite-animation-demo.ts +443 -0
  116. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  117. package/src/examples/static-sprite-demo.ts +193 -0
  118. package/src/examples/sticky-scroll-example.ts +308 -0
  119. package/src/examples/styled-text-demo.ts +282 -0
  120. package/src/examples/tab-select-demo.ts +219 -0
  121. package/src/examples/terminal-title.ts +29 -0
  122. package/src/examples/terminal.ts +305 -0
  123. package/src/examples/text-node-demo.ts +416 -0
  124. package/src/examples/text-selection-demo.ts +377 -0
  125. package/src/examples/text-table-demo.ts +503 -0
  126. package/src/examples/text-truncation-demo.ts +481 -0
  127. package/src/examples/text-wrap.ts +757 -0
  128. package/src/examples/texture-loading-demo.ts +259 -0
  129. package/src/examples/timeline-example.ts +670 -0
  130. package/src/examples/transparency-demo.ts +241 -0
  131. package/src/examples/vnode-composition-demo.ts +404 -0
  132. package/src/index.ts +22 -0
  133. package/src/lib/KeyHandler.integration.test.ts +292 -0
  134. package/src/lib/KeyHandler.stopPropagation.test.ts +289 -0
  135. package/src/lib/KeyHandler.test.ts +662 -0
  136. package/src/lib/KeyHandler.ts +222 -0
  137. package/src/lib/RGBA.test.ts +984 -0
  138. package/src/lib/RGBA.ts +204 -0
  139. package/src/lib/ascii.font.ts +330 -0
  140. package/src/lib/border.test.ts +83 -0
  141. package/src/lib/border.ts +168 -0
  142. package/src/lib/bunfs.test.ts +27 -0
  143. package/src/lib/bunfs.ts +18 -0
  144. package/src/lib/clipboard.test.ts +41 -0
  145. package/src/lib/clipboard.ts +47 -0
  146. package/src/lib/clock.ts +31 -0
  147. package/src/lib/data-paths.test.ts +133 -0
  148. package/src/lib/data-paths.ts +109 -0
  149. package/src/lib/debounce.ts +106 -0
  150. package/src/lib/detect-links.test.ts +98 -0
  151. package/src/lib/detect-links.ts +56 -0
  152. package/src/lib/env.test.ts +228 -0
  153. package/src/lib/env.ts +209 -0
  154. package/src/lib/extmarks-history.ts +51 -0
  155. package/src/lib/extmarks-multiwidth.test.ts +322 -0
  156. package/src/lib/extmarks.test.ts +3457 -0
  157. package/src/lib/extmarks.ts +843 -0
  158. package/src/lib/fonts/block.json +405 -0
  159. package/src/lib/fonts/grid.json +265 -0
  160. package/src/lib/fonts/huge.json +741 -0
  161. package/src/lib/fonts/pallet.json +314 -0
  162. package/src/lib/fonts/shade.json +591 -0
  163. package/src/lib/fonts/slick.json +321 -0
  164. package/src/lib/fonts/tiny.json +69 -0
  165. package/src/lib/hast-styled-text.ts +59 -0
  166. package/src/lib/index.ts +21 -0
  167. package/src/lib/keymapping.test.ts +280 -0
  168. package/src/lib/keymapping.ts +87 -0
  169. package/src/lib/objects-in-viewport.test.ts +787 -0
  170. package/src/lib/objects-in-viewport.ts +153 -0
  171. package/src/lib/output.capture.ts +58 -0
  172. package/src/lib/parse.keypress-kitty.protocol.test.ts +340 -0
  173. package/src/lib/parse.keypress-kitty.test.ts +663 -0
  174. package/src/lib/parse.keypress-kitty.ts +439 -0
  175. package/src/lib/parse.keypress.test.ts +1849 -0
  176. package/src/lib/parse.keypress.ts +397 -0
  177. package/src/lib/parse.mouse.test.ts +552 -0
  178. package/src/lib/parse.mouse.ts +232 -0
  179. package/src/lib/paste.ts +16 -0
  180. package/src/lib/queue.ts +65 -0
  181. package/src/lib/renderable.validations.test.ts +87 -0
  182. package/src/lib/renderable.validations.ts +83 -0
  183. package/src/lib/scroll-acceleration.ts +98 -0
  184. package/src/lib/selection.ts +240 -0
  185. package/src/lib/singleton.ts +28 -0
  186. package/src/lib/stdin-parser.test.ts +1676 -0
  187. package/src/lib/stdin-parser.ts +1248 -0
  188. package/src/lib/styled-text.ts +178 -0
  189. package/src/lib/terminal-capability-detection.test.ts +202 -0
  190. package/src/lib/terminal-capability-detection.ts +79 -0
  191. package/src/lib/terminal-palette.test.ts +878 -0
  192. package/src/lib/terminal-palette.ts +383 -0
  193. package/src/lib/tree-sitter/assets/README.md +118 -0
  194. package/src/lib/tree-sitter/assets/update.ts +331 -0
  195. package/src/lib/tree-sitter/assets.d.ts +9 -0
  196. package/src/lib/tree-sitter/cache.test.ts +270 -0
  197. package/src/lib/tree-sitter/client.test.ts +1061 -0
  198. package/src/lib/tree-sitter/client.ts +615 -0
  199. package/src/lib/tree-sitter/default-parsers.ts +80 -0
  200. package/src/lib/tree-sitter/download-utils.ts +148 -0
  201. package/src/lib/tree-sitter/index.ts +28 -0
  202. package/src/lib/tree-sitter/parser.worker.ts +1001 -0
  203. package/src/lib/tree-sitter/parsers-config.ts +75 -0
  204. package/src/lib/tree-sitter/resolve-ft.ts +62 -0
  205. package/src/lib/tree-sitter/types.ts +81 -0
  206. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  207. package/src/lib/tree-sitter-styled-text.ts +306 -0
  208. package/src/lib/validate-dir-name.ts +55 -0
  209. package/src/lib/yoga.options.test.ts +628 -0
  210. package/src/lib/yoga.options.ts +346 -0
  211. package/src/plugins/core-slot.ts +579 -0
  212. package/src/plugins/registry.ts +377 -0
  213. package/src/plugins/types.ts +46 -0
  214. package/src/post/filters.ts +888 -0
  215. package/src/renderables/ASCIIFont.ts +219 -0
  216. package/src/renderables/Box.test.ts +160 -0
  217. package/src/renderables/Box.ts +295 -0
  218. package/src/renderables/Code.test.ts +2062 -0
  219. package/src/renderables/Code.ts +357 -0
  220. package/src/renderables/Diff.regression.test.ts +226 -0
  221. package/src/renderables/Diff.test.ts +3027 -0
  222. package/src/renderables/Diff.ts +1209 -0
  223. package/src/renderables/EditBufferRenderable.ts +764 -0
  224. package/src/renderables/FrameBuffer.ts +47 -0
  225. package/src/renderables/Input.test.ts +1228 -0
  226. package/src/renderables/Input.ts +245 -0
  227. package/src/renderables/LineNumberRenderable.ts +675 -0
  228. package/src/renderables/Markdown.ts +1106 -0
  229. package/src/renderables/ScrollBar.ts +422 -0
  230. package/src/renderables/ScrollBox.ts +883 -0
  231. package/src/renderables/Select.test.ts +1010 -0
  232. package/src/renderables/Select.ts +523 -0
  233. package/src/renderables/Slider.test.ts +456 -0
  234. package/src/renderables/Slider.ts +347 -0
  235. package/src/renderables/TabSelect.test.ts +197 -0
  236. package/src/renderables/TabSelect.ts +455 -0
  237. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  238. package/src/renderables/Text.test.ts +2660 -0
  239. package/src/renderables/Text.ts +147 -0
  240. package/src/renderables/TextBufferRenderable.ts +518 -0
  241. package/src/renderables/TextNode.test.ts +1058 -0
  242. package/src/renderables/TextNode.ts +325 -0
  243. package/src/renderables/TextTable.test.ts +1421 -0
  244. package/src/renderables/TextTable.ts +1344 -0
  245. package/src/renderables/Textarea.ts +732 -0
  246. package/src/renderables/TimeToFirstDraw.ts +89 -0
  247. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  248. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  249. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  250. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  251. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  252. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  253. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1787 -0
  254. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  255. package/src/renderables/__tests__/Markdown.test.ts +2287 -0
  256. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  257. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  258. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  259. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  260. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  261. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  262. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  263. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  264. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  265. package/src/renderables/__tests__/Textarea.rendering.test.ts +1864 -0
  266. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  267. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  268. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  269. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  270. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  271. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  272. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  273. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  274. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  275. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  276. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  277. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  278. package/src/renderables/composition/README.md +8 -0
  279. package/src/renderables/composition/VRenderable.ts +32 -0
  280. package/src/renderables/composition/constructs.ts +127 -0
  281. package/src/renderables/composition/vnode.ts +289 -0
  282. package/src/renderables/index.ts +22 -0
  283. package/src/renderables/markdown-parser.ts +66 -0
  284. package/src/renderer.ts +2363 -0
  285. package/src/runtime-plugin-support.ts +39 -0
  286. package/src/runtime-plugin.ts +144 -0
  287. package/src/syntax-style.test.ts +841 -0
  288. package/src/syntax-style.ts +264 -0
  289. package/src/testing/README.md +210 -0
  290. package/src/testing/capture-spans.test.ts +194 -0
  291. package/src/testing/integration.test.ts +276 -0
  292. package/src/testing/manual-clock.ts +106 -0
  293. package/src/testing/mock-keys.test.ts +1356 -0
  294. package/src/testing/mock-keys.ts +449 -0
  295. package/src/testing/mock-mouse.test.ts +218 -0
  296. package/src/testing/mock-mouse.ts +247 -0
  297. package/src/testing/mock-tree-sitter-client.ts +73 -0
  298. package/src/testing/spy.ts +13 -0
  299. package/src/testing/test-recorder.test.ts +415 -0
  300. package/src/testing/test-recorder.ts +145 -0
  301. package/src/testing/test-renderer.ts +116 -0
  302. package/src/testing.ts +7 -0
  303. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  304. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  305. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  306. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  307. package/src/tests/allocator-stats.test.ts +38 -0
  308. package/src/tests/destroy-during-render.test.ts +200 -0
  309. package/src/tests/hover-cursor.test.ts +98 -0
  310. package/src/tests/native-span-feed-async.test.ts +173 -0
  311. package/src/tests/native-span-feed-close.test.ts +120 -0
  312. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  313. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  314. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  315. package/src/tests/opacity.test.ts +123 -0
  316. package/src/tests/renderable.snapshot.test.ts +524 -0
  317. package/src/tests/renderable.test.ts +1281 -0
  318. package/src/tests/renderer.console-startup.test.ts +65 -0
  319. package/src/tests/renderer.control.test.ts +364 -0
  320. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  321. package/src/tests/renderer.cursor.test.ts +26 -0
  322. package/src/tests/renderer.destroy-during-render.test.ts +110 -0
  323. package/src/tests/renderer.focus-restore.test.ts +228 -0
  324. package/src/tests/renderer.focus.test.ts +251 -0
  325. package/src/tests/renderer.idle.test.ts +219 -0
  326. package/src/tests/renderer.input.test.ts +2145 -0
  327. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  328. package/src/tests/renderer.mouse.test.ts +1269 -0
  329. package/src/tests/renderer.palette.test.ts +629 -0
  330. package/src/tests/renderer.selection.test.ts +49 -0
  331. package/src/tests/renderer.slot-registry.test.ts +649 -0
  332. package/src/tests/renderer.useMouse.test.ts +50 -0
  333. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  334. package/src/tests/runtime-plugin-support.test.ts +28 -0
  335. package/src/tests/runtime-plugin.fixture.ts +40 -0
  336. package/src/tests/runtime-plugin.test.ts +190 -0
  337. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  338. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  339. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  340. package/src/tests/scrollbox.test.ts +1530 -0
  341. package/src/tests/wrap-resize-perf.test.ts +229 -0
  342. package/src/tests/yoga-setters.test.ts +921 -0
  343. package/src/text-buffer-view.test.ts +705 -0
  344. package/src/text-buffer-view.ts +189 -0
  345. package/src/text-buffer.test.ts +347 -0
  346. package/src/text-buffer.ts +250 -0
  347. package/src/types.ts +152 -0
  348. package/src/utils.ts +88 -0
  349. package/src/zig/ansi.zig +268 -0
  350. package/src/zig/bench/README.md +50 -0
  351. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  352. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  353. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  354. package/src/zig/bench/rope-markers_bench.zig +713 -0
  355. package/src/zig/bench/rope_bench.zig +514 -0
  356. package/src/zig/bench/styled-text_bench.zig +470 -0
  357. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  358. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  359. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  360. package/src/zig/bench/utf8_bench.zig +799 -0
  361. package/src/zig/bench-utils.zig +431 -0
  362. package/src/zig/bench.zig +217 -0
  363. package/src/zig/buffer.zig +2223 -0
  364. package/src/zig/build.zig +289 -0
  365. package/src/zig/build.zig.zon +16 -0
  366. package/src/zig/edit-buffer.zig +825 -0
  367. package/src/zig/editor-view.zig +802 -0
  368. package/src/zig/event-bus.zig +13 -0
  369. package/src/zig/event-emitter.zig +65 -0
  370. package/src/zig/file-logger.zig +92 -0
  371. package/src/zig/grapheme.zig +599 -0
  372. package/src/zig/lib.zig +1834 -0
  373. package/src/zig/link.zig +333 -0
  374. package/src/zig/logger.zig +43 -0
  375. package/src/zig/mem-registry.zig +125 -0
  376. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  377. package/src/zig/native-span-feed.zig +708 -0
  378. package/src/zig/renderer.zig +1386 -0
  379. package/src/zig/rope.zig +1220 -0
  380. package/src/zig/syntax-style.zig +161 -0
  381. package/src/zig/terminal.zig +975 -0
  382. package/src/zig/test.zig +70 -0
  383. package/src/zig/tests/README.md +18 -0
  384. package/src/zig/tests/buffer_test.zig +2526 -0
  385. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  386. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  387. package/src/zig/tests/editor-view_test.zig +3299 -0
  388. package/src/zig/tests/event-emitter_test.zig +249 -0
  389. package/src/zig/tests/grapheme_test.zig +1304 -0
  390. package/src/zig/tests/link_test.zig +190 -0
  391. package/src/zig/tests/mem-registry_test.zig +473 -0
  392. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  393. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  394. package/src/zig/tests/renderer_test.zig +1010 -0
  395. package/src/zig/tests/rope-nested_test.zig +712 -0
  396. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  397. package/src/zig/tests/rope_test.zig +2362 -0
  398. package/src/zig/tests/segment-merge.test.zig +148 -0
  399. package/src/zig/tests/syntax-style_test.zig +557 -0
  400. package/src/zig/tests/terminal_test.zig +719 -0
  401. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  402. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  403. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  404. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  405. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  406. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  407. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  408. package/src/zig/tests/text-buffer_test.zig +2191 -0
  409. package/src/zig/tests/unicode-width-map.zon +3909 -0
  410. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  411. package/src/zig/tests/utf8_test.zig +4057 -0
  412. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  413. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  414. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  415. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  416. package/src/zig/text-buffer-iterators.zig +499 -0
  417. package/src/zig/text-buffer-segment.zig +404 -0
  418. package/src/zig/text-buffer-view.zig +1371 -0
  419. package/src/zig/text-buffer.zig +1180 -0
  420. package/src/zig/utf8.zig +1948 -0
  421. package/src/zig/utils.zig +9 -0
  422. package/src/zig-structs.ts +261 -0
  423. package/src/zig.ts +3843 -0
  424. package/tsconfig.build.json +22 -0
  425. package/tsconfig.json +28 -0
  426. package/3d/SpriteResourceManager.d.ts +0 -74
  427. package/3d/SpriteUtils.d.ts +0 -13
  428. package/3d/TextureUtils.d.ts +0 -24
  429. package/3d/ThreeRenderable.d.ts +0 -40
  430. package/3d/WGPURenderer.d.ts +0 -61
  431. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  432. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  433. package/3d/animation/SpriteAnimator.d.ts +0 -124
  434. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  435. package/3d/canvas.d.ts +0 -44
  436. package/3d/index.d.ts +0 -12
  437. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  438. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  439. package/3d/physics/physics-interface.d.ts +0 -27
  440. package/3d.d.ts +0 -2
  441. package/3d.js +0 -34042
  442. package/3d.js.map +0 -155
  443. package/LICENSE +0 -21
  444. package/NativeSpanFeed.d.ts +0 -41
  445. package/Renderable.d.ts +0 -334
  446. package/animation/Timeline.d.ts +0 -126
  447. package/ansi.d.ts +0 -13
  448. package/buffer.d.ts +0 -107
  449. package/console.d.ts +0 -143
  450. package/edit-buffer.d.ts +0 -98
  451. package/editor-view.d.ts +0 -73
  452. package/index-e4hzc2j2.js +0 -113
  453. package/index-e4hzc2j2.js.map +0 -10
  454. package/index-nkrr8a4c.js +0 -18415
  455. package/index-nkrr8a4c.js.map +0 -64
  456. package/index-nyw5p3ep.js +0 -12619
  457. package/index-nyw5p3ep.js.map +0 -43
  458. package/index.d.ts +0 -21
  459. package/index.js +0 -430
  460. package/index.js.map +0 -9
  461. package/lib/KeyHandler.d.ts +0 -61
  462. package/lib/RGBA.d.ts +0 -25
  463. package/lib/ascii.font.d.ts +0 -508
  464. package/lib/border.d.ts +0 -49
  465. package/lib/bunfs.d.ts +0 -7
  466. package/lib/clipboard.d.ts +0 -17
  467. package/lib/clock.d.ts +0 -15
  468. package/lib/data-paths.d.ts +0 -26
  469. package/lib/debounce.d.ts +0 -42
  470. package/lib/detect-links.d.ts +0 -6
  471. package/lib/env.d.ts +0 -42
  472. package/lib/extmarks-history.d.ts +0 -17
  473. package/lib/extmarks.d.ts +0 -89
  474. package/lib/hast-styled-text.d.ts +0 -17
  475. package/lib/index.d.ts +0 -21
  476. package/lib/keymapping.d.ts +0 -25
  477. package/lib/objects-in-viewport.d.ts +0 -24
  478. package/lib/output.capture.d.ts +0 -24
  479. package/lib/parse.keypress-kitty.d.ts +0 -2
  480. package/lib/parse.keypress.d.ts +0 -26
  481. package/lib/parse.mouse.d.ts +0 -30
  482. package/lib/paste.d.ts +0 -7
  483. package/lib/queue.d.ts +0 -15
  484. package/lib/renderable.validations.d.ts +0 -12
  485. package/lib/scroll-acceleration.d.ts +0 -43
  486. package/lib/selection.d.ts +0 -63
  487. package/lib/singleton.d.ts +0 -7
  488. package/lib/stdin-parser.d.ts +0 -76
  489. package/lib/styled-text.d.ts +0 -63
  490. package/lib/terminal-capability-detection.d.ts +0 -30
  491. package/lib/terminal-palette.d.ts +0 -50
  492. package/lib/tree-sitter/assets/update.d.ts +0 -11
  493. package/lib/tree-sitter/client.d.ts +0 -47
  494. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  495. package/lib/tree-sitter/download-utils.d.ts +0 -21
  496. package/lib/tree-sitter/index.d.ts +0 -8
  497. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  498. package/lib/tree-sitter/parsers-config.d.ts +0 -38
  499. package/lib/tree-sitter/resolve-ft.d.ts +0 -2
  500. package/lib/tree-sitter/types.d.ts +0 -81
  501. package/lib/tree-sitter-styled-text.d.ts +0 -14
  502. package/lib/validate-dir-name.d.ts +0 -1
  503. package/lib/yoga.options.d.ts +0 -32
  504. package/parser.worker.js +0 -869
  505. package/parser.worker.js.map +0 -12
  506. package/plugins/core-slot.d.ts +0 -72
  507. package/plugins/registry.d.ts +0 -38
  508. package/plugins/types.d.ts +0 -34
  509. package/post/filters.d.ts +0 -105
  510. package/renderables/ASCIIFont.d.ts +0 -52
  511. package/renderables/Box.d.ts +0 -72
  512. package/renderables/Code.d.ts +0 -78
  513. package/renderables/Diff.d.ts +0 -142
  514. package/renderables/EditBufferRenderable.d.ts +0 -162
  515. package/renderables/FrameBuffer.d.ts +0 -16
  516. package/renderables/Input.d.ts +0 -67
  517. package/renderables/LineNumberRenderable.d.ts +0 -74
  518. package/renderables/Markdown.d.ts +0 -173
  519. package/renderables/ScrollBar.d.ts +0 -77
  520. package/renderables/ScrollBox.d.ts +0 -124
  521. package/renderables/Select.d.ts +0 -115
  522. package/renderables/Slider.d.ts +0 -44
  523. package/renderables/TabSelect.d.ts +0 -96
  524. package/renderables/Text.d.ts +0 -36
  525. package/renderables/TextBufferRenderable.d.ts +0 -105
  526. package/renderables/TextNode.d.ts +0 -91
  527. package/renderables/TextTable.d.ts +0 -140
  528. package/renderables/Textarea.d.ts +0 -114
  529. package/renderables/TimeToFirstDraw.d.ts +0 -24
  530. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  531. package/renderables/composition/VRenderable.d.ts +0 -16
  532. package/renderables/composition/constructs.d.ts +0 -35
  533. package/renderables/composition/vnode.d.ts +0 -46
  534. package/renderables/index.d.ts +0 -22
  535. package/renderables/markdown-parser.d.ts +0 -10
  536. package/renderer.d.ts +0 -388
  537. package/runtime-plugin-support.d.ts +0 -3
  538. package/runtime-plugin-support.js +0 -29
  539. package/runtime-plugin-support.js.map +0 -10
  540. package/runtime-plugin.d.ts +0 -11
  541. package/runtime-plugin.js +0 -16
  542. package/runtime-plugin.js.map +0 -9
  543. package/syntax-style.d.ts +0 -54
  544. package/testing/manual-clock.d.ts +0 -16
  545. package/testing/mock-keys.d.ts +0 -81
  546. package/testing/mock-mouse.d.ts +0 -38
  547. package/testing/mock-tree-sitter-client.d.ts +0 -23
  548. package/testing/spy.d.ts +0 -7
  549. package/testing/test-recorder.d.ts +0 -61
  550. package/testing/test-renderer.d.ts +0 -23
  551. package/testing.d.ts +0 -6
  552. package/testing.js +0 -675
  553. package/testing.js.map +0 -15
  554. package/text-buffer-view.d.ts +0 -42
  555. package/text-buffer.d.ts +0 -67
  556. package/types.d.ts +0 -131
  557. package/utils.d.ts +0 -14
  558. package/zig-structs.d.ts +0 -155
  559. package/zig.d.ts +0 -351
  560. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  561. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  562. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  563. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  564. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  565. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  566. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  567. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  568. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  569. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  570. /package/{assets → src/lib/tree-sitter/assets}/zig/tree-sitter-zig.wasm +0 -0
@@ -0,0 +1,357 @@
1
+ import { type RenderContext } from "../types.js"
2
+ import { StyledText } from "../lib/styled-text.js"
3
+ import { SyntaxStyle } from "../syntax-style.js"
4
+ import { getTreeSitterClient, treeSitterToStyledText, TreeSitterClient } from "../lib/tree-sitter/index.js"
5
+ import { TextBufferRenderable, type TextBufferOptions } from "./TextBufferRenderable.js"
6
+ import type { OptimizedBuffer } from "../buffer.js"
7
+ import type { SimpleHighlight } from "../lib/tree-sitter/types.js"
8
+ import type { TextChunk } from "../text-buffer.js"
9
+ import { treeSitterToTextChunks } from "../lib/tree-sitter-styled-text.js"
10
+
11
+ export interface HighlightContext {
12
+ content: string
13
+ filetype: string
14
+ syntaxStyle: SyntaxStyle
15
+ }
16
+
17
+ export type OnHighlightCallback = (
18
+ highlights: SimpleHighlight[],
19
+ context: HighlightContext,
20
+ ) => SimpleHighlight[] | undefined | Promise<SimpleHighlight[] | undefined>
21
+
22
+ export interface ChunkRenderContext extends HighlightContext {
23
+ highlights: SimpleHighlight[]
24
+ }
25
+
26
+ export type OnChunksCallback = (
27
+ chunks: TextChunk[],
28
+ context: ChunkRenderContext,
29
+ ) => TextChunk[] | undefined | Promise<TextChunk[] | undefined>
30
+
31
+ export interface CodeOptions extends TextBufferOptions {
32
+ content?: string
33
+ filetype?: string
34
+ syntaxStyle: SyntaxStyle
35
+ treeSitterClient?: TreeSitterClient
36
+ conceal?: boolean
37
+ drawUnstyledText?: boolean
38
+ streaming?: boolean
39
+ onHighlight?: OnHighlightCallback
40
+ onChunks?: OnChunksCallback
41
+ }
42
+
43
+ export class CodeRenderable extends TextBufferRenderable {
44
+ private _content: string
45
+ private _filetype?: string
46
+ private _syntaxStyle: SyntaxStyle
47
+ private _isHighlighting: boolean = false
48
+ private _treeSitterClient: TreeSitterClient
49
+ private _highlightsDirty: boolean = false
50
+ private _highlightSnapshotId: number = 0
51
+ private _conceal: boolean
52
+ private _drawUnstyledText: boolean
53
+ private _shouldRenderTextBuffer: boolean = true
54
+ private _streaming: boolean
55
+ private _hadInitialContent: boolean = false
56
+ private _lastHighlights: SimpleHighlight[] = []
57
+ private _onHighlight?: OnHighlightCallback
58
+ private _onChunks?: OnChunksCallback
59
+ private _highlightingPromise: Promise<void> = Promise.resolve()
60
+
61
+ protected _contentDefaultOptions = {
62
+ content: "",
63
+ conceal: true,
64
+ drawUnstyledText: true,
65
+ streaming: false,
66
+ } satisfies Partial<CodeOptions>
67
+
68
+ constructor(ctx: RenderContext, options: CodeOptions) {
69
+ super(ctx, options)
70
+
71
+ this._content = options.content ?? this._contentDefaultOptions.content
72
+ this._filetype = options.filetype
73
+ this._syntaxStyle = options.syntaxStyle
74
+ this._treeSitterClient = options.treeSitterClient ?? getTreeSitterClient()
75
+ this._conceal = options.conceal ?? this._contentDefaultOptions.conceal
76
+ this._drawUnstyledText = options.drawUnstyledText ?? this._contentDefaultOptions.drawUnstyledText
77
+ this._streaming = options.streaming ?? this._contentDefaultOptions.streaming
78
+ this._onHighlight = options.onHighlight
79
+ this._onChunks = options.onChunks
80
+
81
+ if (this._content.length > 0) {
82
+ this.textBuffer.setText(this._content)
83
+ this.updateTextInfo()
84
+ this._shouldRenderTextBuffer = this._drawUnstyledText || !this._filetype
85
+ }
86
+
87
+ this._highlightsDirty = this._content.length > 0
88
+ }
89
+
90
+ get content(): string {
91
+ return this._content
92
+ }
93
+
94
+ set content(value: string) {
95
+ if (this._content !== value) {
96
+ this._content = value
97
+ this._highlightsDirty = true
98
+ this._highlightSnapshotId++
99
+
100
+ if (this._streaming && !this._drawUnstyledText && this._filetype) {
101
+ return
102
+ }
103
+
104
+ this.textBuffer.setText(value)
105
+ this.updateTextInfo()
106
+ }
107
+ }
108
+
109
+ get filetype(): string | undefined {
110
+ return this._filetype
111
+ }
112
+
113
+ set filetype(value: string | undefined) {
114
+ if (this._filetype !== value) {
115
+ this._filetype = value
116
+ this._highlightsDirty = true
117
+ }
118
+ }
119
+
120
+ get syntaxStyle(): SyntaxStyle {
121
+ return this._syntaxStyle
122
+ }
123
+
124
+ set syntaxStyle(value: SyntaxStyle) {
125
+ if (this._syntaxStyle !== value) {
126
+ this._syntaxStyle = value
127
+ this._highlightsDirty = true
128
+ }
129
+ }
130
+
131
+ get conceal(): boolean {
132
+ return this._conceal
133
+ }
134
+
135
+ set conceal(value: boolean) {
136
+ if (this._conceal !== value) {
137
+ this._conceal = value
138
+ this._highlightsDirty = true
139
+ }
140
+ }
141
+
142
+ get drawUnstyledText(): boolean {
143
+ return this._drawUnstyledText
144
+ }
145
+
146
+ set drawUnstyledText(value: boolean) {
147
+ if (this._drawUnstyledText !== value) {
148
+ this._drawUnstyledText = value
149
+ this._highlightsDirty = true
150
+ }
151
+ }
152
+
153
+ get streaming(): boolean {
154
+ return this._streaming
155
+ }
156
+
157
+ set streaming(value: boolean) {
158
+ if (this._streaming !== value) {
159
+ this._streaming = value
160
+ this._hadInitialContent = false
161
+ this._lastHighlights = []
162
+ this._highlightsDirty = true
163
+ }
164
+ }
165
+
166
+ get treeSitterClient(): TreeSitterClient {
167
+ return this._treeSitterClient
168
+ }
169
+
170
+ set treeSitterClient(value: TreeSitterClient) {
171
+ if (this._treeSitterClient !== value) {
172
+ this._treeSitterClient = value
173
+ this._highlightsDirty = true
174
+ }
175
+ }
176
+
177
+ get onHighlight(): OnHighlightCallback | undefined {
178
+ return this._onHighlight
179
+ }
180
+
181
+ set onHighlight(value: OnHighlightCallback | undefined) {
182
+ if (this._onHighlight !== value) {
183
+ this._onHighlight = value
184
+ this._highlightsDirty = true
185
+ }
186
+ }
187
+
188
+ get onChunks(): OnChunksCallback | undefined {
189
+ return this._onChunks
190
+ }
191
+
192
+ set onChunks(value: OnChunksCallback | undefined) {
193
+ if (this._onChunks !== value) {
194
+ this._onChunks = value
195
+ this._highlightsDirty = true
196
+ }
197
+ }
198
+
199
+ get isHighlighting(): boolean {
200
+ return this._isHighlighting
201
+ }
202
+
203
+ get highlightingDone(): Promise<void> {
204
+ return this._highlightingPromise
205
+ }
206
+
207
+ protected async transformChunks(chunks: TextChunk[], context: ChunkRenderContext): Promise<TextChunk[]> {
208
+ if (!this._onChunks) return chunks
209
+
210
+ const modified = await this._onChunks(chunks, context)
211
+ return modified ?? chunks
212
+ }
213
+
214
+ private ensureVisibleTextBeforeHighlight(): void {
215
+ if (this.isDestroyed) return
216
+
217
+ const content = this._content
218
+
219
+ if (!this._filetype) {
220
+ this._shouldRenderTextBuffer = true
221
+ return
222
+ }
223
+
224
+ const isInitialContent = this._streaming && !this._hadInitialContent
225
+ const shouldDrawUnstyledNow = this._streaming ? isInitialContent && this._drawUnstyledText : this._drawUnstyledText
226
+
227
+ if (this._streaming && !isInitialContent) {
228
+ this._shouldRenderTextBuffer = true
229
+ } else if (shouldDrawUnstyledNow) {
230
+ this.textBuffer.setText(content)
231
+ this._shouldRenderTextBuffer = true
232
+ } else {
233
+ this._shouldRenderTextBuffer = false
234
+ }
235
+ }
236
+
237
+ private async startHighlight(): Promise<void> {
238
+ const content = this._content
239
+ const filetype = this._filetype
240
+ const snapshotId = ++this._highlightSnapshotId
241
+
242
+ if (!filetype) return
243
+
244
+ const isInitialContent = this._streaming && !this._hadInitialContent
245
+ if (isInitialContent) {
246
+ this._hadInitialContent = true
247
+ }
248
+
249
+ this._isHighlighting = true
250
+
251
+ try {
252
+ const result = await this._treeSitterClient.highlightOnce(content, filetype)
253
+
254
+ if (snapshotId !== this._highlightSnapshotId) {
255
+ return
256
+ }
257
+
258
+ if (this.isDestroyed) return
259
+
260
+ let highlights = result.highlights ?? []
261
+
262
+ if (this._onHighlight && highlights.length >= 0) {
263
+ const context: HighlightContext = {
264
+ content,
265
+ filetype,
266
+ syntaxStyle: this._syntaxStyle,
267
+ }
268
+ const modified = await this._onHighlight(highlights, context)
269
+ if (modified !== undefined) {
270
+ highlights = modified
271
+ }
272
+ }
273
+
274
+ if (snapshotId !== this._highlightSnapshotId) {
275
+ return
276
+ }
277
+
278
+ if (this.isDestroyed) return
279
+
280
+ if (highlights.length > 0) {
281
+ if (this._streaming) {
282
+ this._lastHighlights = highlights
283
+ }
284
+ }
285
+
286
+ if (highlights.length > 0 || this._onChunks) {
287
+ const context: ChunkRenderContext = {
288
+ content,
289
+ filetype,
290
+ syntaxStyle: this._syntaxStyle,
291
+ highlights,
292
+ }
293
+
294
+ let chunks = treeSitterToTextChunks(content, highlights, this._syntaxStyle, {
295
+ enabled: this._conceal,
296
+ })
297
+
298
+ chunks = await this.transformChunks(chunks, context)
299
+
300
+ if (snapshotId !== this._highlightSnapshotId) {
301
+ return
302
+ }
303
+
304
+ if (this.isDestroyed) return
305
+
306
+ const styledText = new StyledText(chunks)
307
+ this.textBuffer.setStyledText(styledText)
308
+ } else {
309
+ this.textBuffer.setText(content)
310
+ }
311
+
312
+ this._shouldRenderTextBuffer = true
313
+ this._isHighlighting = false
314
+ this._highlightsDirty = false
315
+ this.updateTextInfo()
316
+ this.requestRender()
317
+ } catch (error) {
318
+ if (snapshotId !== this._highlightSnapshotId) {
319
+ return
320
+ }
321
+
322
+ console.warn("Code highlighting failed, falling back to plain text:", error)
323
+ if (this.isDestroyed) return
324
+ this.textBuffer.setText(content)
325
+ this._shouldRenderTextBuffer = true
326
+ this._isHighlighting = false
327
+ this._highlightsDirty = false
328
+ this.updateTextInfo()
329
+ this.requestRender()
330
+ }
331
+ }
332
+
333
+ public getLineHighlights(lineIdx: number) {
334
+ return this.textBuffer.getLineHighlights(lineIdx)
335
+ }
336
+
337
+ protected renderSelf(buffer: OptimizedBuffer): void {
338
+ if (this._highlightsDirty) {
339
+ if (this.isDestroyed) return
340
+
341
+ if (this._content.length === 0) {
342
+ this._shouldRenderTextBuffer = false
343
+ this._highlightsDirty = false
344
+ } else if (!this._filetype) {
345
+ this._shouldRenderTextBuffer = true
346
+ this._highlightsDirty = false
347
+ } else {
348
+ this.ensureVisibleTextBeforeHighlight()
349
+ this._highlightsDirty = false
350
+ this._highlightingPromise = this.startHighlight()
351
+ }
352
+ }
353
+
354
+ if (!this._shouldRenderTextBuffer) return
355
+ super.renderSelf(buffer)
356
+ }
357
+ }
@@ -0,0 +1,226 @@
1
+ import { test, expect, beforeEach, afterEach } from "bun:test"
2
+ import { DiffRenderable } from "./Diff.js"
3
+ import { SyntaxStyle } from "../syntax-style.js"
4
+ import { RGBA } from "../lib/RGBA.js"
5
+ import { createTestRenderer, type TestRenderer } from "../testing.js"
6
+ import { ManualClock } from "../testing/manual-clock.js"
7
+ import { MockTreeSitterClient } from "../testing/mock-tree-sitter-client.js"
8
+ import type { SimpleHighlight } from "../lib/tree-sitter/types.js"
9
+ import { BoxRenderable } from "./Box.js"
10
+ import { settleDiffHighlighting } from "./__tests__/renderable-test-utils.js"
11
+
12
+ let currentRenderer: TestRenderer
13
+ let renderOnce: () => Promise<void>
14
+ let captureFrame: () => string
15
+ let mockClient: MockTreeSitterClient
16
+ let clock: ManualClock
17
+
18
+ beforeEach(async () => {
19
+ mockClient = new MockTreeSitterClient()
20
+ clock = new ManualClock()
21
+
22
+ const testRenderer = await createTestRenderer({
23
+ width: 32,
24
+ height: 10,
25
+ gatherStats: true,
26
+ clock,
27
+ })
28
+ currentRenderer = testRenderer.renderer
29
+ renderOnce = testRenderer.renderOnce
30
+ captureFrame = testRenderer.captureCharFrame
31
+ })
32
+
33
+ afterEach(async () => {
34
+ if (currentRenderer) {
35
+ currentRenderer.destroy()
36
+ }
37
+ })
38
+
39
+ // When highlights conceal formatting characters (like **), line lengths change,
40
+ // potentially triggering wrapping changes, height changes, and onResize.
41
+ // This test ensures onResize doesn't cause content resets that create endless loops.
42
+ test("DiffRenderable - no endless loop when concealing markdown formatting", async () => {
43
+ const syntaxStyle = SyntaxStyle.fromStyles({
44
+ default: { fg: RGBA.fromValues(1, 1, 1, 1) },
45
+ })
46
+
47
+ const markdownDiff = `--- a/test.md
48
+ +++ b/test.md
49
+ @@ -1,2 +1,2 @@
50
+ -Some text **boldtext**
51
+ -Short
52
+ +Some text **boldtext**
53
+ +More text **formats**`
54
+
55
+ const mockHighlights: SimpleHighlight[] = [
56
+ [10, 11, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
57
+ [11, 12, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
58
+ [20, 21, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
59
+ [21, 22, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
60
+ [33, 34, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
61
+ [34, 35, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
62
+ [42, 43, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
63
+ [43, 44, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
64
+ ]
65
+
66
+ mockClient.setMockResult({ highlights: mockHighlights })
67
+
68
+ const box = new BoxRenderable(currentRenderer, {
69
+ id: "background-box",
70
+ border: true,
71
+ })
72
+
73
+ const diffRenderable = new DiffRenderable(currentRenderer, {
74
+ id: "test-diff",
75
+ diff: markdownDiff,
76
+ syntaxStyle,
77
+ filetype: "markdown",
78
+ conceal: true,
79
+ treeSitterClient: mockClient,
80
+ })
81
+
82
+ box.add(diffRenderable)
83
+ currentRenderer.root.add(box)
84
+
85
+ await renderOnce()
86
+ diffRenderable.view = "split"
87
+
88
+ await renderOnce()
89
+ diffRenderable.wrapMode = "word"
90
+
91
+ await settleDiffHighlighting(diffRenderable, mockClient, renderOnce)
92
+
93
+ const stats = currentRenderer.getStats()
94
+ expect(stats.frameCount).toBeLessThan(25)
95
+ })
96
+
97
+ // Tests that line numbers align correctly and gutter heights are properly sized
98
+ // when switching between view modes and wrap modes in split view
99
+ test("DiffRenderable - line number alignment and gutter heights in split view with wrapping", async () => {
100
+ const syntaxStyle = SyntaxStyle.fromStyles({
101
+ default: { fg: RGBA.fromValues(1, 1, 1, 1) },
102
+ })
103
+
104
+ const markdownDiff = `--- a/test.md
105
+ +++ b/test.md
106
+ @@ -1,2 +1,2 @@
107
+ -Some text **boldtext**
108
+ -Short
109
+ +Some text **boldtext**
110
+ +More text **formats**`
111
+
112
+ const mockHighlights: SimpleHighlight[] = [
113
+ [10, 11, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
114
+ [11, 12, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
115
+ [20, 21, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
116
+ [21, 22, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
117
+ [33, 34, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
118
+ [34, 35, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
119
+ [42, 43, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
120
+ [43, 44, "conceal", { isInjection: true, injectionLang: "markdown_inline", conceal: "" }],
121
+ ]
122
+
123
+ mockClient.setMockResult({ highlights: mockHighlights })
124
+
125
+ const box = new BoxRenderable(currentRenderer, {
126
+ id: "background-box",
127
+ border: true,
128
+ })
129
+
130
+ const diffRenderable = new DiffRenderable(currentRenderer, {
131
+ id: "test-diff",
132
+ diff: markdownDiff,
133
+ syntaxStyle,
134
+ filetype: "markdown",
135
+ conceal: true,
136
+ treeSitterClient: mockClient,
137
+ })
138
+
139
+ box.add(diffRenderable)
140
+ currentRenderer.root.add(box)
141
+
142
+ await renderOnce()
143
+ const unifiedFrame = captureFrame()
144
+
145
+ expect(unifiedFrame).toContain("1 - Some text")
146
+ expect(unifiedFrame).toContain("2 - Short")
147
+ expect(unifiedFrame).toContain("1 + Some text")
148
+ expect(unifiedFrame).toContain("2 + More text")
149
+
150
+ diffRenderable.view = "split"
151
+ await renderOnce()
152
+ const splitFrame = captureFrame()
153
+
154
+ expect(splitFrame).toContain("1 - Some text")
155
+ expect(splitFrame).toContain("1 + Some text")
156
+ expect(splitFrame).toContain("2 - Short")
157
+ expect(splitFrame).toContain("2 + More text")
158
+
159
+ // First wrapMode toggle: none → word
160
+ diffRenderable.wrapMode = "word"
161
+ await settleDiffHighlighting(diffRenderable, mockClient, renderOnce)
162
+ const splitWrapFrame = captureFrame()
163
+
164
+ const diffChildren = diffRenderable.getChildren()
165
+ const lines = splitWrapFrame.split("\n")
166
+
167
+ let leftLine2Row = -1
168
+ let rightLine2Row = -1
169
+
170
+ for (let i = 0; i < lines.length; i++) {
171
+ const line = lines[i]
172
+ if (line.includes("2 - Short")) {
173
+ leftLine2Row = i
174
+ }
175
+ if (line.includes("2 + More")) {
176
+ rightLine2Row = i
177
+ }
178
+ }
179
+
180
+ expect(leftLine2Row).toBeGreaterThan(-1)
181
+ expect(rightLine2Row).toBeGreaterThan(-1)
182
+ expect(leftLine2Row).toBe(rightLine2Row)
183
+ const leftSide = diffChildren[0]
184
+ const rightSide = diffChildren[1]
185
+ const leftGutter = leftSide.getChildren()[0]
186
+ const rightGutter = rightSide.getChildren()[0]
187
+ const leftCode = leftSide.getChildren()[1]
188
+ const rightCode = rightSide.getChildren()[1]
189
+
190
+ const leftVisualLines = (leftCode as any).lineInfo?.lineSources?.length || 0
191
+ const rightVisualLines = (rightCode as any).lineInfo?.lineSources?.length || 0
192
+
193
+ expect(leftVisualLines).toBe(rightVisualLines)
194
+ expect(leftGutter.height).toBe(leftVisualLines)
195
+ expect(rightGutter.height).toBe(rightVisualLines)
196
+
197
+ // Second wrapMode toggle: word → none → word
198
+ diffRenderable.wrapMode = "none"
199
+ await renderOnce()
200
+ diffRenderable.wrapMode = "word"
201
+ await settleDiffHighlighting(diffRenderable, mockClient, renderOnce)
202
+ const splitWrapFrame2 = captureFrame()
203
+ const lines2 = splitWrapFrame2.split("\n")
204
+ let leftLine2Row2 = -1
205
+ let rightLine2Row2 = -1
206
+
207
+ for (let i = 0; i < lines2.length; i++) {
208
+ const line = lines2[i]
209
+ if (line.includes("2 - Short")) {
210
+ leftLine2Row2 = i
211
+ }
212
+ if (line.includes("2 + More")) {
213
+ rightLine2Row2 = i
214
+ }
215
+ }
216
+
217
+ expect(leftLine2Row2).toBeGreaterThan(-1)
218
+ expect(rightLine2Row2).toBeGreaterThan(-1)
219
+ expect(leftLine2Row2).toBe(rightLine2Row2)
220
+
221
+ expect(splitWrapFrame2).toContain("1 - Some text")
222
+ expect(splitWrapFrame2).toContain("boldtext")
223
+ expect(splitWrapFrame2).toContain("2 - Short")
224
+ expect(splitWrapFrame2).toContain("2 + More text")
225
+ expect(splitWrapFrame2).toContain("formats")
226
+ })