@wendongfly/zihi 1.0.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 (145) hide show
  1. package/bin/daemon.js +23 -0
  2. package/bin/zihi.js +603 -0
  3. package/dist/admin.html +297 -0
  4. package/dist/attach.js +2 -0
  5. package/dist/chat.html +2254 -0
  6. package/dist/client-dist/socket.io.esm.min.js +7 -0
  7. package/dist/client-dist/socket.io.js +4955 -0
  8. package/dist/client-dist/socket.io.min.js +7 -0
  9. package/dist/client-dist/socket.io.msgpack.min.js +7 -0
  10. package/dist/files.html +722 -0
  11. package/dist/icon.png +0 -0
  12. package/dist/icon.svg +4 -0
  13. package/dist/index.html +976 -0
  14. package/dist/index.js +485 -0
  15. package/dist/lib/ansi_up.js +431 -0
  16. package/dist/lib/xterm/LICENSE +21 -0
  17. package/dist/lib/xterm/README.md +230 -0
  18. package/dist/lib/xterm/css/xterm.css +209 -0
  19. package/dist/lib/xterm/lib/xterm.js +2 -0
  20. package/dist/lib/xterm/lib/xterm.js.map +1 -0
  21. package/dist/lib/xterm/package.json +100 -0
  22. package/dist/lib/xterm/src/browser/AccessibilityManager.ts +300 -0
  23. package/dist/lib/xterm/src/browser/Clipboard.ts +93 -0
  24. package/dist/lib/xterm/src/browser/ColorContrastCache.ts +34 -0
  25. package/dist/lib/xterm/src/browser/Lifecycle.ts +33 -0
  26. package/dist/lib/xterm/src/browser/Linkifier2.ts +416 -0
  27. package/dist/lib/xterm/src/browser/LocalizableStrings.ts +12 -0
  28. package/dist/lib/xterm/src/browser/OscLinkProvider.ts +128 -0
  29. package/dist/lib/xterm/src/browser/RenderDebouncer.ts +83 -0
  30. package/dist/lib/xterm/src/browser/ScreenDprMonitor.ts +72 -0
  31. package/dist/lib/xterm/src/browser/Terminal.ts +1305 -0
  32. package/dist/lib/xterm/src/browser/TimeBasedDebouncer.ts +86 -0
  33. package/dist/lib/xterm/src/browser/Types.d.ts +181 -0
  34. package/dist/lib/xterm/src/browser/Viewport.ts +401 -0
  35. package/dist/lib/xterm/src/browser/decorations/BufferDecorationRenderer.ts +134 -0
  36. package/dist/lib/xterm/src/browser/decorations/ColorZoneStore.ts +117 -0
  37. package/dist/lib/xterm/src/browser/decorations/OverviewRulerRenderer.ts +219 -0
  38. package/dist/lib/xterm/src/browser/input/CompositionHelper.ts +246 -0
  39. package/dist/lib/xterm/src/browser/input/Mouse.ts +54 -0
  40. package/dist/lib/xterm/src/browser/input/MoveToCell.ts +249 -0
  41. package/dist/lib/xterm/src/browser/public/Terminal.ts +260 -0
  42. package/dist/lib/xterm/src/browser/renderer/dom/DomRenderer.ts +506 -0
  43. package/dist/lib/xterm/src/browser/renderer/dom/DomRendererRowFactory.ts +522 -0
  44. package/dist/lib/xterm/src/browser/renderer/dom/WidthCache.ts +157 -0
  45. package/dist/lib/xterm/src/browser/renderer/shared/CellColorResolver.ts +137 -0
  46. package/dist/lib/xterm/src/browser/renderer/shared/CharAtlasCache.ts +96 -0
  47. package/dist/lib/xterm/src/browser/renderer/shared/CharAtlasUtils.ts +75 -0
  48. package/dist/lib/xterm/src/browser/renderer/shared/Constants.ts +14 -0
  49. package/dist/lib/xterm/src/browser/renderer/shared/CursorBlinkStateManager.ts +146 -0
  50. package/dist/lib/xterm/src/browser/renderer/shared/CustomGlyphs.ts +687 -0
  51. package/dist/lib/xterm/src/browser/renderer/shared/DevicePixelObserver.ts +41 -0
  52. package/dist/lib/xterm/src/browser/renderer/shared/README.md +1 -0
  53. package/dist/lib/xterm/src/browser/renderer/shared/RendererUtils.ts +58 -0
  54. package/dist/lib/xterm/src/browser/renderer/shared/SelectionRenderModel.ts +91 -0
  55. package/dist/lib/xterm/src/browser/renderer/shared/TextureAtlas.ts +1082 -0
  56. package/dist/lib/xterm/src/browser/renderer/shared/Types.d.ts +173 -0
  57. package/dist/lib/xterm/src/browser/selection/SelectionModel.ts +144 -0
  58. package/dist/lib/xterm/src/browser/selection/Types.d.ts +15 -0
  59. package/dist/lib/xterm/src/browser/services/CharSizeService.ts +102 -0
  60. package/dist/lib/xterm/src/browser/services/CharacterJoinerService.ts +339 -0
  61. package/dist/lib/xterm/src/browser/services/CoreBrowserService.ts +33 -0
  62. package/dist/lib/xterm/src/browser/services/MouseService.ts +46 -0
  63. package/dist/lib/xterm/src/browser/services/RenderService.ts +284 -0
  64. package/dist/lib/xterm/src/browser/services/SelectionService.ts +1029 -0
  65. package/dist/lib/xterm/src/browser/services/Services.ts +138 -0
  66. package/dist/lib/xterm/src/browser/services/ThemeService.ts +237 -0
  67. package/dist/lib/xterm/src/common/CircularList.ts +241 -0
  68. package/dist/lib/xterm/src/common/Clone.ts +23 -0
  69. package/dist/lib/xterm/src/common/Color.ts +356 -0
  70. package/dist/lib/xterm/src/common/CoreTerminal.ts +284 -0
  71. package/dist/lib/xterm/src/common/EventEmitter.ts +73 -0
  72. package/dist/lib/xterm/src/common/InputHandler.ts +3443 -0
  73. package/dist/lib/xterm/src/common/Lifecycle.ts +108 -0
  74. package/dist/lib/xterm/src/common/MultiKeyMap.ts +42 -0
  75. package/dist/lib/xterm/src/common/Platform.ts +43 -0
  76. package/dist/lib/xterm/src/common/SortedList.ts +118 -0
  77. package/dist/lib/xterm/src/common/TaskQueue.ts +166 -0
  78. package/dist/lib/xterm/src/common/TypedArrayUtils.ts +17 -0
  79. package/dist/lib/xterm/src/common/Types.d.ts +553 -0
  80. package/dist/lib/xterm/src/common/WindowsMode.ts +27 -0
  81. package/dist/lib/xterm/src/common/buffer/AttributeData.ts +196 -0
  82. package/dist/lib/xterm/src/common/buffer/Buffer.ts +654 -0
  83. package/dist/lib/xterm/src/common/buffer/BufferLine.ts +520 -0
  84. package/dist/lib/xterm/src/common/buffer/BufferRange.ts +13 -0
  85. package/dist/lib/xterm/src/common/buffer/BufferReflow.ts +223 -0
  86. package/dist/lib/xterm/src/common/buffer/BufferSet.ts +134 -0
  87. package/dist/lib/xterm/src/common/buffer/CellData.ts +94 -0
  88. package/dist/lib/xterm/src/common/buffer/Constants.ts +149 -0
  89. package/dist/lib/xterm/src/common/buffer/Marker.ts +43 -0
  90. package/dist/lib/xterm/src/common/buffer/Types.d.ts +52 -0
  91. package/dist/lib/xterm/src/common/data/Charsets.ts +256 -0
  92. package/dist/lib/xterm/src/common/data/EscapeSequences.ts +153 -0
  93. package/dist/lib/xterm/src/common/input/Keyboard.ts +398 -0
  94. package/dist/lib/xterm/src/common/input/TextDecoder.ts +346 -0
  95. package/dist/lib/xterm/src/common/input/UnicodeV6.ts +132 -0
  96. package/dist/lib/xterm/src/common/input/WriteBuffer.ts +246 -0
  97. package/dist/lib/xterm/src/common/input/XParseColor.ts +80 -0
  98. package/dist/lib/xterm/src/common/parser/Constants.ts +58 -0
  99. package/dist/lib/xterm/src/common/parser/DcsParser.ts +192 -0
  100. package/dist/lib/xterm/src/common/parser/EscapeSequenceParser.ts +792 -0
  101. package/dist/lib/xterm/src/common/parser/OscParser.ts +238 -0
  102. package/dist/lib/xterm/src/common/parser/Params.ts +229 -0
  103. package/dist/lib/xterm/src/common/parser/Types.d.ts +274 -0
  104. package/dist/lib/xterm/src/common/public/AddonManager.ts +53 -0
  105. package/dist/lib/xterm/src/common/public/BufferApiView.ts +35 -0
  106. package/dist/lib/xterm/src/common/public/BufferLineApiView.ts +29 -0
  107. package/dist/lib/xterm/src/common/public/BufferNamespaceApi.ts +36 -0
  108. package/dist/lib/xterm/src/common/public/ParserApi.ts +37 -0
  109. package/dist/lib/xterm/src/common/public/UnicodeApi.ts +27 -0
  110. package/dist/lib/xterm/src/common/services/BufferService.ts +151 -0
  111. package/dist/lib/xterm/src/common/services/CharsetService.ts +34 -0
  112. package/dist/lib/xterm/src/common/services/CoreMouseService.ts +318 -0
  113. package/dist/lib/xterm/src/common/services/CoreService.ts +87 -0
  114. package/dist/lib/xterm/src/common/services/DecorationService.ts +140 -0
  115. package/dist/lib/xterm/src/common/services/InstantiationService.ts +85 -0
  116. package/dist/lib/xterm/src/common/services/LogService.ts +124 -0
  117. package/dist/lib/xterm/src/common/services/OptionsService.ts +201 -0
  118. package/dist/lib/xterm/src/common/services/OscLinkService.ts +115 -0
  119. package/dist/lib/xterm/src/common/services/ServiceRegistry.ts +49 -0
  120. package/dist/lib/xterm/src/common/services/Services.ts +342 -0
  121. package/dist/lib/xterm/src/common/services/UnicodeService.ts +86 -0
  122. package/dist/lib/xterm/src/headless/Terminal.ts +136 -0
  123. package/dist/lib/xterm/src/headless/public/Terminal.ts +195 -0
  124. package/dist/lib/xterm/typings/xterm.d.ts +1844 -0
  125. package/dist/lib/xterm-fit/LICENSE +19 -0
  126. package/dist/lib/xterm-fit/README.md +24 -0
  127. package/dist/lib/xterm-fit/lib/xterm-addon-fit.js +2 -0
  128. package/dist/lib/xterm-fit/lib/xterm-addon-fit.js.map +1 -0
  129. package/dist/lib/xterm-fit/package.json +26 -0
  130. package/dist/lib/xterm-fit/src/FitAddon.ts +89 -0
  131. package/dist/lib/xterm-fit/typings/xterm-addon-fit.d.ts +55 -0
  132. package/dist/lib/xterm-links/LICENSE +19 -0
  133. package/dist/lib/xterm-links/README.md +21 -0
  134. package/dist/lib/xterm-links/lib/xterm-addon-web-links.js +2 -0
  135. package/dist/lib/xterm-links/lib/xterm-addon-web-links.js.map +1 -0
  136. package/dist/lib/xterm-links/package.json +26 -0
  137. package/dist/lib/xterm-links/src/WebLinkProvider.ts +198 -0
  138. package/dist/lib/xterm-links/src/WebLinksAddon.ts +57 -0
  139. package/dist/lib/xterm-links/typings/xterm-addon-web-links.d.ts +53 -0
  140. package/dist/login.html +163 -0
  141. package/dist/manifest.json +12 -0
  142. package/dist/package.json +1 -0
  143. package/dist/sw.js +127 -0
  144. package/dist/sync.html +816 -0
  145. package/package.json +47 -0
@@ -0,0 +1,522 @@
1
+ /**
2
+ * Copyright (c) 2018, 2023 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { IBufferLine, ICellData, IColor } from 'common/Types';
7
+ import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
8
+ import { WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';
9
+ import { CellData } from 'common/buffer/CellData';
10
+ import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
11
+ import { color, rgba } from 'common/Color';
12
+ import { ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
13
+ import { JoinedCellData } from 'browser/services/CharacterJoinerService';
14
+ import { excludeFromContrastRatioDemands } from 'browser/renderer/shared/RendererUtils';
15
+ import { AttributeData } from 'common/buffer/AttributeData';
16
+ import { WidthCache } from 'browser/renderer/dom/WidthCache';
17
+ import { IColorContrastCache } from 'browser/Types';
18
+
19
+
20
+ export const enum RowCss {
21
+ BOLD_CLASS = 'xterm-bold',
22
+ DIM_CLASS = 'xterm-dim',
23
+ ITALIC_CLASS = 'xterm-italic',
24
+ UNDERLINE_CLASS = 'xterm-underline',
25
+ OVERLINE_CLASS = 'xterm-overline',
26
+ STRIKETHROUGH_CLASS = 'xterm-strikethrough',
27
+ CURSOR_CLASS = 'xterm-cursor',
28
+ CURSOR_BLINK_CLASS = 'xterm-cursor-blink',
29
+ CURSOR_STYLE_BLOCK_CLASS = 'xterm-cursor-block',
30
+ CURSOR_STYLE_OUTLINE_CLASS = 'xterm-cursor-outline',
31
+ CURSOR_STYLE_BAR_CLASS = 'xterm-cursor-bar',
32
+ CURSOR_STYLE_UNDERLINE_CLASS = 'xterm-cursor-underline'
33
+ }
34
+
35
+
36
+ export class DomRendererRowFactory {
37
+ private _workCell: CellData = new CellData();
38
+
39
+ private _selectionStart: [number, number] | undefined;
40
+ private _selectionEnd: [number, number] | undefined;
41
+ private _columnSelectMode: boolean = false;
42
+
43
+ public defaultSpacing = 0;
44
+
45
+ constructor(
46
+ private readonly _document: Document,
47
+ @ICharacterJoinerService private readonly _characterJoinerService: ICharacterJoinerService,
48
+ @IOptionsService private readonly _optionsService: IOptionsService,
49
+ @ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService,
50
+ @ICoreService private readonly _coreService: ICoreService,
51
+ @IDecorationService private readonly _decorationService: IDecorationService,
52
+ @IThemeService private readonly _themeService: IThemeService
53
+ ) {}
54
+
55
+ public handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void {
56
+ this._selectionStart = start;
57
+ this._selectionEnd = end;
58
+ this._columnSelectMode = columnSelectMode;
59
+ }
60
+
61
+ public createRow(
62
+ lineData: IBufferLine,
63
+ row: number,
64
+ isCursorRow: boolean,
65
+ cursorStyle: string | undefined,
66
+ cursorInactiveStyle: string | undefined,
67
+ cursorX: number,
68
+ cursorBlink: boolean,
69
+ cellWidth: number,
70
+ widthCache: WidthCache,
71
+ linkStart: number,
72
+ linkEnd: number
73
+ ): HTMLSpanElement[] {
74
+
75
+ const elements: HTMLSpanElement[] = [];
76
+ const joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
77
+ const colors = this._themeService.colors;
78
+
79
+ let lineLength = lineData.getNoBgTrimmedLength();
80
+ if (isCursorRow && lineLength < cursorX + 1) {
81
+ lineLength = cursorX + 1;
82
+ }
83
+
84
+ let charElement: HTMLSpanElement | undefined;
85
+ let cellAmount = 0;
86
+ let text = '';
87
+ let oldBg = 0;
88
+ let oldFg = 0;
89
+ let oldExt = 0;
90
+ let oldLinkHover: number | boolean = false;
91
+ let oldSpacing = 0;
92
+ let oldIsInSelection: boolean = false;
93
+ let spacing = 0;
94
+ const classes: string[] = [];
95
+
96
+ const hasHover = linkStart !== -1 && linkEnd !== -1;
97
+
98
+ for (let x = 0; x < lineLength; x++) {
99
+ lineData.loadCell(x, this._workCell);
100
+ let width = this._workCell.getWidth();
101
+
102
+ // The character to the left is a wide character, drawing is owned by the char at x-1
103
+ if (width === 0) {
104
+ continue;
105
+ }
106
+
107
+ // If true, indicates that the current character(s) to draw were joined.
108
+ let isJoined = false;
109
+ let lastCharX = x;
110
+
111
+ // Process any joined character ranges as needed. Because of how the
112
+ // ranges are produced, we know that they are valid for the characters
113
+ // and attributes of our input.
114
+ let cell = this._workCell;
115
+ if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {
116
+ isJoined = true;
117
+ const range = joinedRanges.shift()!;
118
+
119
+ // We already know the exact start and end column of the joined range,
120
+ // so we get the string and width representing it directly
121
+ cell = new JoinedCellData(
122
+ this._workCell,
123
+ lineData.translateToString(true, range[0], range[1]),
124
+ range[1] - range[0]
125
+ );
126
+
127
+ // Skip over the cells occupied by this range in the loop
128
+ lastCharX = range[1] - 1;
129
+
130
+ // Recalculate width
131
+ width = cell.getWidth();
132
+ }
133
+
134
+ const isInSelection = this._isCellInSelection(x, row);
135
+ const isCursorCell = isCursorRow && x === cursorX;
136
+ const isLinkHover = hasHover && x >= linkStart && x <= linkEnd;
137
+
138
+ let isDecorated = false;
139
+ this._decorationService.forEachDecorationAtCell(x, row, undefined, d => {
140
+ isDecorated = true;
141
+ });
142
+
143
+ // get chars to render for this cell
144
+ let chars = cell.getChars() || WHITESPACE_CELL_CHAR;
145
+ if (chars === ' ' && (cell.isUnderline() || cell.isOverline())) {
146
+ chars = '\xa0';
147
+ }
148
+
149
+ // lookup char render width and calc spacing
150
+ spacing = width * cellWidth - widthCache.get(chars, cell.isBold(), cell.isItalic());
151
+
152
+ if (!charElement) {
153
+ charElement = this._document.createElement('span');
154
+ } else {
155
+ /**
156
+ * chars can only be merged on existing span if:
157
+ * - existing span only contains mergeable chars (cellAmount != 0)
158
+ * - bg did not change (or both are in selection)
159
+ * - fg did not change (or both are in selection and selection fg is set)
160
+ * - ext did not change
161
+ * - underline from hover state did not change
162
+ * - cell content renders to same letter-spacing
163
+ * - cell is not cursor
164
+ */
165
+ if (
166
+ cellAmount
167
+ && (
168
+ (isInSelection && oldIsInSelection)
169
+ || (!isInSelection && !oldIsInSelection && cell.bg === oldBg)
170
+ )
171
+ && (
172
+ (isInSelection && oldIsInSelection && colors.selectionForeground)
173
+ || cell.fg === oldFg
174
+ )
175
+ && cell.extended.ext === oldExt
176
+ && isLinkHover === oldLinkHover
177
+ && spacing === oldSpacing
178
+ && !isCursorCell
179
+ && !isJoined
180
+ && !isDecorated
181
+ ) {
182
+ // no span alterations, thus only account chars skipping all code below
183
+ text += chars;
184
+ cellAmount++;
185
+ continue;
186
+ } else {
187
+ /**
188
+ * cannot merge:
189
+ * - apply left-over text to old span
190
+ * - create new span, reset state holders cellAmount & text
191
+ */
192
+ if (cellAmount) {
193
+ charElement.textContent = text;
194
+ }
195
+ charElement = this._document.createElement('span');
196
+ cellAmount = 0;
197
+ text = '';
198
+ }
199
+ }
200
+ // preserve conditions for next merger eval round
201
+ oldBg = cell.bg;
202
+ oldFg = cell.fg;
203
+ oldExt = cell.extended.ext;
204
+ oldLinkHover = isLinkHover;
205
+ oldSpacing = spacing;
206
+ oldIsInSelection = isInSelection;
207
+
208
+ if (isJoined) {
209
+ // The DOM renderer colors the background of the cursor but for ligatures all cells are
210
+ // joined. The workaround here is to show a cursor around the whole ligature so it shows up,
211
+ // the cursor looks the same when on any character of the ligature though
212
+ if (cursorX >= x && cursorX <= lastCharX) {
213
+ cursorX = x;
214
+ }
215
+ }
216
+
217
+ if (!this._coreService.isCursorHidden && isCursorCell) {
218
+ classes.push(RowCss.CURSOR_CLASS);
219
+ if (this._coreBrowserService.isFocused) {
220
+ if (cursorBlink) {
221
+ classes.push(RowCss.CURSOR_BLINK_CLASS);
222
+ }
223
+ classes.push(
224
+ cursorStyle === 'bar'
225
+ ? RowCss.CURSOR_STYLE_BAR_CLASS
226
+ : cursorStyle === 'underline'
227
+ ? RowCss.CURSOR_STYLE_UNDERLINE_CLASS
228
+ : RowCss.CURSOR_STYLE_BLOCK_CLASS
229
+ );
230
+ } else {
231
+ if (cursorInactiveStyle) {
232
+ switch (cursorInactiveStyle) {
233
+ case 'outline':
234
+ classes.push(RowCss.CURSOR_STYLE_OUTLINE_CLASS);
235
+ break;
236
+ case 'block':
237
+ classes.push(RowCss.CURSOR_STYLE_BLOCK_CLASS);
238
+ break;
239
+ case 'bar':
240
+ classes.push(RowCss.CURSOR_STYLE_BAR_CLASS);
241
+ break;
242
+ case 'underline':
243
+ classes.push(RowCss.CURSOR_STYLE_UNDERLINE_CLASS);
244
+ break;
245
+ default:
246
+ break;
247
+ }
248
+ }
249
+ }
250
+ }
251
+
252
+ if (cell.isBold()) {
253
+ classes.push(RowCss.BOLD_CLASS);
254
+ }
255
+
256
+ if (cell.isItalic()) {
257
+ classes.push(RowCss.ITALIC_CLASS);
258
+ }
259
+
260
+ if (cell.isDim()) {
261
+ classes.push(RowCss.DIM_CLASS);
262
+ }
263
+
264
+ if (cell.isInvisible()) {
265
+ text = WHITESPACE_CELL_CHAR;
266
+ } else {
267
+ text = cell.getChars() || WHITESPACE_CELL_CHAR;
268
+ }
269
+
270
+ if (cell.isUnderline()) {
271
+ classes.push(`${RowCss.UNDERLINE_CLASS}-${cell.extended.underlineStyle}`);
272
+ if (text === ' ') {
273
+ text = '\xa0'; // = &nbsp;
274
+ }
275
+ if (!cell.isUnderlineColorDefault()) {
276
+ if (cell.isUnderlineColorRGB()) {
277
+ charElement.style.textDecorationColor = `rgb(${AttributeData.toColorRGB(cell.getUnderlineColor()).join(',')})`;
278
+ } else {
279
+ let fg = cell.getUnderlineColor();
280
+ if (this._optionsService.rawOptions.drawBoldTextInBrightColors && cell.isBold() && fg < 8) {
281
+ fg += 8;
282
+ }
283
+ charElement.style.textDecorationColor = colors.ansi[fg].css;
284
+ }
285
+ }
286
+ }
287
+
288
+ if (cell.isOverline()) {
289
+ classes.push(RowCss.OVERLINE_CLASS);
290
+ if (text === ' ') {
291
+ text = '\xa0'; // = &nbsp;
292
+ }
293
+ }
294
+
295
+ if (cell.isStrikethrough()) {
296
+ classes.push(RowCss.STRIKETHROUGH_CLASS);
297
+ }
298
+
299
+ // apply link hover underline late, effectively overrides any previous text-decoration
300
+ // settings
301
+ if (isLinkHover) {
302
+ charElement.style.textDecoration = 'underline';
303
+ }
304
+
305
+ let fg = cell.getFgColor();
306
+ let fgColorMode = cell.getFgColorMode();
307
+ let bg = cell.getBgColor();
308
+ let bgColorMode = cell.getBgColorMode();
309
+ const isInverse = !!cell.isInverse();
310
+ if (isInverse) {
311
+ const temp = fg;
312
+ fg = bg;
313
+ bg = temp;
314
+ const temp2 = fgColorMode;
315
+ fgColorMode = bgColorMode;
316
+ bgColorMode = temp2;
317
+ }
318
+
319
+ // Apply any decoration foreground/background overrides, this must happen after inverse has
320
+ // been applied
321
+ let bgOverride: IColor | undefined;
322
+ let fgOverride: IColor | undefined;
323
+ let isTop = false;
324
+ this._decorationService.forEachDecorationAtCell(x, row, undefined, d => {
325
+ if (d.options.layer !== 'top' && isTop) {
326
+ return;
327
+ }
328
+ if (d.backgroundColorRGB) {
329
+ bgColorMode = Attributes.CM_RGB;
330
+ bg = d.backgroundColorRGB.rgba >> 8 & 0xFFFFFF;
331
+ bgOverride = d.backgroundColorRGB;
332
+ }
333
+ if (d.foregroundColorRGB) {
334
+ fgColorMode = Attributes.CM_RGB;
335
+ fg = d.foregroundColorRGB.rgba >> 8 & 0xFFFFFF;
336
+ fgOverride = d.foregroundColorRGB;
337
+ }
338
+ isTop = d.options.layer === 'top';
339
+ });
340
+
341
+ // Apply selection
342
+ if (!isTop && isInSelection) {
343
+ // If in the selection, force the element to be above the selection to improve contrast and
344
+ // support opaque selections. The applies background is not actually needed here as
345
+ // selection is drawn in a seperate container, the main purpose of this to ensuring minimum
346
+ // contrast ratio
347
+ bgOverride = this._coreBrowserService.isFocused ? colors.selectionBackgroundOpaque : colors.selectionInactiveBackgroundOpaque;
348
+ bg = bgOverride.rgba >> 8 & 0xFFFFFF;
349
+ bgColorMode = Attributes.CM_RGB;
350
+ // Since an opaque selection is being rendered, the selection pretends to be a decoration to
351
+ // ensure text is drawn above the selection.
352
+ isTop = true;
353
+ // Apply selection foreground if applicable
354
+ if (colors.selectionForeground) {
355
+ fgColorMode = Attributes.CM_RGB;
356
+ fg = colors.selectionForeground.rgba >> 8 & 0xFFFFFF;
357
+ fgOverride = colors.selectionForeground;
358
+ }
359
+ }
360
+
361
+ // If it's a top decoration, render above the selection
362
+ if (isTop) {
363
+ classes.push('xterm-decoration-top');
364
+ }
365
+
366
+ // Background
367
+ let resolvedBg: IColor;
368
+ switch (bgColorMode) {
369
+ case Attributes.CM_P16:
370
+ case Attributes.CM_P256:
371
+ resolvedBg = colors.ansi[bg];
372
+ classes.push(`xterm-bg-${bg}`);
373
+ break;
374
+ case Attributes.CM_RGB:
375
+ resolvedBg = rgba.toColor(bg >> 16, bg >> 8 & 0xFF, bg & 0xFF);
376
+ this._addStyle(charElement, `background-color:#${padStart((bg >>> 0).toString(16), '0', 6)}`);
377
+ break;
378
+ case Attributes.CM_DEFAULT:
379
+ default:
380
+ if (isInverse) {
381
+ resolvedBg = colors.foreground;
382
+ classes.push(`xterm-bg-${INVERTED_DEFAULT_COLOR}`);
383
+ } else {
384
+ resolvedBg = colors.background;
385
+ }
386
+ }
387
+
388
+ // If there is no background override by now it's the original color, so apply dim if needed
389
+ if (!bgOverride) {
390
+ if (cell.isDim()) {
391
+ bgOverride = color.multiplyOpacity(resolvedBg, 0.5);
392
+ }
393
+ }
394
+
395
+ // Foreground
396
+ switch (fgColorMode) {
397
+ case Attributes.CM_P16:
398
+ case Attributes.CM_P256:
399
+ if (cell.isBold() && fg < 8 && this._optionsService.rawOptions.drawBoldTextInBrightColors) {
400
+ fg += 8;
401
+ }
402
+ if (!this._applyMinimumContrast(charElement, resolvedBg, colors.ansi[fg], cell, bgOverride, undefined)) {
403
+ classes.push(`xterm-fg-${fg}`);
404
+ }
405
+ break;
406
+ case Attributes.CM_RGB:
407
+ const color = rgba.toColor(
408
+ (fg >> 16) & 0xFF,
409
+ (fg >> 8) & 0xFF,
410
+ (fg ) & 0xFF
411
+ );
412
+ if (!this._applyMinimumContrast(charElement, resolvedBg, color, cell, bgOverride, fgOverride)) {
413
+ this._addStyle(charElement, `color:#${padStart(fg.toString(16), '0', 6)}`);
414
+ }
415
+ break;
416
+ case Attributes.CM_DEFAULT:
417
+ default:
418
+ if (!this._applyMinimumContrast(charElement, resolvedBg, colors.foreground, cell, bgOverride, undefined)) {
419
+ if (isInverse) {
420
+ classes.push(`xterm-fg-${INVERTED_DEFAULT_COLOR}`);
421
+ }
422
+ }
423
+ }
424
+
425
+ // apply CSS classes
426
+ // slightly faster than using classList by omitting
427
+ // checks for doubled entries (code above should not have doublets)
428
+ if (classes.length) {
429
+ charElement.className = classes.join(' ');
430
+ classes.length = 0;
431
+ }
432
+
433
+ // exclude conditions for cell merging - never merge these
434
+ if (!isCursorCell && !isJoined && !isDecorated) {
435
+ cellAmount++;
436
+ } else {
437
+ charElement.textContent = text;
438
+ }
439
+ // apply letter-spacing rule
440
+ if (spacing !== this.defaultSpacing) {
441
+ charElement.style.letterSpacing = `${spacing}px`;
442
+ }
443
+
444
+ elements.push(charElement);
445
+ x = lastCharX;
446
+ }
447
+
448
+ // postfix text of last merged span
449
+ if (charElement && cellAmount) {
450
+ charElement.textContent = text;
451
+ }
452
+
453
+ return elements;
454
+ }
455
+
456
+ private _applyMinimumContrast(element: HTMLElement, bg: IColor, fg: IColor, cell: ICellData, bgOverride: IColor | undefined, fgOverride: IColor | undefined): boolean {
457
+ if (this._optionsService.rawOptions.minimumContrastRatio === 1 || excludeFromContrastRatioDemands(cell.getCode())) {
458
+ return false;
459
+ }
460
+
461
+ // Try get from cache first, only use the cache when there are no decoration overrides
462
+ const cache = this._getContrastCache(cell);
463
+ let adjustedColor: IColor | undefined | null = undefined;
464
+ if (!bgOverride && !fgOverride) {
465
+ adjustedColor = cache.getColor(bg.rgba, fg.rgba);
466
+ }
467
+
468
+ // Calculate and store in cache
469
+ if (adjustedColor === undefined) {
470
+ // Dim cells only require half the contrast, otherwise they wouldn't be distinguishable from
471
+ // non-dim cells
472
+ const ratio = this._optionsService.rawOptions.minimumContrastRatio / (cell.isDim() ? 2 : 1);
473
+ adjustedColor = color.ensureContrastRatio(bgOverride || bg, fgOverride || fg, ratio);
474
+ cache.setColor((bgOverride || bg).rgba, (fgOverride || fg).rgba, adjustedColor ?? null);
475
+ }
476
+
477
+ if (adjustedColor) {
478
+ this._addStyle(element, `color:${adjustedColor.css}`);
479
+ return true;
480
+ }
481
+
482
+ return false;
483
+ }
484
+
485
+ private _getContrastCache(cell: ICellData): IColorContrastCache {
486
+ if (cell.isDim()) {
487
+ return this._themeService.colors.halfContrastCache;
488
+ }
489
+ return this._themeService.colors.contrastCache;
490
+ }
491
+
492
+ private _addStyle(element: HTMLElement, style: string): void {
493
+ element.setAttribute('style', `${element.getAttribute('style') || ''}${style};`);
494
+ }
495
+
496
+ private _isCellInSelection(x: number, y: number): boolean {
497
+ const start = this._selectionStart;
498
+ const end = this._selectionEnd;
499
+ if (!start || !end) {
500
+ return false;
501
+ }
502
+ if (this._columnSelectMode) {
503
+ if (start[0] <= end[0]) {
504
+ return x >= start[0] && y >= start[1] &&
505
+ x < end[0] && y <= end[1];
506
+ }
507
+ return x < start[0] && y >= start[1] &&
508
+ x >= end[0] && y <= end[1];
509
+ }
510
+ return (y > start[1] && y < end[1]) ||
511
+ (start[1] === end[1] && y === start[1] && x >= start[0] && x < end[0]) ||
512
+ (start[1] < end[1] && y === end[1] && x < end[0]) ||
513
+ (start[1] < end[1] && y === start[1] && x >= start[0]);
514
+ }
515
+ }
516
+
517
+ function padStart(text: string, padChar: string, length: number): string {
518
+ while (text.length < length) {
519
+ text = padChar + text;
520
+ }
521
+ return text;
522
+ }
@@ -0,0 +1,157 @@
1
+ /**
2
+ * Copyright (c) 2023 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { IDisposable } from 'common/Types';
7
+ import { FontWeight } from 'common/services/Services';
8
+
9
+
10
+ export const enum WidthCacheSettings {
11
+ /** sentinel for unset values in flat cache */
12
+ FLAT_UNSET = -9999,
13
+ /** size of flat cache, size-1 equals highest codepoint handled by flat */
14
+ FLAT_SIZE = 256,
15
+ /** char repeat for measuring */
16
+ REPEAT = 32
17
+ }
18
+
19
+
20
+ const enum FontVariant {
21
+ REGULAR = 0,
22
+ BOLD = 1,
23
+ ITALIC = 2,
24
+ BOLD_ITALIC = 3
25
+ }
26
+
27
+
28
+ export class WidthCache implements IDisposable {
29
+ // flat cache for regular variant up to CacheSettings.FLAT_SIZE
30
+ // NOTE: ~4x faster access than holey (serving >>80% of terminal content)
31
+ // It has a small memory footprint (only 1MB for full BMP caching),
32
+ // still the sweet spot is not reached before touching 32k different codepoints,
33
+ // thus we store the remaining <<20% of terminal data in a holey structure.
34
+ protected _flat = new Float32Array(WidthCacheSettings.FLAT_SIZE);
35
+
36
+ // holey cache for bold, italic and bold&italic for any string
37
+ // FIXME: can grow really big over time (~8.5 MB for full BMP caching),
38
+ // so a shared API across terminals is needed
39
+ protected _holey: Map<string, number> | undefined;
40
+
41
+ private _font = '';
42
+ private _fontSize = 0;
43
+ private _weight: FontWeight = 'normal';
44
+ private _weightBold: FontWeight = 'bold';
45
+ private _container: HTMLDivElement;
46
+ private _measureElements: HTMLSpanElement[] = [];
47
+
48
+ constructor(_document: Document) {
49
+ this._container = _document.createElement('div');
50
+ this._container.style.position = 'absolute';
51
+ this._container.style.top = '-50000px';
52
+ this._container.style.width = '50000px';
53
+ // SP should stack in spans
54
+ this._container.style.whiteSpace = 'pre';
55
+ // avoid undercuts in non-monospace fonts from kerning
56
+ this._container.style.fontKerning = 'none';
57
+
58
+ const regular = _document.createElement('span');
59
+
60
+ const bold = _document.createElement('span');
61
+ bold.style.fontWeight = 'bold';
62
+
63
+ const italic = _document.createElement('span');
64
+ italic.style.fontStyle = 'italic';
65
+
66
+ const boldItalic = _document.createElement('span');
67
+ boldItalic.style.fontWeight = 'bold';
68
+ boldItalic.style.fontStyle = 'italic';
69
+
70
+ // NOTE: must be in order of FontVariant
71
+ this._measureElements = [regular, bold, italic, boldItalic];
72
+ this._container.appendChild(regular);
73
+ this._container.appendChild(bold);
74
+ this._container.appendChild(italic);
75
+ this._container.appendChild(boldItalic);
76
+
77
+ _document.body.appendChild(this._container);
78
+
79
+ this.clear();
80
+ }
81
+
82
+ public dispose(): void {
83
+ this._container.remove(); // remove elements from DOM
84
+ this._measureElements.length = 0; // release element refs
85
+ this._holey = undefined; // free cache memory via GC
86
+ }
87
+
88
+ /**
89
+ * Clear the width cache.
90
+ */
91
+ public clear(): void {
92
+ this._flat.fill(WidthCacheSettings.FLAT_UNSET);
93
+ // .clear() has some overhead, re-assign instead (>3 times faster)
94
+ this._holey = new Map<string, number>();
95
+ }
96
+
97
+ /**
98
+ * Set the font for measuring.
99
+ * Must be called for any changes on font settings.
100
+ * Also clears the cache.
101
+ */
102
+ public setFont(font: string, fontSize: number, weight: FontWeight, weightBold: FontWeight): void {
103
+ // skip if nothing changed
104
+ if (font === this._font
105
+ && fontSize === this._fontSize
106
+ && weight === this._weight
107
+ && weightBold === this._weightBold
108
+ ) {
109
+ return;
110
+ }
111
+
112
+ this._font = font;
113
+ this._fontSize = fontSize;
114
+ this._weight = weight;
115
+ this._weightBold = weightBold;
116
+
117
+ this._container.style.fontFamily = this._font;
118
+ this._container.style.fontSize = `${this._fontSize}px`;
119
+ this._measureElements[FontVariant.REGULAR].style.fontWeight = `${weight}`;
120
+ this._measureElements[FontVariant.BOLD].style.fontWeight = `${weightBold}`;
121
+ this._measureElements[FontVariant.ITALIC].style.fontWeight = `${weight}`;
122
+ this._measureElements[FontVariant.BOLD_ITALIC].style.fontWeight = `${weightBold}`;
123
+
124
+ this.clear();
125
+ }
126
+
127
+ /**
128
+ * Get the render width for cell content `c` with current font settings.
129
+ * `variant` denotes the font variant to be used.
130
+ */
131
+ public get(c: string, bold: boolean | number, italic: boolean | number): number {
132
+ let cp = 0;
133
+ if (!bold && !italic && c.length === 1 && (cp = c.charCodeAt(0)) < WidthCacheSettings.FLAT_SIZE) {
134
+ return this._flat[cp] !== WidthCacheSettings.FLAT_UNSET
135
+ ? this._flat[cp]
136
+ : (this._flat[cp] = this._measure(c, 0));
137
+ }
138
+ let key = c;
139
+ if (bold) key += 'B';
140
+ if (italic) key += 'I';
141
+ let width = this._holey!.get(key);
142
+ if (width === undefined) {
143
+ let variant = 0;
144
+ if (bold) variant |= FontVariant.BOLD;
145
+ if (italic) variant |= FontVariant.ITALIC;
146
+ width = this._measure(c, variant);
147
+ this._holey!.set(key, width);
148
+ }
149
+ return width;
150
+ }
151
+
152
+ protected _measure(c: string, variant: FontVariant): number {
153
+ const el = this._measureElements[variant];
154
+ el.textContent = c.repeat(WidthCacheSettings.REPEAT);
155
+ return el.offsetWidth / WidthCacheSettings.REPEAT;
156
+ }
157
+ }