@fairyhunter13/opentui-core 0.1.112 → 0.1.114

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 (591) 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 +144 -0
  7. package/package.json +63 -51
  8. package/scripts/build.ts +400 -0
  9. package/scripts/publish.ts +60 -0
  10. package/src/3d/SpriteResourceManager.ts +286 -0
  11. package/src/3d/SpriteUtils.ts +70 -0
  12. package/src/3d/TextureUtils.ts +196 -0
  13. package/src/3d/ThreeRenderable.ts +197 -0
  14. package/src/3d/WGPURenderer.ts +294 -0
  15. package/src/3d/animation/ExplodingSpriteEffect.ts +513 -0
  16. package/src/3d/animation/PhysicsExplodingSpriteEffect.ts +429 -0
  17. package/src/3d/animation/SpriteAnimator.ts +633 -0
  18. package/src/3d/animation/SpriteParticleGenerator.ts +435 -0
  19. package/src/3d/canvas.ts +464 -0
  20. package/src/3d/index.ts +12 -0
  21. package/src/3d/physics/PlanckPhysicsAdapter.ts +72 -0
  22. package/src/3d/physics/RapierPhysicsAdapter.ts +66 -0
  23. package/src/3d/physics/physics-interface.ts +31 -0
  24. package/src/3d/shaders/supersampling.wgsl +201 -0
  25. package/src/3d.ts +3 -0
  26. package/src/NativeSpanFeed.ts +300 -0
  27. package/src/Renderable.ts +1704 -0
  28. package/src/__snapshots__/buffer.test.ts.snap +28 -0
  29. package/src/animation/Timeline.test.ts +2709 -0
  30. package/src/animation/Timeline.ts +598 -0
  31. package/src/ansi.ts +18 -0
  32. package/src/benchmark/attenuation-benchmark.ts +81 -0
  33. package/src/benchmark/colormatrix-benchmark.ts +128 -0
  34. package/src/benchmark/gain-benchmark.ts +80 -0
  35. package/src/benchmark/latest-all-bench-run.json +707 -0
  36. package/src/benchmark/latest-async-bench-run.json +336 -0
  37. package/src/benchmark/latest-default-bench-run.json +657 -0
  38. package/src/benchmark/latest-large-bench-run.json +707 -0
  39. package/src/benchmark/latest-quick-bench-run.json +207 -0
  40. package/src/benchmark/markdown-benchmark.ts +1796 -0
  41. package/src/benchmark/native-span-feed-async-benchmark.ts +355 -0
  42. package/src/benchmark/native-span-feed-benchmark.md +56 -0
  43. package/src/benchmark/native-span-feed-benchmark.ts +596 -0
  44. package/src/benchmark/native-span-feed-compare.ts +280 -0
  45. package/src/benchmark/renderer-benchmark.ts +754 -0
  46. package/src/benchmark/text-table-benchmark.ts +948 -0
  47. package/src/buffer.test.ts +291 -0
  48. package/src/buffer.ts +554 -0
  49. package/src/console.test.ts +612 -0
  50. package/src/console.ts +1254 -0
  51. package/src/edit-buffer.test.ts +1769 -0
  52. package/src/edit-buffer.ts +411 -0
  53. package/src/editor-view.test.ts +1032 -0
  54. package/src/editor-view.ts +284 -0
  55. package/src/examples/ascii-font-selection-demo.ts +245 -0
  56. package/src/examples/assets/Water_2_M_Normal.jpg +0 -0
  57. package/src/examples/assets/concrete.png +0 -0
  58. package/src/examples/assets/crate.png +0 -0
  59. package/src/examples/assets/crate_emissive.png +0 -0
  60. package/src/examples/assets/forrest_background.png +0 -0
  61. package/src/examples/assets/hast-example.json +1018 -0
  62. package/src/examples/assets/heart.png +0 -0
  63. package/src/examples/assets/main_char_heavy_attack.png +0 -0
  64. package/src/examples/assets/main_char_idle.png +0 -0
  65. package/src/examples/assets/main_char_jump_end.png +0 -0
  66. package/src/examples/assets/main_char_jump_landing.png +0 -0
  67. package/src/examples/assets/main_char_jump_start.png +0 -0
  68. package/src/examples/assets/main_char_run_loop.png +0 -0
  69. package/src/examples/assets/roughness_map.jpg +0 -0
  70. package/src/examples/build.ts +115 -0
  71. package/src/examples/code-demo.ts +924 -0
  72. package/src/examples/console-demo.ts +358 -0
  73. package/src/examples/core-plugin-slots-demo.ts +759 -0
  74. package/src/examples/diff-demo.ts +701 -0
  75. package/src/examples/draggable-three-demo.ts +259 -0
  76. package/src/examples/editor-demo.ts +322 -0
  77. package/src/examples/extmarks-demo.ts +196 -0
  78. package/src/examples/focus-restore-demo.ts +310 -0
  79. package/src/examples/fonts.ts +245 -0
  80. package/src/examples/fractal-shader-demo.ts +268 -0
  81. package/src/examples/framebuffer-demo.ts +674 -0
  82. package/src/examples/full-unicode-demo.ts +241 -0
  83. package/src/examples/golden-star-demo.ts +933 -0
  84. package/src/examples/grayscale-buffer-demo.ts +249 -0
  85. package/src/examples/hast-syntax-highlighting-demo.ts +129 -0
  86. package/src/examples/index.ts +926 -0
  87. package/src/examples/input-demo.ts +377 -0
  88. package/src/examples/input-select-layout-demo.ts +425 -0
  89. package/src/examples/install.sh +143 -0
  90. package/src/examples/keypress-debug-demo.ts +452 -0
  91. package/src/examples/lib/HexList.ts +122 -0
  92. package/src/examples/lib/PaletteGrid.ts +125 -0
  93. package/src/examples/lib/standalone-keys.ts +25 -0
  94. package/src/examples/lib/tab-controller.ts +243 -0
  95. package/src/examples/lights-phong-demo.ts +290 -0
  96. package/src/examples/link-demo.ts +220 -0
  97. package/src/examples/live-state-demo.ts +480 -0
  98. package/src/examples/markdown-demo.ts +725 -0
  99. package/src/examples/mouse-interaction-demo.ts +428 -0
  100. package/src/examples/nested-zindex-demo.ts +357 -0
  101. package/src/examples/opacity-example.ts +235 -0
  102. package/src/examples/opentui-demo.ts +1057 -0
  103. package/src/examples/physx-planck-2d-demo.ts +623 -0
  104. package/src/examples/physx-rapier-2d-demo.ts +655 -0
  105. package/src/examples/relative-positioning-demo.ts +323 -0
  106. package/src/examples/scroll-example.ts +214 -0
  107. package/src/examples/scrollbox-mouse-test.ts +112 -0
  108. package/src/examples/scrollbox-overlay-hit-test.ts +206 -0
  109. package/src/examples/select-demo.ts +237 -0
  110. package/src/examples/shader-cube-demo.ts +1015 -0
  111. package/src/examples/simple-layout-example.ts +591 -0
  112. package/src/examples/slider-demo.ts +617 -0
  113. package/src/examples/split-mode-demo.ts +453 -0
  114. package/src/examples/sprite-animation-demo.ts +443 -0
  115. package/src/examples/sprite-particle-generator-demo.ts +486 -0
  116. package/src/examples/static-sprite-demo.ts +193 -0
  117. package/src/examples/sticky-scroll-example.ts +308 -0
  118. package/src/examples/styled-text-demo.ts +282 -0
  119. package/src/examples/tab-select-demo.ts +219 -0
  120. package/src/examples/terminal-title.ts +29 -0
  121. package/src/examples/terminal.ts +305 -0
  122. package/src/examples/text-node-demo.ts +416 -0
  123. package/src/examples/text-selection-demo.ts +377 -0
  124. package/src/examples/text-table-demo.ts +503 -0
  125. package/src/examples/text-truncation-demo.ts +481 -0
  126. package/src/examples/text-wrap.ts +757 -0
  127. package/src/examples/texture-loading-demo.ts +259 -0
  128. package/src/examples/timeline-example.ts +670 -0
  129. package/src/examples/transparency-demo.ts +400 -0
  130. package/src/examples/vnode-composition-demo.ts +404 -0
  131. package/src/examples/wide-grapheme-overlay-demo.ts +280 -0
  132. package/src/index.ts +24 -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 +170 -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 +35 -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 +317 -0
  168. package/src/lib/keymapping.ts +115 -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 +2290 -0
  187. package/src/lib/stdin-parser.ts +1810 -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 +334 -0
  195. package/src/lib/tree-sitter/assets.d.ts +9 -0
  196. package/src/lib/tree-sitter/cache.test.ts +273 -0
  197. package/src/lib/tree-sitter/client.test.ts +1165 -0
  198. package/src/lib/tree-sitter/client.ts +607 -0
  199. package/src/lib/tree-sitter/default-parsers.ts +86 -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 +1042 -0
  203. package/src/lib/tree-sitter/parsers-config.ts +81 -0
  204. package/src/lib/tree-sitter/resolve-ft.test.ts +55 -0
  205. package/src/lib/tree-sitter/resolve-ft.ts +189 -0
  206. package/src/lib/tree-sitter/types.ts +82 -0
  207. package/src/lib/tree-sitter-styled-text.test.ts +1253 -0
  208. package/src/lib/tree-sitter-styled-text.ts +306 -0
  209. package/src/lib/validate-dir-name.ts +55 -0
  210. package/src/lib/yoga.options.test.ts +628 -0
  211. package/src/lib/yoga.options.ts +346 -0
  212. package/src/plugins/core-slot.ts +579 -0
  213. package/src/plugins/registry.ts +402 -0
  214. package/src/plugins/types.ts +46 -0
  215. package/src/post/effects.ts +930 -0
  216. package/src/post/filters.ts +489 -0
  217. package/src/post/matrices.ts +288 -0
  218. package/src/renderables/ASCIIFont.ts +219 -0
  219. package/src/renderables/Box.test.ts +205 -0
  220. package/src/renderables/Box.ts +326 -0
  221. package/src/renderables/Code.test.ts +2062 -0
  222. package/src/renderables/Code.ts +357 -0
  223. package/src/renderables/Diff.regression.test.ts +226 -0
  224. package/src/renderables/Diff.test.ts +3101 -0
  225. package/src/renderables/Diff.ts +1211 -0
  226. package/src/renderables/EditBufferRenderable.test.ts +288 -0
  227. package/src/renderables/EditBufferRenderable.ts +1166 -0
  228. package/src/renderables/FrameBuffer.ts +47 -0
  229. package/src/renderables/Input.test.ts +1228 -0
  230. package/src/renderables/Input.ts +247 -0
  231. package/src/renderables/LineNumberRenderable.ts +724 -0
  232. package/src/renderables/Markdown.ts +1393 -0
  233. package/src/renderables/ScrollBar.ts +422 -0
  234. package/src/renderables/ScrollBox.ts +883 -0
  235. package/src/renderables/Select.test.ts +1033 -0
  236. package/src/renderables/Select.ts +524 -0
  237. package/src/renderables/Slider.test.ts +456 -0
  238. package/src/renderables/Slider.ts +342 -0
  239. package/src/renderables/TabSelect.test.ts +197 -0
  240. package/src/renderables/TabSelect.ts +455 -0
  241. package/src/renderables/Text.selection-buffer.test.ts +123 -0
  242. package/src/renderables/Text.test.ts +2660 -0
  243. package/src/renderables/Text.ts +147 -0
  244. package/src/renderables/TextBufferRenderable.ts +518 -0
  245. package/src/renderables/TextNode.test.ts +1058 -0
  246. package/src/renderables/TextNode.ts +325 -0
  247. package/src/renderables/TextTable.test.ts +1421 -0
  248. package/src/renderables/TextTable.ts +1344 -0
  249. package/src/renderables/Textarea.ts +430 -0
  250. package/src/renderables/TimeToFirstDraw.ts +89 -0
  251. package/src/renderables/__snapshots__/Code.test.ts.snap +13 -0
  252. package/src/renderables/__snapshots__/Diff.test.ts.snap +785 -0
  253. package/src/renderables/__snapshots__/Text.test.ts.snap +421 -0
  254. package/src/renderables/__snapshots__/TextTable.test.ts.snap +215 -0
  255. package/src/renderables/__tests__/LineNumberRenderable.scrollbox-simple.test.ts +144 -0
  256. package/src/renderables/__tests__/LineNumberRenderable.scrollbox.test.ts +816 -0
  257. package/src/renderables/__tests__/LineNumberRenderable.test.ts +1865 -0
  258. package/src/renderables/__tests__/LineNumberRenderable.wrapping.test.ts +85 -0
  259. package/src/renderables/__tests__/Markdown.code-colors.test.ts +242 -0
  260. package/src/renderables/__tests__/Markdown.test.ts +2518 -0
  261. package/src/renderables/__tests__/MultiRenderable.selection.test.ts +87 -0
  262. package/src/renderables/__tests__/Textarea.buffer.test.ts +682 -0
  263. package/src/renderables/__tests__/Textarea.destroyed-events.test.ts +675 -0
  264. package/src/renderables/__tests__/Textarea.editing.test.ts +2041 -0
  265. package/src/renderables/__tests__/Textarea.error-handling.test.ts +35 -0
  266. package/src/renderables/__tests__/Textarea.events.test.ts +738 -0
  267. package/src/renderables/__tests__/Textarea.highlights.test.ts +590 -0
  268. package/src/renderables/__tests__/Textarea.keybinding.test.ts +3149 -0
  269. package/src/renderables/__tests__/Textarea.paste.test.ts +357 -0
  270. package/src/renderables/__tests__/Textarea.rendering.test.ts +1866 -0
  271. package/src/renderables/__tests__/Textarea.scroll.test.ts +733 -0
  272. package/src/renderables/__tests__/Textarea.selection.test.ts +1590 -0
  273. package/src/renderables/__tests__/Textarea.stress.test.ts +670 -0
  274. package/src/renderables/__tests__/Textarea.undo-redo.test.ts +383 -0
  275. package/src/renderables/__tests__/Textarea.visual-lines.test.ts +310 -0
  276. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.code.test.ts.snap +221 -0
  277. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox-simple.test.ts.snap +89 -0
  278. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.scrollbox.test.ts.snap +457 -0
  279. package/src/renderables/__tests__/__snapshots__/LineNumberRenderable.test.ts.snap +158 -0
  280. package/src/renderables/__tests__/__snapshots__/Textarea.rendering.test.ts.snap +387 -0
  281. package/src/renderables/__tests__/markdown-parser.test.ts +217 -0
  282. package/src/renderables/__tests__/renderable-test-utils.ts +60 -0
  283. package/src/renderables/composition/README.md +8 -0
  284. package/src/renderables/composition/VRenderable.ts +32 -0
  285. package/src/renderables/composition/constructs.ts +127 -0
  286. package/src/renderables/composition/vnode.ts +289 -0
  287. package/src/renderables/index.ts +23 -0
  288. package/src/renderables/markdown-parser.ts +66 -0
  289. package/src/renderer.ts +2681 -0
  290. package/src/runtime-plugin-support.ts +39 -0
  291. package/src/runtime-plugin.ts +615 -0
  292. package/src/syntax-style.test.ts +841 -0
  293. package/src/syntax-style.ts +257 -0
  294. package/src/testing/README.md +210 -0
  295. package/src/testing/capture-spans.test.ts +194 -0
  296. package/src/testing/integration.test.ts +276 -0
  297. package/src/testing/manual-clock.ts +117 -0
  298. package/src/testing/mock-keys.test.ts +1378 -0
  299. package/src/testing/mock-keys.ts +457 -0
  300. package/src/testing/mock-mouse.test.ts +218 -0
  301. package/src/testing/mock-mouse.ts +247 -0
  302. package/src/testing/mock-tree-sitter-client.ts +73 -0
  303. package/src/testing/spy.ts +13 -0
  304. package/src/testing/test-recorder.test.ts +415 -0
  305. package/src/testing/test-recorder.ts +145 -0
  306. package/src/testing/test-renderer.ts +132 -0
  307. package/src/testing.ts +7 -0
  308. package/src/tests/__snapshots__/absolute-positioning.snapshot.test.ts.snap +481 -0
  309. package/src/tests/__snapshots__/renderable.snapshot.test.ts.snap +19 -0
  310. package/src/tests/__snapshots__/scrollbox.test.ts.snap +29 -0
  311. package/src/tests/absolute-positioning.snapshot.test.ts +638 -0
  312. package/src/tests/allocator-stats.test.ts +38 -0
  313. package/src/tests/destroy-during-render.test.ts +200 -0
  314. package/src/tests/destroy-on-exit.fixture.ts +36 -0
  315. package/src/tests/destroy-on-exit.test.ts +41 -0
  316. package/src/tests/hover-cursor.test.ts +98 -0
  317. package/src/tests/native-span-feed-async.test.ts +173 -0
  318. package/src/tests/native-span-feed-close.test.ts +120 -0
  319. package/src/tests/native-span-feed-coverage.test.ts +227 -0
  320. package/src/tests/native-span-feed-edge-cases.test.ts +352 -0
  321. package/src/tests/native-span-feed-use-after-free.test.ts +45 -0
  322. package/src/tests/opacity.test.ts +123 -0
  323. package/src/tests/renderable.snapshot.test.ts +524 -0
  324. package/src/tests/renderable.test.ts +1281 -0
  325. package/src/tests/renderer.clock.test.ts +158 -0
  326. package/src/tests/renderer.console-startup.test.ts +185 -0
  327. package/src/tests/renderer.control.test.ts +425 -0
  328. package/src/tests/renderer.core-slot-binding.test.ts +952 -0
  329. package/src/tests/renderer.cursor.test.ts +26 -0
  330. package/src/tests/renderer.destroy-during-render.test.ts +147 -0
  331. package/src/tests/renderer.focus-restore.test.ts +257 -0
  332. package/src/tests/renderer.focus.test.ts +294 -0
  333. package/src/tests/renderer.idle.test.ts +219 -0
  334. package/src/tests/renderer.input.test.ts +2237 -0
  335. package/src/tests/renderer.kitty-flags.test.ts +195 -0
  336. package/src/tests/renderer.mouse.test.ts +1274 -0
  337. package/src/tests/renderer.palette.test.ts +629 -0
  338. package/src/tests/renderer.selection.test.ts +49 -0
  339. package/src/tests/renderer.slot-registry.test.ts +684 -0
  340. package/src/tests/renderer.useMouse.test.ts +47 -0
  341. package/src/tests/runtime-plugin-node-modules-cycle.fixture.ts +76 -0
  342. package/src/tests/runtime-plugin-node-modules-mjs.fixture.ts +43 -0
  343. package/src/tests/runtime-plugin-node-modules-no-bare-rewrite.fixture.ts +67 -0
  344. package/src/tests/runtime-plugin-node-modules-package-type-cache.fixture.ts +72 -0
  345. package/src/tests/runtime-plugin-node-modules-runtime-specifier.fixture.ts +44 -0
  346. package/src/tests/runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts +85 -0
  347. package/src/tests/runtime-plugin-path-alias.fixture.ts +43 -0
  348. package/src/tests/runtime-plugin-resolve-roots.fixture.ts +65 -0
  349. package/src/tests/runtime-plugin-support.fixture.ts +11 -0
  350. package/src/tests/runtime-plugin-support.test.ts +19 -0
  351. package/src/tests/runtime-plugin-windows-file-url.fixture.ts +30 -0
  352. package/src/tests/runtime-plugin.fixture.ts +40 -0
  353. package/src/tests/runtime-plugin.test.ts +354 -0
  354. package/src/tests/scrollbox-culling-bug.test.ts +114 -0
  355. package/src/tests/scrollbox-hitgrid-resize.test.ts +136 -0
  356. package/src/tests/scrollbox-hitgrid.test.ts +909 -0
  357. package/src/tests/scrollbox.test.ts +1530 -0
  358. package/src/tests/wrap-resize-perf.test.ts +276 -0
  359. package/src/tests/yoga-setters.test.ts +921 -0
  360. package/src/text-buffer-view.test.ts +705 -0
  361. package/src/text-buffer-view.ts +189 -0
  362. package/src/text-buffer.test.ts +347 -0
  363. package/src/text-buffer.ts +250 -0
  364. package/src/types.ts +161 -0
  365. package/src/utils.ts +88 -0
  366. package/src/zig/ansi.zig +268 -0
  367. package/src/zig/bench/README.md +50 -0
  368. package/src/zig/bench/buffer-draw-text-buffer_bench.zig +887 -0
  369. package/src/zig/bench/edit-buffer_bench.zig +476 -0
  370. package/src/zig/bench/native-span-feed_bench.zig +100 -0
  371. package/src/zig/bench/rope-markers_bench.zig +713 -0
  372. package/src/zig/bench/rope_bench.zig +514 -0
  373. package/src/zig/bench/styled-text_bench.zig +470 -0
  374. package/src/zig/bench/text-buffer-coords_bench.zig +362 -0
  375. package/src/zig/bench/text-buffer-view_bench.zig +459 -0
  376. package/src/zig/bench/text-chunk-graphemes_bench.zig +273 -0
  377. package/src/zig/bench/utf8_bench.zig +799 -0
  378. package/src/zig/bench-utils.zig +431 -0
  379. package/src/zig/bench.zig +217 -0
  380. package/src/zig/buffer-methods.zig +211 -0
  381. package/src/zig/buffer.zig +2281 -0
  382. package/src/zig/build.zig +289 -0
  383. package/src/zig/build.zig.zon +16 -0
  384. package/src/zig/edit-buffer.zig +825 -0
  385. package/src/zig/editor-view.zig +802 -0
  386. package/src/zig/event-bus.zig +13 -0
  387. package/src/zig/event-emitter.zig +65 -0
  388. package/src/zig/file-logger.zig +92 -0
  389. package/src/zig/grapheme.zig +599 -0
  390. package/src/zig/lib.zig +1854 -0
  391. package/src/zig/link.zig +333 -0
  392. package/src/zig/logger.zig +43 -0
  393. package/src/zig/mem-registry.zig +125 -0
  394. package/src/zig/native-span-feed-bench-lib.zig +7 -0
  395. package/src/zig/native-span-feed.zig +708 -0
  396. package/src/zig/renderer.zig +1393 -0
  397. package/src/zig/rope.zig +1220 -0
  398. package/src/zig/syntax-style.zig +161 -0
  399. package/src/zig/terminal.zig +987 -0
  400. package/src/zig/test.zig +72 -0
  401. package/src/zig/tests/README.md +18 -0
  402. package/src/zig/tests/buffer-methods_test.zig +1109 -0
  403. package/src/zig/tests/buffer_test.zig +2557 -0
  404. package/src/zig/tests/edit-buffer-history_test.zig +271 -0
  405. package/src/zig/tests/edit-buffer_test.zig +1689 -0
  406. package/src/zig/tests/editor-view_test.zig +3299 -0
  407. package/src/zig/tests/event-emitter_test.zig +249 -0
  408. package/src/zig/tests/grapheme_test.zig +1304 -0
  409. package/src/zig/tests/link_test.zig +190 -0
  410. package/src/zig/tests/mem-registry_test.zig +473 -0
  411. package/src/zig/tests/memory_leak_regression_test.zig +159 -0
  412. package/src/zig/tests/native-span-feed_test.zig +1264 -0
  413. package/src/zig/tests/renderer_test.zig +1017 -0
  414. package/src/zig/tests/rope-nested_test.zig +712 -0
  415. package/src/zig/tests/rope_fuzz_test.zig +238 -0
  416. package/src/zig/tests/rope_test.zig +2362 -0
  417. package/src/zig/tests/segment-merge.test.zig +148 -0
  418. package/src/zig/tests/syntax-style_test.zig +557 -0
  419. package/src/zig/tests/terminal_test.zig +754 -0
  420. package/src/zig/tests/text-buffer-drawing_test.zig +3237 -0
  421. package/src/zig/tests/text-buffer-highlights_test.zig +666 -0
  422. package/src/zig/tests/text-buffer-iterators_test.zig +776 -0
  423. package/src/zig/tests/text-buffer-segment_test.zig +320 -0
  424. package/src/zig/tests/text-buffer-selection_test.zig +1035 -0
  425. package/src/zig/tests/text-buffer-selection_viewport_test.zig +358 -0
  426. package/src/zig/tests/text-buffer-view_test.zig +3649 -0
  427. package/src/zig/tests/text-buffer_test.zig +2191 -0
  428. package/src/zig/tests/unicode-width-map.zon +3909 -0
  429. package/src/zig/tests/utf8_no_zwj_test.zig +260 -0
  430. package/src/zig/tests/utf8_test.zig +4057 -0
  431. package/src/zig/tests/utf8_wcwidth_cursor_test.zig +267 -0
  432. package/src/zig/tests/utf8_wcwidth_test.zig +357 -0
  433. package/src/zig/tests/word-wrap-editing_test.zig +498 -0
  434. package/src/zig/tests/wrap-cache-perf_test.zig +113 -0
  435. package/src/zig/text-buffer-iterators.zig +499 -0
  436. package/src/zig/text-buffer-segment.zig +404 -0
  437. package/src/zig/text-buffer-view.zig +1371 -0
  438. package/src/zig/text-buffer.zig +1180 -0
  439. package/src/zig/utf8.zig +1948 -0
  440. package/src/zig/utils.zig +9 -0
  441. package/src/zig-structs.ts +261 -0
  442. package/src/zig.ts +3884 -0
  443. package/tsconfig.build.json +24 -0
  444. package/tsconfig.json +27 -0
  445. package/3d/SpriteResourceManager.d.ts +0 -74
  446. package/3d/SpriteUtils.d.ts +0 -13
  447. package/3d/TextureUtils.d.ts +0 -24
  448. package/3d/ThreeRenderable.d.ts +0 -40
  449. package/3d/WGPURenderer.d.ts +0 -61
  450. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  451. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  452. package/3d/animation/SpriteAnimator.d.ts +0 -124
  453. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  454. package/3d/canvas.d.ts +0 -44
  455. package/3d/index.d.ts +0 -12
  456. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  457. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  458. package/3d/physics/physics-interface.d.ts +0 -27
  459. package/3d.d.ts +0 -2
  460. package/3d.js +0 -34041
  461. package/3d.js.map +0 -155
  462. package/LICENSE +0 -21
  463. package/NativeSpanFeed.d.ts +0 -41
  464. package/Renderable.d.ts +0 -334
  465. package/animation/Timeline.d.ts +0 -126
  466. package/ansi.d.ts +0 -13
  467. package/buffer.d.ts +0 -111
  468. package/console.d.ts +0 -144
  469. package/edit-buffer.d.ts +0 -98
  470. package/editor-view.d.ts +0 -73
  471. package/index-8fks7yv1.js +0 -411
  472. package/index-8fks7yv1.js.map +0 -10
  473. package/index-egy5e2rs.js +0 -12267
  474. package/index-egy5e2rs.js.map +0 -42
  475. package/index-tse8gzh0.js +0 -20614
  476. package/index-tse8gzh0.js.map +0 -67
  477. package/index.d.ts +0 -23
  478. package/index.js +0 -478
  479. package/index.js.map +0 -9
  480. package/lib/KeyHandler.d.ts +0 -61
  481. package/lib/RGBA.d.ts +0 -25
  482. package/lib/ascii.font.d.ts +0 -508
  483. package/lib/border.d.ts +0 -51
  484. package/lib/bunfs.d.ts +0 -7
  485. package/lib/clipboard.d.ts +0 -17
  486. package/lib/clock.d.ts +0 -15
  487. package/lib/data-paths.d.ts +0 -26
  488. package/lib/debounce.d.ts +0 -42
  489. package/lib/detect-links.d.ts +0 -6
  490. package/lib/env.d.ts +0 -42
  491. package/lib/extmarks-history.d.ts +0 -17
  492. package/lib/extmarks.d.ts +0 -89
  493. package/lib/hast-styled-text.d.ts +0 -17
  494. package/lib/index.d.ts +0 -21
  495. package/lib/keymapping.d.ts +0 -25
  496. package/lib/objects-in-viewport.d.ts +0 -24
  497. package/lib/output.capture.d.ts +0 -24
  498. package/lib/parse.keypress-kitty.d.ts +0 -2
  499. package/lib/parse.keypress.d.ts +0 -26
  500. package/lib/parse.mouse.d.ts +0 -30
  501. package/lib/paste.d.ts +0 -7
  502. package/lib/queue.d.ts +0 -15
  503. package/lib/renderable.validations.d.ts +0 -12
  504. package/lib/scroll-acceleration.d.ts +0 -43
  505. package/lib/selection.d.ts +0 -63
  506. package/lib/singleton.d.ts +0 -7
  507. package/lib/stdin-parser.d.ts +0 -87
  508. package/lib/styled-text.d.ts +0 -63
  509. package/lib/terminal-capability-detection.d.ts +0 -30
  510. package/lib/terminal-palette.d.ts +0 -50
  511. package/lib/tree-sitter/assets/update.d.ts +0 -11
  512. package/lib/tree-sitter/client.d.ts +0 -47
  513. package/lib/tree-sitter/default-parsers.d.ts +0 -2
  514. package/lib/tree-sitter/download-utils.d.ts +0 -21
  515. package/lib/tree-sitter/index.d.ts +0 -8
  516. package/lib/tree-sitter/parser.worker.d.ts +0 -1
  517. package/lib/tree-sitter/parsers-config.d.ts +0 -53
  518. package/lib/tree-sitter/resolve-ft.d.ts +0 -5
  519. package/lib/tree-sitter/types.d.ts +0 -82
  520. package/lib/tree-sitter-styled-text.d.ts +0 -14
  521. package/lib/validate-dir-name.d.ts +0 -1
  522. package/lib/yoga.options.d.ts +0 -32
  523. package/parser.worker.js +0 -899
  524. package/parser.worker.js.map +0 -12
  525. package/plugins/core-slot.d.ts +0 -72
  526. package/plugins/registry.d.ts +0 -42
  527. package/plugins/types.d.ts +0 -34
  528. package/post/effects.d.ts +0 -147
  529. package/post/filters.d.ts +0 -65
  530. package/post/matrices.d.ts +0 -20
  531. package/renderables/ASCIIFont.d.ts +0 -52
  532. package/renderables/Box.d.ts +0 -81
  533. package/renderables/Code.d.ts +0 -78
  534. package/renderables/Diff.d.ts +0 -142
  535. package/renderables/EditBufferRenderable.d.ts +0 -237
  536. package/renderables/FrameBuffer.d.ts +0 -16
  537. package/renderables/Input.d.ts +0 -67
  538. package/renderables/LineNumberRenderable.d.ts +0 -78
  539. package/renderables/Markdown.d.ts +0 -185
  540. package/renderables/ScrollBar.d.ts +0 -77
  541. package/renderables/ScrollBox.d.ts +0 -124
  542. package/renderables/Select.d.ts +0 -115
  543. package/renderables/Slider.d.ts +0 -47
  544. package/renderables/TabSelect.d.ts +0 -96
  545. package/renderables/Text.d.ts +0 -36
  546. package/renderables/TextBufferRenderable.d.ts +0 -105
  547. package/renderables/TextNode.d.ts +0 -91
  548. package/renderables/TextTable.d.ts +0 -140
  549. package/renderables/Textarea.d.ts +0 -63
  550. package/renderables/TimeToFirstDraw.d.ts +0 -24
  551. package/renderables/__tests__/renderable-test-utils.d.ts +0 -12
  552. package/renderables/composition/VRenderable.d.ts +0 -16
  553. package/renderables/composition/constructs.d.ts +0 -35
  554. package/renderables/composition/vnode.d.ts +0 -46
  555. package/renderables/index.d.ts +0 -23
  556. package/renderables/markdown-parser.d.ts +0 -10
  557. package/renderer.d.ts +0 -419
  558. package/runtime-plugin-support.d.ts +0 -3
  559. package/runtime-plugin-support.js +0 -29
  560. package/runtime-plugin-support.js.map +0 -10
  561. package/runtime-plugin.d.ts +0 -16
  562. package/runtime-plugin.js +0 -16
  563. package/runtime-plugin.js.map +0 -9
  564. package/syntax-style.d.ts +0 -54
  565. package/testing/manual-clock.d.ts +0 -17
  566. package/testing/mock-keys.d.ts +0 -81
  567. package/testing/mock-mouse.d.ts +0 -38
  568. package/testing/mock-tree-sitter-client.d.ts +0 -23
  569. package/testing/spy.d.ts +0 -7
  570. package/testing/test-recorder.d.ts +0 -61
  571. package/testing/test-renderer.d.ts +0 -23
  572. package/testing.d.ts +0 -6
  573. package/testing.js +0 -697
  574. package/testing.js.map +0 -15
  575. package/text-buffer-view.d.ts +0 -42
  576. package/text-buffer.d.ts +0 -67
  577. package/types.d.ts +0 -139
  578. package/utils.d.ts +0 -14
  579. package/zig-structs.d.ts +0 -155
  580. package/zig.d.ts +0 -353
  581. /package/{assets → src/lib/tree-sitter/assets}/javascript/highlights.scm +0 -0
  582. /package/{assets → src/lib/tree-sitter/assets}/javascript/tree-sitter-javascript.wasm +0 -0
  583. /package/{assets → src/lib/tree-sitter/assets}/markdown/highlights.scm +0 -0
  584. /package/{assets → src/lib/tree-sitter/assets}/markdown/injections.scm +0 -0
  585. /package/{assets → src/lib/tree-sitter/assets}/markdown/tree-sitter-markdown.wasm +0 -0
  586. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/highlights.scm +0 -0
  587. /package/{assets → src/lib/tree-sitter/assets}/markdown_inline/tree-sitter-markdown_inline.wasm +0 -0
  588. /package/{assets → src/lib/tree-sitter/assets}/typescript/highlights.scm +0 -0
  589. /package/{assets → src/lib/tree-sitter/assets}/typescript/tree-sitter-typescript.wasm +0 -0
  590. /package/{assets → src/lib/tree-sitter/assets}/zig/highlights.scm +0 -0
  591. /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 override 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
+ })