@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,354 @@
1
+ import { describe, expect, it } from "bun:test"
2
+ import { join } from "node:path"
3
+ import * as coreRuntime from "../index.js"
4
+ import { createRuntimePlugin, runtimeModuleIdForSpecifier } from "../runtime-plugin.js"
5
+
6
+ type ResolveResult = { path: string; namespace?: string } | void
7
+ type ResolveCallback = (args: { path: string; importer: string }) => ResolveResult | Promise<ResolveResult>
8
+ type LoadCallback = (args: { path: string }) => unknown | Promise<unknown>
9
+ type ModuleCallback = () => unknown | Promise<unknown>
10
+
11
+ type ResolveHandler = {
12
+ filter: RegExp
13
+ callback: ResolveCallback
14
+ }
15
+
16
+ type MockBuild = {
17
+ onResolve: (args: { filter: RegExp }, callback: ResolveCallback) => void
18
+ onLoad: (args: { filter: RegExp }, callback: LoadCallback) => void
19
+ module: (path: string, callback: ModuleCallback) => void
20
+ }
21
+
22
+ const createMockBuild = (): {
23
+ build: MockBuild
24
+ resolveHandlers: ResolveHandler[]
25
+ modules: Map<string, ModuleCallback>
26
+ } => {
27
+ const resolveHandlers: ResolveHandler[] = []
28
+ const modules = new Map<string, ModuleCallback>()
29
+
30
+ const build: MockBuild = {
31
+ onResolve(args, callback) {
32
+ resolveHandlers.push({ filter: args.filter, callback })
33
+ },
34
+ onLoad() {
35
+ return
36
+ },
37
+ module(path, callback) {
38
+ modules.set(path, callback)
39
+ },
40
+ }
41
+
42
+ return { build, resolveHandlers, modules }
43
+ }
44
+
45
+ const resolveSpecifier = async (handlers: ResolveHandler[], specifier: string): Promise<ResolveResult> => {
46
+ for (const handler of handlers) {
47
+ if (!handler.filter.test(specifier)) continue
48
+
49
+ const result = await handler.callback({
50
+ path: specifier,
51
+ importer: import.meta.path,
52
+ })
53
+
54
+ if (result) {
55
+ return result
56
+ }
57
+ }
58
+
59
+ return undefined
60
+ }
61
+
62
+ describe("runtime plugin", () => {
63
+ it("registers core runtime modules by default", async () => {
64
+ const { build, resolveHandlers, modules } = createMockBuild()
65
+ createRuntimePlugin().setup(build as any)
66
+
67
+ const coreResolution = await resolveSpecifier(resolveHandlers, "@fairyhunter13/opentui-core")
68
+ const core3dResolution = await resolveSpecifier(resolveHandlers, "@fairyhunter13/opentui-core/3d")
69
+ const coreTestingResolution = await resolveSpecifier(resolveHandlers, "@fairyhunter13/opentui-core/testing")
70
+
71
+ expect(coreResolution).toEqual({ path: runtimeModuleIdForSpecifier("@fairyhunter13/opentui-core") })
72
+ expect(core3dResolution).toBeUndefined()
73
+ expect(coreTestingResolution).toEqual({ path: runtimeModuleIdForSpecifier("@fairyhunter13/opentui-core/testing") })
74
+
75
+ if (!coreResolution || !coreTestingResolution) {
76
+ throw new Error("Expected core runtime module resolutions")
77
+ }
78
+
79
+ const coreModuleFactory = modules.get(coreResolution.path)
80
+ const coreTestingModuleFactory = modules.get(coreTestingResolution.path)
81
+
82
+ expect(coreModuleFactory).toBeDefined()
83
+ expect(coreTestingModuleFactory).toBeDefined()
84
+
85
+ if (!coreModuleFactory || !coreTestingModuleFactory) {
86
+ throw new Error("Expected core runtime module factories")
87
+ }
88
+
89
+ expect(await coreModuleFactory()).toEqual({
90
+ exports: coreRuntime as Record<string, unknown>,
91
+ loader: "object",
92
+ })
93
+
94
+ const coreTestingModule = (await coreTestingModuleFactory()) as {
95
+ exports: Record<string, unknown>
96
+ loader: string
97
+ }
98
+
99
+ expect(coreTestingModule.loader).toBe("object")
100
+ expect(typeof coreTestingModule.exports.createTestRenderer).toBe("function")
101
+ })
102
+
103
+ it("registers @fairyhunter13/opentui-core/3d only when added explicitly", async () => {
104
+ const { build, resolveHandlers, modules } = createMockBuild()
105
+
106
+ createRuntimePlugin({
107
+ additional: {
108
+ "@fairyhunter13/opentui-core/3d": { ThreeRenderable: "three-value" },
109
+ },
110
+ }).setup(build as any)
111
+
112
+ const core3dResolution = await resolveSpecifier(resolveHandlers, "@fairyhunter13/opentui-core/3d")
113
+
114
+ expect(core3dResolution).toEqual({ path: runtimeModuleIdForSpecifier("@fairyhunter13/opentui-core/3d") })
115
+
116
+ if (!core3dResolution) {
117
+ throw new Error("Expected @fairyhunter13/opentui-core/3d runtime module resolution")
118
+ }
119
+
120
+ const core3dModuleFactory = modules.get(core3dResolution.path)
121
+
122
+ expect(core3dModuleFactory).toBeDefined()
123
+
124
+ if (!core3dModuleFactory) {
125
+ throw new Error("Expected @fairyhunter13/opentui-core/3d runtime module factory")
126
+ }
127
+
128
+ expect(await core3dModuleFactory()).toEqual({
129
+ exports: { ThreeRenderable: "three-value" },
130
+ loader: "object",
131
+ })
132
+ })
133
+
134
+ it("registers additional runtime modules with sync and async loaders", async () => {
135
+ const { build, resolveHandlers, modules } = createMockBuild()
136
+
137
+ createRuntimePlugin({
138
+ core: { marker: "core" },
139
+ additional: {
140
+ "fixture-sync": { value: "sync-value" },
141
+ "@fixture/async-module": async () => ({ value: "async-value" }),
142
+ },
143
+ }).setup(build as any)
144
+
145
+ const coreResolution = await resolveSpecifier(resolveHandlers, "@fairyhunter13/opentui-core")
146
+ const syncResolution = await resolveSpecifier(resolveHandlers, "fixture-sync")
147
+ const asyncResolution = await resolveSpecifier(resolveHandlers, "@fixture/async-module")
148
+
149
+ expect(coreResolution).toEqual({ path: runtimeModuleIdForSpecifier("@fairyhunter13/opentui-core") })
150
+ expect(syncResolution).toEqual({ path: runtimeModuleIdForSpecifier("fixture-sync") })
151
+ expect(asyncResolution).toEqual({ path: runtimeModuleIdForSpecifier("@fixture/async-module") })
152
+
153
+ if (!coreResolution || !syncResolution || !asyncResolution) {
154
+ throw new Error("Expected runtime module resolutions")
155
+ }
156
+
157
+ const coreModuleFactory = modules.get(coreResolution.path)
158
+ const syncModuleFactory = modules.get(syncResolution.path)
159
+ const asyncModuleFactory = modules.get(asyncResolution.path)
160
+
161
+ expect(coreModuleFactory).toBeDefined()
162
+ expect(syncModuleFactory).toBeDefined()
163
+ expect(asyncModuleFactory).toBeDefined()
164
+
165
+ if (!coreModuleFactory || !syncModuleFactory || !asyncModuleFactory) {
166
+ throw new Error("Expected runtime module factories")
167
+ }
168
+
169
+ expect(await coreModuleFactory()).toEqual({ exports: { marker: "core" }, loader: "object" })
170
+ expect(await syncModuleFactory()).toEqual({ exports: { value: "sync-value" }, loader: "object" })
171
+ expect(await asyncModuleFactory()).toEqual({ exports: { value: "async-value" }, loader: "object" })
172
+ })
173
+
174
+ it("escapes exact-match resolver filters for special characters", async () => {
175
+ const { build, resolveHandlers } = createMockBuild()
176
+
177
+ createRuntimePlugin({
178
+ additional: {
179
+ "fixture.with.dot": { value: "dot-value" },
180
+ },
181
+ }).setup(build as any)
182
+
183
+ const exactMatch = await resolveSpecifier(resolveHandlers, "fixture.with.dot")
184
+ const nonMatch = await resolveSpecifier(resolveHandlers, "fixtureXwithXdot")
185
+
186
+ expect(exactMatch).toEqual({ path: runtimeModuleIdForSpecifier("fixture.with.dot") })
187
+ expect(nonMatch).toBeUndefined()
188
+ })
189
+
190
+ it("encodes runtime module IDs deterministically", () => {
191
+ expect(runtimeModuleIdForSpecifier("@fairyhunter13/opentui-core/testing")).toBe(
192
+ "opentui:runtime-module:%40opentui%2Fcore%2Ftesting",
193
+ )
194
+ })
195
+
196
+ it("resolves runtime modules end-to-end in a subprocess", () => {
197
+ const fixturePath = join(import.meta.dir, "runtime-plugin.fixture.ts")
198
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
199
+ cwd: join(import.meta.dir, "..", ".."),
200
+ stdout: "pipe",
201
+ stderr: "pipe",
202
+ env: process.env,
203
+ })
204
+
205
+ const stdout = result.stdout.toString().trim()
206
+
207
+ expect(result.exitCode).toBe(0)
208
+ expect(stdout).toContain("core=core-value;coreTesting=true;sync=sync-value;async=async-value")
209
+ })
210
+
211
+ it("resolves bare imports from external runtime roots", () => {
212
+ const fixturePath = join(import.meta.dir, "runtime-plugin-resolve-roots.fixture.ts")
213
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
214
+ cwd: join(import.meta.dir, "..", ".."),
215
+ stdout: "pipe",
216
+ stderr: "pipe",
217
+ env: process.env,
218
+ })
219
+
220
+ const stdout = result.stdout.toString().trim()
221
+
222
+ expect(result.exitCode).toBe(0)
223
+ expect(stdout).toContain("marker=resolved-from-external-root")
224
+ })
225
+
226
+ it("rewrites runtime specifiers in node_modules modules by default", () => {
227
+ const fixturePath = join(import.meta.dir, "runtime-plugin-node-modules-runtime-specifier.fixture.ts")
228
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
229
+ cwd: join(import.meta.dir, "..", ".."),
230
+ stdout: "pipe",
231
+ stderr: "pipe",
232
+ env: process.env,
233
+ })
234
+
235
+ const stdout = result.stdout.toString().trim()
236
+
237
+ expect(result.exitCode).toBe(0)
238
+ expect(stdout).toContain("marker=resolved-from-node-modules-runtime-specifier")
239
+ })
240
+
241
+ it("rewrites runtime specifiers in node_modules .mjs modules", () => {
242
+ const fixturePath = join(import.meta.dir, "runtime-plugin-node-modules-mjs.fixture.ts")
243
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
244
+ cwd: join(import.meta.dir, "..", ".."),
245
+ stdout: "pipe",
246
+ stderr: "pipe",
247
+ env: process.env,
248
+ })
249
+
250
+ const stdout = result.stdout.toString().trim()
251
+
252
+ expect(result.exitCode).toBe(0)
253
+ expect(stdout).toContain("marker=resolved-from-node-modules-mjs")
254
+ })
255
+
256
+ it("rewrites runtime specifiers across node_modules ESM cycles", () => {
257
+ const fixturePath = join(import.meta.dir, "runtime-plugin-node-modules-cycle.fixture.ts")
258
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
259
+ cwd: join(import.meta.dir, "..", ".."),
260
+ stdout: "pipe",
261
+ stderr: "pipe",
262
+ env: process.env,
263
+ })
264
+
265
+ const stdout = result.stdout.toString().trim()
266
+
267
+ expect(result.exitCode).toBe(0)
268
+ expect(stdout).toContain(
269
+ "a=resolved-from-node-modules-cycle;b=resolved-from-node-modules-cycle;aBase=resolved-from-node-modules-cycle",
270
+ )
271
+ })
272
+
273
+ it("does not keep stale node_modules package type across plugin instances", () => {
274
+ const fixturePath = join(import.meta.dir, "runtime-plugin-node-modules-package-type-cache.fixture.ts")
275
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
276
+ cwd: join(import.meta.dir, "..", ".."),
277
+ stdout: "pipe",
278
+ stderr: "pipe",
279
+ env: process.env,
280
+ })
281
+
282
+ const stdout = result.stdout.toString().trim()
283
+
284
+ expect(result.exitCode).toBe(0)
285
+ expect(stdout).toContain("marker=resolved-after-package-type-change")
286
+ })
287
+
288
+ it("rewrites bare imports for scoped node_modules package siblings when enabled", () => {
289
+ const fixturePath = join(import.meta.dir, "runtime-plugin-node-modules-scoped-package-bare-rewrite.fixture.ts")
290
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
291
+ cwd: join(import.meta.dir, "..", ".."),
292
+ stdout: "pipe",
293
+ stderr: "pipe",
294
+ env: process.env,
295
+ })
296
+
297
+ const stdout = result.stdout.toString().trim()
298
+
299
+ expect(result.exitCode).toBe(0)
300
+ expect(stdout).toContain(
301
+ "entry=entry-runtime-marker;scoped=scoped-runtime-marker:resolved-from-scoped-package-parent",
302
+ )
303
+ })
304
+
305
+ it("does not rewrite non-runtime bare imports in node_modules modules by default", () => {
306
+ const fixturePath = join(import.meta.dir, "runtime-plugin-node-modules-no-bare-rewrite.fixture.ts")
307
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
308
+ cwd: join(import.meta.dir, "..", ".."),
309
+ stdout: "pipe",
310
+ stderr: "pipe",
311
+ env: process.env,
312
+ })
313
+
314
+ const stdout = result.stdout.toString().trim()
315
+
316
+ expect(result.exitCode).toBe(0)
317
+ expect(stdout).toContain("errorContainsMissingBareDependency=true")
318
+ })
319
+
320
+ it("rewrites runtime specifiers when Bun canonicalizes a symlinked import path", () => {
321
+ const fixturePath = join(import.meta.dir, "runtime-plugin-path-alias.fixture.ts")
322
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
323
+ cwd: join(import.meta.dir, "..", ".."),
324
+ stdout: "pipe",
325
+ stderr: "pipe",
326
+ env: process.env,
327
+ })
328
+
329
+ const stdout = result.stdout.toString().trim()
330
+
331
+ expect(result.exitCode).toBe(0)
332
+ expect(stdout).toContain("aliasPathCanonicalized=true")
333
+ expect(stdout).toContain("marker=resolved-from-path-alias")
334
+ })
335
+
336
+ it("rewrites runtime specifiers for file URL imports on Windows", () => {
337
+ if (process.platform !== "win32") {
338
+ return
339
+ }
340
+
341
+ const fixturePath = join(import.meta.dir, "runtime-plugin-windows-file-url.fixture.ts")
342
+ const result = Bun.spawnSync([process.execPath, fixturePath], {
343
+ cwd: join(import.meta.dir, "..", ".."),
344
+ stdout: "pipe",
345
+ stderr: "pipe",
346
+ env: process.env,
347
+ })
348
+
349
+ const stdout = result.stdout.toString().trim()
350
+
351
+ expect(result.exitCode).toBe(0)
352
+ expect(stdout).toContain("marker=resolved-from-windows-file-url")
353
+ })
354
+ })
@@ -0,0 +1,114 @@
1
+ import { test, expect, beforeEach, afterEach } from "bun:test"
2
+ import { createTestRenderer, type TestRenderer } from "../testing.js"
3
+ import { ManualClock } from "../testing/manual-clock.js"
4
+ import { ScrollBoxRenderable } from "../renderables/ScrollBox.js"
5
+ import { BoxRenderable } from "../renderables/Box.js"
6
+ import { TextRenderable } from "../renderables/Text.js"
7
+ import { TestRecorder } from "../testing/test-recorder.js"
8
+
9
+ let testRenderer: TestRenderer
10
+ let renderOnce: () => Promise<void>
11
+ let clock: ManualClock
12
+
13
+ beforeEach(async () => {
14
+ clock = new ManualClock()
15
+ ;({ renderer: testRenderer, renderOnce } = await createTestRenderer({ width: 50, height: 12, clock }))
16
+ })
17
+
18
+ afterEach(() => {
19
+ testRenderer.destroy()
20
+ })
21
+
22
+ test("scrollbox culling issue: last item not visible in frame after content grows with stickyScroll", async () => {
23
+ // ISSUE: During updateLayout, when content.onSizeChange triggers recalculateBarProps,
24
+ // it changes translateY via the scrollbar onChange callback. Then _getVisibleChildren()
25
+ // is called for culling, but it uses the NEW translateY value with OLD child layout
26
+ // positions (since children haven't had updateFromLayout called yet). This causes
27
+ // incorrect culling where the last item is not rendered even though it should be visible.
28
+
29
+ // Container box with border to see constraints clearly
30
+ const container = new BoxRenderable(testRenderer, {
31
+ width: 48,
32
+ height: 10,
33
+ border: true,
34
+ })
35
+ testRenderer.root.add(container)
36
+
37
+ const scrollBox = new ScrollBoxRenderable(testRenderer, {
38
+ width: "100%",
39
+ height: "100%",
40
+ stickyScroll: true,
41
+ stickyStart: "bottom",
42
+ })
43
+ container.add(scrollBox)
44
+
45
+ const recorder = new TestRecorder(testRenderer)
46
+ recorder.rec()
47
+
48
+ for (let i = 0; i < 50; i++) {
49
+ const item = new BoxRenderable(testRenderer, {
50
+ id: `item-${i}`,
51
+ height: 3,
52
+ border: true,
53
+ })
54
+
55
+ const text = new TextRenderable(testRenderer, {
56
+ content: `Item ${i}`,
57
+ })
58
+ item.add(text)
59
+
60
+ scrollBox.add(item)
61
+ await renderOnce()
62
+ }
63
+
64
+ // Advance clock to trigger any pending re-render scheduled by stickyScroll's requestRender()
65
+ clock.advance(100)
66
+ await renderOnce()
67
+
68
+ recorder.stop()
69
+
70
+ const frames = recorder.recordedFrames
71
+
72
+ // With stickyScroll to bottom, there should NEVER be empty space at the bottom
73
+ // when there are items available to render
74
+
75
+ for (let frameIdx = 0; frameIdx < frames.length; frameIdx++) {
76
+ const frame = frames[frameIdx].frame
77
+ const lines = frame.split("\n")
78
+
79
+ const containerStart = lines.findIndex((line) => line.startsWith("┌"))
80
+ const containerEnd = containerStart + 10 - 1
81
+
82
+ if (containerStart >= 0 && containerEnd > containerStart && containerEnd < lines.length) {
83
+ const contentLines = lines.slice(containerStart + 1, containerEnd)
84
+
85
+ let emptyLinesAtBottom = 0
86
+
87
+ for (let i = contentLines.length - 1; i >= 0; i--) {
88
+ const line = contentLines[i]
89
+ const content = line.replace(/^[│\s]*/, "").replace(/[│█▄\s]*$/, "")
90
+
91
+ if (content.length === 0) {
92
+ emptyLinesAtBottom++
93
+ } else {
94
+ break
95
+ }
96
+ }
97
+
98
+ const expectedItems = frameIdx + 1
99
+
100
+ // With stickyScroll to bottom, once we have enough items to fill the viewport,
101
+ // there should be NO empty space at the bottom
102
+ // Viewport is 8 lines (10 - 2 for borders), items are 3 lines each
103
+ // So with 3+ items (9 lines of content), we should always fill the viewport
104
+ if (expectedItems >= 3) {
105
+ expect(emptyLinesAtBottom).toBe(0)
106
+ }
107
+ }
108
+ }
109
+
110
+ // With stickyScroll to bottom, the last item should be visible after all items are added
111
+ const finalFrame = frames[frames.length - 1].frame
112
+ const hasItem49 = finalFrame.includes("Item 49")
113
+ expect(hasItem49).toBe(true)
114
+ })
@@ -0,0 +1,136 @@
1
+ import { test, expect } from "bun:test"
2
+ import { createTestRenderer, type MockMouse, type TestRenderer } from "../testing.js"
3
+ import { ScrollBoxRenderable } from "../renderables/ScrollBox.js"
4
+ import { BoxRenderable } from "../renderables/Box.js"
5
+ import { Renderable } from "../Renderable.js"
6
+
7
+ test("hit grid works at all Y coordinates after terminal shrink", async () => {
8
+ // Start wide: 160x50 = 8000 cells
9
+ const { renderer, mockMouse, resize } = await createTestRenderer({
10
+ width: 160,
11
+ height: 50,
12
+ })
13
+
14
+ const scrollBox = new ScrollBoxRenderable(renderer, {
15
+ width: "100%",
16
+ height: "100%",
17
+ scrollY: true,
18
+ })
19
+ renderer.root.add(scrollBox)
20
+
21
+ const items: BoxRenderable[] = []
22
+ for (let i = 0; i < 200; i++) {
23
+ const item = new BoxRenderable(renderer, {
24
+ id: `item-${i}`,
25
+ height: 2,
26
+ })
27
+ items.push(item)
28
+ scrollBox.add(item)
29
+ }
30
+
31
+ await renderer.idle()
32
+
33
+ // Verify hit grid works at the original size
34
+ const hitBefore = renderer.hitTest(5, 10)
35
+ expect(hitBefore).not.toBe(0)
36
+
37
+ // Shrink to narrow+tall: 60x100 = 6000 cells (smaller total area)
38
+ resize(60, 100)
39
+ renderer.root.resize(60, 100)
40
+ await renderer.idle()
41
+
42
+ // Row 70 is beyond the old height (50). Before the fix, checkHit
43
+ // returned 0 here because hitGridHeight was still 50.
44
+ const hitAtRow70 = renderer.hitTest(5, 70)
45
+ expect(hitAtRow70).not.toBe(0)
46
+
47
+ // Row 95 -- near the bottom of the new terminal
48
+ const hitAtRow95 = renderer.hitTest(5, 95)
49
+ expect(hitAtRow95).not.toBe(0)
50
+
51
+ renderer.destroy()
52
+ })
53
+
54
+ test("mouse scroll reaches scrollbox after terminal shrink", async () => {
55
+ const { renderer, mockMouse, resize } = await createTestRenderer({
56
+ width: 160,
57
+ height: 50,
58
+ })
59
+
60
+ const scrollBox = new ScrollBoxRenderable(renderer, {
61
+ width: "100%",
62
+ height: "100%",
63
+ scrollY: true,
64
+ })
65
+ renderer.root.add(scrollBox)
66
+
67
+ for (let i = 0; i < 200; i++) {
68
+ scrollBox.add(
69
+ new BoxRenderable(renderer, {
70
+ id: `item-${i}`,
71
+ height: 2,
72
+ }),
73
+ )
74
+ }
75
+
76
+ await renderer.idle()
77
+
78
+ // Shrink terminal
79
+ resize(60, 100)
80
+ renderer.root.resize(60, 100)
81
+ await renderer.idle()
82
+
83
+ // Scroll to bottom first so we have room to scroll up
84
+ scrollBox.scrollTop = scrollBox.scrollHeight - 100
85
+ await renderer.idle()
86
+ const positionBefore = scrollBox.scrollTop
87
+
88
+ // Mouse wheel at row 70 (beyond the old height of 50)
89
+ await mockMouse.scroll(30, 70, "up")
90
+ await renderer.idle()
91
+
92
+ // scrollTop should have decreased -- the scroll event reached the scrollbox
93
+ expect(scrollBox.scrollTop).toBeLessThan(positionBefore)
94
+
95
+ renderer.destroy()
96
+ })
97
+
98
+ test("hit grid works after multiple resize cycles", async () => {
99
+ const { renderer, resize } = await createTestRenderer({
100
+ width: 80,
101
+ height: 40,
102
+ })
103
+
104
+ const box = new BoxRenderable(renderer, {
105
+ id: "target",
106
+ width: "100%",
107
+ height: "100%",
108
+ })
109
+ renderer.root.add(box)
110
+ await renderer.idle()
111
+
112
+ // Grow: 80x40=3200 -> 120x60=7200
113
+ resize(120, 60)
114
+ renderer.root.resize(120, 60)
115
+ await renderer.idle()
116
+ expect(renderer.hitTest(5, 55)).not.toBe(0)
117
+
118
+ // Shrink back: 120x60=7200 -> 80x40=3200
119
+ resize(80, 40)
120
+ renderer.root.resize(80, 40)
121
+ await renderer.idle()
122
+ expect(renderer.hitTest(5, 35)).not.toBe(0)
123
+ // x=100 is outside the new width, should return 0
124
+ expect(renderer.hitTest(100, 10)).toBe(0)
125
+
126
+ // Shrink further: 80x40=3200 -> 40x30=1200
127
+ resize(40, 30)
128
+ renderer.root.resize(40, 30)
129
+ await renderer.idle()
130
+ expect(renderer.hitTest(5, 25)).not.toBe(0)
131
+ // Old coordinates should be out of bounds
132
+ expect(renderer.hitTest(5, 35)).toBe(0)
133
+ expect(renderer.hitTest(50, 10)).toBe(0)
134
+
135
+ renderer.destroy()
136
+ })