@jitl/opentui-core 0.1.97 → 0.2.15

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 (132) hide show
  1. package/NativeSpanFeed.d.ts +2 -2
  2. package/README.md +2 -1
  3. package/Renderable.d.ts +12 -1
  4. package/audio.d.ts +89 -0
  5. package/buffer.d.ts +6 -5
  6. package/console.d.ts +3 -1
  7. package/edit-buffer.d.ts +1 -1
  8. package/editor-view.d.ts +1 -1
  9. package/{index-yxe6e14n.js → index-46f5e8m6.js} +1388 -1721
  10. package/index-46f5e8m6.js.map +36 -0
  11. package/index-5zwezmgj.js +639 -0
  12. package/index-5zwezmgj.js.map +11 -0
  13. package/index-axv7cw60.js +44 -0
  14. package/index-axv7cw60.js.map +10 -0
  15. package/{index-rhfjv9c1.js → index-g9agybj3.js} +4626 -984
  16. package/index-g9agybj3.js.map +82 -0
  17. package/index-k18nf2r7.js +21 -0
  18. package/{ffi-x3zvcksd.js.map → index-k18nf2r7.js.map} +1 -1
  19. package/{index-tkk6cmr2.js → index-rp7vz5rh.js} +125 -23
  20. package/index-rp7vz5rh.js.map +10 -0
  21. package/{index-kcpn1hka.js → index-xwsdfq5x.js} +16 -6
  22. package/index-xwsdfq5x.js.map +10 -0
  23. package/index.d.ts +1 -0
  24. package/index.js +37 -17
  25. package/index.js.map +1 -1
  26. package/lib/RGBA.d.ts +22 -6
  27. package/lib/clipboard.d.ts +1 -1
  28. package/lib/{keymapping.d.ts → keybinding.internal.d.ts} +10 -2
  29. package/lib/objects-in-viewport.d.ts +4 -4
  30. package/lib/parse.keypress-kitty.d.ts +1 -0
  31. package/lib/parse.keypress.d.ts +1 -0
  32. package/lib/render-geometry.d.ts +8 -0
  33. package/lib/stdin-parser.d.ts +4 -1
  34. package/lib/terminal-capability-detection.d.ts +2 -0
  35. package/lib/terminal-palette.d.ts +20 -5
  36. package/lib/tree-sitter/assets/update.d.ts +1 -0
  37. package/lib/tree-sitter/client.d.ts +2 -0
  38. package/lib/tree-sitter/default-parsers.d.ts +1 -1
  39. package/lib/tree-sitter/index.d.ts +0 -2
  40. package/lib/tree-sitter/update-assets.d.ts +3 -0
  41. package/lib/tree-sitter/update-assets.js +377 -0
  42. package/lib/tree-sitter/update-assets.js.map +12 -0
  43. package/lib/tree-sitter-styled-text.d.ts +6 -4
  44. package/node22-bun-ffi-structs-ha8fmzzb.js +396 -0
  45. package/node22-bun-ffi-structs-ha8fmzzb.js.map +10 -0
  46. package/package.json +23 -22
  47. package/parser.worker.js +161 -24
  48. package/parser.worker.js.map +12 -5
  49. package/platform/bun-ffi-structs.d.ts +2 -0
  50. package/platform/ffi.d.ts +126 -0
  51. package/platform/node22-bun-ffi-structs.d.ts +33 -0
  52. package/platform/node22-ffi.d.ts +33 -0
  53. package/{compat → platform}/runtime.d.ts +6 -0
  54. package/platform/worker.d.ts +4 -0
  55. package/renderables/Code.d.ts +4 -0
  56. package/renderables/Markdown.d.ts +62 -0
  57. package/renderables/ScrollBox.d.ts +1 -0
  58. package/renderables/Select.d.ts +3 -1
  59. package/renderables/TabSelect.d.ts +3 -1
  60. package/renderables/TextBufferRenderable.d.ts +1 -0
  61. package/renderables/TextTable.d.ts +15 -1
  62. package/renderables/Textarea.d.ts +5 -3
  63. package/renderables/markdown-parser.d.ts +1 -0
  64. package/renderer-theme-mode.d.ts +29 -0
  65. package/renderer.d.ts +142 -16
  66. package/runtime-plugin-support-configure.d.ts +4 -0
  67. package/runtime-plugin-support-configure.js +20 -0
  68. package/{index-re3ntm60.js.map → runtime-plugin-support-configure.js.map} +1 -1
  69. package/runtime-plugin-support.d.ts +3 -3
  70. package/runtime-plugin-support.js +9 -18
  71. package/runtime-plugin-support.js.map +3 -3
  72. package/runtime-plugin.d.ts +1 -4
  73. package/runtime-plugin.js +5 -5
  74. package/syntax-style.d.ts +11 -3
  75. package/testing/terminal-capabilities.d.ts +7 -0
  76. package/testing/test-recorder.d.ts +6 -6
  77. package/testing/test-renderer.d.ts +34 -2
  78. package/testing.d.ts +2 -0
  79. package/testing.js +329 -23
  80. package/testing.js.map +7 -5
  81. package/text-buffer-view.d.ts +2 -1
  82. package/text-buffer.d.ts +1 -1
  83. package/types.d.ts +33 -1
  84. package/zig-structs.d.ts +111 -20
  85. package/zig.d.ts +57 -7
  86. package/3d/SpriteResourceManager.d.ts +0 -74
  87. package/3d/SpriteUtils.d.ts +0 -13
  88. package/3d/TextureUtils.d.ts +0 -24
  89. package/3d/ThreeRenderable.d.ts +0 -40
  90. package/3d/WGPURenderer.d.ts +0 -61
  91. package/3d/animation/ExplodingSpriteEffect.d.ts +0 -71
  92. package/3d/animation/PhysicsExplodingSpriteEffect.d.ts +0 -76
  93. package/3d/animation/SpriteAnimator.d.ts +0 -124
  94. package/3d/animation/SpriteParticleGenerator.d.ts +0 -62
  95. package/3d/canvas.d.ts +0 -44
  96. package/3d/index.d.ts +0 -12
  97. package/3d/physics/PlanckPhysicsAdapter.d.ts +0 -19
  98. package/3d/physics/RapierPhysicsAdapter.d.ts +0 -19
  99. package/3d/physics/physics-interface.d.ts +0 -27
  100. package/3d.d.ts +0 -2
  101. package/3d.js +0 -33843
  102. package/3d.js.map +0 -155
  103. package/Worker-vajwjk0s.js +0 -94
  104. package/Worker-vajwjk0s.js.map +0 -10
  105. package/compat/FFIType.d.ts +0 -304
  106. package/compat/Worker.d.ts +0 -1
  107. package/compat/bun-ffi-structs.d.ts +0 -2
  108. package/compat/ffi.d.ts +0 -86
  109. package/compat/nodejs/Worker.d.ts +0 -16
  110. package/compat/nodejs/bun-ffi-structs/index.d.ts +0 -46
  111. package/compat/nodejs/ffi.d.ts +0 -21
  112. package/compat/nodejs/registerResolveJs.d.ts +0 -1
  113. package/compat/nodejs/runtime.d.ts +0 -7
  114. package/compat/nodejs/test.d.ts +0 -4
  115. package/compat/nodejs/trampoline.worker.d.ts +0 -1
  116. package/compat/test.d.ts +0 -1
  117. package/compat/testHelpers.d.ts +0 -18
  118. package/ffi-x3zvcksd.js +0 -25
  119. package/index-5yqvbmcz.js +0 -220
  120. package/index-5yqvbmcz.js.map +0 -10
  121. package/index-bnfz2g63.js +0 -654
  122. package/index-bnfz2g63.js.map +0 -10
  123. package/index-cbvybypy.js +0 -43
  124. package/index-cbvybypy.js.map +0 -10
  125. package/index-kcpn1hka.js.map +0 -10
  126. package/index-re3ntm60.js +0 -51
  127. package/index-rhfjv9c1.js.map +0 -70
  128. package/index-tkk6cmr2.js.map +0 -10
  129. package/index-yxe6e14n.js.map +0 -42
  130. package/runtime-hdpkc6qf.js +0 -220
  131. package/runtime-hdpkc6qf.js.map +0 -17
  132. /package/{compat/nodejs/registerBun.d.ts → native-event-worker-repro.worker.d.ts} +0 -0
@@ -6,18 +6,20 @@ import {
6
6
  BaseRenderable,
7
7
  BorderCharArrays,
8
8
  BorderChars,
9
+ BoxRenderable,
9
10
  CliRenderEvents,
10
11
  CliRenderer,
12
+ CodeRenderable,
11
13
  ConsolePosition,
14
+ DEFAULT_BACKGROUND_RGB,
15
+ DEFAULT_FOREGROUND_RGB,
12
16
  DataPathsManager,
13
17
  DebugOverlayCorner,
14
- Edge,
15
18
  EditBuffer,
16
19
  EditBufferRenderable,
17
20
  EditBufferRenderableEvents,
18
21
  EditorView,
19
22
  ExtmarksController,
20
- Gutter,
21
23
  InternalKeyHandler,
22
24
  KeyEvent,
23
25
  KeyHandler,
@@ -36,18 +38,25 @@ import {
36
38
  RenderableEvents,
37
39
  RendererControlState,
38
40
  RootRenderable,
41
+ RootTextNodeRenderable,
39
42
  Selection,
40
43
  SpanInfoStruct,
41
44
  StdinParser,
42
45
  StyledText,
46
+ SyntaxStyle,
43
47
  SystemClock,
44
48
  TargetChannel,
45
49
  TerminalConsole,
46
50
  TerminalPalette,
47
51
  TextAttributes,
48
52
  TextBuffer,
53
+ TextBufferRenderable,
54
+ TextBufferView,
55
+ TextNodeRenderable,
56
+ TextRenderable,
49
57
  TreeSitterClient,
50
58
  addDefaultParsers,
59
+ ansi256IndexToRgb,
51
60
  attributesWithLink,
52
61
  basenameToFiletype,
53
62
  bg,
@@ -74,9 +83,11 @@ import {
74
83
  brightYellow,
75
84
  buildKeyBindingsMap,
76
85
  buildKittyKeyboardFlags,
86
+ buildTerminalPaletteSignature,
77
87
  capture,
78
88
  clearEnvCache,
79
89
  convertGlobalToLocalSelection,
90
+ convertThemeToStyles,
80
91
  coordinateToCharacterIndex,
81
92
  createCliRenderer,
82
93
  createExtmarksController,
@@ -102,7 +113,7 @@ import {
102
113
  getBorderSides,
103
114
  getCharacterPositions,
104
115
  getDataPaths,
105
- getKeyBindingKey,
116
+ getKeyBindingAction,
106
117
  getLinkId,
107
118
  getObjectsInViewport,
108
119
  getTreeSitterClient,
@@ -116,18 +127,20 @@ import {
116
127
  isEditBufferRenderable,
117
128
  isRenderable,
118
129
  isStyledText,
130
+ isTextNodeRenderable,
119
131
  isVNode,
120
132
  isValidBorderStyle,
121
- isValidPercentage,
122
133
  italic,
123
134
  link,
124
135
  magenta,
125
- main,
126
136
  maybeMakeRenderable,
127
137
  measureText,
128
138
  mergeKeyAliases,
129
139
  mergeKeyBindings,
130
140
  nonAlphanumericKeys,
141
+ normalizeColorValue,
142
+ normalizeIndexedColorIndex,
143
+ normalizeTerminalPalette,
131
144
  parseAlign,
132
145
  parseAlignItems,
133
146
  parseBorderStyle,
@@ -160,7 +173,7 @@ import {
160
173
  stringWidth,
161
174
  stripAnsiSequences,
162
175
  t,
163
- toArrayBuffer,
176
+ terminalNamedSingleStrokeKeys,
164
177
  treeSitterToStyledText,
165
178
  treeSitterToTextChunks,
166
179
  underline,
@@ -168,10 +181,13 @@ import {
168
181
  white,
169
182
  wrapWithDelegates,
170
183
  yellow
171
- } from "./index-rhfjv9c1.js";
184
+ } from "./index-g9agybj3.js";
185
+ import {
186
+ toArrayBuffer
187
+ } from "./index-5zwezmgj.js";
172
188
  import {
173
189
  __export
174
- } from "./index-re3ntm60.js";
190
+ } from "./index-k18nf2r7.js";
175
191
 
176
192
  // src/index.ts
177
193
  var exports_src2 = {};
@@ -181,14 +197,15 @@ __export(exports_src2, {
181
197
  white: () => white,
182
198
  vstyles: () => vstyles,
183
199
  visualizeRenderableTree: () => visualizeRenderableTree,
184
- updateAssets: () => main,
185
200
  underline: () => underline,
186
201
  treeSitterToTextChunks: () => treeSitterToTextChunks,
187
202
  treeSitterToStyledText: () => treeSitterToStyledText,
203
+ terminalNamedSingleStrokeKeys: () => terminalNamedSingleStrokeKeys,
188
204
  t: () => t,
189
205
  stripAnsiSequences: () => stripAnsiSequences,
190
206
  stringToStyledText: () => stringToStyledText,
191
207
  strikethrough: () => strikethrough,
208
+ setupAudio: () => setupAudio,
192
209
  setRenderLibPath: () => setRenderLibPath,
193
210
  rgbToHex: () => rgbToHex,
194
211
  reverse: () => reverse,
@@ -218,6 +235,9 @@ __export(exports_src2, {
218
235
  parseBorderStyle: () => parseBorderStyle,
219
236
  parseAlignItems: () => parseAlignItems,
220
237
  parseAlign: () => parseAlign,
238
+ normalizeTerminalPalette: () => normalizeTerminalPalette,
239
+ normalizeIndexedColorIndex: () => normalizeIndexedColorIndex,
240
+ normalizeColorValue: () => normalizeColorValue,
221
241
  nonAlphanumericKeys: () => nonAlphanumericKeys,
222
242
  measureText: () => measureText,
223
243
  maybeMakeRenderable: () => maybeMakeRenderable,
@@ -256,6 +276,7 @@ __export(exports_src2, {
256
276
  dim: () => dim,
257
277
  detectLinks: () => detectLinks,
258
278
  delegate: () => delegate,
279
+ defaultTextareaKeyBindings: () => defaultTextareaKeyBindings,
259
280
  decodePasteBytes: () => decodePasteBytes,
260
281
  cyan: () => cyan,
261
282
  createTimeline: () => createTimeline,
@@ -270,6 +291,7 @@ __export(exports_src2, {
270
291
  convertGlobalToLocalSelection: () => convertGlobalToLocalSelection,
271
292
  clearEnvCache: () => clearEnvCache,
272
293
  capture: () => capture,
294
+ buildTerminalPaletteSignature: () => buildTerminalPaletteSignature,
273
295
  buildKittyKeyboardFlags: () => buildKittyKeyboardFlags,
274
296
  brightYellow: () => brightYellow,
275
297
  brightWhite: () => brightWhite,
@@ -303,6 +325,7 @@ __export(exports_src2, {
303
325
  applyChromaticAberration: () => applyChromaticAberration,
304
326
  applyBrightness: () => applyBrightness,
305
327
  applyAsciiArt: () => applyAsciiArt,
328
+ ansi256IndexToRgb: () => ansi256IndexToRgb,
306
329
  addDefaultParsers: () => addDefaultParsers,
307
330
  Yoga: () => exports_src,
308
331
  VignetteEffect: () => VignetteEffect,
@@ -390,6 +413,8 @@ __export(exports_src2, {
390
413
  DataPathsManager: () => DataPathsManager,
391
414
  DEUTERANOPIA_SIM_MATRIX: () => DEUTERANOPIA_SIM_MATRIX,
392
415
  DEUTERANOPIA_COMP_MATRIX: () => DEUTERANOPIA_COMP_MATRIX,
416
+ DEFAULT_FOREGROUND_RGB: () => DEFAULT_FOREGROUND_RGB,
417
+ DEFAULT_BACKGROUND_RGB: () => DEFAULT_BACKGROUND_RGB,
393
418
  ConsolePosition: () => ConsolePosition,
394
419
  CodeRenderable: () => CodeRenderable,
395
420
  Code: () => Code,
@@ -403,6 +428,7 @@ __export(exports_src2, {
403
428
  BorderCharArrays: () => BorderCharArrays,
404
429
  BloomEffect: () => BloomEffect,
405
430
  BaseRenderable: () => BaseRenderable,
431
+ Audio: () => Audio,
406
432
  ArrowRenderable: () => ArrowRenderable,
407
433
  ATTRIBUTE_BASE_MASK: () => ATTRIBUTE_BASE_MASK,
408
434
  ATTRIBUTE_BASE_BITS: () => ATTRIBUTE_BASE_BITS,
@@ -412,327 +438,21 @@ __export(exports_src2, {
412
438
  ACHROMATOPSIA_MATRIX: () => ACHROMATOPSIA_MATRIX
413
439
  });
414
440
 
415
- // src/text-buffer-view.ts
416
- class TextBufferView {
417
- lib;
418
- viewPtr;
419
- textBuffer;
420
- _destroyed = false;
421
- constructor(lib, ptr, textBuffer) {
422
- this.lib = lib;
423
- this.viewPtr = ptr;
424
- this.textBuffer = textBuffer;
425
- }
426
- static create(textBuffer) {
427
- const lib = resolveRenderLib();
428
- const viewPtr = lib.createTextBufferView(textBuffer.ptr);
429
- return new TextBufferView(lib, viewPtr, textBuffer);
430
- }
431
- guard() {
432
- if (this._destroyed)
433
- throw new Error("TextBufferView is destroyed");
434
- }
435
- get ptr() {
436
- this.guard();
437
- return this.viewPtr;
438
- }
439
- setSelection(start, end, bgColor, fgColor) {
440
- this.guard();
441
- this.lib.textBufferViewSetSelection(this.viewPtr, start, end, bgColor || null, fgColor || null);
442
- }
443
- updateSelection(end, bgColor, fgColor) {
444
- this.guard();
445
- this.lib.textBufferViewUpdateSelection(this.viewPtr, end, bgColor || null, fgColor || null);
446
- }
447
- resetSelection() {
448
- this.guard();
449
- this.lib.textBufferViewResetSelection(this.viewPtr);
450
- }
451
- getSelection() {
452
- this.guard();
453
- return this.lib.textBufferViewGetSelection(this.viewPtr);
454
- }
455
- hasSelection() {
456
- this.guard();
457
- return this.getSelection() !== null;
458
- }
459
- setLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor) {
460
- this.guard();
461
- return this.lib.textBufferViewSetLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null);
462
- }
463
- updateLocalSelection(anchorX, anchorY, focusX, focusY, bgColor, fgColor) {
464
- this.guard();
465
- return this.lib.textBufferViewUpdateLocalSelection(this.viewPtr, anchorX, anchorY, focusX, focusY, bgColor || null, fgColor || null);
466
- }
467
- resetLocalSelection() {
468
- this.guard();
469
- this.lib.textBufferViewResetLocalSelection(this.viewPtr);
470
- }
471
- setWrapWidth(width) {
472
- this.guard();
473
- this.lib.textBufferViewSetWrapWidth(this.viewPtr, width ?? 0);
474
- }
475
- setWrapMode(mode) {
476
- this.guard();
477
- this.lib.textBufferViewSetWrapMode(this.viewPtr, mode);
478
- }
479
- setViewportSize(width, height) {
480
- this.guard();
481
- this.lib.textBufferViewSetViewportSize(this.viewPtr, width, height);
482
- }
483
- setViewport(x, y, width, height) {
484
- this.guard();
485
- this.lib.textBufferViewSetViewport(this.viewPtr, x, y, width, height);
486
- }
487
- get lineInfo() {
488
- this.guard();
489
- return this.lib.textBufferViewGetLineInfo(this.viewPtr);
490
- }
491
- get logicalLineInfo() {
492
- this.guard();
493
- return this.lib.textBufferViewGetLogicalLineInfo(this.viewPtr);
494
- }
495
- getSelectedText() {
496
- this.guard();
497
- const byteSize = this.textBuffer.byteSize;
498
- if (byteSize === 0)
499
- return "";
500
- const selectedBytes = this.lib.textBufferViewGetSelectedTextBytes(this.viewPtr, byteSize);
501
- if (!selectedBytes)
502
- return "";
503
- return this.lib.decoder.decode(selectedBytes);
504
- }
505
- getPlainText() {
506
- this.guard();
507
- const byteSize = this.textBuffer.byteSize;
508
- if (byteSize === 0)
509
- return "";
510
- const plainBytes = this.lib.textBufferViewGetPlainTextBytes(this.viewPtr, byteSize);
511
- if (!plainBytes)
512
- return "";
513
- return this.lib.decoder.decode(plainBytes);
514
- }
515
- setTabIndicator(indicator) {
516
- this.guard();
517
- const codePoint = typeof indicator === "string" ? indicator.codePointAt(0) ?? 0 : indicator;
518
- this.lib.textBufferViewSetTabIndicator(this.viewPtr, codePoint);
519
- }
520
- setTabIndicatorColor(color) {
521
- this.guard();
522
- this.lib.textBufferViewSetTabIndicatorColor(this.viewPtr, color);
523
- }
524
- setTruncate(truncate) {
525
- this.guard();
526
- this.lib.textBufferViewSetTruncate(this.viewPtr, truncate);
527
- }
528
- measureForDimensions(width, height) {
529
- this.guard();
530
- return this.lib.textBufferViewMeasureForDimensions(this.viewPtr, width, height);
531
- }
532
- getVirtualLineCount() {
533
- this.guard();
534
- return this.lib.textBufferViewGetVirtualLineCount(this.viewPtr);
535
- }
536
- destroy() {
537
- if (this._destroyed)
538
- return;
539
- this._destroyed = true;
540
- this.lib.destroyTextBufferView(this.viewPtr);
541
- }
441
+ // src/post/effects.ts
442
+ function toU8(value) {
443
+ return Math.round(Math.max(0, Math.min(1, Number.isFinite(value) ? value : 0)) * 255);
542
444
  }
543
- // src/syntax-style.ts
544
- function convertThemeToStyles(theme) {
545
- const flatStyles = {};
546
- for (const tokenStyle of theme) {
547
- const styleDefinition = {};
548
- if (tokenStyle.style.foreground) {
549
- styleDefinition.fg = parseColor(tokenStyle.style.foreground);
550
- }
551
- if (tokenStyle.style.background) {
552
- styleDefinition.bg = parseColor(tokenStyle.style.background);
553
- }
554
- if (tokenStyle.style.bold !== undefined) {
555
- styleDefinition.bold = tokenStyle.style.bold;
556
- }
557
- if (tokenStyle.style.italic !== undefined) {
558
- styleDefinition.italic = tokenStyle.style.italic;
559
- }
560
- if (tokenStyle.style.underline !== undefined) {
561
- styleDefinition.underline = tokenStyle.style.underline;
562
- }
563
- if (tokenStyle.style.dim !== undefined) {
564
- styleDefinition.dim = tokenStyle.style.dim;
565
- }
566
- for (const scope of tokenStyle.scope) {
567
- flatStyles[scope] = styleDefinition;
568
- }
569
- }
570
- return flatStyles;
445
+ function channel(buffer, index) {
446
+ return (buffer[index] & 255) / 255;
571
447
  }
572
-
573
- class SyntaxStyle {
574
- lib;
575
- stylePtr;
576
- _destroyed = false;
577
- nameCache = new Map;
578
- styleDefs = new Map;
579
- mergedCache = new Map;
580
- constructor(lib, ptr) {
581
- this.lib = lib;
582
- this.stylePtr = ptr;
583
- }
584
- static create() {
585
- const lib = resolveRenderLib();
586
- const ptr = lib.createSyntaxStyle();
587
- return new SyntaxStyle(lib, ptr);
588
- }
589
- static fromTheme(theme) {
590
- const style = SyntaxStyle.create();
591
- const flatStyles = convertThemeToStyles(theme);
592
- for (const [name, styleDef] of Object.entries(flatStyles)) {
593
- style.registerStyle(name, styleDef);
594
- }
595
- return style;
596
- }
597
- static fromStyles(styles) {
598
- const style = SyntaxStyle.create();
599
- for (const [name, styleDef] of Object.entries(styles)) {
600
- style.registerStyle(name, styleDef);
601
- }
602
- return style;
603
- }
604
- guard() {
605
- if (this._destroyed)
606
- throw new Error("NativeSyntaxStyle is destroyed");
607
- }
608
- registerStyle(name, style) {
609
- this.guard();
610
- const attributes = createTextAttributes({
611
- bold: style.bold,
612
- italic: style.italic,
613
- underline: style.underline,
614
- dim: style.dim
615
- });
616
- const id = this.lib.syntaxStyleRegister(this.stylePtr, name, style.fg || null, style.bg || null, attributes);
617
- this.nameCache.set(name, id);
618
- this.styleDefs.set(name, style);
619
- return id;
620
- }
621
- resolveStyleId(name) {
622
- this.guard();
623
- const cached = this.nameCache.get(name);
624
- if (cached !== undefined)
625
- return cached;
626
- const id = this.lib.syntaxStyleResolveByName(this.stylePtr, name);
627
- if (id !== null) {
628
- this.nameCache.set(name, id);
629
- }
630
- return id;
631
- }
632
- getStyleId(name) {
633
- this.guard();
634
- const id = this.resolveStyleId(name);
635
- if (id !== null)
636
- return id;
637
- if (name.includes(".")) {
638
- const baseName = name.split(".")[0];
639
- return this.resolveStyleId(baseName);
640
- }
641
- return null;
642
- }
643
- get ptr() {
644
- this.guard();
645
- return this.stylePtr;
646
- }
647
- getStyleCount() {
648
- this.guard();
649
- return this.lib.syntaxStyleGetStyleCount(this.stylePtr);
650
- }
651
- clearNameCache() {
652
- this.nameCache.clear();
653
- }
654
- getStyle(name) {
655
- this.guard();
656
- if (Object.prototype.hasOwnProperty.call(this.styleDefs, name)) {
657
- return;
658
- }
659
- const style = this.styleDefs.get(name);
660
- if (style)
661
- return style;
662
- if (name.includes(".")) {
663
- const baseName = name.split(".")[0];
664
- if (Object.prototype.hasOwnProperty.call(this.styleDefs, baseName)) {
665
- return;
666
- }
667
- return this.styleDefs.get(baseName);
668
- }
669
- return;
670
- }
671
- mergeStyles(...styleNames) {
672
- this.guard();
673
- const cacheKey = styleNames.join(":");
674
- const cached = this.mergedCache.get(cacheKey);
675
- if (cached)
676
- return cached;
677
- const styleDefinition = {};
678
- for (const name of styleNames) {
679
- const style = this.getStyle(name);
680
- if (!style)
681
- continue;
682
- if (style.fg)
683
- styleDefinition.fg = style.fg;
684
- if (style.bg)
685
- styleDefinition.bg = style.bg;
686
- if (style.bold !== undefined)
687
- styleDefinition.bold = style.bold;
688
- if (style.italic !== undefined)
689
- styleDefinition.italic = style.italic;
690
- if (style.underline !== undefined)
691
- styleDefinition.underline = style.underline;
692
- if (style.dim !== undefined)
693
- styleDefinition.dim = style.dim;
694
- }
695
- const attributes = createTextAttributes({
696
- bold: styleDefinition.bold,
697
- italic: styleDefinition.italic,
698
- underline: styleDefinition.underline,
699
- dim: styleDefinition.dim
700
- });
701
- const merged = {
702
- fg: styleDefinition.fg,
703
- bg: styleDefinition.bg,
704
- attributes
705
- };
706
- this.mergedCache.set(cacheKey, merged);
707
- return merged;
708
- }
709
- clearCache() {
710
- this.guard();
711
- this.mergedCache.clear();
712
- }
713
- getCacheSize() {
714
- this.guard();
715
- return this.mergedCache.size;
716
- }
717
- getAllStyles() {
718
- this.guard();
719
- return new Map(this.styleDefs);
720
- }
721
- getRegisteredNames() {
722
- this.guard();
723
- return Array.from(this.styleDefs.keys());
724
- }
725
- destroy() {
726
- if (this._destroyed)
727
- return;
728
- this._destroyed = true;
729
- this.nameCache.clear();
730
- this.styleDefs.clear();
731
- this.mergedCache.clear();
732
- this.lib.destroySyntaxStyle(this.stylePtr);
733
- }
448
+ function setRgb(buffer, base, r, g, b) {
449
+ const a = buffer[base + 3] & 255;
450
+ buffer[base] = toU8(r);
451
+ buffer[base + 1] = toU8(g);
452
+ buffer[base + 2] = toU8(b);
453
+ buffer[base + 3] = a;
734
454
  }
735
- // src/post/effects.ts
455
+
736
456
  class DistortionEffect {
737
457
  glitchChancePerSecond = 0.5;
738
458
  maxGlitchLines = 3;
@@ -796,8 +516,8 @@ class DistortionEffect {
796
516
  if (glitch.type === "shift" || glitch.type === "flip") {
797
517
  if (!tempChar) {
798
518
  tempChar = new Uint32Array(width);
799
- tempFg = new Float32Array(width * 4);
800
- tempBg = new Float32Array(width * 4);
519
+ tempFg = new Uint16Array(width * 4);
520
+ tempBg = new Uint16Array(width * 4);
801
521
  tempAttr = new Uint8Array(width);
802
522
  }
803
523
  try {
@@ -904,12 +624,8 @@ class DistortionEffect {
904
624
  gBg = 1 - gFg;
905
625
  bBg = 1 - bFg;
906
626
  }
907
- buf.fg[destColorIndex] = rFg;
908
- buf.fg[destColorIndex + 1] = gFg;
909
- buf.fg[destColorIndex + 2] = bFg;
910
- buf.bg[destColorIndex] = rBg;
911
- buf.bg[destColorIndex + 1] = gBg;
912
- buf.bg[destColorIndex + 2] = bBg;
627
+ setRgb(buf.fg, destColorIndex, rFg, gFg, bFg);
628
+ setRgb(buf.bg, destColorIndex, rBg, gBg, bBg);
913
629
  }
914
630
  }
915
631
  }
@@ -1174,9 +890,7 @@ class FlamesEffect {
1174
890
  g = flameIntensity * 0.5;
1175
891
  b = 0;
1176
892
  }
1177
- bg2[colorIndex] = Math.max(bg2[colorIndex], r * flameIntensity);
1178
- bg2[colorIndex + 1] = Math.max(bg2[colorIndex + 1], g * flameIntensity);
1179
- bg2[colorIndex + 2] = Math.max(bg2[colorIndex + 2], b * flameIntensity);
893
+ setRgb(bg2, colorIndex, Math.max(channel(bg2, colorIndex), r * flameIntensity), Math.max(channel(bg2, colorIndex + 1), g * flameIntensity), Math.max(channel(bg2, colorIndex + 2), b * flameIntensity));
1180
894
  }
1181
895
  }
1182
896
  }
@@ -1242,12 +956,8 @@ class CRTRollingBarEffect {
1242
956
  const rowMultiplier = 1 + this._intensity * barFactor;
1243
957
  for (let x = 0;x < width; x++) {
1244
958
  const colorIndex = (y * width + x) * 4;
1245
- fg2[colorIndex] = Math.min(1, fg2[colorIndex] * rowMultiplier);
1246
- fg2[colorIndex + 1] = Math.min(1, fg2[colorIndex + 1] * rowMultiplier);
1247
- fg2[colorIndex + 2] = Math.min(1, fg2[colorIndex + 2] * rowMultiplier);
1248
- bg2[colorIndex] = Math.min(1, bg2[colorIndex] * rowMultiplier);
1249
- bg2[colorIndex + 1] = Math.min(1, bg2[colorIndex + 1] * rowMultiplier);
1250
- bg2[colorIndex + 2] = Math.min(1, bg2[colorIndex + 2] * rowMultiplier);
959
+ setRgb(fg2, colorIndex, Math.min(1, channel(fg2, colorIndex) * rowMultiplier), Math.min(1, channel(fg2, colorIndex + 1) * rowMultiplier), Math.min(1, channel(fg2, colorIndex + 2) * rowMultiplier));
960
+ setRgb(bg2, colorIndex, Math.min(1, channel(bg2, colorIndex) * rowMultiplier), Math.min(1, channel(bg2, colorIndex + 1) * rowMultiplier), Math.min(1, channel(bg2, colorIndex + 2) * rowMultiplier));
1251
961
  }
1252
962
  }
1253
963
  }
@@ -1346,23 +1056,34 @@ class RainbowTextEffect {
1346
1056
  for (let y = 0;y < height; y++) {
1347
1057
  for (let x = 0;x < width; x++) {
1348
1058
  const colorIndex = (y * width + x) * 4;
1349
- const r = fg2[colorIndex];
1350
- const g = fg2[colorIndex + 1];
1351
- const b = fg2[colorIndex + 2];
1059
+ const r = channel(fg2, colorIndex);
1060
+ const g = channel(fg2, colorIndex + 1);
1061
+ const b = channel(fg2, colorIndex + 2);
1352
1062
  if (r >= whiteThreshold && g >= whiteThreshold && b >= whiteThreshold) {
1353
1063
  const projection = x * cosAngle + y * sinAngle;
1354
1064
  const maxProjection = width * cosAngle + height * sinAngle;
1355
1065
  const hue = (projection / maxProjection * repeats + this.time * 0.1) % 1;
1356
1066
  const [newR, newG, newB] = this.hsvToRgb(hue, saturation, value);
1357
- fg2[colorIndex] = newR;
1358
- fg2[colorIndex + 1] = newG;
1359
- fg2[colorIndex + 2] = newB;
1067
+ setRgb(fg2, colorIndex, newR, newG, newB);
1360
1068
  }
1361
1069
  }
1362
1070
  }
1363
1071
  }
1364
1072
  }
1365
1073
  // src/post/filters.ts
1074
+ function toU82(value) {
1075
+ return Math.round(Math.max(0, Math.min(1, Number.isFinite(value) ? value : 0)) * 255);
1076
+ }
1077
+ function channel2(buffer, index) {
1078
+ return (buffer[index] & 255) / 255;
1079
+ }
1080
+ function setRgb2(buffer, base, r, g, b) {
1081
+ const a = buffer[base + 3] & 255;
1082
+ buffer[base] = toU82(r);
1083
+ buffer[base + 1] = toU82(g);
1084
+ buffer[base + 2] = toU82(b);
1085
+ buffer[base + 3] = a;
1086
+ }
1366
1087
  function applyScanlines(buffer, strength = 0.8, step = 2) {
1367
1088
  if (strength === 1 || step < 1)
1368
1089
  return;
@@ -1462,7 +1183,7 @@ function applyNoise(buffer, strength = 0.1) {
1462
1183
  function applyChromaticAberration(buffer, strength = 1) {
1463
1184
  const width = buffer.width;
1464
1185
  const height = buffer.height;
1465
- const srcFg = Float32Array.from(buffer.buffers.fg);
1186
+ const srcFg = Uint16Array.from(buffer.buffers.fg);
1466
1187
  const destFg = buffer.buffers.fg;
1467
1188
  const centerX = width / 2;
1468
1189
  const centerY = height / 2;
@@ -1477,9 +1198,7 @@ function applyChromaticAberration(buffer, strength = 1) {
1477
1198
  const gIndex = (y * width + x) * 4;
1478
1199
  const bIndex = (y * width + bX) * 4;
1479
1200
  const destIndex = (y * width + x) * 4;
1480
- destFg[destIndex] = srcFg[rIndex];
1481
- destFg[destIndex + 1] = srcFg[gIndex + 1];
1482
- destFg[destIndex + 2] = srcFg[bIndex + 2];
1201
+ setRgb2(destFg, destIndex, channel2(srcFg, rIndex), channel2(srcFg, gIndex + 1), channel2(srcFg, bIndex + 2));
1483
1202
  }
1484
1203
  }
1485
1204
  }
@@ -1493,9 +1212,9 @@ function applyAsciiArt(buffer, ramp = ' .\'`^"",:;Il!i><~+_-?][}{1)(|\\/tfjrxnuv
1493
1212
  for (let x = 0;x < width; x++) {
1494
1213
  const index = y * width + x;
1495
1214
  const colorIndex = index * 4;
1496
- const bgR = bg2[colorIndex];
1497
- const bgG = bg2[colorIndex + 1];
1498
- const bgB = bg2[colorIndex + 2];
1215
+ const bgR = channel2(bg2, colorIndex);
1216
+ const bgG = channel2(bg2, colorIndex + 1);
1217
+ const bgB = channel2(bg2, colorIndex + 2);
1499
1218
  const lum = 0.299 * bgR + 0.587 * bgG + 0.114 * bgB;
1500
1219
  const rampIndex = Math.min(rampLength - 1, Math.floor(lum * rampLength));
1501
1220
  chars[index] = ramp[rampIndex].charCodeAt(0);
@@ -1676,16 +1395,16 @@ class BloomEffect {
1676
1395
  return;
1677
1396
  const width = buffer.width;
1678
1397
  const height = buffer.height;
1679
- const srcFg = Float32Array.from(buffer.buffers.fg);
1680
- const srcBg = Float32Array.from(buffer.buffers.bg);
1398
+ const srcFg = Uint16Array.from(buffer.buffers.fg);
1399
+ const srcBg = Uint16Array.from(buffer.buffers.bg);
1681
1400
  const destFg = buffer.buffers.fg;
1682
1401
  const destBg = buffer.buffers.bg;
1683
1402
  const brightPixels = [];
1684
1403
  for (let y = 0;y < height; y++) {
1685
1404
  for (let x = 0;x < width; x++) {
1686
1405
  const index = (y * width + x) * 4;
1687
- const fgLum = 0.299 * srcFg[index] + 0.587 * srcFg[index + 1] + 0.114 * srcFg[index + 2];
1688
- const bgLum = 0.299 * srcBg[index] + 0.587 * srcBg[index + 1] + 0.114 * srcBg[index + 2];
1406
+ const fgLum = 0.299 * channel2(srcFg, index) + 0.587 * channel2(srcFg, index + 1) + 0.114 * channel2(srcFg, index + 2);
1407
+ const bgLum = 0.299 * channel2(srcBg, index) + 0.587 * channel2(srcBg, index + 1) + 0.114 * channel2(srcBg, index + 2);
1689
1408
  const lum = Math.max(fgLum, bgLum);
1690
1409
  if (lum > threshold) {
1691
1410
  const intensity = (lum - threshold) / (1 - threshold + 0.000001);
@@ -1711,12 +1430,8 @@ class BloomEffect {
1711
1430
  const falloff = 1 - distSq / radiusSq;
1712
1431
  const bloomAmount = bright.intensity * strength * falloff;
1713
1432
  const destIndex = (sampleY * width + sampleX) * 4;
1714
- destFg[destIndex] = Math.min(1, destFg[destIndex] + bloomAmount);
1715
- destFg[destIndex + 1] = Math.min(1, destFg[destIndex + 1] + bloomAmount);
1716
- destFg[destIndex + 2] = Math.min(1, destFg[destIndex + 2] + bloomAmount);
1717
- destBg[destIndex] = Math.min(1, destBg[destIndex] + bloomAmount);
1718
- destBg[destIndex + 1] = Math.min(1, destBg[destIndex + 1] + bloomAmount);
1719
- destBg[destIndex + 2] = Math.min(1, destBg[destIndex + 2] + bloomAmount);
1433
+ setRgb2(destFg, destIndex, Math.min(1, channel2(destFg, destIndex) + bloomAmount), Math.min(1, channel2(destFg, destIndex + 1) + bloomAmount), Math.min(1, channel2(destFg, destIndex + 2) + bloomAmount));
1434
+ setRgb2(destBg, destIndex, Math.min(1, channel2(destBg, destIndex) + bloomAmount), Math.min(1, channel2(destBg, destIndex + 1) + bloomAmount), Math.min(1, channel2(destBg, destIndex + 2) + bloomAmount));
1720
1435
  }
1721
1436
  }
1722
1437
  }
@@ -3061,15 +2776,6 @@ class SlotRenderable extends Renderable {
3061
2776
  }
3062
2777
  }
3063
2778
  // src/NativeSpanFeed.ts
3064
- function toPointer(value) {
3065
- if (typeof value === "bigint") {
3066
- if (value > BigInt(Number.MAX_SAFE_INTEGER)) {
3067
- throw new Error("Pointer exceeds safe integer range");
3068
- }
3069
- return Number(value);
3070
- }
3071
- return value;
3072
- }
3073
2779
  function toNumber(value) {
3074
2780
  return typeof value === "bigint" ? Number(value) : value;
3075
2781
  }
@@ -3090,12 +2796,11 @@ class NativeSpanFeed {
3090
2796
  }
3091
2797
  static attach(streamPtr, _options) {
3092
2798
  const lib = resolveRenderLib();
3093
- const ptr = toPointer(streamPtr);
3094
- const stream = new NativeSpanFeed(ptr);
3095
- lib.registerNativeSpanFeedStream(ptr, stream.eventHandler);
3096
- const status = lib.attachNativeSpanFeed(ptr);
2799
+ const stream = new NativeSpanFeed(streamPtr);
2800
+ lib.registerNativeSpanFeedStream(streamPtr, stream.eventHandler);
2801
+ const status = lib.attachNativeSpanFeed(streamPtr);
3097
2802
  if (status !== 0) {
3098
- lib.unregisterNativeSpanFeedStream(ptr);
2803
+ lib.unregisterNativeSpanFeedStream(streamPtr);
3099
2804
  throw new Error(`Failed to attach stream: ${status}`);
3100
2805
  }
3101
2806
  return stream;
@@ -3229,7 +2934,7 @@ class NativeSpanFeed {
3229
2934
  break;
3230
2935
  }
3231
2936
  case 6 /* Error */: {
3232
- const code = arg0;
2937
+ const code = toNumber(arg0);
3233
2938
  for (const handler of this.errorHandlers)
3234
2939
  handler(code);
3235
2940
  break;
@@ -3319,6 +3024,362 @@ class NativeSpanFeed {
3319
3024
  }
3320
3025
  }
3321
3026
  }
3027
+ // src/audio.ts
3028
+ import { EventEmitter } from "events";
3029
+ import { readFile } from "fs/promises";
3030
+ function statusToError(action, status) {
3031
+ return new Error(`Audio ${action} failed: ${status}`);
3032
+ }
3033
+ function toBytes(data) {
3034
+ return data instanceof Uint8Array ? data : new Uint8Array(data);
3035
+ }
3036
+
3037
+ class Audio extends EventEmitter {
3038
+ static create(options = {}) {
3039
+ return new Audio(resolveRenderLib(), options);
3040
+ }
3041
+ lib;
3042
+ defaultStartOptions;
3043
+ engine = null;
3044
+ groups = new Map;
3045
+ playbackStarted = false;
3046
+ mixerStarted = false;
3047
+ constructor(lib, options) {
3048
+ super();
3049
+ this.lib = lib;
3050
+ this.defaultStartOptions = options.startOptions;
3051
+ const createOptions = options.sampleRate == null && options.playbackChannels == null ? undefined : {
3052
+ sampleRate: options.sampleRate == null ? undefined : Math.max(0, Math.trunc(options.sampleRate)),
3053
+ playbackChannels: options.playbackChannels == null ? undefined : Math.max(0, Math.trunc(options.playbackChannels))
3054
+ };
3055
+ this.engine = this.lib.createAudioEngine(createOptions);
3056
+ if (!this.engine) {
3057
+ this.emitError("createAudioEngine", undefined, "Audio createAudioEngine returned null");
3058
+ return;
3059
+ }
3060
+ if (options.autoStart ?? false) {
3061
+ this.start(this.defaultStartOptions);
3062
+ }
3063
+ }
3064
+ emitError(action, status, message, cause) {
3065
+ const error = message ? new Error(message) : statusToError(action, status ?? -1);
3066
+ if (cause)
3067
+ error.cause = cause;
3068
+ this.emit("error", error, { action, status });
3069
+ }
3070
+ start(options) {
3071
+ if (this.playbackStarted)
3072
+ return true;
3073
+ const engine2 = this.engine;
3074
+ if (!engine2) {
3075
+ this.emitError("start", undefined, "Audio engine unavailable during start");
3076
+ return false;
3077
+ }
3078
+ const startOptions = options ?? this.defaultStartOptions;
3079
+ const status = this.lib.audioStart(engine2, startOptions);
3080
+ if (status !== 0) {
3081
+ this.emitError("start", status);
3082
+ return false;
3083
+ }
3084
+ this.playbackStarted = true;
3085
+ this.mixerStarted = true;
3086
+ this.emit("started");
3087
+ return true;
3088
+ }
3089
+ startMixer() {
3090
+ if (this.mixerStarted)
3091
+ return true;
3092
+ const engine2 = this.engine;
3093
+ if (!engine2) {
3094
+ this.emitError("startMixer", undefined, "Audio engine unavailable during startMixer");
3095
+ return false;
3096
+ }
3097
+ const status = this.lib.audioStartMixer(engine2);
3098
+ if (status !== 0) {
3099
+ this.emitError("startMixer", status);
3100
+ return false;
3101
+ }
3102
+ this.mixerStarted = true;
3103
+ this.emit("mixerStarted");
3104
+ return true;
3105
+ }
3106
+ stop() {
3107
+ if (!this.mixerStarted)
3108
+ return true;
3109
+ const engine2 = this.engine;
3110
+ if (!engine2) {
3111
+ this.emitError("stop", undefined, "Audio engine unavailable during stop");
3112
+ return false;
3113
+ }
3114
+ const status = this.lib.audioStop(engine2);
3115
+ if (status !== 0) {
3116
+ this.emitError("stop", status);
3117
+ return false;
3118
+ }
3119
+ this.playbackStarted = false;
3120
+ this.mixerStarted = false;
3121
+ this.emit("stopped");
3122
+ return true;
3123
+ }
3124
+ isStarted() {
3125
+ return this.playbackStarted;
3126
+ }
3127
+ isMixerStarted() {
3128
+ return this.mixerStarted;
3129
+ }
3130
+ loadSound(data) {
3131
+ const engine2 = this.engine;
3132
+ if (!engine2) {
3133
+ this.emitError("loadSound", undefined, "Audio engine unavailable during loadSound");
3134
+ return null;
3135
+ }
3136
+ const result = this.lib.audioLoad(engine2, toBytes(data));
3137
+ if (result.status !== 0 || result.soundId == null) {
3138
+ this.emitError("loadSound", result.status);
3139
+ return null;
3140
+ }
3141
+ return result.soundId;
3142
+ }
3143
+ async loadSoundFile(filePath) {
3144
+ const bytes = await readFile(filePath).catch((err) => {
3145
+ this.emitError("loadSoundFile", undefined, `Failed to read file '${filePath}': ${err.message}`, err);
3146
+ return null;
3147
+ });
3148
+ if (bytes == null)
3149
+ return null;
3150
+ return this.loadSound(bytes);
3151
+ }
3152
+ unloadSound(sound) {
3153
+ const engine2 = this.engine;
3154
+ if (!engine2) {
3155
+ this.emitError("unloadSound", undefined, "Audio engine unavailable during unloadSound");
3156
+ return false;
3157
+ }
3158
+ const status = this.lib.audioUnload(engine2, sound);
3159
+ if (status !== 0) {
3160
+ this.emitError("unloadSound", status);
3161
+ return false;
3162
+ }
3163
+ return true;
3164
+ }
3165
+ group(name) {
3166
+ const existing = this.groups.get(name);
3167
+ if (existing != null) {
3168
+ return existing;
3169
+ }
3170
+ const engine2 = this.engine;
3171
+ if (!engine2) {
3172
+ this.emitError("group", undefined, "Audio engine unavailable during group");
3173
+ return null;
3174
+ }
3175
+ const result = this.lib.audioCreateGroup(engine2, name);
3176
+ if (result.status !== 0 || result.groupId == null) {
3177
+ this.emitError("group", result.status);
3178
+ return null;
3179
+ }
3180
+ this.groups.set(name, result.groupId);
3181
+ return result.groupId;
3182
+ }
3183
+ play(sound, options) {
3184
+ const rawOptions = options ? {
3185
+ volume: options.volume,
3186
+ pan: options.pan,
3187
+ loop: options.loop,
3188
+ groupId: options.groupId ?? 0
3189
+ } : undefined;
3190
+ const engine2 = this.engine;
3191
+ if (!engine2) {
3192
+ this.emitError("play", undefined, "Audio engine unavailable during play");
3193
+ return null;
3194
+ }
3195
+ const result = this.lib.audioPlay(engine2, sound, rawOptions);
3196
+ if (result.status !== 0 || result.voiceId == null) {
3197
+ this.emitError("play", result.status);
3198
+ return null;
3199
+ }
3200
+ return result.voiceId;
3201
+ }
3202
+ stopVoice(voice) {
3203
+ const engine2 = this.engine;
3204
+ if (!engine2) {
3205
+ this.emitError("stopVoice", undefined, "Audio engine unavailable during stopVoice");
3206
+ return false;
3207
+ }
3208
+ const status = this.lib.audioStopVoice(engine2, voice);
3209
+ if (status !== 0) {
3210
+ this.emitError("stopVoice", status);
3211
+ return false;
3212
+ }
3213
+ return true;
3214
+ }
3215
+ setVoiceGroup(voice, group) {
3216
+ const engine2 = this.engine;
3217
+ if (!engine2) {
3218
+ this.emitError("setVoiceGroup", undefined, "Audio engine unavailable during setVoiceGroup");
3219
+ return false;
3220
+ }
3221
+ const status = this.lib.audioSetVoiceGroup(engine2, voice, group);
3222
+ if (status !== 0) {
3223
+ this.emitError("setVoiceGroup", status);
3224
+ return false;
3225
+ }
3226
+ return true;
3227
+ }
3228
+ setGroupVolume(group, volume) {
3229
+ const engine2 = this.engine;
3230
+ if (!engine2) {
3231
+ this.emitError("setGroupVolume", undefined, "Audio engine unavailable during setGroupVolume");
3232
+ return false;
3233
+ }
3234
+ const status = this.lib.audioSetGroupVolume(engine2, group, volume);
3235
+ if (status !== 0) {
3236
+ this.emitError("setGroupVolume", status);
3237
+ return false;
3238
+ }
3239
+ return true;
3240
+ }
3241
+ setMasterVolume(volume) {
3242
+ const engine2 = this.engine;
3243
+ if (!engine2) {
3244
+ this.emitError("setMasterVolume", undefined, "Audio engine unavailable during setMasterVolume");
3245
+ return false;
3246
+ }
3247
+ const status = this.lib.audioSetMasterVolume(engine2, volume);
3248
+ if (status !== 0) {
3249
+ this.emitError("setMasterVolume", status);
3250
+ return false;
3251
+ }
3252
+ return true;
3253
+ }
3254
+ mixFrames(frameCount, channels = 2) {
3255
+ const engine2 = this.engine;
3256
+ if (!engine2) {
3257
+ this.emitError("mixFrames", undefined, "Audio engine unavailable during mixFrames");
3258
+ return null;
3259
+ }
3260
+ const output = new Float32Array(frameCount * channels);
3261
+ const status = this.lib.audioMixToBuffer(engine2, output, frameCount, channels);
3262
+ if (status !== 0) {
3263
+ this.emitError("mixFrames", status);
3264
+ return null;
3265
+ }
3266
+ return output;
3267
+ }
3268
+ enableTap(capacityFrames = 8192) {
3269
+ const engine2 = this.engine;
3270
+ if (!engine2) {
3271
+ this.emitError("enableTap", undefined, "Audio engine unavailable during enableTap");
3272
+ return false;
3273
+ }
3274
+ const status = this.lib.audioEnableTap(engine2, true, capacityFrames);
3275
+ if (status !== 0) {
3276
+ this.emitError("enableTap", status);
3277
+ return false;
3278
+ }
3279
+ return true;
3280
+ }
3281
+ disableTap() {
3282
+ const engine2 = this.engine;
3283
+ if (!engine2) {
3284
+ this.emitError("enableTap", undefined, "Audio engine unavailable during disableTap");
3285
+ return false;
3286
+ }
3287
+ const status = this.lib.audioEnableTap(engine2, false, 0);
3288
+ if (status !== 0) {
3289
+ this.emitError("enableTap", status);
3290
+ return false;
3291
+ }
3292
+ return true;
3293
+ }
3294
+ readTapFrames(frameCount, channels = 2) {
3295
+ const engine2 = this.engine;
3296
+ if (!engine2) {
3297
+ this.emitError("readTapFrames", undefined, "Audio engine unavailable during readTapFrames");
3298
+ return null;
3299
+ }
3300
+ const output = new Float32Array(frameCount * channels);
3301
+ const result = this.lib.audioReadTap(engine2, output, frameCount, channels);
3302
+ if (result.status !== 0) {
3303
+ this.emitError("readTapFrames", result.status);
3304
+ return null;
3305
+ }
3306
+ return { frames: output, framesRead: result.framesRead };
3307
+ }
3308
+ listPlaybackDevices() {
3309
+ const engine2 = this.engine;
3310
+ if (!engine2) {
3311
+ this.emitError("listPlaybackDevices", undefined, "Audio engine unavailable during listPlaybackDevices");
3312
+ return null;
3313
+ }
3314
+ const refreshStatus = this.lib.audioRefreshPlaybackDevices(engine2);
3315
+ if (refreshStatus !== 0) {
3316
+ this.emitError("listPlaybackDevices", refreshStatus);
3317
+ return null;
3318
+ }
3319
+ const count = this.lib.audioGetPlaybackDeviceCount(engine2);
3320
+ const devices = [];
3321
+ for (let index = 0;index < count; index += 1) {
3322
+ devices.push({
3323
+ index,
3324
+ name: this.lib.audioGetPlaybackDeviceName(engine2, index),
3325
+ isDefault: this.lib.audioIsPlaybackDeviceDefault(engine2, index)
3326
+ });
3327
+ }
3328
+ return devices;
3329
+ }
3330
+ selectPlaybackDevice(index) {
3331
+ const engine2 = this.engine;
3332
+ if (!engine2) {
3333
+ this.emitError("selectPlaybackDevice", undefined, "Audio engine unavailable during selectPlaybackDevice");
3334
+ return false;
3335
+ }
3336
+ const refreshStatus = this.lib.audioRefreshPlaybackDevices(engine2);
3337
+ if (refreshStatus !== 0) {
3338
+ this.emitError("selectPlaybackDevice", refreshStatus);
3339
+ return false;
3340
+ }
3341
+ const status = this.lib.audioSelectPlaybackDevice(engine2, index);
3342
+ if (status !== 0) {
3343
+ this.emitError("selectPlaybackDevice", status);
3344
+ return false;
3345
+ }
3346
+ return true;
3347
+ }
3348
+ clearPlaybackDeviceSelection() {
3349
+ const engine2 = this.engine;
3350
+ if (!engine2) {
3351
+ this.emitError("clearPlaybackDeviceSelection", undefined, "Audio engine unavailable during clearPlaybackDeviceSelection");
3352
+ return;
3353
+ }
3354
+ this.lib.audioClearPlaybackDeviceSelection(engine2);
3355
+ }
3356
+ getStats() {
3357
+ const engine2 = this.engine;
3358
+ if (!engine2) {
3359
+ this.emitError("getStats", undefined, "Audio engine unavailable during getStats");
3360
+ return null;
3361
+ }
3362
+ const stats = this.lib.audioGetStats(engine2);
3363
+ if (stats == null) {
3364
+ this.emitError("getStats", undefined, "Failed to retrieve audio stats");
3365
+ }
3366
+ return stats;
3367
+ }
3368
+ dispose() {
3369
+ if (!this.engine)
3370
+ return;
3371
+ if (this.mixerStarted) {
3372
+ this.stop();
3373
+ }
3374
+ this.groups.clear();
3375
+ this.lib.destroyAudioEngine(this.engine);
3376
+ this.engine = null;
3377
+ this.emit("disposed");
3378
+ }
3379
+ }
3380
+ function setupAudio(options = {}) {
3381
+ return Audio.create(options);
3382
+ }
3322
3383
  // src/renderables/FrameBuffer.ts
3323
3384
  class FrameBufferRenderable extends Renderable {
3324
3385
  frameBuffer;
@@ -3506,1139 +3567,9 @@ class ASCIIFontRenderable extends FrameBufferRenderable {
3506
3567
  }
3507
3568
  }
3508
3569
  }
3509
- // src/renderables/Box.ts
3510
- function isGapType(value) {
3511
- if (value === undefined) {
3512
- return true;
3513
- }
3514
- if (typeof value === "number" && !Number.isNaN(value)) {
3515
- return true;
3516
- }
3517
- return isValidPercentage(value);
3518
- }
3519
-
3520
- class BoxRenderable extends Renderable {
3521
- _backgroundColor;
3522
- _border;
3523
- _borderStyle;
3524
- _borderColor;
3525
- _focusedBorderColor;
3526
- _customBorderCharsObj;
3527
- _customBorderChars;
3528
- borderSides;
3529
- shouldFill;
3530
- _title;
3531
- _titleAlignment;
3532
- _bottomTitle;
3533
- _bottomTitleAlignment;
3534
- _defaultOptions = {
3535
- backgroundColor: "transparent",
3536
- borderStyle: "single",
3537
- border: false,
3538
- borderColor: "#FFFFFF",
3539
- shouldFill: true,
3540
- titleAlignment: "left",
3541
- bottomTitleAlignment: "left",
3542
- focusedBorderColor: "#00AAFF"
3543
- };
3544
- constructor(ctx, options) {
3545
- super(ctx, options);
3546
- if (options.focusable === true) {
3547
- this._focusable = true;
3548
- }
3549
- this._backgroundColor = parseColor(options.backgroundColor || this._defaultOptions.backgroundColor);
3550
- this._border = options.border ?? this._defaultOptions.border;
3551
- if (!options.border && (options.borderStyle || options.borderColor || options.focusedBorderColor || options.customBorderChars)) {
3552
- this._border = true;
3553
- }
3554
- this._borderStyle = parseBorderStyle(options.borderStyle, this._defaultOptions.borderStyle);
3555
- this._borderColor = parseColor(options.borderColor || this._defaultOptions.borderColor);
3556
- this._focusedBorderColor = parseColor(options.focusedBorderColor || this._defaultOptions.focusedBorderColor);
3557
- this._customBorderCharsObj = options.customBorderChars;
3558
- this._customBorderChars = this._customBorderCharsObj ? borderCharsToArray(this._customBorderCharsObj) : undefined;
3559
- this.borderSides = getBorderSides(this._border);
3560
- this.shouldFill = options.shouldFill ?? this._defaultOptions.shouldFill;
3561
- this._title = options.title;
3562
- this._titleAlignment = options.titleAlignment || this._defaultOptions.titleAlignment;
3563
- this._bottomTitle = options.bottomTitle;
3564
- this._bottomTitleAlignment = options.bottomTitleAlignment || this._defaultOptions.bottomTitleAlignment;
3565
- this.applyYogaBorders();
3566
- const hasInitialGapProps = options.gap !== undefined || options.rowGap !== undefined || options.columnGap !== undefined;
3567
- if (hasInitialGapProps) {
3568
- this.applyYogaGap(options);
3569
- }
3570
- }
3571
- initializeBorder() {
3572
- if (this._border === false) {
3573
- this._border = true;
3574
- this.borderSides = getBorderSides(this._border);
3575
- this.applyYogaBorders();
3576
- }
3577
- }
3578
- get customBorderChars() {
3579
- return this._customBorderCharsObj;
3580
- }
3581
- set customBorderChars(value) {
3582
- this._customBorderCharsObj = value;
3583
- this._customBorderChars = value ? borderCharsToArray(value) : undefined;
3584
- this.requestRender();
3585
- }
3586
- get backgroundColor() {
3587
- return this._backgroundColor;
3588
- }
3589
- set backgroundColor(value) {
3590
- const newColor = parseColor(value ?? this._defaultOptions.backgroundColor);
3591
- if (this._backgroundColor !== newColor) {
3592
- this._backgroundColor = newColor;
3593
- this.requestRender();
3594
- }
3595
- }
3596
- get border() {
3597
- return this._border;
3598
- }
3599
- set border(value) {
3600
- if (this._border !== value) {
3601
- this._border = value;
3602
- this.borderSides = getBorderSides(value);
3603
- this.applyYogaBorders();
3604
- this.requestRender();
3605
- }
3606
- }
3607
- get borderStyle() {
3608
- return this._borderStyle;
3609
- }
3610
- set borderStyle(value) {
3611
- const _value = parseBorderStyle(value, this._defaultOptions.borderStyle);
3612
- if (this._borderStyle !== _value || !this._border) {
3613
- this._borderStyle = _value;
3614
- this._customBorderChars = undefined;
3615
- this.initializeBorder();
3616
- this.requestRender();
3617
- }
3618
- }
3619
- get borderColor() {
3620
- return this._borderColor;
3621
- }
3622
- set borderColor(value) {
3623
- const newColor = parseColor(value ?? this._defaultOptions.borderColor);
3624
- if (this._borderColor !== newColor) {
3625
- this._borderColor = newColor;
3626
- this.initializeBorder();
3627
- this.requestRender();
3628
- }
3629
- }
3630
- get focusedBorderColor() {
3631
- return this._focusedBorderColor;
3632
- }
3633
- set focusedBorderColor(value) {
3634
- const newColor = parseColor(value ?? this._defaultOptions.focusedBorderColor);
3635
- if (this._focusedBorderColor !== newColor) {
3636
- this._focusedBorderColor = newColor;
3637
- this.initializeBorder();
3638
- if (this._focused) {
3639
- this.requestRender();
3640
- }
3641
- }
3642
- }
3643
- get title() {
3644
- return this._title;
3645
- }
3646
- set title(value) {
3647
- if (this._title !== value) {
3648
- this._title = value;
3649
- this.requestRender();
3650
- }
3651
- }
3652
- get titleAlignment() {
3653
- return this._titleAlignment;
3654
- }
3655
- set titleAlignment(value) {
3656
- if (this._titleAlignment !== value) {
3657
- this._titleAlignment = value;
3658
- this.requestRender();
3659
- }
3660
- }
3661
- get bottomTitle() {
3662
- return this._bottomTitle;
3663
- }
3664
- set bottomTitle(value) {
3665
- if (this._bottomTitle !== value) {
3666
- this._bottomTitle = value;
3667
- this.requestRender();
3668
- }
3669
- }
3670
- get bottomTitleAlignment() {
3671
- return this._bottomTitleAlignment;
3672
- }
3673
- set bottomTitleAlignment(value) {
3674
- if (this._bottomTitleAlignment !== value) {
3675
- this._bottomTitleAlignment = value;
3676
- this.requestRender();
3677
- }
3678
- }
3679
- renderSelf(buffer) {
3680
- const currentBorderColor = this._focused ? this._focusedBorderColor : this._borderColor;
3681
- buffer.drawBox({
3682
- x: this.x,
3683
- y: this.y,
3684
- width: this.width,
3685
- height: this.height,
3686
- borderStyle: this._borderStyle,
3687
- customBorderChars: this._customBorderChars,
3688
- border: this._border,
3689
- borderColor: currentBorderColor,
3690
- backgroundColor: this._backgroundColor,
3691
- shouldFill: this.shouldFill,
3692
- title: this._title,
3693
- titleAlignment: this._titleAlignment,
3694
- bottomTitle: this._bottomTitle,
3695
- bottomTitleAlignment: this._bottomTitleAlignment
3696
- });
3697
- }
3698
- getScissorRect() {
3699
- const baseRect = super.getScissorRect();
3700
- if (!this.borderSides.top && !this.borderSides.right && !this.borderSides.bottom && !this.borderSides.left) {
3701
- return baseRect;
3702
- }
3703
- const leftInset = this.borderSides.left ? 1 : 0;
3704
- const rightInset = this.borderSides.right ? 1 : 0;
3705
- const topInset = this.borderSides.top ? 1 : 0;
3706
- const bottomInset = this.borderSides.bottom ? 1 : 0;
3707
- return {
3708
- x: baseRect.x + leftInset,
3709
- y: baseRect.y + topInset,
3710
- width: Math.max(0, baseRect.width - leftInset - rightInset),
3711
- height: Math.max(0, baseRect.height - topInset - bottomInset)
3712
- };
3713
- }
3714
- applyYogaBorders() {
3715
- const node = this.yogaNode;
3716
- node.setBorder(Edge.Left, this.borderSides.left ? 1 : 0);
3717
- node.setBorder(Edge.Right, this.borderSides.right ? 1 : 0);
3718
- node.setBorder(Edge.Top, this.borderSides.top ? 1 : 0);
3719
- node.setBorder(Edge.Bottom, this.borderSides.bottom ? 1 : 0);
3720
- this.requestRender();
3721
- }
3722
- applyYogaGap(options) {
3723
- const node = this.yogaNode;
3724
- if (isGapType(options.gap)) {
3725
- node.setGap(Gutter.All, options.gap);
3726
- }
3727
- if (isGapType(options.rowGap)) {
3728
- node.setGap(Gutter.Row, options.rowGap);
3729
- }
3730
- if (isGapType(options.columnGap)) {
3731
- node.setGap(Gutter.Column, options.columnGap);
3732
- }
3733
- }
3734
- set gap(gap) {
3735
- if (isGapType(gap)) {
3736
- this.yogaNode.setGap(Gutter.All, gap);
3737
- this.requestRender();
3738
- }
3739
- }
3740
- set rowGap(rowGap) {
3741
- if (isGapType(rowGap)) {
3742
- this.yogaNode.setGap(Gutter.Row, rowGap);
3743
- this.requestRender();
3744
- }
3745
- }
3746
- set columnGap(columnGap) {
3747
- if (isGapType(columnGap)) {
3748
- this.yogaNode.setGap(Gutter.Column, columnGap);
3749
- this.requestRender();
3750
- }
3751
- }
3752
- }
3753
- // src/renderables/TextBufferRenderable.ts
3754
- class TextBufferRenderable extends Renderable {
3755
- selectable = true;
3756
- _defaultFg;
3757
- _defaultBg;
3758
- _defaultAttributes;
3759
- _selectionBg;
3760
- _selectionFg;
3761
- _wrapMode = "word";
3762
- lastLocalSelection = null;
3763
- _tabIndicator;
3764
- _tabIndicatorColor;
3765
- _scrollX = 0;
3766
- _scrollY = 0;
3767
- _truncate = false;
3768
- textBuffer;
3769
- textBufferView;
3770
- _textBufferSyntaxStyle;
3771
- _defaultOptions = {
3772
- fg: RGBA.fromValues(1, 1, 1, 1),
3773
- bg: RGBA.fromValues(0, 0, 0, 0),
3774
- selectionBg: undefined,
3775
- selectionFg: undefined,
3776
- selectable: true,
3777
- attributes: 0,
3778
- wrapMode: "word",
3779
- tabIndicator: undefined,
3780
- tabIndicatorColor: undefined,
3781
- truncate: false
3782
- };
3783
- constructor(ctx, options) {
3784
- super(ctx, options);
3785
- this._defaultFg = parseColor(options.fg ?? this._defaultOptions.fg);
3786
- this._defaultBg = parseColor(options.bg ?? this._defaultOptions.bg);
3787
- this._defaultAttributes = options.attributes ?? this._defaultOptions.attributes;
3788
- this._selectionBg = options.selectionBg ? parseColor(options.selectionBg) : this._defaultOptions.selectionBg;
3789
- this._selectionFg = options.selectionFg ? parseColor(options.selectionFg) : this._defaultOptions.selectionFg;
3790
- this.selectable = options.selectable ?? this._defaultOptions.selectable;
3791
- this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
3792
- this._tabIndicator = options.tabIndicator ?? this._defaultOptions.tabIndicator;
3793
- this._tabIndicatorColor = options.tabIndicatorColor ? parseColor(options.tabIndicatorColor) : this._defaultOptions.tabIndicatorColor;
3794
- this._truncate = options.truncate ?? this._defaultOptions.truncate;
3795
- this.textBuffer = TextBuffer.create(this._ctx.widthMethod);
3796
- this.textBufferView = TextBufferView.create(this.textBuffer);
3797
- this._textBufferSyntaxStyle = SyntaxStyle.create();
3798
- this.textBuffer.setSyntaxStyle(this._textBufferSyntaxStyle);
3799
- this.textBufferView.setWrapMode(this._wrapMode);
3800
- this.setupMeasureFunc();
3801
- this.textBuffer.setDefaultFg(this._defaultFg);
3802
- this.textBuffer.setDefaultBg(this._defaultBg);
3803
- this.textBuffer.setDefaultAttributes(this._defaultAttributes);
3804
- if (this._tabIndicator !== undefined) {
3805
- this.textBufferView.setTabIndicator(this._tabIndicator);
3806
- }
3807
- if (this._tabIndicatorColor !== undefined) {
3808
- this.textBufferView.setTabIndicatorColor(this._tabIndicatorColor);
3809
- }
3810
- if (this._wrapMode !== "none" && this.width > 0) {
3811
- this.textBufferView.setWrapWidth(this.width);
3812
- }
3813
- if (this.width > 0 && this.height > 0) {
3814
- this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
3815
- }
3816
- this.textBufferView.setTruncate(this._truncate);
3817
- this.updateTextInfo();
3818
- }
3819
- onMouseEvent(event) {
3820
- if (event.type === "scroll") {
3821
- this.handleScroll(event);
3822
- }
3823
- }
3824
- handleScroll(event) {
3825
- if (!event.scroll)
3826
- return;
3827
- const { direction, delta } = event.scroll;
3828
- if (direction === "up") {
3829
- this.scrollY -= delta;
3830
- } else if (direction === "down") {
3831
- this.scrollY += delta;
3832
- }
3833
- if (this._wrapMode === "none") {
3834
- if (direction === "left") {
3835
- this.scrollX -= delta;
3836
- } else if (direction === "right") {
3837
- this.scrollX += delta;
3838
- }
3839
- }
3840
- }
3841
- get lineInfo() {
3842
- return this.textBufferView.logicalLineInfo;
3843
- }
3844
- get lineCount() {
3845
- return this.textBuffer.getLineCount();
3846
- }
3847
- get virtualLineCount() {
3848
- return this.textBufferView.getVirtualLineCount();
3849
- }
3850
- get scrollY() {
3851
- return this._scrollY;
3852
- }
3853
- set scrollY(value) {
3854
- const maxScrollY = Math.max(0, this.scrollHeight - this.height);
3855
- const clamped = Math.max(0, Math.min(value, maxScrollY));
3856
- if (this._scrollY !== clamped) {
3857
- this._scrollY = clamped;
3858
- this.updateViewportOffset();
3859
- this.requestRender();
3860
- }
3861
- }
3862
- get scrollX() {
3863
- return this._scrollX;
3864
- }
3865
- set scrollX(value) {
3866
- const maxScrollX = Math.max(0, this.scrollWidth - this.width);
3867
- const clamped = Math.max(0, Math.min(value, maxScrollX));
3868
- if (this._scrollX !== clamped) {
3869
- this._scrollX = clamped;
3870
- this.updateViewportOffset();
3871
- this.requestRender();
3872
- }
3873
- }
3874
- get scrollWidth() {
3875
- return this.lineInfo.lineWidthColsMax;
3876
- }
3877
- get scrollHeight() {
3878
- return this.lineInfo.lineStartCols.length;
3879
- }
3880
- get maxScrollY() {
3881
- return Math.max(0, this.scrollHeight - this.height);
3882
- }
3883
- get maxScrollX() {
3884
- return Math.max(0, this.scrollWidth - this.width);
3885
- }
3886
- updateViewportOffset() {
3887
- if (this.width > 0 && this.height > 0) {
3888
- this.textBufferView.setViewport(this._scrollX, this._scrollY, this.width, this.height);
3889
- }
3890
- }
3891
- get plainText() {
3892
- return this.textBuffer.getPlainText();
3893
- }
3894
- get textLength() {
3895
- return this.textBuffer.length;
3896
- }
3897
- get fg() {
3898
- return this._defaultFg;
3899
- }
3900
- set fg(value) {
3901
- const newColor = parseColor(value ?? this._defaultOptions.fg);
3902
- if (this._defaultFg !== newColor) {
3903
- this._defaultFg = newColor;
3904
- this.textBuffer.setDefaultFg(this._defaultFg);
3905
- this.onFgChanged(newColor);
3906
- this.requestRender();
3907
- }
3908
- }
3909
- get selectionBg() {
3910
- return this._selectionBg;
3911
- }
3912
- set selectionBg(value) {
3913
- const newColor = value ? parseColor(value) : this._defaultOptions.selectionBg;
3914
- if (this._selectionBg !== newColor) {
3915
- this._selectionBg = newColor;
3916
- if (this.lastLocalSelection) {
3917
- this.updateLocalSelection(this.lastLocalSelection);
3918
- }
3919
- this.requestRender();
3920
- }
3921
- }
3922
- get selectionFg() {
3923
- return this._selectionFg;
3924
- }
3925
- set selectionFg(value) {
3926
- const newColor = value ? parseColor(value) : this._defaultOptions.selectionFg;
3927
- if (this._selectionFg !== newColor) {
3928
- this._selectionFg = newColor;
3929
- if (this.lastLocalSelection) {
3930
- this.updateLocalSelection(this.lastLocalSelection);
3931
- }
3932
- this.requestRender();
3933
- }
3934
- }
3935
- get bg() {
3936
- return this._defaultBg;
3937
- }
3938
- set bg(value) {
3939
- const newColor = parseColor(value ?? this._defaultOptions.bg);
3940
- if (this._defaultBg !== newColor) {
3941
- this._defaultBg = newColor;
3942
- this.textBuffer.setDefaultBg(this._defaultBg);
3943
- this.onBgChanged(newColor);
3944
- this.requestRender();
3945
- }
3946
- }
3947
- get attributes() {
3948
- return this._defaultAttributes;
3949
- }
3950
- set attributes(value) {
3951
- if (this._defaultAttributes !== value) {
3952
- this._defaultAttributes = value;
3953
- this.textBuffer.setDefaultAttributes(this._defaultAttributes);
3954
- this.onAttributesChanged(value);
3955
- this.requestRender();
3956
- }
3957
- }
3958
- get wrapMode() {
3959
- return this._wrapMode;
3960
- }
3961
- set wrapMode(value) {
3962
- if (this._wrapMode !== value) {
3963
- this._wrapMode = value;
3964
- this.textBufferView.setWrapMode(this._wrapMode);
3965
- if (value !== "none" && this.width > 0) {
3966
- this.textBufferView.setWrapWidth(this.width);
3967
- }
3968
- this.yogaNode.markDirty();
3969
- this.requestRender();
3970
- }
3971
- }
3972
- get tabIndicator() {
3973
- return this._tabIndicator;
3974
- }
3975
- set tabIndicator(value) {
3976
- if (this._tabIndicator !== value) {
3977
- this._tabIndicator = value;
3978
- if (value !== undefined) {
3979
- this.textBufferView.setTabIndicator(value);
3980
- }
3981
- this.requestRender();
3982
- }
3983
- }
3984
- get tabIndicatorColor() {
3985
- return this._tabIndicatorColor;
3986
- }
3987
- set tabIndicatorColor(value) {
3988
- const newColor = value ? parseColor(value) : undefined;
3989
- if (this._tabIndicatorColor !== newColor) {
3990
- this._tabIndicatorColor = newColor;
3991
- if (newColor !== undefined) {
3992
- this.textBufferView.setTabIndicatorColor(newColor);
3993
- }
3994
- this.requestRender();
3995
- }
3996
- }
3997
- get truncate() {
3998
- return this._truncate;
3999
- }
4000
- set truncate(value) {
4001
- if (this._truncate !== value) {
4002
- this._truncate = value;
4003
- this.textBufferView.setTruncate(value);
4004
- this.requestRender();
4005
- }
4006
- }
4007
- onResize(width, height) {
4008
- this.textBufferView.setViewport(this._scrollX, this._scrollY, width, height);
4009
- this.yogaNode.markDirty();
4010
- this.requestRender();
4011
- this.emit("line-info-change");
4012
- }
4013
- refreshLocalSelection() {
4014
- if (this.lastLocalSelection) {
4015
- return this.updateLocalSelection(this.lastLocalSelection);
4016
- }
4017
- return false;
4018
- }
4019
- updateLocalSelection(localSelection) {
4020
- if (!localSelection?.isActive) {
4021
- this.textBufferView.resetLocalSelection();
4022
- return true;
4023
- }
4024
- return this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
4025
- }
4026
- updateTextInfo() {
4027
- if (this.lastLocalSelection) {
4028
- this.updateLocalSelection(this.lastLocalSelection);
4029
- }
4030
- this.yogaNode.markDirty();
4031
- this.requestRender();
4032
- this.emit("line-info-change");
4033
- }
4034
- setupMeasureFunc() {
4035
- const measureFunc = (width, widthMode, height, heightMode) => {
4036
- let effectiveWidth;
4037
- if (widthMode === MeasureMode.Undefined || isNaN(width)) {
4038
- effectiveWidth = 0;
4039
- } else {
4040
- effectiveWidth = width;
4041
- }
4042
- const effectiveHeight = isNaN(height) ? 1 : height;
4043
- const measureResult = this.textBufferView.measureForDimensions(Math.floor(effectiveWidth), Math.floor(effectiveHeight));
4044
- const measuredWidth = measureResult ? Math.max(1, measureResult.widthColsMax) : 1;
4045
- const measuredHeight = measureResult ? Math.max(1, measureResult.lineCount) : 1;
4046
- if (widthMode === MeasureMode.AtMost && this._positionType !== "absolute") {
4047
- return {
4048
- width: Math.min(effectiveWidth, measuredWidth),
4049
- height: Math.min(effectiveHeight, measuredHeight)
4050
- };
4051
- }
4052
- return {
4053
- width: measuredWidth,
4054
- height: measuredHeight
4055
- };
4056
- };
4057
- this.yogaNode.setMeasureFunc(measureFunc);
4058
- }
4059
- shouldStartSelection(x, y) {
4060
- if (!this.selectable)
4061
- return false;
4062
- const localX = x - this.x;
4063
- const localY = y - this.y;
4064
- return localX >= 0 && localX < this.width && localY >= 0 && localY < this.height;
4065
- }
4066
- onSelectionChanged(selection) {
4067
- const localSelection = convertGlobalToLocalSelection(selection, this.x, this.y);
4068
- this.lastLocalSelection = localSelection;
4069
- let changed;
4070
- if (!localSelection?.isActive) {
4071
- this.textBufferView.resetLocalSelection();
4072
- changed = true;
4073
- } else if (selection?.isStart) {
4074
- changed = this.textBufferView.setLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
4075
- } else {
4076
- changed = this.textBufferView.updateLocalSelection(localSelection.anchorX, localSelection.anchorY, localSelection.focusX, localSelection.focusY, this._selectionBg, this._selectionFg);
4077
- }
4078
- if (changed) {
4079
- this.requestRender();
4080
- }
4081
- return this.hasSelection();
4082
- }
4083
- getSelectedText() {
4084
- return this.textBufferView.getSelectedText();
4085
- }
4086
- hasSelection() {
4087
- return this.textBufferView.hasSelection();
4088
- }
4089
- getSelection() {
4090
- return this.textBufferView.getSelection();
4091
- }
4092
- render(buffer, deltaTime) {
4093
- if (!this.visible)
4094
- return;
4095
- this.markClean();
4096
- this._ctx.addToHitGrid(this.x, this.y, this.width, this.height, this.num);
4097
- this.renderSelf(buffer);
4098
- if (this.buffered && this.frameBuffer) {
4099
- buffer.drawFrameBuffer(this.x, this.y, this.frameBuffer);
4100
- }
4101
- }
4102
- renderSelf(buffer) {
4103
- if (this.textBuffer.ptr) {
4104
- buffer.drawTextBuffer(this.textBufferView, this.x, this.y);
4105
- }
4106
- }
4107
- destroy() {
4108
- if (this.isDestroyed)
4109
- return;
4110
- this.textBuffer.setSyntaxStyle(null);
4111
- this._textBufferSyntaxStyle.destroy();
4112
- this.textBufferView.destroy();
4113
- this.textBuffer.destroy();
4114
- super.destroy();
4115
- }
4116
- onFgChanged(newColor) {}
4117
- onBgChanged(newColor) {}
4118
- onAttributesChanged(newAttributes) {}
4119
- }
4120
-
4121
- // src/renderables/Code.ts
4122
- class CodeRenderable extends TextBufferRenderable {
4123
- _content;
4124
- _filetype;
4125
- _syntaxStyle;
4126
- _isHighlighting = false;
4127
- _treeSitterClient;
4128
- _highlightsDirty = false;
4129
- _highlightSnapshotId = 0;
4130
- _conceal;
4131
- _drawUnstyledText;
4132
- _shouldRenderTextBuffer = true;
4133
- _streaming;
4134
- _hadInitialContent = false;
4135
- _lastHighlights = [];
4136
- _onHighlight;
4137
- _onChunks;
4138
- _highlightingPromise = Promise.resolve();
4139
- _contentDefaultOptions = {
4140
- content: "",
4141
- conceal: true,
4142
- drawUnstyledText: true,
4143
- streaming: false
4144
- };
4145
- constructor(ctx, options) {
4146
- super(ctx, options);
4147
- this._content = options.content ?? this._contentDefaultOptions.content;
4148
- this._filetype = options.filetype;
4149
- this._syntaxStyle = options.syntaxStyle;
4150
- this._treeSitterClient = options.treeSitterClient ?? getTreeSitterClient();
4151
- this._conceal = options.conceal ?? this._contentDefaultOptions.conceal;
4152
- this._drawUnstyledText = options.drawUnstyledText ?? this._contentDefaultOptions.drawUnstyledText;
4153
- this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
4154
- this._onHighlight = options.onHighlight;
4155
- this._onChunks = options.onChunks;
4156
- if (this._content.length > 0) {
4157
- this.textBuffer.setText(this._content);
4158
- this.updateTextInfo();
4159
- this._shouldRenderTextBuffer = this._drawUnstyledText || !this._filetype;
4160
- }
4161
- this._highlightsDirty = this._content.length > 0;
4162
- }
4163
- get content() {
4164
- return this._content;
4165
- }
4166
- set content(value) {
4167
- if (this._content !== value) {
4168
- this._content = value;
4169
- this._highlightsDirty = true;
4170
- this._highlightSnapshotId++;
4171
- if (this._streaming && !this._drawUnstyledText && this._filetype) {
4172
- return;
4173
- }
4174
- this.textBuffer.setText(value);
4175
- this.updateTextInfo();
4176
- }
4177
- }
4178
- get filetype() {
4179
- return this._filetype;
4180
- }
4181
- set filetype(value) {
4182
- if (this._filetype !== value) {
4183
- this._filetype = value;
4184
- this._highlightsDirty = true;
4185
- }
4186
- }
4187
- get syntaxStyle() {
4188
- return this._syntaxStyle;
4189
- }
4190
- set syntaxStyle(value) {
4191
- if (this._syntaxStyle !== value) {
4192
- this._syntaxStyle = value;
4193
- this._highlightsDirty = true;
4194
- }
4195
- }
4196
- get conceal() {
4197
- return this._conceal;
4198
- }
4199
- set conceal(value) {
4200
- if (this._conceal !== value) {
4201
- this._conceal = value;
4202
- this._highlightsDirty = true;
4203
- }
4204
- }
4205
- get drawUnstyledText() {
4206
- return this._drawUnstyledText;
4207
- }
4208
- set drawUnstyledText(value) {
4209
- if (this._drawUnstyledText !== value) {
4210
- this._drawUnstyledText = value;
4211
- this._highlightsDirty = true;
4212
- }
4213
- }
4214
- get streaming() {
4215
- return this._streaming;
4216
- }
4217
- set streaming(value) {
4218
- if (this._streaming !== value) {
4219
- this._streaming = value;
4220
- this._hadInitialContent = false;
4221
- this._lastHighlights = [];
4222
- this._highlightsDirty = true;
4223
- }
4224
- }
4225
- get treeSitterClient() {
4226
- return this._treeSitterClient;
4227
- }
4228
- set treeSitterClient(value) {
4229
- if (this._treeSitterClient !== value) {
4230
- this._treeSitterClient = value;
4231
- this._highlightsDirty = true;
4232
- }
4233
- }
4234
- get onHighlight() {
4235
- return this._onHighlight;
4236
- }
4237
- set onHighlight(value) {
4238
- if (this._onHighlight !== value) {
4239
- this._onHighlight = value;
4240
- this._highlightsDirty = true;
4241
- }
4242
- }
4243
- get onChunks() {
4244
- return this._onChunks;
4245
- }
4246
- set onChunks(value) {
4247
- if (this._onChunks !== value) {
4248
- this._onChunks = value;
4249
- this._highlightsDirty = true;
4250
- }
4251
- }
4252
- get isHighlighting() {
4253
- return this._isHighlighting;
4254
- }
4255
- get highlightingDone() {
4256
- return this._highlightingPromise;
4257
- }
4258
- async transformChunks(chunks, context) {
4259
- if (!this._onChunks)
4260
- return chunks;
4261
- const modified = await this._onChunks(chunks, context);
4262
- return modified ?? chunks;
4263
- }
4264
- ensureVisibleTextBeforeHighlight() {
4265
- if (this.isDestroyed)
4266
- return;
4267
- const content = this._content;
4268
- if (!this._filetype) {
4269
- this._shouldRenderTextBuffer = true;
4270
- return;
4271
- }
4272
- const isInitialContent = this._streaming && !this._hadInitialContent;
4273
- const shouldDrawUnstyledNow = this._streaming ? isInitialContent && this._drawUnstyledText : this._drawUnstyledText;
4274
- if (this._streaming && !isInitialContent) {
4275
- this._shouldRenderTextBuffer = true;
4276
- } else if (shouldDrawUnstyledNow) {
4277
- this.textBuffer.setText(content);
4278
- this._shouldRenderTextBuffer = true;
4279
- } else {
4280
- this._shouldRenderTextBuffer = false;
4281
- }
4282
- }
4283
- async startHighlight() {
4284
- const content = this._content;
4285
- const filetype = this._filetype;
4286
- const snapshotId = ++this._highlightSnapshotId;
4287
- if (!filetype)
4288
- return;
4289
- const isInitialContent = this._streaming && !this._hadInitialContent;
4290
- if (isInitialContent) {
4291
- this._hadInitialContent = true;
4292
- }
4293
- this._isHighlighting = true;
4294
- try {
4295
- const result = await this._treeSitterClient.highlightOnce(content, filetype);
4296
- if (snapshotId !== this._highlightSnapshotId) {
4297
- return;
4298
- }
4299
- if (this.isDestroyed)
4300
- return;
4301
- let highlights = result.highlights ?? [];
4302
- if (this._onHighlight && highlights.length >= 0) {
4303
- const context = {
4304
- content,
4305
- filetype,
4306
- syntaxStyle: this._syntaxStyle
4307
- };
4308
- const modified = await this._onHighlight(highlights, context);
4309
- if (modified !== undefined) {
4310
- highlights = modified;
4311
- }
4312
- }
4313
- if (snapshotId !== this._highlightSnapshotId) {
4314
- return;
4315
- }
4316
- if (this.isDestroyed)
4317
- return;
4318
- if (highlights.length > 0) {
4319
- if (this._streaming) {
4320
- this._lastHighlights = highlights;
4321
- }
4322
- }
4323
- if (highlights.length > 0 || this._onChunks) {
4324
- const context = {
4325
- content,
4326
- filetype,
4327
- syntaxStyle: this._syntaxStyle,
4328
- highlights
4329
- };
4330
- let chunks = treeSitterToTextChunks(content, highlights, this._syntaxStyle, {
4331
- enabled: this._conceal
4332
- });
4333
- chunks = await this.transformChunks(chunks, context);
4334
- if (snapshotId !== this._highlightSnapshotId) {
4335
- return;
4336
- }
4337
- if (this.isDestroyed)
4338
- return;
4339
- const styledText = new StyledText(chunks);
4340
- this.textBuffer.setStyledText(styledText);
4341
- } else {
4342
- this.textBuffer.setText(content);
4343
- }
4344
- this._shouldRenderTextBuffer = true;
4345
- this._isHighlighting = false;
4346
- this._highlightsDirty = false;
4347
- this.updateTextInfo();
4348
- this.requestRender();
4349
- } catch (error) {
4350
- if (snapshotId !== this._highlightSnapshotId) {
4351
- return;
4352
- }
4353
- console.warn("Code highlighting failed, falling back to plain text:", error);
4354
- if (this.isDestroyed)
4355
- return;
4356
- this.textBuffer.setText(content);
4357
- this._shouldRenderTextBuffer = true;
4358
- this._isHighlighting = false;
4359
- this._highlightsDirty = false;
4360
- this.updateTextInfo();
4361
- this.requestRender();
4362
- }
4363
- }
4364
- getLineHighlights(lineIdx) {
4365
- return this.textBuffer.getLineHighlights(lineIdx);
4366
- }
4367
- renderSelf(buffer) {
4368
- if (this._highlightsDirty) {
4369
- if (this.isDestroyed)
4370
- return;
4371
- if (this._content.length === 0) {
4372
- this._shouldRenderTextBuffer = false;
4373
- this._highlightsDirty = false;
4374
- } else if (!this._filetype) {
4375
- this._shouldRenderTextBuffer = true;
4376
- this._highlightsDirty = false;
4377
- } else {
4378
- this.ensureVisibleTextBeforeHighlight();
4379
- this._highlightsDirty = false;
4380
- this._highlightingPromise = this.startHighlight();
4381
- }
4382
- }
4383
- if (!this._shouldRenderTextBuffer)
4384
- return;
4385
- super.renderSelf(buffer);
4386
- }
4387
- }
4388
- // src/renderables/TextNode.ts
4389
- var BrandedTextNodeRenderable = Symbol.for("@jitl/opentui-core/TextNodeRenderable");
4390
- function isTextNodeRenderable(obj) {
4391
- return !!obj?.[BrandedTextNodeRenderable];
4392
- }
4393
- function styledTextToTextNodes(styledText) {
4394
- return styledText.chunks.map((chunk) => {
4395
- const node = new TextNodeRenderable({
4396
- fg: chunk.fg,
4397
- bg: chunk.bg,
4398
- attributes: chunk.attributes,
4399
- link: chunk.link
4400
- });
4401
- node.add(chunk.text);
4402
- return node;
4403
- });
4404
- }
4405
-
4406
- class TextNodeRenderable extends BaseRenderable {
4407
- [BrandedTextNodeRenderable] = true;
4408
- _fg;
4409
- _bg;
4410
- _attributes;
4411
- _link;
4412
- _children = [];
4413
- parent = null;
4414
- constructor(options) {
4415
- super(options);
4416
- this._fg = options.fg ? parseColor(options.fg) : undefined;
4417
- this._bg = options.bg ? parseColor(options.bg) : undefined;
4418
- this._attributes = options.attributes ?? 0;
4419
- this._link = options.link;
4420
- }
4421
- get children() {
4422
- return this._children;
4423
- }
4424
- set children(children) {
4425
- this._children = children;
4426
- this.requestRender();
4427
- }
4428
- requestRender() {
4429
- this.markDirty();
4430
- this.parent?.requestRender();
4431
- }
4432
- add(obj, index) {
4433
- if (typeof obj === "string") {
4434
- if (index !== undefined) {
4435
- this._children.splice(index, 0, obj);
4436
- this.requestRender();
4437
- return index;
4438
- }
4439
- const insertIndex = this._children.length;
4440
- this._children.push(obj);
4441
- this.requestRender();
4442
- return insertIndex;
4443
- }
4444
- if (isTextNodeRenderable(obj)) {
4445
- if (index !== undefined) {
4446
- this._children.splice(index, 0, obj);
4447
- obj.parent = this;
4448
- this.requestRender();
4449
- return index;
4450
- }
4451
- const insertIndex = this._children.length;
4452
- this._children.push(obj);
4453
- obj.parent = this;
4454
- this.requestRender();
4455
- return insertIndex;
4456
- }
4457
- if (isStyledText(obj)) {
4458
- const textNodes = styledTextToTextNodes(obj);
4459
- if (index !== undefined) {
4460
- this._children.splice(index, 0, ...textNodes);
4461
- textNodes.forEach((node) => node.parent = this);
4462
- this.requestRender();
4463
- return index;
4464
- }
4465
- const insertIndex = this._children.length;
4466
- this._children.push(...textNodes);
4467
- textNodes.forEach((node) => node.parent = this);
4468
- this.requestRender();
4469
- return insertIndex;
4470
- }
4471
- throw new Error("TextNodeRenderable only accepts strings, TextNodeRenderable instances, or StyledText instances");
4472
- }
4473
- replace(obj, index) {
4474
- this._children[index] = obj;
4475
- if (typeof obj !== "string") {
4476
- obj.parent = this;
4477
- }
4478
- this.requestRender();
4479
- }
4480
- insertBefore(child, anchorNode) {
4481
- if (!anchorNode || !isTextNodeRenderable(anchorNode)) {
4482
- throw new Error("Anchor must be a TextNodeRenderable");
4483
- }
4484
- const anchorIndex = this._children.indexOf(anchorNode);
4485
- if (anchorIndex === -1) {
4486
- throw new Error("Anchor node not found in children");
4487
- }
4488
- if (typeof child === "string") {
4489
- this._children.splice(anchorIndex, 0, child);
4490
- } else if (isTextNodeRenderable(child)) {
4491
- this._children.splice(anchorIndex, 0, child);
4492
- child.parent = this;
4493
- } else if (child instanceof StyledText) {
4494
- const textNodes = styledTextToTextNodes(child);
4495
- this._children.splice(anchorIndex, 0, ...textNodes);
4496
- textNodes.forEach((node) => node.parent = this);
4497
- } else {
4498
- throw new Error("Child must be a string, TextNodeRenderable, or StyledText instance");
4499
- }
4500
- this.requestRender();
4501
- return this;
4502
- }
4503
- remove(id) {
4504
- const childIndex = this.getRenderableIndex(id);
4505
- if (childIndex === -1) {
4506
- throw new Error("Child not found in children");
4507
- }
4508
- const child = this._children[childIndex];
4509
- this._children.splice(childIndex, 1);
4510
- child.parent = null;
4511
- this.requestRender();
4512
- return this;
4513
- }
4514
- clear() {
4515
- this._children = [];
4516
- this.requestRender();
4517
- }
4518
- mergeStyles(parentStyle) {
4519
- return {
4520
- fg: this._fg ?? parentStyle.fg,
4521
- bg: this._bg ?? parentStyle.bg,
4522
- attributes: this._attributes | parentStyle.attributes,
4523
- link: this._link ?? parentStyle.link
4524
- };
4525
- }
4526
- gatherWithInheritedStyle(parentStyle = {
4527
- fg: undefined,
4528
- bg: undefined,
4529
- attributes: 0
4530
- }) {
4531
- const currentStyle = this.mergeStyles(parentStyle);
4532
- const chunks = [];
4533
- for (const child of this._children) {
4534
- if (typeof child === "string") {
4535
- chunks.push({
4536
- __isChunk: true,
4537
- text: child,
4538
- fg: currentStyle.fg,
4539
- bg: currentStyle.bg,
4540
- attributes: currentStyle.attributes,
4541
- link: currentStyle.link
4542
- });
4543
- } else {
4544
- const childChunks = child.gatherWithInheritedStyle(currentStyle);
4545
- chunks.push(...childChunks);
4546
- }
4547
- }
4548
- this.markClean();
4549
- return chunks;
4550
- }
4551
- static fromString(text, options = {}) {
4552
- const node = new TextNodeRenderable(options);
4553
- node.add(text);
4554
- return node;
4555
- }
4556
- static fromNodes(nodes, options = {}) {
4557
- const node = new TextNodeRenderable(options);
4558
- for (const childNode of nodes) {
4559
- node.add(childNode);
4560
- }
4561
- return node;
4562
- }
4563
- toChunks(parentStyle = {
4564
- fg: undefined,
4565
- bg: undefined,
4566
- attributes: 0
4567
- }) {
4568
- return this.gatherWithInheritedStyle(parentStyle);
4569
- }
4570
- getChildren() {
4571
- return this._children.filter((child) => typeof child !== "string");
4572
- }
4573
- getChildrenCount() {
4574
- return this._children.length;
4575
- }
4576
- getRenderable(id) {
4577
- return this._children.find((child) => typeof child !== "string" && child.id === id);
4578
- }
4579
- getRenderableIndex(id) {
4580
- return this._children.findIndex((child) => isTextNodeRenderable(child) && child.id === id);
4581
- }
4582
- get fg() {
4583
- return this._fg;
4584
- }
4585
- set fg(fg2) {
4586
- if (!fg2) {
4587
- this._fg = undefined;
4588
- this.requestRender();
4589
- return;
4590
- }
4591
- this._fg = parseColor(fg2);
4592
- this.requestRender();
4593
- }
4594
- set bg(bg2) {
4595
- if (!bg2) {
4596
- this._bg = undefined;
4597
- this.requestRender();
4598
- return;
4599
- }
4600
- this._bg = parseColor(bg2);
4601
- this.requestRender();
4602
- }
4603
- get bg() {
4604
- return this._bg;
4605
- }
4606
- set attributes(attributes) {
4607
- this._attributes = attributes;
4608
- this.requestRender();
4609
- }
4610
- get attributes() {
4611
- return this._attributes;
4612
- }
4613
- set link(link2) {
4614
- this._link = link2;
4615
- this.requestRender();
4616
- }
4617
- get link() {
4618
- return this._link;
4619
- }
4620
- findDescendantById(id) {
4621
- return;
4622
- }
4623
- }
4624
-
4625
- class RootTextNodeRenderable extends TextNodeRenderable {
4626
- ctx;
4627
- textParent;
4628
- constructor(ctx, options, textParent) {
4629
- super(options);
4630
- this.ctx = ctx;
4631
- this.textParent = textParent;
4632
- }
4633
- requestRender() {
4634
- this.markDirty();
4635
- this.ctx.requestRender();
4636
- }
4637
- }
4638
-
4639
- // src/renderables/composition/constructs.ts
4640
- function Generic(props, ...children) {
4641
- return h(VRenderable, props || {}, ...children);
3570
+ // src/renderables/composition/constructs.ts
3571
+ function Generic(props, ...children) {
3572
+ return h(VRenderable, props || {}, ...children);
4642
3573
  }
4643
3574
  function Box(props, ...children) {
4644
3575
  return h(BoxRenderable, props || {}, ...children);
@@ -5235,49 +4166,271 @@ class LineNumberRenderable extends Renderable {
5235
4166
  }
5236
4167
  }
5237
4168
  }
5238
- // ../../node_modules/.bun/diff@8.0.2/node_modules/diff/libesm/patch/parse.js
4169
+ // ../../node_modules/.bun/diff@9.0.0/node_modules/diff/libesm/patch/parse.js
5239
4170
  function parsePatch(uniDiff) {
5240
4171
  const diffstr = uniDiff.split(/\n/), list = [];
5241
4172
  let i = 0;
4173
+ function isGitDiffHeader(line) {
4174
+ return /^diff --git /.test(line);
4175
+ }
4176
+ function isDiffHeader(line) {
4177
+ return isGitDiffHeader(line) || /^Index:\s/.test(line) || /^diff(?: -r \w+)+\s/.test(line);
4178
+ }
4179
+ function isFileHeader(line) {
4180
+ return /^(---|\+\+\+)\s/.test(line);
4181
+ }
4182
+ function isHunkHeader(line) {
4183
+ return /^@@\s/.test(line);
4184
+ }
5242
4185
  function parseIndex() {
4186
+ var _a;
5243
4187
  const index = {};
4188
+ index.hunks = [];
5244
4189
  list.push(index);
4190
+ let seenDiffHeader = false;
5245
4191
  while (i < diffstr.length) {
5246
4192
  const line = diffstr[i];
5247
- if (/^(---|\+\+\+|@@)\s/.test(line)) {
4193
+ if (isFileHeader(line) || isHunkHeader(line)) {
5248
4194
  break;
5249
4195
  }
5250
- const header = /^(?:Index:|diff(?: -r \w+)+)\s+(.+?)\s*$/.exec(line);
5251
- if (header) {
5252
- index.index = header[1];
4196
+ if (isGitDiffHeader(line)) {
4197
+ if (seenDiffHeader) {
4198
+ return;
4199
+ }
4200
+ seenDiffHeader = true;
4201
+ index.isGit = true;
4202
+ const paths = parseGitDiffHeader(line);
4203
+ if (paths) {
4204
+ index.oldFileName = paths.oldFileName;
4205
+ index.newFileName = paths.newFileName;
4206
+ }
4207
+ i++;
4208
+ while (i < diffstr.length) {
4209
+ const extLine = diffstr[i];
4210
+ if (isFileHeader(extLine) || isHunkHeader(extLine) || isDiffHeader(extLine)) {
4211
+ break;
4212
+ }
4213
+ const renameFromMatch = /^rename from (.*)/.exec(extLine);
4214
+ if (renameFromMatch) {
4215
+ index.oldFileName = "a/" + unquoteIfQuoted(renameFromMatch[1]);
4216
+ index.isRename = true;
4217
+ }
4218
+ const renameToMatch = /^rename to (.*)/.exec(extLine);
4219
+ if (renameToMatch) {
4220
+ index.newFileName = "b/" + unquoteIfQuoted(renameToMatch[1]);
4221
+ index.isRename = true;
4222
+ }
4223
+ const copyFromMatch = /^copy from (.*)/.exec(extLine);
4224
+ if (copyFromMatch) {
4225
+ index.oldFileName = "a/" + unquoteIfQuoted(copyFromMatch[1]);
4226
+ index.isCopy = true;
4227
+ }
4228
+ const copyToMatch = /^copy to (.*)/.exec(extLine);
4229
+ if (copyToMatch) {
4230
+ index.newFileName = "b/" + unquoteIfQuoted(copyToMatch[1]);
4231
+ index.isCopy = true;
4232
+ }
4233
+ const newFileModeMatch = /^new file mode (\d+)/.exec(extLine);
4234
+ if (newFileModeMatch) {
4235
+ index.isCreate = true;
4236
+ index.newMode = newFileModeMatch[1];
4237
+ }
4238
+ const deletedFileModeMatch = /^deleted file mode (\d+)/.exec(extLine);
4239
+ if (deletedFileModeMatch) {
4240
+ index.isDelete = true;
4241
+ index.oldMode = deletedFileModeMatch[1];
4242
+ }
4243
+ const oldModeMatch = /^old mode (\d+)/.exec(extLine);
4244
+ if (oldModeMatch) {
4245
+ index.oldMode = oldModeMatch[1];
4246
+ }
4247
+ const newModeMatch = /^new mode (\d+)/.exec(extLine);
4248
+ if (newModeMatch) {
4249
+ index.newMode = newModeMatch[1];
4250
+ }
4251
+ if (/^Binary files /.test(extLine)) {
4252
+ index.isBinary = true;
4253
+ }
4254
+ i++;
4255
+ }
4256
+ continue;
4257
+ } else if (isDiffHeader(line)) {
4258
+ if (seenDiffHeader) {
4259
+ return;
4260
+ }
4261
+ seenDiffHeader = true;
4262
+ const headerMatch = /^(?:Index:|diff(?: -r \w+)+)\s+/.exec(line);
4263
+ if (headerMatch) {
4264
+ index.index = line.substring(headerMatch[0].length).trim();
4265
+ }
5253
4266
  }
5254
4267
  i++;
5255
4268
  }
5256
4269
  parseFileHeader(index);
5257
4270
  parseFileHeader(index);
5258
- index.hunks = [];
4271
+ if (index.oldFileName === undefined !== (index.newFileName === undefined)) {
4272
+ throw new Error("Missing " + (index.oldFileName !== undefined ? '"+++ ..."' : '"--- ..."') + " file header for " + ((_a = index.oldFileName) !== null && _a !== undefined ? _a : index.newFileName));
4273
+ }
5259
4274
  while (i < diffstr.length) {
5260
4275
  const line = diffstr[i];
5261
- if (/^(Index:\s|diff\s|---\s|\+\+\+\s|===================================================================)/.test(line)) {
4276
+ if (isDiffHeader(line) || isFileHeader(line) || /^===================================================================/.test(line)) {
5262
4277
  break;
5263
- } else if (/^@@/.test(line)) {
4278
+ } else if (isHunkHeader(line)) {
5264
4279
  index.hunks.push(parseHunk());
5265
- } else if (line) {
5266
- throw new Error("Unknown line " + (i + 1) + " " + JSON.stringify(line));
5267
4280
  } else {
5268
4281
  i++;
5269
4282
  }
5270
4283
  }
5271
4284
  }
4285
+ function parseGitDiffHeader(line) {
4286
+ const rest = line.substring("diff --git ".length);
4287
+ if (rest.startsWith('"')) {
4288
+ const oldPath = parseQuotedFileName(rest);
4289
+ if (oldPath === null) {
4290
+ return null;
4291
+ }
4292
+ const afterOld = rest.substring(oldPath.rawLength + 1);
4293
+ let newFileName;
4294
+ if (afterOld.startsWith('"')) {
4295
+ const newPath = parseQuotedFileName(afterOld);
4296
+ if (newPath === null) {
4297
+ return null;
4298
+ }
4299
+ newFileName = newPath.fileName;
4300
+ } else {
4301
+ newFileName = afterOld;
4302
+ }
4303
+ return {
4304
+ oldFileName: oldPath.fileName,
4305
+ newFileName
4306
+ };
4307
+ }
4308
+ const quoteIdx = rest.indexOf('"');
4309
+ if (quoteIdx > 0) {
4310
+ const oldFileName = rest.substring(0, quoteIdx - 1);
4311
+ const newPath = parseQuotedFileName(rest.substring(quoteIdx));
4312
+ if (newPath === null) {
4313
+ return null;
4314
+ }
4315
+ return {
4316
+ oldFileName,
4317
+ newFileName: newPath.fileName
4318
+ };
4319
+ }
4320
+ if (rest.startsWith("a/")) {
4321
+ const splits = [];
4322
+ let idx = 0;
4323
+ while (true) {
4324
+ idx = rest.indexOf(" b/", idx + 1);
4325
+ if (idx === -1) {
4326
+ break;
4327
+ }
4328
+ splits.push(idx);
4329
+ }
4330
+ if (splits.length > 0) {
4331
+ const mid = splits[Math.floor(splits.length / 2)];
4332
+ return {
4333
+ oldFileName: rest.substring(0, mid),
4334
+ newFileName: rest.substring(mid + 1)
4335
+ };
4336
+ }
4337
+ }
4338
+ return null;
4339
+ }
4340
+ function unquoteIfQuoted(s) {
4341
+ if (s.startsWith('"')) {
4342
+ const parsed = parseQuotedFileName(s);
4343
+ if (parsed) {
4344
+ return parsed.fileName;
4345
+ }
4346
+ }
4347
+ return s;
4348
+ }
4349
+ function parseQuotedFileName(s) {
4350
+ if (!s.startsWith('"')) {
4351
+ return null;
4352
+ }
4353
+ let result = "";
4354
+ let j = 1;
4355
+ while (j < s.length) {
4356
+ if (s[j] === '"') {
4357
+ return { fileName: result, rawLength: j + 1 };
4358
+ }
4359
+ if (s[j] === "\\" && j + 1 < s.length) {
4360
+ j++;
4361
+ switch (s[j]) {
4362
+ case "a":
4363
+ result += "\x07";
4364
+ break;
4365
+ case "b":
4366
+ result += "\b";
4367
+ break;
4368
+ case "f":
4369
+ result += "\f";
4370
+ break;
4371
+ case "n":
4372
+ result += `
4373
+ `;
4374
+ break;
4375
+ case "r":
4376
+ result += "\r";
4377
+ break;
4378
+ case "t":
4379
+ result += "\t";
4380
+ break;
4381
+ case "v":
4382
+ result += "\v";
4383
+ break;
4384
+ case "\\":
4385
+ result += "\\";
4386
+ break;
4387
+ case '"':
4388
+ result += '"';
4389
+ break;
4390
+ case "0":
4391
+ case "1":
4392
+ case "2":
4393
+ case "3":
4394
+ case "4":
4395
+ case "5":
4396
+ case "6":
4397
+ case "7": {
4398
+ if (j + 2 >= s.length || s[j + 1] < "0" || s[j + 1] > "7" || s[j + 2] < "0" || s[j + 2] > "7") {
4399
+ return null;
4400
+ }
4401
+ const bytes = [parseInt(s.substring(j, j + 3), 8)];
4402
+ j += 3;
4403
+ while (s[j] === "\\" && s[j + 1] >= "0" && s[j + 1] <= "7") {
4404
+ if (j + 3 >= s.length || s[j + 2] < "0" || s[j + 2] > "7" || s[j + 3] < "0" || s[j + 3] > "7") {
4405
+ return null;
4406
+ }
4407
+ bytes.push(parseInt(s.substring(j + 1, j + 4), 8));
4408
+ j += 4;
4409
+ }
4410
+ result += new TextDecoder("utf-8").decode(new Uint8Array(bytes));
4411
+ continue;
4412
+ }
4413
+ default:
4414
+ return null;
4415
+ }
4416
+ } else {
4417
+ result += s[j];
4418
+ }
4419
+ j++;
4420
+ }
4421
+ return null;
4422
+ }
5272
4423
  function parseFileHeader(index) {
5273
- const fileHeader = /^(---|\+\+\+)\s+(.*)\r?$/.exec(diffstr[i]);
5274
- if (fileHeader) {
5275
- const data = fileHeader[2].split("\t", 2), header = (data[1] || "").trim();
5276
- let fileName = data[0].replace(/\\\\/g, "\\");
5277
- if (/^".*"$/.test(fileName)) {
5278
- fileName = fileName.substr(1, fileName.length - 2);
5279
- }
5280
- if (fileHeader[1] === "---") {
4424
+ const fileHeaderMatch = /^(---|\+\+\+)\s+/.exec(diffstr[i]);
4425
+ if (fileHeaderMatch) {
4426
+ const prefix = fileHeaderMatch[1], data = diffstr[i].substring(3).trim().split("\t", 2), header = (data[1] || "").trim();
4427
+ let fileName = data[0];
4428
+ if (fileName.startsWith('"')) {
4429
+ fileName = unquoteIfQuoted(fileName);
4430
+ } else {
4431
+ fileName = fileName.replace(/\\\\/g, "\\");
4432
+ }
4433
+ if (prefix === "---") {
5281
4434
  index.oldFileName = fileName;
5282
4435
  index.oldHeader = header;
5283
4436
  } else {
@@ -5332,110 +4485,16 @@ function parsePatch(uniDiff) {
5332
4485
  if (removeCount !== hunk.oldLines) {
5333
4486
  throw new Error("Removed line count did not match for hunk at line " + (chunkHeaderIndex + 1));
5334
4487
  }
5335
- return hunk;
5336
- }
5337
- while (i < diffstr.length) {
5338
- parseIndex();
5339
- }
5340
- return list;
5341
- }
5342
- // src/renderables/Text.ts
5343
- class TextRenderable extends TextBufferRenderable {
5344
- _text;
5345
- _hasManualStyledText = false;
5346
- rootTextNode;
5347
- _contentDefaultOptions = {
5348
- content: ""
5349
- };
5350
- constructor(ctx, options) {
5351
- super(ctx, options);
5352
- const content = options.content ?? this._contentDefaultOptions.content;
5353
- const styledText = typeof content === "string" ? stringToStyledText(content) : content;
5354
- this._text = styledText;
5355
- this._hasManualStyledText = options.content !== undefined && content !== "";
5356
- this.rootTextNode = new RootTextNodeRenderable(ctx, {
5357
- id: `${this.id}-root`,
5358
- fg: this._defaultFg,
5359
- bg: this._defaultBg,
5360
- attributes: this._defaultAttributes
5361
- }, this);
5362
- this.updateTextBuffer(styledText);
5363
- }
5364
- updateTextBuffer(styledText) {
5365
- this.textBuffer.setStyledText(styledText);
5366
- this.clearChunks(styledText);
5367
- }
5368
- clearChunks(styledText) {}
5369
- get content() {
5370
- return this._text;
5371
- }
5372
- get chunks() {
5373
- return this._text.chunks;
5374
- }
5375
- get textNode() {
5376
- return this.rootTextNode;
5377
- }
5378
- set content(value) {
5379
- this._hasManualStyledText = true;
5380
- const styledText = typeof value === "string" ? stringToStyledText(value) : value;
5381
- if (this._text !== styledText) {
5382
- this._text = styledText;
5383
- this.updateTextBuffer(styledText);
5384
- this.updateTextInfo();
5385
- }
5386
- }
5387
- updateTextFromNodes() {
5388
- if (this.rootTextNode.isDirty && !this._hasManualStyledText) {
5389
- const chunks = this.rootTextNode.gatherWithInheritedStyle({
5390
- fg: this._defaultFg,
5391
- bg: this._defaultBg,
5392
- attributes: this._defaultAttributes,
5393
- link: undefined
5394
- });
5395
- this.textBuffer.setStyledText(new StyledText(chunks));
5396
- this.refreshLocalSelection();
5397
- this.yogaNode.markDirty();
4488
+ if (i < diffstr.length && diffstr[i] && /^[+ -]/.test(diffstr[i]) && !isFileHeader(diffstr[i])) {
4489
+ throw new Error("Hunk at line " + (chunkHeaderIndex + 1) + " has more lines than expected (expected " + hunk.oldLines + " old lines and " + hunk.newLines + " new lines)");
5398
4490
  }
4491
+ return hunk;
5399
4492
  }
5400
- add(obj, index) {
5401
- return this.rootTextNode.add(obj, index);
5402
- }
5403
- remove(id) {
5404
- this.rootTextNode.remove(id);
5405
- }
5406
- insertBefore(obj, anchor) {
5407
- this.rootTextNode.insertBefore(obj, anchor);
5408
- return this.rootTextNode.children.indexOf(obj);
5409
- }
5410
- getTextChildren() {
5411
- return this.rootTextNode.getChildren();
5412
- }
5413
- clear() {
5414
- this.rootTextNode.clear();
5415
- const emptyStyledText = stringToStyledText("");
5416
- this._text = emptyStyledText;
5417
- this.updateTextBuffer(emptyStyledText);
5418
- this.updateTextInfo();
5419
- this.requestRender();
5420
- }
5421
- onLifecyclePass = () => {
5422
- this.updateTextFromNodes();
5423
- };
5424
- onFgChanged(newColor) {
5425
- this.rootTextNode.fg = newColor;
5426
- }
5427
- onBgChanged(newColor) {
5428
- this.rootTextNode.bg = newColor;
5429
- }
5430
- onAttributesChanged(newAttributes) {
5431
- this.rootTextNode.attributes = newAttributes;
5432
- }
5433
- destroy() {
5434
- this.rootTextNode.children.length = 0;
5435
- super.destroy();
4493
+ while (i < diffstr.length) {
4494
+ parseIndex();
5436
4495
  }
4496
+ return list;
5437
4497
  }
5438
-
5439
4498
  // src/renderables/Diff.ts
5440
4499
  class DiffRenderable extends Renderable {
5441
4500
  _diff;
@@ -6412,7 +5471,7 @@ class DiffRenderable extends Renderable {
6412
5471
  }
6413
5472
  }
6414
5473
  // src/renderables/Textarea.ts
6415
- var defaultTextareaKeybindings = [
5474
+ var defaultTextareaKeyBindings = [
6416
5475
  { name: "left", action: "move-left" },
6417
5476
  { name: "right", action: "move-right" },
6418
5477
  { name: "up", action: "move-up" },
@@ -6449,8 +5508,10 @@ var defaultTextareaKeybindings = [
6449
5508
  { name: "delete", action: "delete" },
6450
5509
  { name: "delete", shift: true, action: "delete" },
6451
5510
  { name: "return", action: "newline" },
5511
+ { name: "kpenter", action: "newline" },
6452
5512
  { name: "linefeed", action: "newline" },
6453
5513
  { name: "return", meta: true, action: "submit" },
5514
+ { name: "kpenter", meta: true, action: "submit" },
6454
5515
  { name: "-", ctrl: true, action: "undo" },
6455
5516
  { name: ".", ctrl: true, action: "redo" },
6456
5517
  { name: "z", super: true, action: "undo" },
@@ -6514,7 +5575,7 @@ class TextareaRenderable extends EditBufferRenderable {
6514
5575
  this._placeholderColor = parseColor(options.placeholderColor ?? defaults.placeholderColor);
6515
5576
  this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, options.keyAliasMap || {});
6516
5577
  this._keyBindings = options.keyBindings || [];
6517
- const mergedBindings = mergeKeyBindings(defaultTextareaKeybindings, this._keyBindings);
5578
+ const mergedBindings = mergeKeyBindings(defaultTextareaKeyBindings, this._keyBindings);
6518
5579
  this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap);
6519
5580
  this._actionHandlers = this.buildActionHandlers();
6520
5581
  this._submitListener = options.onSubmit;
@@ -6582,19 +5643,13 @@ class TextareaRenderable extends EditBufferRenderable {
6582
5643
  this.insertText(stripAnsiSequences(decodePasteBytes(event.bytes)));
6583
5644
  }
6584
5645
  handleKeyPress(key) {
6585
- const bindingKey = getKeyBindingKey({
6586
- name: key.name,
6587
- ctrl: key.ctrl,
6588
- shift: key.shift,
6589
- meta: key.meta,
6590
- super: key.super,
6591
- action: "move-left"
6592
- });
6593
- const action = this._keyBindingsMap.get(bindingKey);
6594
- if (action) {
6595
- const handler = this._actionHandlers.get(action);
6596
- if (handler) {
6597
- return handler();
5646
+ if (this.traits.suspend !== true) {
5647
+ const action = getKeyBindingAction(this._keyBindingsMap, key);
5648
+ if (action) {
5649
+ const handler = this._actionHandlers.get(action);
5650
+ if (handler) {
5651
+ return handler();
5652
+ }
6598
5653
  }
6599
5654
  }
6600
5655
  if (!key.ctrl && !key.meta && !key.super && !key.hyper) {
@@ -6708,12 +5763,12 @@ class TextareaRenderable extends EditBufferRenderable {
6708
5763
  }
6709
5764
  set keyBindings(bindings) {
6710
5765
  this._keyBindings = bindings;
6711
- const mergedBindings = mergeKeyBindings(defaultTextareaKeybindings, bindings);
5766
+ const mergedBindings = mergeKeyBindings(defaultTextareaKeyBindings, bindings);
6712
5767
  this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap);
6713
5768
  }
6714
5769
  set keyAliasMap(aliases) {
6715
5770
  this._keyAliasMap = mergeKeyAliases(defaultKeyAliases, aliases);
6716
- const mergedBindings = mergeKeyBindings(defaultTextareaKeybindings, this._keyBindings);
5771
+ const mergedBindings = mergeKeyBindings(defaultTextareaKeyBindings, this._keyBindings);
6717
5772
  this._keyBindingsMap = buildKeyBindingsMap(mergedBindings, this._keyAliasMap);
6718
5773
  }
6719
5774
  get extmarks() {
@@ -6750,6 +5805,7 @@ class InputRenderable extends TextareaRenderable {
6750
5805
  wrapMode: "none",
6751
5806
  keyBindings: [
6752
5807
  { name: "return", action: "submit" },
5808
+ { name: "kpenter", action: "submit" },
6753
5809
  { name: "linefeed", action: "submit" },
6754
5810
  ...options.keyBindings || []
6755
5811
  ]
@@ -6895,7 +5951,9 @@ class TextTableRenderable extends Renderable {
6895
5951
  _wrapMode;
6896
5952
  _columnWidthMode;
6897
5953
  _columnFitter;
6898
- _cellPadding;
5954
+ _cellPaddingX;
5955
+ _cellPaddingY;
5956
+ _columnGap;
6899
5957
  _showBorders;
6900
5958
  _border;
6901
5959
  _outerBorder;
@@ -6926,6 +5984,9 @@ class TextTableRenderable extends Renderable {
6926
5984
  columnWidthMode: "full",
6927
5985
  columnFitter: "proportional",
6928
5986
  cellPadding: 0,
5987
+ cellPaddingX: undefined,
5988
+ cellPaddingY: undefined,
5989
+ columnGap: 0,
6929
5990
  showBorders: true,
6930
5991
  border: true,
6931
5992
  outerBorder: true,
@@ -6946,7 +6007,9 @@ class TextTableRenderable extends Renderable {
6946
6007
  this._wrapMode = options.wrapMode ?? this._defaultOptions.wrapMode;
6947
6008
  this._columnWidthMode = options.columnWidthMode ?? this._defaultOptions.columnWidthMode;
6948
6009
  this._columnFitter = this.resolveColumnFitter(options.columnFitter);
6949
- this._cellPadding = this.resolveCellPadding(options.cellPadding);
6010
+ this._cellPaddingX = this.resolveCellPadding(options.cellPaddingX ?? options.cellPadding);
6011
+ this._cellPaddingY = this.resolveCellPadding(options.cellPaddingY ?? options.cellPadding);
6012
+ this._columnGap = this.resolveColumnGap(options.columnGap);
6950
6013
  this._showBorders = options.showBorders ?? this._defaultOptions.showBorders;
6951
6014
  this._border = options.border ?? this._defaultOptions.border;
6952
6015
  this._hasExplicitOuterBorder = options.outerBorder !== undefined;
@@ -7005,13 +6068,44 @@ class TextTableRenderable extends Renderable {
7005
6068
  this.invalidateLayoutAndRaster();
7006
6069
  }
7007
6070
  get cellPadding() {
7008
- return this._cellPadding;
6071
+ return this._cellPaddingX === this._cellPaddingY ? this._cellPaddingX : 0;
7009
6072
  }
7010
6073
  set cellPadding(value) {
7011
6074
  const next = this.resolveCellPadding(value);
7012
- if (this._cellPadding === next)
6075
+ if (this._cellPaddingX === next && this._cellPaddingY === next)
6076
+ return;
6077
+ this._cellPaddingX = next;
6078
+ this._cellPaddingY = next;
6079
+ this.invalidateLayoutAndRaster();
6080
+ }
6081
+ get cellPaddingX() {
6082
+ return this._cellPaddingX;
6083
+ }
6084
+ set cellPaddingX(value) {
6085
+ const next = this.resolveCellPadding(value);
6086
+ if (this._cellPaddingX === next)
6087
+ return;
6088
+ this._cellPaddingX = next;
6089
+ this.invalidateLayoutAndRaster();
6090
+ }
6091
+ get cellPaddingY() {
6092
+ return this._cellPaddingY;
6093
+ }
6094
+ set cellPaddingY(value) {
6095
+ const next = this.resolveCellPadding(value);
6096
+ if (this._cellPaddingY === next)
7013
6097
  return;
7014
- this._cellPadding = next;
6098
+ this._cellPaddingY = next;
6099
+ this.invalidateLayoutAndRaster();
6100
+ }
6101
+ get columnGap() {
6102
+ return this._columnGap;
6103
+ }
6104
+ set columnGap(value) {
6105
+ const next = this.resolveColumnGap(value);
6106
+ if (this._columnGap === next)
6107
+ return;
6108
+ this._columnGap = next;
7015
6109
  this.invalidateLayoutAndRaster();
7016
6110
  }
7017
6111
  get showBorders() {
@@ -7327,7 +6421,7 @@ class TextTableRenderable extends Renderable {
7327
6421
  const borderLayout = this.resolveBorderLayout();
7328
6422
  const columnWidths = this.computeColumnWidths(maxTableWidth, borderLayout);
7329
6423
  const rowHeights = this.computeRowHeights(columnWidths);
7330
- const columnOffsets = this.computeOffsets(columnWidths, borderLayout.left, borderLayout.right, borderLayout.innerVertical);
6424
+ const columnOffsets = this.computeOffsets(columnWidths, borderLayout.left, borderLayout.right, borderLayout.innerVertical, this.getInterColumnGap(borderLayout));
7331
6425
  const rowOffsets = this.computeOffsets(rowHeights, borderLayout.top, borderLayout.bottom, borderLayout.innerHorizontal);
7332
6426
  return {
7333
6427
  columnWidths,
@@ -7359,7 +6453,7 @@ class TextTableRenderable extends Renderable {
7359
6453
  if (maxTableWidth === undefined || !Number.isFinite(maxTableWidth) || maxTableWidth <= 0) {
7360
6454
  return intrinsicWidths;
7361
6455
  }
7362
- const maxContentWidth = Math.max(1, Math.floor(maxTableWidth) - this.getVerticalBorderCount(borderLayout));
6456
+ const maxContentWidth = Math.max(1, Math.floor(maxTableWidth) - this.getVerticalBorderCount(borderLayout) - this.getTotalInterColumnGap(borderLayout));
7363
6457
  const currentWidth = intrinsicWidths.reduce((sum, width) => sum + width, 0);
7364
6458
  if (currentWidth === maxContentWidth) {
7365
6459
  return intrinsicWidths;
@@ -7542,17 +6636,26 @@ class TextTableRenderable extends Renderable {
7542
6636
  }
7543
6637
  return rowHeights;
7544
6638
  }
7545
- computeOffsets(parts, startBoundary, endBoundary, includeInnerBoundaries) {
6639
+ computeOffsets(parts, startBoundary, endBoundary, includeInnerBoundaries, innerGap = 0) {
7546
6640
  const offsets = [startBoundary ? 0 : -1];
7547
6641
  let cursor = offsets[0] ?? 0;
7548
6642
  for (let idx = 0;idx < parts.length; idx++) {
7549
6643
  const size = parts[idx] ?? 1;
7550
- const hasBoundaryAfter = idx < parts.length - 1 ? includeInnerBoundaries : endBoundary;
7551
- cursor += size + (hasBoundaryAfter ? 1 : 0);
6644
+ const separatorAfter = idx < parts.length - 1 ? includeInnerBoundaries ? 1 : innerGap : endBoundary ? 1 : 0;
6645
+ cursor += size + separatorAfter;
7552
6646
  offsets.push(cursor);
7553
6647
  }
7554
6648
  return offsets;
7555
6649
  }
6650
+ getInterColumnGap(borderLayout) {
6651
+ if (borderLayout.innerVertical) {
6652
+ return 0;
6653
+ }
6654
+ return this._columnGap;
6655
+ }
6656
+ getTotalInterColumnGap(borderLayout) {
6657
+ return Math.max(0, this._columnCount - 1) * this.getInterColumnGap(borderLayout);
6658
+ }
7556
6659
  applyLayoutToViews(layout) {
7557
6660
  const horizontalPadding = this.getHorizontalCellPadding();
7558
6661
  const verticalPadding = this.getVerticalCellPadding();
@@ -7614,14 +6717,15 @@ class TextTableRenderable extends Renderable {
7614
6717
  drawCellRange(buffer, firstRow, lastRow) {
7615
6718
  const colOffsets = this._layout.columnOffsets;
7616
6719
  const rowOffsets = this._layout.rowOffsets;
7617
- const cellPadding = this._cellPadding;
6720
+ const cellPaddingX = this._cellPaddingX;
6721
+ const cellPaddingY = this._cellPaddingY;
7618
6722
  for (let rowIdx = firstRow;rowIdx <= lastRow; rowIdx++) {
7619
- const cellY = (rowOffsets[rowIdx] ?? 0) + 1 + cellPadding;
6723
+ const cellY = (rowOffsets[rowIdx] ?? 0) + 1 + cellPaddingY;
7620
6724
  for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7621
6725
  const cell = this._cells[rowIdx]?.[colIdx];
7622
6726
  if (!cell)
7623
6727
  continue;
7624
- buffer.drawTextBuffer(cell.textBufferView, (colOffsets[colIdx] ?? 0) + 1 + cellPadding, cellY);
6728
+ buffer.drawTextBuffer(cell.textBufferView, (colOffsets[colIdx] ?? 0) + 1 + cellPaddingX, cellY);
7625
6729
  }
7626
6730
  }
7627
6731
  }
@@ -7650,7 +6754,15 @@ class TextTableRenderable extends Renderable {
7650
6754
  for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7651
6755
  const cellX = (colOffsets[colIdx] ?? 0) + 1;
7652
6756
  const colWidth = colWidths[colIdx] ?? 1;
7653
- buffer.fillRect(cellX, cellY, colWidth, rowHeight, this._backgroundColor);
6757
+ if (this._backgroundColor.a < 1) {
6758
+ for (let y = cellY;y < cellY + rowHeight; y++) {
6759
+ for (let x = cellX;x < cellX + colWidth; x++) {
6760
+ buffer.setCell(x, y, " ", this._defaultFg, this._backgroundColor, this._defaultAttributes);
6761
+ }
6762
+ }
6763
+ } else {
6764
+ buffer.fillRect(cellX, cellY, colWidth, rowHeight, this._backgroundColor);
6765
+ }
7654
6766
  }
7655
6767
  }
7656
6768
  }
@@ -7690,6 +6802,11 @@ class TextTableRenderable extends Renderable {
7690
6802
  return { rowIdx, colIdx };
7691
6803
  }
7692
6804
  applySelectionToCells(localSelection, isStart) {
6805
+ if (localSelection.anchorX === localSelection.focusX && localSelection.anchorY === localSelection.focusY) {
6806
+ this.resetCellSelections();
6807
+ this._lastSelectionMode = null;
6808
+ return;
6809
+ }
7693
6810
  const minSelY = Math.min(localSelection.anchorY, localSelection.focusY);
7694
6811
  const maxSelY = Math.max(localSelection.anchorY, localSelection.focusY);
7695
6812
  const firstRow = this.findRowForLocalY(minSelY);
@@ -7703,7 +6820,7 @@ class TextTableRenderable extends Renderable {
7703
6820
  this.resetRowSelection(rowIdx);
7704
6821
  continue;
7705
6822
  }
7706
- const cellTop = (this._layout.rowOffsets[rowIdx] ?? 0) + 1 + this._cellPadding;
6823
+ const cellTop = (this._layout.rowOffsets[rowIdx] ?? 0) + 1 + this._cellPaddingY;
7707
6824
  for (let colIdx = 0;colIdx < this._columnCount; colIdx++) {
7708
6825
  const cell = this._cells[rowIdx]?.[colIdx];
7709
6826
  if (!cell)
@@ -7712,7 +6829,7 @@ class TextTableRenderable extends Renderable {
7712
6829
  cell.textBufferView.resetLocalSelection();
7713
6830
  continue;
7714
6831
  }
7715
- const cellLeft = (this._layout.columnOffsets[colIdx] ?? 0) + 1 + this._cellPadding;
6832
+ const cellLeft = (this._layout.columnOffsets[colIdx] ?? 0) + 1 + this._cellPaddingX;
7716
6833
  let coords = {
7717
6834
  anchorX: localSelection.anchorX - cellLeft,
7718
6835
  anchorY: localSelection.anchorY - cellTop,
@@ -7720,6 +6837,10 @@ class TextTableRenderable extends Renderable {
7720
6837
  focusY: localSelection.focusY - cellTop
7721
6838
  };
7722
6839
  const isAnchorCell = selection.anchorCell !== null && selection.anchorCell.rowIdx === rowIdx && selection.anchorCell.colIdx === colIdx;
6840
+ if (selection.mode === "single-cell" && !isAnchorCell) {
6841
+ cell.textBufferView.resetLocalSelection();
6842
+ continue;
6843
+ }
7723
6844
  const forceSet = isAnchorCell && selection.mode !== "single-cell";
7724
6845
  if (forceSet) {
7725
6846
  coords = this.getFullCellSelectionCoords(rowIdx, colIdx);
@@ -7854,10 +6975,10 @@ class TextTableRenderable extends Renderable {
7854
6975
  return;
7855
6976
  }
7856
6977
  getHorizontalCellPadding() {
7857
- return this._cellPadding * 2;
6978
+ return this._cellPaddingX * 2;
7858
6979
  }
7859
6980
  getVerticalCellPadding() {
7860
- return this._cellPadding * 2;
6981
+ return this._cellPaddingY * 2;
7861
6982
  }
7862
6983
  resolveColumnFitter(value) {
7863
6984
  if (value === undefined) {
@@ -7871,6 +6992,12 @@ class TextTableRenderable extends Renderable {
7871
6992
  }
7872
6993
  return Math.max(0, Math.floor(value));
7873
6994
  }
6995
+ resolveColumnGap(value) {
6996
+ if (value === undefined || !Number.isFinite(value)) {
6997
+ return this._defaultOptions.columnGap;
6998
+ }
6999
+ return Math.max(0, Math.floor(value));
7000
+ }
7874
7001
  invalidateLayoutAndRaster(markYogaDirty = true) {
7875
7002
  this._layoutDirty = true;
7876
7003
  this._rasterDirty = true;
@@ -9157,9 +8284,13 @@ function parseMarkdownIncremental(newContent, prevState, trailingUnstable = 2) {
9157
8284
  if (!prevState || prevState.tokens.length === 0) {
9158
8285
  try {
9159
8286
  const tokens = x.lex(newContent, { gfm: true });
9160
- return { content: newContent, tokens };
8287
+ return {
8288
+ content: newContent,
8289
+ tokens,
8290
+ stableTokenCount: Math.max(0, tokens.length - trailingUnstable)
8291
+ };
9161
8292
  } catch {
9162
- return { content: newContent, tokens: [] };
8293
+ return { content: newContent, tokens: [], stableTokenCount: 0 };
9163
8294
  }
9164
8295
  }
9165
8296
  let offset = 0;
@@ -9181,23 +8312,32 @@ function parseMarkdownIncremental(newContent, prevState, trailingUnstable = 2) {
9181
8312
  const stableTokens = prevState.tokens.slice(0, reuseCount);
9182
8313
  const remainingContent = newContent.slice(offset);
9183
8314
  if (!remainingContent) {
9184
- return { content: newContent, tokens: stableTokens };
8315
+ return {
8316
+ content: newContent,
8317
+ tokens: stableTokens,
8318
+ stableTokenCount: stableTokens.length
8319
+ };
9185
8320
  }
9186
8321
  try {
9187
8322
  const newTokens = x.lex(remainingContent, { gfm: true });
9188
- return { content: newContent, tokens: [...stableTokens, ...newTokens] };
8323
+ return {
8324
+ content: newContent,
8325
+ tokens: [...stableTokens, ...newTokens],
8326
+ stableTokenCount: trailingUnstable === 0 ? stableTokens.length + newTokens.length : stableTokens.length
8327
+ };
9189
8328
  } catch {
9190
8329
  try {
9191
8330
  const fullTokens = x.lex(newContent, { gfm: true });
9192
- return { content: newContent, tokens: fullTokens };
8331
+ return { content: newContent, tokens: fullTokens, stableTokenCount: 0 };
9193
8332
  } catch {
9194
- return { content: newContent, tokens: [] };
8333
+ return { content: newContent, tokens: [], stableTokenCount: 0 };
9195
8334
  }
9196
8335
  }
9197
8336
  }
9198
8337
 
9199
8338
  // src/renderables/Markdown.ts
9200
8339
  var TRAILING_MARKDOWN_BLOCK_BREAKS_RE = /(?:\r?\n){2,}$/;
8340
+ var TRAILING_MARKDOWN_BLOCK_NEWLINES_RE = /(?:\r?\n)+$/;
9201
8341
  function colorsEqual(left, right) {
9202
8342
  if (!left || !right)
9203
8343
  return left === right;
@@ -9214,9 +8354,11 @@ class MarkdownRenderable extends Renderable {
9214
8354
  _treeSitterClient;
9215
8355
  _tableOptions;
9216
8356
  _renderNode;
8357
+ _internalBlockMode;
9217
8358
  _parseState = null;
9218
8359
  _streaming = false;
9219
8360
  _blockStates = [];
8361
+ _stableBlockCount = 0;
9220
8362
  _styleDirty = false;
9221
8363
  _linkifyMarkdownChunks = (chunks, context) => detectLinks(chunks, {
9222
8364
  content: context.content,
@@ -9226,7 +8368,8 @@ class MarkdownRenderable extends Renderable {
9226
8368
  content: "",
9227
8369
  conceal: true,
9228
8370
  concealCode: false,
9229
- streaming: false
8371
+ streaming: false,
8372
+ internalBlockMode: "coalesced"
9230
8373
  };
9231
8374
  constructor(ctx, options) {
9232
8375
  super(ctx, {
@@ -9244,6 +8387,7 @@ class MarkdownRenderable extends Renderable {
9244
8387
  this._tableOptions = options.tableOptions;
9245
8388
  this._renderNode = options.renderNode;
9246
8389
  this._streaming = options.streaming ?? this._contentDefaultOptions.streaming;
8390
+ this._internalBlockMode = options.internalBlockMode ?? this._contentDefaultOptions.internalBlockMode;
9247
8391
  this.updateBlocks();
9248
8392
  }
9249
8393
  get content() {
@@ -9323,6 +8467,28 @@ class MarkdownRenderable extends Renderable {
9323
8467
  this._tableOptions = value;
9324
8468
  this.applyTableOptionsToBlocks();
9325
8469
  }
8470
+ get renderNode() {
8471
+ return this._renderNode;
8472
+ }
8473
+ set renderNode(value) {
8474
+ if (this._renderNode === value)
8475
+ return;
8476
+ this._renderNode = value;
8477
+ this.clearBlockStates();
8478
+ this._parseState = null;
8479
+ this.updateBlocks(true);
8480
+ this.requestRender();
8481
+ }
8482
+ get internalBlockMode() {
8483
+ return this._internalBlockMode;
8484
+ }
8485
+ set internalBlockMode(value) {
8486
+ if (this._internalBlockMode === value)
8487
+ return;
8488
+ this._internalBlockMode = value;
8489
+ this.updateBlocks(true);
8490
+ this.requestRender();
8491
+ }
9326
8492
  getStyle(group) {
9327
8493
  if (!this._syntaxStyle)
9328
8494
  return;
@@ -9475,7 +8641,11 @@ class MarkdownRenderable extends Renderable {
9475
8641
  break;
9476
8642
  }
9477
8643
  }
9478
- createMarkdownCodeRenderable(content, id, marginBottom = 0) {
8644
+ applyMargins(renderable, marginTop, marginBottom) {
8645
+ renderable.marginTop = marginTop;
8646
+ renderable.marginBottom = marginBottom;
8647
+ }
8648
+ createMarkdownCodeRenderable(content, id, marginBottom = 0, onChunks = this._linkifyMarkdownChunks, baseHighlight) {
9479
8649
  return new CodeRenderable(this.ctx, {
9480
8650
  id,
9481
8651
  content,
@@ -9486,12 +8656,239 @@ class MarkdownRenderable extends Renderable {
9486
8656
  conceal: this._conceal,
9487
8657
  drawUnstyledText: false,
9488
8658
  streaming: true,
9489
- onChunks: this._linkifyMarkdownChunks,
8659
+ baseHighlight,
8660
+ onChunks,
9490
8661
  treeSitterClient: this._treeSitterClient,
9491
8662
  width: "100%",
9492
8663
  marginBottom
9493
8664
  });
9494
8665
  }
8666
+ getBlockquoteContent(token) {
8667
+ return "text" in token && typeof token.text === "string" && token.text ? token.text : " ";
8668
+ }
8669
+ getBlockquoteBorderColor() {
8670
+ return this.getStyle("conceal")?.fg ?? this.getStyle("default")?.fg ?? this._fg ?? "#FFFFFF";
8671
+ }
8672
+ createBlockquoteRenderable(token, id, marginBottom = 0) {
8673
+ const renderable = new BoxRenderable(this.ctx, {
8674
+ id,
8675
+ width: "100%",
8676
+ border: ["left"],
8677
+ borderColor: this.getBlockquoteBorderColor(),
8678
+ paddingLeft: 1,
8679
+ flexShrink: 0,
8680
+ marginBottom
8681
+ });
8682
+ renderable.add(this.createMarkdownCodeRenderable(this.getBlockquoteContent(token), `${id}-content`, 0, this._linkifyMarkdownChunks, "markup.quote"));
8683
+ return renderable;
8684
+ }
8685
+ createListRenderable(token, id, marginBottom = 0) {
8686
+ const list = new BoxRenderable(this.ctx, {
8687
+ id,
8688
+ width: "100%",
8689
+ flexDirection: "column",
8690
+ flexShrink: 0,
8691
+ marginBottom
8692
+ });
8693
+ for (const item of this.getListItemInputs(token, id)) {
8694
+ list.add(this.createListItemRenderable(item));
8695
+ }
8696
+ return list;
8697
+ }
8698
+ getListItemInputs(token, id) {
8699
+ const items = token.items ?? [];
8700
+ const start = token.start === "" || token.start === undefined || token.start === null ? 1 : Number(token.start);
8701
+ const markerWidth = Math.max(1, ...items.map((_2, index) => (token.ordered ? `${start + index}.` : "-").length));
8702
+ return items.map((item, index) => ({
8703
+ item,
8704
+ marker: token.ordered ? `${start + index}.` : "-",
8705
+ markerWidth,
8706
+ id: `${id}-item-${index}`
8707
+ }));
8708
+ }
8709
+ applyListRenderable(renderable, token, previousToken, id, marginBottom = 0) {
8710
+ if (!(renderable instanceof BoxRenderable))
8711
+ return false;
8712
+ renderable.marginBottom = marginBottom;
8713
+ const inputs = this.getListItemInputs(token, id);
8714
+ const previousItems = previousToken?.items ?? [];
8715
+ const rows = renderable.getChildren();
8716
+ for (let index = 0;index < inputs.length; index += 1) {
8717
+ const input = inputs[index];
8718
+ const existing = rows[index];
8719
+ if (existing instanceof BoxRenderable && this.applyListItemRenderable(existing, input, previousItems[index])) {
8720
+ continue;
8721
+ }
8722
+ existing?.destroyRecursively();
8723
+ renderable.add(this.createListItemRenderable(input), index);
8724
+ }
8725
+ for (let index = rows.length - 1;index >= inputs.length; index -= 1) {
8726
+ rows[index]?.destroyRecursively();
8727
+ }
8728
+ return true;
8729
+ }
8730
+ createListItemRenderable(input) {
8731
+ const row = new BoxRenderable(this.ctx, {
8732
+ id: input.id,
8733
+ width: "100%",
8734
+ flexDirection: "row",
8735
+ flexShrink: 0,
8736
+ marginBottom: /\n[ \t]*\n$/.test(input.item.raw) ? 1 : 0
8737
+ });
8738
+ row.add(new TextRenderable(this.ctx, {
8739
+ id: `${input.id}-marker`,
8740
+ content: new StyledText([this.createChunk(input.marker.padStart(input.markerWidth) + " ", "markup.list")]),
8741
+ width: input.markerWidth + 1,
8742
+ flexShrink: 0
8743
+ }));
8744
+ const content = new BoxRenderable(this.ctx, {
8745
+ id: `${input.id}-content`,
8746
+ flexDirection: "column",
8747
+ flexGrow: 1,
8748
+ flexShrink: 1
8749
+ });
8750
+ row.add(content);
8751
+ let pendingMarginTop = 0;
8752
+ for (let index = 0;index < input.item.tokens.length; index += 1) {
8753
+ const child = input.item.tokens[index];
8754
+ if (!child)
8755
+ continue;
8756
+ if (child.type === "checkbox")
8757
+ continue;
8758
+ if (child.type === "space") {
8759
+ pendingMarginTop = Math.max(pendingMarginTop, 1);
8760
+ continue;
8761
+ }
8762
+ const renderable = this.createListChildRenderable(child, `${input.id}-child-${index}`);
8763
+ if (!renderable)
8764
+ continue;
8765
+ renderable.marginTop = child.type === "list" ? 0 : pendingMarginTop;
8766
+ pendingMarginTop = 0;
8767
+ content.add(renderable);
8768
+ }
8769
+ return row;
8770
+ }
8771
+ applyListItemRenderable(row, input, previousItem) {
8772
+ this.applyListItemMarker(row, input);
8773
+ const content = row.getChildren()[1];
8774
+ if (!(content instanceof BoxRenderable))
8775
+ return false;
8776
+ if (previousItem && previousItem.raw === input.item.raw) {
8777
+ return true;
8778
+ }
8779
+ return this.applyListItemChildren(content, input.item, previousItem, input.id);
8780
+ }
8781
+ applyListItemChildren(content, item, previousItem, id) {
8782
+ const previousTokens = previousItem ? this.getRenderableListItemTokens(previousItem) : [];
8783
+ const children = content.getChildren();
8784
+ let childIndex = 0;
8785
+ let pendingMarginTop = 0;
8786
+ for (let tokenIndex = 0;tokenIndex < item.tokens.length; tokenIndex += 1) {
8787
+ const token = item.tokens[tokenIndex];
8788
+ if (!token)
8789
+ continue;
8790
+ if (token.type === "checkbox")
8791
+ continue;
8792
+ if (token.type === "space") {
8793
+ pendingMarginTop = Math.max(pendingMarginTop, 1);
8794
+ continue;
8795
+ }
8796
+ const existing = children[childIndex];
8797
+ const childId = `${id}-child-${tokenIndex}`;
8798
+ const marginTop = token.type === "list" ? 0 : pendingMarginTop;
8799
+ pendingMarginTop = 0;
8800
+ if (!existing) {
8801
+ const renderable = this.createListChildRenderable(token, childId);
8802
+ if (!renderable)
8803
+ return false;
8804
+ renderable.marginTop = marginTop;
8805
+ content.add(renderable, childIndex);
8806
+ childIndex += 1;
8807
+ continue;
8808
+ }
8809
+ if (!this.applyListChildRenderable(existing, token, previousTokens[childIndex], childId)) {
8810
+ return false;
8811
+ }
8812
+ existing.marginTop = marginTop;
8813
+ childIndex += 1;
8814
+ }
8815
+ this.destroyListItemChildrenAfter(content, childIndex);
8816
+ return true;
8817
+ }
8818
+ getRenderableListItemTokens(item) {
8819
+ const tokens = [];
8820
+ for (const token of item.tokens) {
8821
+ if (token.type === "checkbox" || token.type === "space")
8822
+ continue;
8823
+ tokens.push(token);
8824
+ }
8825
+ return tokens;
8826
+ }
8827
+ applyListChildRenderable(renderable, token, previousToken, id) {
8828
+ if ((token.type === "text" || token.type === "paragraph") && renderable instanceof CodeRenderable) {
8829
+ this.applyMarkdownCodeRenderable(renderable, this.getListChildMarkdownRaw(token), 0);
8830
+ return true;
8831
+ }
8832
+ if (token.type === "list" && renderable instanceof BoxRenderable) {
8833
+ return this.applyListRenderable(renderable, token, previousToken, id);
8834
+ }
8835
+ if (token.type === "code" && renderable instanceof CodeRenderable) {
8836
+ this.applyCodeBlockRenderable(renderable, token, 0);
8837
+ return true;
8838
+ }
8839
+ return previousToken?.raw === token.raw;
8840
+ }
8841
+ destroyListItemChildrenAfter(content, index) {
8842
+ const children = content.getChildren();
8843
+ for (let i = children.length - 1;i >= index; i -= 1) {
8844
+ children[i]?.destroyRecursively();
8845
+ }
8846
+ }
8847
+ getListChildMarkdownRaw(token) {
8848
+ return token.type === "paragraph" ? this.normalizeScrollbackMarkdownBlockRaw(token.raw) : token.raw;
8849
+ }
8850
+ applyListItemMarker(row, input) {
8851
+ const marker = row.getChildren()[0];
8852
+ if (!(marker instanceof TextRenderable))
8853
+ return;
8854
+ const marginBottom = /\n[ \t]*\n$/.test(input.item.raw) ? 1 : 0;
8855
+ const markerWidth = input.markerWidth + 1;
8856
+ const markerText = input.marker.padStart(input.markerWidth) + " ";
8857
+ if (row.marginBottom !== marginBottom)
8858
+ row.marginBottom = marginBottom;
8859
+ if (marker.width !== markerWidth)
8860
+ marker.width = markerWidth;
8861
+ if (marker.chunks[0]?.text !== markerText) {
8862
+ marker.content = new StyledText([this.createChunk(markerText, "markup.list")]);
8863
+ }
8864
+ }
8865
+ createListChildRenderable(token, id) {
8866
+ if (token.type === "text" || token.type === "paragraph") {
8867
+ return this.createMarkdownCodeRenderable(this.getListChildMarkdownRaw(token), id);
8868
+ }
8869
+ if (token.type === "list")
8870
+ return this.createListRenderable(token, id);
8871
+ if (token.type === "code")
8872
+ return this.createCodeRenderable(token, id);
8873
+ if (token.type === "blockquote")
8874
+ return this.createBlockquoteRenderable(token, id);
8875
+ if (token.type === "hr")
8876
+ return this.createHorizontalRuleRenderable(id);
8877
+ if (token.type === "table")
8878
+ return this.createTableBlock(token, id).renderable;
8879
+ return token.raw ? this.createMarkdownCodeRenderable(token.raw, id) : null;
8880
+ }
8881
+ createHorizontalRuleRenderable(id, marginBottom = 0) {
8882
+ return new BoxRenderable(this.ctx, {
8883
+ id,
8884
+ width: "100%",
8885
+ height: 1,
8886
+ border: ["top"],
8887
+ borderColor: this.getStyle("conceal")?.fg ?? this._fg ?? "#888888",
8888
+ flexShrink: 0,
8889
+ marginBottom
8890
+ });
8891
+ }
9495
8892
  createCodeRenderable(token, id, marginBottom = 0) {
9496
8893
  return new CodeRenderable(this.ctx, {
9497
8894
  id,
@@ -9501,14 +8898,14 @@ class MarkdownRenderable extends Renderable {
9501
8898
  fg: this._fg,
9502
8899
  bg: this._bg,
9503
8900
  conceal: this._concealCode,
9504
- drawUnstyledText: !(this._streaming && this._concealCode),
8901
+ drawUnstyledText: !this._streaming,
9505
8902
  streaming: this._streaming,
9506
8903
  treeSitterClient: this._treeSitterClient,
9507
8904
  width: "100%",
9508
8905
  marginBottom
9509
8906
  });
9510
8907
  }
9511
- applyMarkdownCodeRenderable(renderable, content, marginBottom) {
8908
+ applyMarkdownCodeRenderable(renderable, content, marginBottom, baseHighlight) {
9512
8909
  renderable.content = content;
9513
8910
  renderable.filetype = "markdown";
9514
8911
  renderable.syntaxStyle = this._syntaxStyle;
@@ -9517,21 +8914,39 @@ class MarkdownRenderable extends Renderable {
9517
8914
  renderable.conceal = this._conceal;
9518
8915
  renderable.drawUnstyledText = false;
9519
8916
  renderable.streaming = true;
8917
+ renderable.baseHighlight = baseHighlight;
8918
+ renderable.marginBottom = marginBottom;
8919
+ }
8920
+ applyBlockquoteRenderable(renderable, token, marginBottom) {
8921
+ if (!(renderable instanceof BoxRenderable))
8922
+ return;
8923
+ renderable.borderColor = this.getBlockquoteBorderColor();
9520
8924
  renderable.marginBottom = marginBottom;
8925
+ const child = renderable.getChildren()[0];
8926
+ if (child instanceof CodeRenderable) {
8927
+ this.applyMarkdownCodeRenderable(child, this.getBlockquoteContent(token), 0, "markup.quote");
8928
+ return;
8929
+ }
8930
+ for (const existing of renderable.getChildren()) {
8931
+ existing.destroyRecursively();
8932
+ }
8933
+ renderable.add(this.createMarkdownCodeRenderable(this.getBlockquoteContent(token), `${renderable.id}-content`, 0, this._linkifyMarkdownChunks, "markup.quote"));
9521
8934
  }
9522
8935
  applyCodeBlockRenderable(renderable, token, marginBottom) {
9523
- renderable.content = token.text;
8936
+ if (!(renderable instanceof CodeRenderable))
8937
+ return;
9524
8938
  renderable.filetype = infoStringToFiletype(token.lang ?? "");
9525
8939
  renderable.syntaxStyle = this._syntaxStyle;
9526
8940
  renderable.fg = this._fg;
9527
8941
  renderable.bg = this._bg;
9528
8942
  renderable.conceal = this._concealCode;
9529
- renderable.drawUnstyledText = !(this._streaming && this._concealCode);
8943
+ renderable.drawUnstyledText = !this._streaming;
9530
8944
  renderable.streaming = this._streaming;
8945
+ renderable.content = token.text;
9531
8946
  renderable.marginBottom = marginBottom;
9532
8947
  }
9533
8948
  shouldRenderSeparately(token) {
9534
- return token.type === "code" || token.type === "table" || token.type === "blockquote";
8949
+ return token.type === "code" || token.type === "table" || token.type === "blockquote" || token.type === "hr";
9535
8950
  }
9536
8951
  getInterBlockMargin(token, hasNextToken) {
9537
8952
  if (!hasNextToken)
@@ -9550,6 +8965,9 @@ class MarkdownRenderable extends Renderable {
9550
8965
  return raw.replace(TRAILING_MARKDOWN_BLOCK_BREAKS_RE, `
9551
8966
  `);
9552
8967
  }
8968
+ normalizeScrollbackMarkdownBlockRaw(raw) {
8969
+ return raw.replace(TRAILING_MARKDOWN_BLOCK_NEWLINES_RE, "");
8970
+ }
9553
8971
  buildRenderableTokens(tokens) {
9554
8972
  if (this._renderNode) {
9555
8973
  return tokens.filter((token) => token.type !== "space");
@@ -9591,6 +9009,36 @@ class MarkdownRenderable extends Renderable {
9591
9009
  flushMarkdownRaw();
9592
9010
  return renderTokens;
9593
9011
  }
9012
+ buildTopLevelRenderBlocks(tokens) {
9013
+ const blocks = [];
9014
+ let gapBefore = "";
9015
+ for (let i = 0;i < tokens.length; i += 1) {
9016
+ const token = tokens[i];
9017
+ if (token.type === "space") {
9018
+ gapBefore += token.raw;
9019
+ continue;
9020
+ }
9021
+ const prev = blocks[blocks.length - 1];
9022
+ const marginTop = prev && this.shouldAddTopLevelMargin(prev.token, token, gapBefore) ? 1 : 0;
9023
+ blocks.push({
9024
+ token,
9025
+ sourceTokenEnd: i + 1,
9026
+ marginTop
9027
+ });
9028
+ gapBefore = "";
9029
+ }
9030
+ return blocks;
9031
+ }
9032
+ shouldAddTopLevelMargin(prev, current, gapBefore) {
9033
+ if (this.isSeparatedTopLevelBlock(prev) || this.isSeparatedTopLevelBlock(current))
9034
+ return true;
9035
+ if (prev.type !== "paragraph" || current.type !== "paragraph")
9036
+ return false;
9037
+ return TRAILING_MARKDOWN_BLOCK_BREAKS_RE.test(prev.raw + gapBefore);
9038
+ }
9039
+ isSeparatedTopLevelBlock(token) {
9040
+ return token.type === "heading" || token.type === "list" || this.shouldRenderSeparately(token);
9041
+ }
9594
9042
  getTableRowsToRender(table) {
9595
9043
  return table.rows;
9596
9044
  }
@@ -9712,13 +9160,31 @@ class MarkdownRenderable extends Renderable {
9712
9160
  changed
9713
9161
  };
9714
9162
  }
9163
+ resolveTableStyle(options = this._tableOptions) {
9164
+ if (options?.style === "columns") {
9165
+ return "columns";
9166
+ }
9167
+ if (options?.style === "grid") {
9168
+ return "grid";
9169
+ }
9170
+ return this._internalBlockMode === "top-level" ? "columns" : "grid";
9171
+ }
9172
+ usesBorderlessColumnSpacing(options = this._tableOptions) {
9173
+ const style = this.resolveTableStyle(options);
9174
+ const borders = options?.borders ?? style === "grid";
9175
+ return style === "columns" && !borders;
9176
+ }
9715
9177
  resolveTableRenderableOptions() {
9716
- const borders = this._tableOptions?.borders ?? true;
9178
+ const style = this.resolveTableStyle();
9179
+ const borders = this._tableOptions?.borders ?? style === "grid";
9717
9180
  return {
9718
- columnWidthMode: this._tableOptions?.widthMode ?? "full",
9181
+ columnWidthMode: this._tableOptions?.widthMode ?? (style === "columns" ? "content" : "full"),
9719
9182
  columnFitter: this._tableOptions?.columnFitter ?? "proportional",
9720
9183
  wrapMode: this._tableOptions?.wrapMode ?? "word",
9721
9184
  cellPadding: this._tableOptions?.cellPadding ?? 0,
9185
+ cellPaddingX: this._tableOptions?.cellPaddingX ?? this._tableOptions?.cellPadding ?? 0,
9186
+ cellPaddingY: this._tableOptions?.cellPaddingY ?? this._tableOptions?.cellPadding ?? 0,
9187
+ columnGap: this.usesBorderlessColumnSpacing() ? 2 : 0,
9722
9188
  border: borders,
9723
9189
  outerBorder: this._tableOptions?.outerBorder ?? borders,
9724
9190
  showBorders: borders,
@@ -9731,7 +9197,9 @@ class MarkdownRenderable extends Renderable {
9731
9197
  tableRenderable.columnWidthMode = options.columnWidthMode;
9732
9198
  tableRenderable.columnFitter = options.columnFitter;
9733
9199
  tableRenderable.wrapMode = options.wrapMode;
9734
- tableRenderable.cellPadding = options.cellPadding;
9200
+ tableRenderable.cellPaddingX = options.cellPaddingX;
9201
+ tableRenderable.cellPaddingY = options.cellPaddingY;
9202
+ tableRenderable.columnGap = options.columnGap;
9735
9203
  tableRenderable.border = options.border;
9736
9204
  tableRenderable.outerBorder = options.outerBorder;
9737
9205
  tableRenderable.showBorders = options.showBorders;
@@ -9763,6 +9231,9 @@ class MarkdownRenderable extends Renderable {
9763
9231
  columnFitter: options.columnFitter,
9764
9232
  wrapMode: options.wrapMode,
9765
9233
  cellPadding: options.cellPadding,
9234
+ cellPaddingX: options.cellPaddingX,
9235
+ cellPaddingY: options.cellPaddingY,
9236
+ columnGap: options.columnGap,
9766
9237
  border: options.border,
9767
9238
  outerBorder: options.outerBorder,
9768
9239
  showBorders: options.showBorders,
@@ -9783,12 +9254,106 @@ class MarkdownRenderable extends Renderable {
9783
9254
  tableContentCache: cache
9784
9255
  };
9785
9256
  }
9257
+ getStableBlockCount(blocks, stableTokenCount) {
9258
+ if (this._internalBlockMode !== "top-level") {
9259
+ return 0;
9260
+ }
9261
+ let stableBlockCount = 0;
9262
+ for (const block of blocks) {
9263
+ if (block.sourceTokenEnd <= stableTokenCount) {
9264
+ stableBlockCount += 1;
9265
+ continue;
9266
+ }
9267
+ break;
9268
+ }
9269
+ return stableBlockCount;
9270
+ }
9271
+ syncTopLevelBlockState(state, block, tableContentCache = state.tableContentCache) {
9272
+ state.token = block.token;
9273
+ state.tokenRaw = block.token.raw;
9274
+ state.marginTop = block.marginTop;
9275
+ state.tableContentCache = tableContentCache;
9276
+ }
9277
+ getTopLevelBlockRaw(token) {
9278
+ if (!token.raw) {
9279
+ return;
9280
+ }
9281
+ return this.shouldRenderSeparately(token) ? token.raw : this.normalizeScrollbackMarkdownBlockRaw(token.raw);
9282
+ }
9283
+ createTopLevelDefaultRenderable(block, index) {
9284
+ const { token, marginTop } = block;
9285
+ const id = `${this.id}-block-${index}`;
9286
+ if (token.type === "code") {
9287
+ const renderable2 = this.createCodeRenderable(token, id);
9288
+ renderable2.marginTop = marginTop;
9289
+ return { renderable: renderable2 };
9290
+ }
9291
+ if (token.type === "table") {
9292
+ const next = this.createTableBlock(token, id);
9293
+ next.renderable.marginTop = marginTop;
9294
+ return next;
9295
+ }
9296
+ if (token.type === "blockquote") {
9297
+ const renderable2 = this.createBlockquoteRenderable(token, id);
9298
+ renderable2.marginTop = marginTop;
9299
+ return { renderable: renderable2 };
9300
+ }
9301
+ if (token.type === "list") {
9302
+ const renderable2 = this.createListRenderable(token, id);
9303
+ renderable2.marginTop = marginTop;
9304
+ return { renderable: renderable2 };
9305
+ }
9306
+ if (token.type === "hr") {
9307
+ const renderable2 = this.createHorizontalRuleRenderable(id);
9308
+ renderable2.marginTop = marginTop;
9309
+ return { renderable: renderable2 };
9310
+ }
9311
+ const markdownRaw = this.getTopLevelBlockRaw(token);
9312
+ if (!markdownRaw) {
9313
+ return { renderable: undefined };
9314
+ }
9315
+ const renderable = this.createMarkdownCodeRenderable(markdownRaw, id);
9316
+ renderable.marginTop = marginTop;
9317
+ return { renderable };
9318
+ }
9319
+ createTopLevelRenderable(block, index) {
9320
+ if (!this._renderNode) {
9321
+ return this.createTopLevelDefaultRenderable(block, index);
9322
+ }
9323
+ let next;
9324
+ const context = {
9325
+ syntaxStyle: this._syntaxStyle,
9326
+ conceal: this._conceal,
9327
+ concealCode: this._concealCode,
9328
+ treeSitterClient: this._treeSitterClient,
9329
+ defaultRender: () => {
9330
+ next = this.createTopLevelDefaultRenderable(block, index);
9331
+ return next.renderable ?? null;
9332
+ }
9333
+ };
9334
+ const custom = this._renderNode(block.token, context);
9335
+ if (custom) {
9336
+ const marginTop = typeof custom.marginTop === "number" ? Math.max(custom.marginTop, block.marginTop) : block.marginTop;
9337
+ this.applyMargins(custom, marginTop, 0);
9338
+ return { renderable: custom };
9339
+ }
9340
+ return next ?? this.createTopLevelDefaultRenderable(block, index);
9341
+ }
9786
9342
  createDefaultRenderable(token, index, hasNextToken = false) {
9787
9343
  const id = `${this.id}-block-${index}`;
9788
9344
  const marginBottom = this.getInterBlockMargin(token, hasNextToken);
9789
9345
  if (token.type === "code") {
9790
9346
  return this.createCodeRenderable(token, id, marginBottom);
9791
9347
  }
9348
+ if (token.type === "blockquote") {
9349
+ return this.createBlockquoteRenderable(token, id, marginBottom);
9350
+ }
9351
+ if (token.type === "list") {
9352
+ return this.createListRenderable(token, id, marginBottom);
9353
+ }
9354
+ if (token.type === "hr") {
9355
+ return this.createHorizontalRuleRenderable(id, marginBottom);
9356
+ }
9792
9357
  if (token.type === "table") {
9793
9358
  return this.createTableBlock(token, id, marginBottom).renderable;
9794
9359
  }
@@ -9800,12 +9365,28 @@ class MarkdownRenderable extends Renderable {
9800
9365
  }
9801
9366
  return this.createMarkdownCodeRenderable(token.raw, id, marginBottom);
9802
9367
  }
9803
- updateBlockRenderable(state, token, index, hasNextToken) {
9368
+ updateBlockRenderable(state, token, index, hasNextToken, forceListRefresh = false) {
9804
9369
  const marginBottom = this.getInterBlockMargin(token, hasNextToken);
9805
9370
  if (token.type === "code") {
9806
9371
  this.applyCodeBlockRenderable(state.renderable, token, marginBottom);
9807
9372
  return;
9808
9373
  }
9374
+ if (token.type === "blockquote") {
9375
+ this.applyBlockquoteRenderable(state.renderable, token, marginBottom);
9376
+ return;
9377
+ }
9378
+ if (token.type === "list") {
9379
+ if (!this.applyListRenderable(state.renderable, token, forceListRefresh ? undefined : state.token, `${this.id}-block-${index}`, marginBottom)) {
9380
+ state.renderable.destroyRecursively();
9381
+ state.renderable = this.createListRenderable(token, `${this.id}-block-${index}`, marginBottom);
9382
+ this.add(state.renderable, index);
9383
+ }
9384
+ return;
9385
+ }
9386
+ if (token.type === "hr") {
9387
+ state.renderable.marginBottom = marginBottom;
9388
+ return;
9389
+ }
9809
9390
  if (token.type === "table") {
9810
9391
  const tableToken = token;
9811
9392
  const { cache, changed } = this.buildTableContentCache(tableToken, state.tableContentCache);
@@ -9817,7 +9398,7 @@ class MarkdownRenderable extends Renderable {
9817
9398
  }
9818
9399
  state.renderable.destroyRecursively();
9819
9400
  const fallbackRenderable = this.createMarkdownCodeRenderable(tableToken.raw, `${this.id}-block-${index}`, marginBottom);
9820
- this.add(fallbackRenderable);
9401
+ this.add(fallbackRenderable, index);
9821
9402
  state.renderable = fallbackRenderable;
9822
9403
  state.tableContentCache = undefined;
9823
9404
  return;
@@ -9833,26 +9414,94 @@ class MarkdownRenderable extends Renderable {
9833
9414
  }
9834
9415
  state.renderable.destroyRecursively();
9835
9416
  const tableRenderable = this.createTextTableRenderable(cache.content, `${this.id}-block-${index}`, marginBottom);
9836
- this.add(tableRenderable);
9417
+ this.add(tableRenderable, index);
9837
9418
  state.renderable = tableRenderable;
9838
9419
  state.tableContentCache = cache;
9839
9420
  return;
9840
9421
  }
9841
9422
  if (state.renderable instanceof CodeRenderable) {
9842
- this.applyMarkdownCodeRenderable(state.renderable, token.raw, marginBottom);
9423
+ this.applyMarkdownCodeRenderable(state.renderable, this.getTopLevelBlockRaw(token) ?? token.raw, marginBottom);
9843
9424
  return;
9844
9425
  }
9845
9426
  state.renderable.destroyRecursively();
9846
- const markdownRenderable = this.createMarkdownCodeRenderable(token.raw, `${this.id}-block-${index}`, marginBottom);
9847
- this.add(markdownRenderable);
9427
+ const markdownRenderable = this.createMarkdownCodeRenderable(this.getTopLevelBlockRaw(token) ?? token.raw, `${this.id}-block-${index}`, marginBottom);
9428
+ this.add(markdownRenderable, index);
9848
9429
  state.renderable = markdownRenderable;
9849
9430
  }
9431
+ updateTopLevelBlocks(tokens, forceTableRefresh) {
9432
+ const blocks = this.buildTopLevelRenderBlocks(tokens);
9433
+ this._stableBlockCount = this.getStableBlockCount(blocks, this._parseState?.stableTokenCount ?? 0);
9434
+ let blockIndex = 0;
9435
+ for (let i = 0;i < blocks.length; i += 1) {
9436
+ const block = blocks[i];
9437
+ const existing = this._blockStates[blockIndex];
9438
+ if (existing && existing.token === block.token && !forceTableRefresh) {
9439
+ if (existing.marginTop !== block.marginTop) {
9440
+ this.applyMargins(existing.renderable, block.marginTop, 0);
9441
+ }
9442
+ this.syncTopLevelBlockState(existing, block);
9443
+ blockIndex++;
9444
+ continue;
9445
+ }
9446
+ if (existing && existing.tokenRaw === block.token.raw && existing.token.type === block.token.type && !forceTableRefresh) {
9447
+ if (existing.marginTop !== block.marginTop) {
9448
+ this.applyMargins(existing.renderable, block.marginTop, 0);
9449
+ }
9450
+ this.syncTopLevelBlockState(existing, block);
9451
+ blockIndex++;
9452
+ continue;
9453
+ }
9454
+ if (existing && !forceTableRefresh && !this._renderNode && existing.token.type === block.token.type && this.canUpdateBlockRenderable(existing.renderable, block.token)) {
9455
+ this.updateBlockRenderable(existing, block.token, blockIndex, blockIndex < blocks.length - 1);
9456
+ existing.renderable.marginBottom = 0;
9457
+ if (existing.marginTop !== block.marginTop) {
9458
+ this.applyMargins(existing.renderable, block.marginTop, 0);
9459
+ }
9460
+ this.syncTopLevelBlockState(existing, block);
9461
+ blockIndex++;
9462
+ continue;
9463
+ }
9464
+ if (existing) {
9465
+ existing.renderable.destroyRecursively();
9466
+ }
9467
+ const next = this.createTopLevelRenderable(block, blockIndex);
9468
+ if (next.renderable) {
9469
+ this.add(next.renderable, blockIndex);
9470
+ this._blockStates[blockIndex] = {
9471
+ token: block.token,
9472
+ tokenRaw: block.token.raw,
9473
+ marginTop: block.marginTop,
9474
+ renderable: next.renderable,
9475
+ tableContentCache: next.tableContentCache
9476
+ };
9477
+ }
9478
+ blockIndex++;
9479
+ }
9480
+ while (this._blockStates.length > blockIndex) {
9481
+ const removed = this._blockStates.pop();
9482
+ removed.renderable.destroyRecursively();
9483
+ }
9484
+ }
9485
+ canUpdateBlockRenderable(renderable, token) {
9486
+ if (token.type === "code")
9487
+ return renderable instanceof CodeRenderable;
9488
+ if (token.type === "table")
9489
+ return renderable instanceof TextTableRenderable;
9490
+ if (token.type === "blockquote")
9491
+ return renderable instanceof BoxRenderable;
9492
+ if (token.type === "list")
9493
+ return renderable instanceof BoxRenderable;
9494
+ if (token.type === "hr")
9495
+ return renderable instanceof BoxRenderable;
9496
+ return renderable instanceof CodeRenderable;
9497
+ }
9850
9498
  updateBlocks(forceTableRefresh = false) {
9851
9499
  if (this.isDestroyed)
9852
9500
  return;
9853
9501
  if (!this._content) {
9854
9502
  this.clearBlockStates();
9855
9503
  this._parseState = null;
9504
+ this._stableBlockCount = 0;
9856
9505
  return;
9857
9506
  }
9858
9507
  const trailingUnstable = this._streaming ? 2 : 0;
@@ -9860,17 +9509,24 @@ class MarkdownRenderable extends Renderable {
9860
9509
  const tokens = this._parseState.tokens;
9861
9510
  if (tokens.length === 0 && this._content.length > 0) {
9862
9511
  this.clearBlockStates();
9512
+ this._stableBlockCount = 0;
9863
9513
  const fallback = this.createMarkdownCodeRenderable(this._content, `${this.id}-fallback`);
9864
9514
  this.add(fallback);
9865
9515
  this._blockStates = [
9866
9516
  {
9867
9517
  token: { type: "text", raw: this._content, text: this._content },
9868
9518
  tokenRaw: this._content,
9519
+ marginTop: 0,
9869
9520
  renderable: fallback
9870
9521
  }
9871
9522
  ];
9872
9523
  return;
9873
9524
  }
9525
+ if (this._internalBlockMode === "top-level") {
9526
+ this.updateTopLevelBlocks(tokens, forceTableRefresh);
9527
+ return;
9528
+ }
9529
+ this._stableBlockCount = 0;
9874
9530
  const blockTokens = this.buildRenderableTokens(tokens);
9875
9531
  const lastBlockIndex = blockTokens.length - 1;
9876
9532
  let blockIndex = 0;
@@ -9935,7 +9591,7 @@ class MarkdownRenderable extends Renderable {
9935
9591
  tableContentCache = cache ?? undefined;
9936
9592
  }
9937
9593
  if (renderable) {
9938
- this.add(renderable);
9594
+ this.add(renderable, blockIndex);
9939
9595
  this._blockStates[blockIndex] = {
9940
9596
  token,
9941
9597
  tokenRaw: token.raw,
@@ -9955,8 +9611,13 @@ class MarkdownRenderable extends Renderable {
9955
9611
  state.renderable.destroyRecursively();
9956
9612
  }
9957
9613
  this._blockStates = [];
9614
+ this._stableBlockCount = 0;
9958
9615
  }
9959
9616
  rerenderBlocks() {
9617
+ if (this._internalBlockMode === "top-level") {
9618
+ this.updateBlocks(true);
9619
+ return;
9620
+ }
9960
9621
  for (let i = 0;i < this._blockStates.length; i++) {
9961
9622
  const state = this._blockStates[i];
9962
9623
  const hasNextToken = i < this._blockStates.length - 1;
@@ -9965,6 +9626,18 @@ class MarkdownRenderable extends Renderable {
9965
9626
  this.applyCodeBlockRenderable(state.renderable, state.token, marginBottom);
9966
9627
  continue;
9967
9628
  }
9629
+ if (state.token.type === "blockquote") {
9630
+ this.applyBlockquoteRenderable(state.renderable, state.token, marginBottom);
9631
+ continue;
9632
+ }
9633
+ if (state.token.type === "list") {
9634
+ this.updateBlockRenderable(state, state.token, i, hasNextToken, true);
9635
+ continue;
9636
+ }
9637
+ if (state.token.type === "hr") {
9638
+ state.renderable.marginBottom = marginBottom;
9639
+ continue;
9640
+ }
9968
9641
  if (state.token.type === "table") {
9969
9642
  const tableToken = state.token;
9970
9643
  const { cache } = this.buildTableContentCache(tableToken, state.tableContentCache, true);
@@ -9974,7 +9647,7 @@ class MarkdownRenderable extends Renderable {
9974
9647
  } else {
9975
9648
  state.renderable.destroyRecursively();
9976
9649
  const fallbackRenderable = this.createMarkdownCodeRenderable(tableToken.raw, `${this.id}-block-${i}`, marginBottom);
9977
- this.add(fallbackRenderable);
9650
+ this.add(fallbackRenderable, i);
9978
9651
  state.renderable = fallbackRenderable;
9979
9652
  }
9980
9653
  state.tableContentCache = undefined;
@@ -9989,18 +9662,18 @@ class MarkdownRenderable extends Renderable {
9989
9662
  }
9990
9663
  state.renderable.destroyRecursively();
9991
9664
  const tableRenderable = this.createTextTableRenderable(cache.content, `${this.id}-block-${i}`, marginBottom);
9992
- this.add(tableRenderable);
9665
+ this.add(tableRenderable, i);
9993
9666
  state.renderable = tableRenderable;
9994
9667
  state.tableContentCache = cache;
9995
9668
  continue;
9996
9669
  }
9997
9670
  if (state.renderable instanceof CodeRenderable) {
9998
- this.applyMarkdownCodeRenderable(state.renderable, state.token.raw, marginBottom);
9671
+ this.applyMarkdownCodeRenderable(state.renderable, this.getTopLevelBlockRaw(state.token) ?? state.token.raw, marginBottom);
9999
9672
  continue;
10000
9673
  }
10001
9674
  state.renderable.destroyRecursively();
10002
- const markdownRenderable = this.createMarkdownCodeRenderable(state.token.raw, `${this.id}-block-${i}`, marginBottom);
10003
- this.add(markdownRenderable);
9675
+ const markdownRenderable = this.createMarkdownCodeRenderable(this.getTopLevelBlockRaw(state.token) ?? state.token.raw, `${this.id}-block-${i}`, marginBottom);
9676
+ this.add(markdownRenderable, i);
10004
9677
  state.renderable = markdownRenderable;
10005
9678
  }
10006
9679
  }
@@ -10619,11 +10292,19 @@ class ContentRenderable extends BoxRenderable {
10619
10292
  set viewportCulling(value) {
10620
10293
  this._viewportCulling = value;
10621
10294
  }
10295
+ _hasVisibleChildFilter() {
10296
+ return this._viewportCulling;
10297
+ }
10622
10298
  _getVisibleChildren() {
10623
10299
  if (this._viewportCulling) {
10624
- return getObjectsInViewport(this.viewport, this.getChildrenSortedByPrimaryAxis(), this.primaryAxis, 0).map((child) => child.num);
10300
+ return getObjectsInViewport({
10301
+ x: this.viewport.screenX,
10302
+ y: this.viewport.screenY,
10303
+ width: this.viewport.width,
10304
+ height: this.viewport.height
10305
+ }, this.getChildrenSortedByPrimaryAxis(), this.primaryAxis, 0).map((child) => child.num);
10625
10306
  }
10626
- return this.getChildrenSortedByPrimaryAxis().map((child) => child.num);
10307
+ return super._getVisibleChildren();
10627
10308
  }
10628
10309
  }
10629
10310
  var SCROLLBOX_PADDING_KEYS = [
@@ -11210,7 +10891,9 @@ class ScrollBoxRenderable extends BoxRenderable {
11210
10891
  } finally {
11211
10892
  this._isApplyingStickyScroll = wasApplyingStickyScroll;
11212
10893
  }
11213
- this.requestRender();
10894
+ process.nextTick(() => {
10895
+ this.requestRender();
10896
+ });
11214
10897
  }
11215
10898
  set padding(value) {
11216
10899
  this.content.padding = value;
@@ -11516,15 +11199,7 @@ class SelectRenderable extends Renderable {
11516
11199
  this.requestRender();
11517
11200
  }
11518
11201
  handleKeyPress(key) {
11519
- const bindingKey = getKeyBindingKey({
11520
- name: key.name,
11521
- ctrl: key.ctrl,
11522
- shift: key.shift,
11523
- meta: key.meta,
11524
- super: key.super,
11525
- action: "move-up"
11526
- });
11527
- const action = this._keyBindingsMap.get(bindingKey);
11202
+ const action = getKeyBindingAction(this._keyBindingsMap, key);
11528
11203
  if (action) {
11529
11204
  switch (action) {
11530
11205
  case "move-up":
@@ -11884,15 +11559,7 @@ class TabSelectRenderable extends Renderable {
11884
11559
  return this._tabWidth;
11885
11560
  }
11886
11561
  handleKeyPress(key) {
11887
- const bindingKey = getKeyBindingKey({
11888
- name: key.name,
11889
- ctrl: key.ctrl,
11890
- shift: key.shift,
11891
- meta: key.meta,
11892
- super: key.super,
11893
- action: "move-left"
11894
- });
11895
- const action = this._keyBindingsMap.get(bindingKey);
11562
+ const action = getKeyBindingAction(this._keyBindingsMap, key);
11896
11563
  if (action) {
11897
11564
  switch (action) {
11898
11565
  case "move-left":
@@ -12068,7 +11735,7 @@ class TimeToFirstDrawRenderable extends Renderable {
12068
11735
  return Math.max(0, Math.floor(value));
12069
11736
  }
12070
11737
  }
12071
- export { TextBufferView, convertThemeToStyles, SyntaxStyle, DistortionEffect, VignetteEffect, CloudsEffect, FlamesEffect, CRTRollingBarEffect, RainbowTextEffect, applyScanlines, applyInvert, applyNoise, applyChromaticAberration, applyAsciiArt, applyBrightness, applyGain, applySaturation, BloomEffect, SEPIA_MATRIX, PROTANOPIA_SIM_MATRIX, DEUTERANOPIA_SIM_MATRIX, TRITANOPIA_SIM_MATRIX, ACHROMATOPSIA_MATRIX, PROTANOPIA_COMP_MATRIX, DEUTERANOPIA_COMP_MATRIX, TRITANOPIA_COMP_MATRIX, TECHNICOLOR_MATRIX, SOLARIZATION_MATRIX, SYNTHWAVE_MATRIX, GREENSCALE_MATRIX, GRAYSCALE_MATRIX, INVERT_MATRIX, Timeline, engine, createTimeline, SlotRegistry, createSlotRegistry, createCoreSlotRegistry, registerCorePlugin, resolveCoreSlot, SlotRenderable, NativeSpanFeed, FrameBufferRenderable, ASCIIFontRenderable, BoxRenderable, TextBufferRenderable, CodeRenderable, isTextNodeRenderable, TextNodeRenderable, RootTextNodeRenderable, Generic, Box, Text, ASCIIFont, Input, Select, TabSelect, FrameBuffer, Code, ScrollBox, vstyles, VRenderable, LineNumberRenderable, TextRenderable, DiffRenderable, TextareaRenderable, InputRenderableEvents, InputRenderable, TextTableRenderable, MarkdownRenderable, SliderRenderable, ScrollBarRenderable, ArrowRenderable, ScrollBoxRenderable, SelectRenderableEvents, SelectRenderable, TabSelectRenderableEvents, TabSelectRenderable, TimeToFirstDrawRenderable, exports_src2 as exports_src };
11738
+ export { DistortionEffect, VignetteEffect, CloudsEffect, FlamesEffect, CRTRollingBarEffect, RainbowTextEffect, applyScanlines, applyInvert, applyNoise, applyChromaticAberration, applyAsciiArt, applyBrightness, applyGain, applySaturation, BloomEffect, SEPIA_MATRIX, PROTANOPIA_SIM_MATRIX, DEUTERANOPIA_SIM_MATRIX, TRITANOPIA_SIM_MATRIX, ACHROMATOPSIA_MATRIX, PROTANOPIA_COMP_MATRIX, DEUTERANOPIA_COMP_MATRIX, TRITANOPIA_COMP_MATRIX, TECHNICOLOR_MATRIX, SOLARIZATION_MATRIX, SYNTHWAVE_MATRIX, GREENSCALE_MATRIX, GRAYSCALE_MATRIX, INVERT_MATRIX, Timeline, engine, createTimeline, SlotRegistry, createSlotRegistry, createCoreSlotRegistry, registerCorePlugin, resolveCoreSlot, SlotRenderable, NativeSpanFeed, Audio, setupAudio, FrameBufferRenderable, ASCIIFontRenderable, Generic, Box, Text, ASCIIFont, Input, Select, TabSelect, FrameBuffer, Code, ScrollBox, vstyles, VRenderable, LineNumberRenderable, DiffRenderable, defaultTextareaKeyBindings, TextareaRenderable, InputRenderableEvents, InputRenderable, TextTableRenderable, MarkdownRenderable, SliderRenderable, ScrollBarRenderable, ArrowRenderable, ScrollBoxRenderable, SelectRenderableEvents, SelectRenderable, TabSelectRenderableEvents, TabSelectRenderable, TimeToFirstDrawRenderable, exports_src2 as exports_src };
12072
11739
 
12073
- //# debugId=AD3EE32E00BF5BFC64756E2164756E21
12074
- //# sourceMappingURL=index-yxe6e14n.js.map
11740
+ //# debugId=F2F05271FFA5C07164756E2164756E21
11741
+ //# sourceMappingURL=index-46f5e8m6.js.map