@floegence/floeterm-terminal-web 0.14.1 → 0.15.0

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 (156) hide show
  1. package/README.md +78 -445
  2. package/dist/core/TerminalInputBridge.d.ts +7 -3
  3. package/dist/core/TerminalInputBridge.d.ts.map +1 -1
  4. package/dist/core/TerminalInputBridge.js +63 -4
  5. package/dist/core/TerminalInputBridge.js.map +1 -1
  6. package/dist/entries/live.d.ts +4 -4
  7. package/dist/entries/live.d.ts.map +1 -1
  8. package/dist/entries/live.js +2 -2
  9. package/dist/entries/live.js.map +1 -1
  10. package/dist/entries/semantic.d.ts +9 -0
  11. package/dist/entries/semantic.d.ts.map +1 -0
  12. package/dist/entries/semantic.js +5 -0
  13. package/dist/entries/semantic.js.map +1 -0
  14. package/dist/entries/sessions.d.ts +1 -1
  15. package/dist/entries/sessions.d.ts.map +1 -1
  16. package/dist/index.d.ts +4 -26
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +3 -16
  19. package/dist/index.js.map +1 -1
  20. package/dist/live/client.d.ts +4 -6
  21. package/dist/live/client.d.ts.map +1 -1
  22. package/dist/live/client.js +19 -72
  23. package/dist/live/client.js.map +1 -1
  24. package/dist/live/codec.d.ts +8 -21
  25. package/dist/live/codec.d.ts.map +1 -1
  26. package/dist/live/codec.js +79 -111
  27. package/dist/live/codec.js.map +1 -1
  28. package/dist/live/transport.d.ts +38 -18
  29. package/dist/live/transport.d.ts.map +1 -1
  30. package/dist/live/transport.js +59 -133
  31. package/dist/live/transport.js.map +1 -1
  32. package/dist/semantic/RendererSurface.d.ts +65 -0
  33. package/dist/semantic/RendererSurface.d.ts.map +1 -0
  34. package/dist/semantic/RendererSurface.js +566 -0
  35. package/dist/semantic/RendererSurface.js.map +1 -0
  36. package/dist/semantic/presentation.d.ts +97 -0
  37. package/dist/semantic/presentation.d.ts.map +1 -0
  38. package/dist/semantic/presentation.js +102 -0
  39. package/dist/semantic/presentation.js.map +1 -0
  40. package/dist/types.d.ts +13 -494
  41. package/dist/types.d.ts.map +1 -1
  42. package/dist/types.js +1 -37
  43. package/dist/types.js.map +1 -1
  44. package/package.json +11 -19
  45. package/dist/checkpoint/GhosttyCheckpoint.worker.d.ts +0 -2
  46. package/dist/checkpoint/GhosttyCheckpoint.worker.d.ts.map +0 -1
  47. package/dist/checkpoint/GhosttyCheckpoint.worker.js +0 -9
  48. package/dist/checkpoint/GhosttyCheckpoint.worker.js.map +0 -1
  49. package/dist/checkpoint/GhosttyCheckpointActor.d.ts +0 -44
  50. package/dist/checkpoint/GhosttyCheckpointActor.d.ts.map +0 -1
  51. package/dist/checkpoint/GhosttyCheckpointActor.js +0 -284
  52. package/dist/checkpoint/GhosttyCheckpointActor.js.map +0 -1
  53. package/dist/checkpoint/GhosttyCheckpointEngine.d.ts +0 -62
  54. package/dist/checkpoint/GhosttyCheckpointEngine.d.ts.map +0 -1
  55. package/dist/checkpoint/GhosttyCheckpointEngine.js +0 -175
  56. package/dist/checkpoint/GhosttyCheckpointEngine.js.map +0 -1
  57. package/dist/checkpoint/GhosttyCheckpointWorkerRuntime.d.ts +0 -31
  58. package/dist/checkpoint/GhosttyCheckpointWorkerRuntime.d.ts.map +0 -1
  59. package/dist/checkpoint/GhosttyCheckpointWorkerRuntime.js +0 -112
  60. package/dist/checkpoint/GhosttyCheckpointWorkerRuntime.js.map +0 -1
  61. package/dist/core/PagedTerminalOutputCoordinator.d.ts +0 -130
  62. package/dist/core/PagedTerminalOutputCoordinator.d.ts.map +0 -1
  63. package/dist/core/PagedTerminalOutputCoordinator.js +0 -1213
  64. package/dist/core/PagedTerminalOutputCoordinator.js.map +0 -1
  65. package/dist/core/TerminalCore.d.ts +0 -286
  66. package/dist/core/TerminalCore.d.ts.map +0 -1
  67. package/dist/core/TerminalCore.js +0 -3566
  68. package/dist/core/TerminalCore.js.map +0 -1
  69. package/dist/core/TerminalOutputPipeline.d.ts +0 -86
  70. package/dist/core/TerminalOutputPipeline.d.ts.map +0 -1
  71. package/dist/core/TerminalOutputPipeline.js +0 -511
  72. package/dist/core/TerminalOutputPipeline.js.map +0 -1
  73. package/dist/core/TerminalRenderScheduler.d.ts +0 -45
  74. package/dist/core/TerminalRenderScheduler.d.ts.map +0 -1
  75. package/dist/core/TerminalRenderScheduler.js +0 -145
  76. package/dist/core/TerminalRenderScheduler.js.map +0 -1
  77. package/dist/core/TerminalScrollbarOverlay.d.ts +0 -63
  78. package/dist/core/TerminalScrollbarOverlay.d.ts.map +0 -1
  79. package/dist/core/TerminalScrollbarOverlay.js +0 -493
  80. package/dist/core/TerminalScrollbarOverlay.js.map +0 -1
  81. package/dist/entries/history.d.ts +0 -4
  82. package/dist/entries/history.d.ts.map +0 -1
  83. package/dist/entries/history.js +0 -2
  84. package/dist/entries/history.js.map +0 -1
  85. package/dist/entries/preload.d.ts +0 -3
  86. package/dist/entries/preload.d.ts.map +0 -1
  87. package/dist/entries/preload.js +0 -2
  88. package/dist/entries/preload.js.map +0 -1
  89. package/dist/fabric/BeamtermFabricRenderer.d.ts +0 -67
  90. package/dist/fabric/BeamtermFabricRenderer.d.ts.map +0 -1
  91. package/dist/fabric/BeamtermFabricRenderer.js +0 -659
  92. package/dist/fabric/BeamtermFabricRenderer.js.map +0 -1
  93. package/dist/fabric/TerminalFabricCoordinator.d.ts +0 -40
  94. package/dist/fabric/TerminalFabricCoordinator.d.ts.map +0 -1
  95. package/dist/fabric/TerminalFabricCoordinator.js +0 -141
  96. package/dist/fabric/TerminalFabricCoordinator.js.map +0 -1
  97. package/dist/fabric/TerminalLiveFabric.d.ts +0 -44
  98. package/dist/fabric/TerminalLiveFabric.d.ts.map +0 -1
  99. package/dist/fabric/TerminalLiveFabric.js +0 -117
  100. package/dist/fabric/TerminalLiveFabric.js.map +0 -1
  101. package/dist/fabric/types.d.ts +0 -152
  102. package/dist/fabric/types.d.ts.map +0 -1
  103. package/dist/fabric/types.js +0 -2
  104. package/dist/fabric/types.js.map +0 -1
  105. package/dist/internal/BeamtermResourceLoader.d.ts +0 -3
  106. package/dist/internal/BeamtermResourceLoader.d.ts.map +0 -1
  107. package/dist/internal/BeamtermResourceLoader.js +0 -14
  108. package/dist/internal/BeamtermResourceLoader.js.map +0 -1
  109. package/dist/internal/GhosttyCompatibilityVersion.d.ts +0 -2
  110. package/dist/internal/GhosttyCompatibilityVersion.d.ts.map +0 -1
  111. package/dist/internal/GhosttyCompatibilityVersion.js +0 -2
  112. package/dist/internal/GhosttyCompatibilityVersion.js.map +0 -1
  113. package/dist/internal/GhosttyScrollbackCompat.d.ts +0 -16
  114. package/dist/internal/GhosttyScrollbackCompat.d.ts.map +0 -1
  115. package/dist/internal/GhosttyScrollbackCompat.js +0 -43
  116. package/dist/internal/GhosttyScrollbackCompat.js.map +0 -1
  117. package/dist/internal/GhosttyScrollbarCompat.d.ts +0 -12
  118. package/dist/internal/GhosttyScrollbarCompat.d.ts.map +0 -1
  119. package/dist/internal/GhosttyScrollbarCompat.js +0 -160
  120. package/dist/internal/GhosttyScrollbarCompat.js.map +0 -1
  121. package/dist/internal/SequenceBuffer.d.ts +0 -19
  122. package/dist/internal/SequenceBuffer.d.ts.map +0 -1
  123. package/dist/internal/SequenceBuffer.js +0 -83
  124. package/dist/internal/SequenceBuffer.js.map +0 -1
  125. package/dist/internal/TerminalInitializationScheduler.d.ts +0 -38
  126. package/dist/internal/TerminalInitializationScheduler.d.ts.map +0 -1
  127. package/dist/internal/TerminalInitializationScheduler.js +0 -112
  128. package/dist/internal/TerminalInitializationScheduler.js.map +0 -1
  129. package/dist/internal/TerminalResourceLoader.d.ts +0 -40
  130. package/dist/internal/TerminalResourceLoader.d.ts.map +0 -1
  131. package/dist/internal/TerminalResourceLoader.js +0 -165
  132. package/dist/internal/TerminalResourceLoader.js.map +0 -1
  133. package/dist/internal/UnicodeSafeUrlProvider.d.ts +0 -17
  134. package/dist/internal/UnicodeSafeUrlProvider.d.ts.map +0 -1
  135. package/dist/internal/UnicodeSafeUrlProvider.js +0 -32
  136. package/dist/internal/UnicodeSafeUrlProvider.js.map +0 -1
  137. package/dist/internal/scheduleUiTurn.d.ts +0 -5
  138. package/dist/internal/scheduleUiTurn.d.ts.map +0 -1
  139. package/dist/internal/scheduleUiTurn.js +0 -37
  140. package/dist/internal/scheduleUiTurn.js.map +0 -1
  141. package/dist/manager/TerminalInstanceController.d.ts +0 -88
  142. package/dist/manager/TerminalInstanceController.d.ts.map +0 -1
  143. package/dist/manager/TerminalInstanceController.js +0 -1076
  144. package/dist/manager/TerminalInstanceController.js.map +0 -1
  145. package/dist/utils/errors.d.ts +0 -3
  146. package/dist/utils/errors.d.ts.map +0 -1
  147. package/dist/utils/errors.js +0 -11
  148. package/dist/utils/errors.js.map +0 -1
  149. package/dist/utils/history.d.ts +0 -2
  150. package/dist/utils/history.d.ts.map +0 -1
  151. package/dist/utils/history.js +0 -12
  152. package/dist/utils/history.js.map +0 -1
  153. package/dist/utils/xtermAutoResponseFilter.d.ts +0 -2
  154. package/dist/utils/xtermAutoResponseFilter.d.ts.map +0 -1
  155. package/dist/utils/xtermAutoResponseFilter.js +0 -109
  156. package/dist/utils/xtermAutoResponseFilter.js.map +0 -1
@@ -1,659 +0,0 @@
1
- import { terminalFabricCoordinator } from './TerminalFabricCoordinator.js';
2
- import { loadBeamtermModule, } from '../internal/BeamtermResourceLoader.js';
3
- export { loadBeamtermModule } from '../internal/BeamtermResourceLoader.js';
4
- const createResolvedFabricCell = () => ({
5
- symbol: ' ',
6
- width: 1,
7
- styleKey: '',
8
- style: null,
9
- simple: true,
10
- blank: true,
11
- });
12
- const DEFAULT_BACKGROUND = 0x000000;
13
- const DEFAULT_FOREGROUND = 0xffffff;
14
- const MAX_STYLE_CACHE_ENTRIES = 4096;
15
- export const parseHexColor = (value, fallback) => {
16
- if (!value) {
17
- return fallback;
18
- }
19
- const trimmed = value.trim();
20
- const shortHex = /^#([0-9a-fA-F]{3})$/.exec(trimmed);
21
- if (shortHex) {
22
- const [r, g, b] = shortHex[1].split('');
23
- return Number.parseInt(`${r}${r}${g}${g}${b}${b}`, 16);
24
- }
25
- const longHex = /^#([0-9a-fA-F]{6})$/.exec(trimmed);
26
- if (longHex) {
27
- return Number.parseInt(longHex[1], 16);
28
- }
29
- return fallback;
30
- };
31
- export const formatHexColor = (value) => {
32
- const normalized = Number.isFinite(value) ? Math.max(0, Math.min(0xffffff, Math.trunc(value))) : 0;
33
- return `#${normalized.toString(16).padStart(6, '0')}`;
34
- };
35
- export const createStyle = (module, cell, defaultTheme, cache) => {
36
- const fg = cell.attrs.inverse
37
- ? defaultTheme.background
38
- : (cell.fg.r << 16) | (cell.fg.g << 8) | cell.fg.b;
39
- const bg = cell.attrs.inverse
40
- ? defaultTheme.foreground
41
- : (cell.bg.r << 16) | (cell.bg.g << 8) | cell.bg.b;
42
- const key = cache ? styleCacheKey(fg, bg, cell.attrs) : '';
43
- const existing = key ? cache?.get(key) : undefined;
44
- if (existing) {
45
- return existing;
46
- }
47
- let style = module.style().fg(fg).bg(bg);
48
- if (cell.attrs.bold) {
49
- style = style.bold();
50
- }
51
- if (cell.attrs.italic) {
52
- style = style.italic();
53
- }
54
- if (cell.attrs.underline) {
55
- style = style.underline();
56
- }
57
- if (cell.attrs.strikethrough) {
58
- style = style.strikethrough();
59
- }
60
- if (cache && key) {
61
- if (cache.size >= MAX_STYLE_CACHE_ENTRIES) {
62
- cache.clear();
63
- }
64
- cache.set(key, style);
65
- }
66
- return style;
67
- };
68
- export const hasWebGL2 = () => {
69
- if (typeof document === 'undefined') {
70
- return false;
71
- }
72
- const canvas = document.createElement('canvas');
73
- try {
74
- return Boolean(canvas.getContext('webgl2'));
75
- }
76
- catch {
77
- return false;
78
- }
79
- };
80
- export const createBeamtermRenderer = (module, canvas, fontFamilies, fontSize) => module.BeamtermRenderer.withDynamicAtlasCanvas(canvas, fontFamilies, fontSize, false);
81
- export const createCell = (module, symbol, style) => new module.Cell(symbol, style);
82
- export class BeamtermFabricRenderer {
83
- constructor() {
84
- this.backend = 'beamterm_webgl2';
85
- this.renderPath = 'main_thread_webgl2';
86
- this.module = null;
87
- this.renderer = null;
88
- this.frameBatch = null;
89
- this.target = null;
90
- this.canvas = null;
91
- this.visible = true;
92
- this.initialized = false;
93
- this.fontFamilies = ['monospace'];
94
- this.fontSize = 12;
95
- this.currentTheme = {
96
- background: DEFAULT_BACKGROUND,
97
- foreground: DEFAULT_FOREGROUND,
98
- };
99
- this.styleCache = new Map();
100
- this.lastRenderedRows = 0;
101
- this.lastDirtyCells = 0;
102
- this.geometry = null;
103
- this.surfaceBackgroundCss = null;
104
- this.hostInlineBackgroundColor = null;
105
- this.sourceGridCoverage = null;
106
- this.surfaceCoverageKey = '';
107
- this.pendingFullClearCoverage = null;
108
- this.resolvedCell = createResolvedFabricCell();
109
- this.resolvedLookahead = createResolvedFabricCell();
110
- }
111
- async initialize(target) {
112
- this.target = target;
113
- this.currentTheme = {
114
- background: parseHexColor(target.theme.background, DEFAULT_BACKGROUND),
115
- foreground: parseHexColor(target.theme.foreground, DEFAULT_FOREGROUND),
116
- };
117
- let canvas = null;
118
- let ghosttyCanvas = null;
119
- try {
120
- const webgl2Supported = hasWebGL2();
121
- terminalFabricCoordinator.setRendererState({
122
- webgl2Supported,
123
- backend: 'beamterm_webgl2',
124
- renderPath: 'main_thread_webgl2',
125
- });
126
- if (!webgl2Supported) {
127
- throw new Error('WebGL2 is not available for Beamterm');
128
- }
129
- this.module = await loadBeamtermModule();
130
- terminalFabricCoordinator.setRendererState({ beamtermLoaded: true });
131
- canvas = document.createElement('canvas');
132
- canvas.className = 'floeterm-beamterm-canvas';
133
- canvas.setAttribute('aria-hidden', 'true');
134
- canvas.style.position = 'absolute';
135
- canvas.style.inset = '0';
136
- canvas.style.width = '100%';
137
- canvas.style.height = '100%';
138
- canvas.style.pointerEvents = 'none';
139
- canvas.style.zIndex = '2';
140
- ghosttyCanvas = target.getGhosttyCanvas();
141
- if (ghosttyCanvas) {
142
- ghosttyCanvas.style.opacity = '0';
143
- }
144
- const host = target.container;
145
- const computed = getComputedStyle(host);
146
- if (computed.position === 'static') {
147
- host.style.position = 'relative';
148
- }
149
- this.hostInlineBackgroundColor = host.style.backgroundColor;
150
- host.appendChild(canvas);
151
- this.canvas = canvas;
152
- this.syncBackgroundSurface();
153
- this.fontFamilies = normalizeFontFamilies(target.fontFamily);
154
- this.fontSize = target.fontSize;
155
- this.renderer = createBeamtermRenderer(this.module, canvas, this.fontFamilies, this.fontSize);
156
- this.renderer.setCanvasPaddingColor(this.currentTheme.background);
157
- this.installEventForwarding(canvas);
158
- this.resize(host.clientWidth, host.clientHeight);
159
- this.initialized = true;
160
- terminalFabricCoordinator.incrementRendererCounts({ active: 1, visible: 1 });
161
- terminalFabricCoordinator.setRendererState({
162
- backend: 'beamterm_webgl2',
163
- renderPath: 'main_thread_webgl2',
164
- lastError: '',
165
- });
166
- }
167
- catch (error) {
168
- this.renderer?.free();
169
- this.renderer = null;
170
- this.module = null;
171
- this.canvas = null;
172
- canvas?.remove();
173
- this.restoreBackgroundSurface();
174
- terminalFabricCoordinator.noteRendererError(error);
175
- throw error;
176
- }
177
- }
178
- isActive() {
179
- return this.initialized && Boolean(this.renderer && this.module);
180
- }
181
- startFrame(frame, options) {
182
- void frame;
183
- if (!this.renderer || !this.visible) {
184
- return;
185
- }
186
- if (options.theme.background !== this.currentTheme.background) {
187
- this.renderer.setCanvasPaddingColor(options.theme.background);
188
- }
189
- this.currentTheme = options.theme;
190
- this.syncBackgroundSurface();
191
- this.lastRenderedRows = 0;
192
- this.lastDirtyCells = 0;
193
- this.frameBatch?.free();
194
- this.frameBatch = this.renderer.batch();
195
- if (frame.forceAll) {
196
- this.pendingFullClearCoverage = { cols: options.cols, rows: options.rows };
197
- }
198
- else {
199
- this.pendingFullClearCoverage = null;
200
- this.paintOutsideSourceGrid(this.frameBatch, options.cols, options.rows, options.theme.background);
201
- }
202
- }
203
- writeRow(sourceRenderer, row, cells, cols, hints = {}) {
204
- const batch = this.frameBatch;
205
- if (!batch || !this.module || !this.visible) {
206
- return;
207
- }
208
- if (this.pendingFullClearCoverage) {
209
- const coverage = this.pendingFullClearCoverage;
210
- this.pendingFullClearCoverage = null;
211
- batch.clear(this.currentTheme.background);
212
- this.recordSurfaceCoverage(coverage.cols, coverage.rows, this.currentTheme.background);
213
- }
214
- let col = 0;
215
- while (col < cols) {
216
- resolveSourceCell(this.module, sourceRenderer, cells[col] ?? {}, row, col, hints, this.currentTheme, this.styleCache, this.resolvedCell);
217
- const current = this.resolvedCell;
218
- if (!current.style) {
219
- col += 1;
220
- continue;
221
- }
222
- if (!current.simple) {
223
- batch.cell(col, row, createCell(this.module, current.symbol, current.style));
224
- const renderedWidth = Math.max(1, Math.min(cols - col, Math.floor(current.width)));
225
- this.lastDirtyCells += renderedWidth;
226
- col += renderedWidth;
227
- continue;
228
- }
229
- const runStart = col;
230
- const runStyleKey = current.styleKey;
231
- const runStyle = current.style;
232
- const blankRun = current.blank;
233
- let text = blankRun ? '' : current.symbol;
234
- col += 1;
235
- while (col < cols) {
236
- resolveSourceCell(this.module, sourceRenderer, cells[col] ?? {}, row, col, hints, this.currentTheme, this.styleCache, this.resolvedLookahead);
237
- const next = this.resolvedLookahead;
238
- if (!next.simple || next.blank !== blankRun || next.styleKey !== runStyleKey)
239
- break;
240
- if (!blankRun)
241
- text += next.symbol;
242
- col += 1;
243
- }
244
- const runLength = col - runStart;
245
- if (blankRun) {
246
- batch.fill(runStart, row, runLength, 1, createCell(this.module, ' ', runStyle));
247
- }
248
- else {
249
- batch.text(runStart, row, text, runStyle);
250
- }
251
- this.lastDirtyCells += runLength;
252
- }
253
- this.lastRenderedRows += 1;
254
- }
255
- finishFrame(cursor) {
256
- if (!this.renderer || !this.visible) {
257
- return {
258
- rendered: false,
259
- renderedRows: 0,
260
- dirtyCells: 0,
261
- };
262
- }
263
- const batch = this.frameBatch;
264
- if (cursor?.visible && this.module && batch) {
265
- batch.cell(Math.max(0, cursor.x), Math.max(0, cursor.y), createCell(this.module, ' ', this.module.style().fg(this.currentTheme.background).bg(this.currentTheme.foreground)));
266
- }
267
- try {
268
- this.renderer.render();
269
- return {
270
- rendered: true,
271
- renderedRows: this.lastRenderedRows,
272
- dirtyCells: this.lastDirtyCells,
273
- };
274
- }
275
- finally {
276
- batch?.free();
277
- this.frameBatch = null;
278
- this.pendingFullClearCoverage = null;
279
- }
280
- }
281
- finishSubmittedFrame() {
282
- const gl = this.canvas?.getContext('webgl2');
283
- if (!this.renderer || !this.visible || !gl) {
284
- throw new Error('Cannot finish a Beamterm frame without an active WebGL2 renderer');
285
- }
286
- gl.finish();
287
- }
288
- resize(width, height) {
289
- if (!this.renderer || !this.canvas) {
290
- return;
291
- }
292
- const cssWidth = Math.max(1, Math.floor(width));
293
- const cssHeight = Math.max(1, Math.floor(height));
294
- this.canvas.style.width = `${cssWidth}px`;
295
- this.canvas.style.height = `${cssHeight}px`;
296
- this.renderer.resize(cssWidth, cssHeight);
297
- this.surfaceCoverageKey = '';
298
- if (this.sourceGridCoverage && this.module) {
299
- const batch = this.renderer.batch();
300
- try {
301
- this.paintOutsideSourceGrid(batch, this.sourceGridCoverage.cols, this.sourceGridCoverage.rows, this.currentTheme.background);
302
- }
303
- finally {
304
- batch.free();
305
- }
306
- }
307
- this.renderer.render();
308
- this.geometry = readBeamtermGeometry(this.renderer, this.canvas, cssWidth, cssHeight);
309
- }
310
- getGeometry() {
311
- return this.geometry ? { ...this.geometry } : null;
312
- }
313
- setAppearance(appearance) {
314
- if (appearance.theme) {
315
- this.currentTheme = {
316
- background: parseHexColor(appearance.theme.background, this.currentTheme.background),
317
- foreground: parseHexColor(appearance.theme.foreground, this.currentTheme.foreground),
318
- };
319
- this.syncBackgroundSurface();
320
- this.renderer?.setCanvasPaddingColor(this.currentTheme.background);
321
- this.styleCache.clear();
322
- }
323
- if (!this.renderer || (!appearance.fontFamily && typeof appearance.fontSize !== 'number')) {
324
- return;
325
- }
326
- const family = appearance.fontFamily ? normalizeFontFamilies(appearance.fontFamily) : this.fontFamilies;
327
- const size = typeof appearance.fontSize === 'number' ? appearance.fontSize : this.fontSize;
328
- const familyChanged = family.length !== this.fontFamilies.length
329
- || family.some((value, index) => value !== this.fontFamilies[index]);
330
- if (!familyChanged && size === this.fontSize) {
331
- return;
332
- }
333
- try {
334
- this.renderer.replaceWithDynamicAtlas(family, size);
335
- this.fontFamilies = family;
336
- this.fontSize = size;
337
- this.styleCache.clear();
338
- if (this.geometry) {
339
- this.resize(this.geometry.width, this.geometry.height);
340
- }
341
- }
342
- catch (error) {
343
- this.target?.logger.warn('[BeamtermFabricRenderer] Dynamic atlas replacement failed', { error });
344
- }
345
- }
346
- setVisible(visible) {
347
- if (visible === this.visible) {
348
- return;
349
- }
350
- this.visible = visible;
351
- if (this.canvas) {
352
- this.canvas.style.display = visible ? 'block' : 'none';
353
- }
354
- terminalFabricCoordinator.incrementRendererCounts({
355
- visible: visible ? 1 : -1,
356
- offscreen: visible ? -1 : 1,
357
- });
358
- }
359
- loseContextForTest() {
360
- const gl = this.canvas?.getContext('webgl2');
361
- const extension = gl?.getExtension('WEBGL_lose_context');
362
- extension?.loseContext();
363
- }
364
- getDiagnostics() {
365
- return terminalFabricCoordinator.getDiagnostics();
366
- }
367
- dispose() {
368
- if (!this.initialized && !this.renderer && !this.canvas) {
369
- return;
370
- }
371
- this.frameBatch?.free();
372
- this.frameBatch = null;
373
- this.renderer?.free();
374
- this.renderer = null;
375
- this.module = null;
376
- this.initialized = false;
377
- this.geometry = null;
378
- this.sourceGridCoverage = null;
379
- this.surfaceCoverageKey = '';
380
- this.pendingFullClearCoverage = null;
381
- const wasVisible = this.visible;
382
- this.visible = false;
383
- this.styleCache.clear();
384
- this.canvas?.remove();
385
- this.canvas = null;
386
- this.restoreBackgroundSurface();
387
- terminalFabricCoordinator.incrementRendererCounts({
388
- active: -1,
389
- visible: wasVisible ? -1 : 0,
390
- offscreen: wasVisible ? 0 : -1,
391
- });
392
- }
393
- syncBackgroundSurface() {
394
- const nextBackground = formatHexColor(this.currentTheme.background);
395
- if (this.surfaceBackgroundCss === nextBackground) {
396
- return;
397
- }
398
- this.surfaceBackgroundCss = nextBackground;
399
- if (this.canvas) {
400
- this.canvas.style.backgroundColor = nextBackground;
401
- }
402
- if (this.target?.container) {
403
- this.target.container.style.backgroundColor = nextBackground;
404
- }
405
- }
406
- paintOutsideSourceGrid(batch, sourceCols, sourceRows, background) {
407
- if (!this.renderer || !this.module) {
408
- return;
409
- }
410
- const terminalSize = this.renderer.terminalSize();
411
- const rendererCols = Math.max(0, Math.floor(terminalSize.cols));
412
- const rendererRows = Math.max(0, Math.floor(terminalSize.rows));
413
- terminalSize.free();
414
- const cols = Math.max(0, Math.min(rendererCols, Math.floor(sourceCols)));
415
- const rows = Math.max(0, Math.min(rendererRows, Math.floor(sourceRows)));
416
- const coverageKey = `${rendererCols}:${rendererRows}:${cols}:${rows}:${background}`;
417
- this.sourceGridCoverage = { cols, rows };
418
- if (coverageKey === this.surfaceCoverageKey) {
419
- return;
420
- }
421
- this.surfaceCoverageKey = coverageKey;
422
- const backgroundCell = createCell(this.module, ' ', this.module.style().fg(background).bg(background));
423
- if (cols < rendererCols && rows > 0) {
424
- batch.fill(cols, 0, rendererCols - cols, rows, backgroundCell);
425
- }
426
- if (rows < rendererRows) {
427
- batch.fill(0, rows, rendererCols, rendererRows - rows, backgroundCell);
428
- }
429
- }
430
- recordSurfaceCoverage(sourceCols, sourceRows, background) {
431
- if (!this.renderer) {
432
- return;
433
- }
434
- const terminalSize = this.renderer.terminalSize();
435
- const rendererCols = Math.max(0, Math.floor(terminalSize.cols));
436
- const rendererRows = Math.max(0, Math.floor(terminalSize.rows));
437
- terminalSize.free();
438
- const cols = Math.max(0, Math.min(rendererCols, Math.floor(sourceCols)));
439
- const rows = Math.max(0, Math.min(rendererRows, Math.floor(sourceRows)));
440
- this.sourceGridCoverage = { cols, rows };
441
- this.surfaceCoverageKey = `${rendererCols}:${rendererRows}:${cols}:${rows}:${background}`;
442
- }
443
- restoreBackgroundSurface() {
444
- if (this.target?.container && this.hostInlineBackgroundColor !== null) {
445
- this.target.container.style.backgroundColor = this.hostInlineBackgroundColor;
446
- }
447
- this.hostInlineBackgroundColor = null;
448
- this.surfaceBackgroundCss = null;
449
- }
450
- installEventForwarding(canvas) {
451
- canvas.addEventListener('webglcontextlost', event => {
452
- event.preventDefault();
453
- const error = new Error('Beamterm WebGL2 context lost');
454
- terminalFabricCoordinator.noteRendererError(error);
455
- this.target?.onRendererError(error);
456
- });
457
- canvas.addEventListener('webglcontextrestored', () => {
458
- terminalFabricCoordinator.noteContextRestore();
459
- });
460
- }
461
- }
462
- const resolveSourceCell = (module, sourceRenderer, cell, row, col, hints, theme, cache, target) => {
463
- const flags = Number(cell.flags ?? 0);
464
- const selected = isCellInSelection(row, col, hints.selection);
465
- const hovered = isCellHovered(row, col, cell, hints.hover);
466
- const inverse = !selected && (flags & 16) !== 0;
467
- const foreground = inverse
468
- ? theme.background
469
- : selected
470
- ? packColor(hints.selection.foreground.r, hints.selection.foreground.g, hints.selection.foreground.b, theme.foreground)
471
- : packColor(cell.fg_r, cell.fg_g, cell.fg_b, theme.foreground);
472
- const background = inverse
473
- ? theme.foreground
474
- : selected
475
- ? packColor(hints.selection.background.r, hints.selection.background.g, hints.selection.background.b, theme.background)
476
- : packColor(cell.bg_r, cell.bg_g, cell.bg_b, theme.background);
477
- const bold = (flags & 1) !== 0;
478
- const italic = (flags & 2) !== 0;
479
- const underline = (flags & 4) !== 0 || hovered;
480
- const strikethrough = (flags & 8) !== 0;
481
- const styleKey = [
482
- foreground,
483
- background,
484
- bold ? 1 : 0,
485
- italic ? 1 : 0,
486
- underline ? 1 : 0,
487
- strikethrough ? 1 : 0,
488
- ].join(':');
489
- let style = cache.get(styleKey);
490
- if (!style) {
491
- style = module.style().fg(foreground).bg(background);
492
- if (bold)
493
- style = style.bold();
494
- if (italic)
495
- style = style.italic();
496
- if (underline)
497
- style = style.underline();
498
- if (strikethrough)
499
- style = style.strikethrough();
500
- if (cache.size >= MAX_STYLE_CACHE_ENTRIES)
501
- cache.clear();
502
- cache.set(styleKey, style);
503
- }
504
- const graphemeLength = Number(cell.grapheme_len ?? 0);
505
- const invisible = (flags & 32) !== 0;
506
- const symbol = invisible ? ' ' : resolveSourceSymbol(sourceRenderer, cell, row, col);
507
- const width = Number(cell.width ?? 1) || 1;
508
- target.symbol = symbol;
509
- target.width = width;
510
- target.styleKey = styleKey;
511
- target.style = style;
512
- target.simple = graphemeLength <= 0 && width === 1;
513
- target.blank = symbol === ' ';
514
- };
515
- const resolveSourceSymbol = (renderer, cell, row, col) => {
516
- if ((cell.grapheme_len ?? 0) > 0) {
517
- const grapheme = renderer.currentBuffer?.getGraphemeString?.(row, col);
518
- if (grapheme)
519
- return grapheme;
520
- }
521
- const codepoint = Number(cell.codepoint ?? 32);
522
- if (!Number.isFinite(codepoint) || codepoint <= 0)
523
- return ' ';
524
- try {
525
- return String.fromCodePoint(codepoint);
526
- }
527
- catch {
528
- return ' ';
529
- }
530
- };
531
- const packColor = (red, green, blue, fallback) => {
532
- const r = Number(red);
533
- const g = Number(green);
534
- const b = Number(blue);
535
- if (![r, g, b].every(value => Number.isInteger(value) && value >= 0 && value <= 255))
536
- return fallback;
537
- return (r << 16) | (g << 8) | b;
538
- };
539
- const isCellInSelection = (row, col, selection) => {
540
- if (!selection)
541
- return false;
542
- if (selection.startRow === selection.endRow) {
543
- return row === selection.startRow && col >= selection.startCol && col <= selection.endCol;
544
- }
545
- if (row === selection.startRow)
546
- return col >= selection.startCol;
547
- if (row === selection.endRow)
548
- return col <= selection.endCol;
549
- return row > selection.startRow && row < selection.endRow;
550
- };
551
- const isCellHovered = (row, col, cell, hover) => {
552
- if (!hover)
553
- return false;
554
- const hoverId = Number(hover.hyperlinkId ?? 0);
555
- if (hoverId > 0 && Number(cell.hyperlink_id ?? 0) === hoverId)
556
- return true;
557
- const range = hover.range;
558
- if (!range)
559
- return false;
560
- if (row === range.startY && row === range.endY)
561
- return col >= range.startX && col <= range.endX;
562
- if (row === range.startY)
563
- return col >= range.startX;
564
- if (row === range.endY)
565
- return col <= range.endX;
566
- return row > range.startY && row < range.endY;
567
- };
568
- export const sameRenderableStyle = (left, right) => (left.fg.r === right.fg.r
569
- && left.fg.g === right.fg.g
570
- && left.fg.b === right.fg.b
571
- && left.bg.r === right.bg.r
572
- && left.bg.g === right.bg.g
573
- && left.bg.b === right.bg.b
574
- && Boolean(left.attrs.bold) === Boolean(right.attrs.bold)
575
- && Boolean(left.attrs.italic) === Boolean(right.attrs.italic)
576
- && Boolean(left.attrs.underline) === Boolean(right.attrs.underline)
577
- && Boolean(left.attrs.strikethrough) === Boolean(right.attrs.strikethrough)
578
- && Boolean(left.attrs.inverse) === Boolean(right.attrs.inverse)
579
- && Boolean(left.attrs.invisible) === Boolean(right.attrs.invisible)
580
- && Boolean(left.attrs.faint) === Boolean(right.attrs.faint));
581
- const readBeamtermGeometry = (renderer, canvas, width, height) => {
582
- const cellSize = renderer.cellSize();
583
- const terminalSize = renderer.terminalSize();
584
- try {
585
- const cellWidth = Number(cellSize.width);
586
- const cellHeight = Number(cellSize.height);
587
- const cols = Math.floor(Number(terminalSize.cols));
588
- const rows = Math.floor(Number(terminalSize.rows));
589
- if (!Number.isFinite(cellWidth)
590
- || !Number.isFinite(cellHeight)
591
- || !Number.isFinite(cols)
592
- || !Number.isFinite(rows)
593
- || cellWidth <= 0
594
- || cellHeight <= 0
595
- || cols <= 0
596
- || rows <= 0) {
597
- return null;
598
- }
599
- const scaleX = resolveBeamtermCellScale(cellWidth, cols, canvas.width, width);
600
- const scaleY = resolveBeamtermCellScale(cellHeight, rows, canvas.height, height);
601
- const cssCellWidth = cellWidth / scaleX;
602
- const cssCellHeight = cellHeight / scaleY;
603
- return {
604
- width,
605
- height,
606
- cellWidth: cssCellWidth,
607
- cellHeight: cssCellHeight,
608
- cols,
609
- rows,
610
- };
611
- }
612
- finally {
613
- cellSize.free();
614
- terminalSize.free();
615
- }
616
- };
617
- const resolveBeamtermCellScale = (cellSize, cellCount, backingExtent, cssExtent) => {
618
- const backingScale = resolveCanvasBackingScale(backingExtent, cssExtent);
619
- if (backingScale <= 1) {
620
- return 1;
621
- }
622
- const gridExtent = cellSize * cellCount;
623
- const cssError = relativeExtentError(gridExtent, cssExtent);
624
- const backingError = relativeExtentError(gridExtent, backingExtent);
625
- return backingError < cssError ? backingScale : 1;
626
- };
627
- const relativeExtentError = (actual, expected) => {
628
- if (!Number.isFinite(actual) || !Number.isFinite(expected) || expected <= 0) {
629
- return Number.POSITIVE_INFINITY;
630
- }
631
- return Math.abs(actual - expected) / expected;
632
- };
633
- const resolveCanvasBackingScale = (backingSize, cssSize) => {
634
- const scale = Number(backingSize) / Number(cssSize);
635
- if (Number.isFinite(scale) && scale > 0) {
636
- return scale;
637
- }
638
- const dpr = typeof window !== 'undefined' ? Number(window.devicePixelRatio) : 1;
639
- return Number.isFinite(dpr) && dpr > 0 ? dpr : 1;
640
- };
641
- export const normalizeFontFamilies = (fontFamily) => {
642
- const families = fontFamily
643
- .split(',')
644
- .map(part => part.trim().replace(/^['"]|['"]$/g, ''))
645
- .filter(Boolean);
646
- return families.length > 0 ? families : ['monospace'];
647
- };
648
- const styleCacheKey = (fg, bg, attrs) => [
649
- fg,
650
- bg,
651
- attrs.bold ? 1 : 0,
652
- attrs.italic ? 1 : 0,
653
- attrs.underline ? 1 : 0,
654
- attrs.strikethrough ? 1 : 0,
655
- attrs.inverse ? 1 : 0,
656
- attrs.invisible ? 1 : 0,
657
- attrs.faint ? 1 : 0,
658
- ].join(':');
659
- //# sourceMappingURL=BeamtermFabricRenderer.js.map