@wendongfly/zihi 1.1.0 → 1.1.2

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 (157) hide show
  1. package/dist/index.js +1 -1
  2. package/dist/lib/xterm/README.md +27 -14
  3. package/dist/lib/xterm/css/xterm.css +81 -5
  4. package/dist/lib/xterm/lib/xterm.js +1 -1
  5. package/dist/lib/xterm/lib/xterm.js.map +1 -1
  6. package/dist/lib/xterm/lib/xterm.mjs +53 -0
  7. package/dist/lib/xterm/lib/xterm.mjs.map +7 -0
  8. package/dist/lib/xterm/package.json +49 -38
  9. package/dist/lib/xterm/src/browser/AccessibilityManager.ts +185 -50
  10. package/dist/lib/xterm/src/browser/CoreBrowserTerminal.ts +1339 -0
  11. package/dist/lib/xterm/src/browser/Linkifier.ts +403 -0
  12. package/dist/lib/xterm/src/browser/LocalizableStrings.ts +15 -4
  13. package/dist/lib/xterm/src/browser/OscLinkProvider.ts +2 -1
  14. package/dist/lib/xterm/src/browser/RenderDebouncer.ts +6 -5
  15. package/dist/lib/xterm/src/browser/TimeBasedDebouncer.ts +2 -2
  16. package/dist/lib/xterm/src/browser/Types.ts +226 -0
  17. package/dist/lib/xterm/src/browser/Viewport.ts +148 -357
  18. package/dist/lib/xterm/src/browser/decorations/BufferDecorationRenderer.ts +17 -12
  19. package/dist/lib/xterm/src/browser/decorations/OverviewRulerRenderer.ts +47 -52
  20. package/dist/lib/xterm/src/browser/input/CompositionHelper.ts +5 -3
  21. package/dist/lib/xterm/src/browser/input/MoveToCell.ts +3 -1
  22. package/dist/lib/xterm/src/browser/public/Terminal.ts +39 -24
  23. package/dist/lib/xterm/src/browser/renderer/dom/DomRenderer.ts +76 -40
  24. package/dist/lib/xterm/src/browser/renderer/dom/DomRendererRowFactory.ts +47 -23
  25. package/dist/lib/xterm/src/browser/renderer/dom/WidthCache.ts +19 -9
  26. package/dist/lib/xterm/src/browser/renderer/shared/Constants.ts +0 -8
  27. package/dist/lib/xterm/src/browser/renderer/shared/RendererUtils.ts +38 -1
  28. package/dist/lib/xterm/src/browser/renderer/shared/SelectionRenderModel.ts +6 -4
  29. package/dist/lib/xterm/src/browser/renderer/shared/Types.ts +84 -0
  30. package/dist/lib/xterm/src/browser/selection/Types.ts +15 -0
  31. package/dist/lib/xterm/src/browser/services/CharSizeService.ts +57 -32
  32. package/dist/lib/xterm/src/browser/services/CoreBrowserService.ts +108 -4
  33. package/dist/lib/xterm/src/browser/services/LinkProviderService.ts +28 -0
  34. package/dist/lib/xterm/src/browser/services/RenderService.ts +132 -40
  35. package/dist/lib/xterm/src/browser/services/SelectionService.ts +19 -9
  36. package/dist/lib/xterm/src/browser/services/Services.ts +36 -16
  37. package/dist/lib/xterm/src/browser/services/ThemeService.ts +19 -58
  38. package/dist/lib/xterm/src/browser/shared/Constants.ts +8 -0
  39. package/dist/lib/xterm/src/common/CircularList.ts +5 -5
  40. package/dist/lib/xterm/src/common/Color.ts +34 -14
  41. package/dist/lib/xterm/src/common/CoreTerminal.ts +40 -41
  42. package/dist/lib/xterm/src/common/InputHandler.ts +177 -125
  43. package/dist/lib/xterm/src/common/Platform.ts +2 -1
  44. package/dist/lib/xterm/src/common/SortedList.ts +86 -10
  45. package/dist/lib/xterm/src/common/TaskQueue.ts +7 -7
  46. package/dist/lib/xterm/src/common/Types.ts +552 -0
  47. package/dist/lib/xterm/src/common/buffer/AttributeData.ts +15 -0
  48. package/dist/lib/xterm/src/common/buffer/Buffer.ts +15 -7
  49. package/dist/lib/xterm/src/common/buffer/BufferLine.ts +53 -22
  50. package/dist/lib/xterm/src/common/buffer/BufferRange.ts +1 -1
  51. package/dist/lib/xterm/src/common/buffer/BufferReflow.ts +9 -6
  52. package/dist/lib/xterm/src/common/buffer/BufferSet.ts +5 -5
  53. package/dist/lib/xterm/src/common/buffer/Constants.ts +10 -2
  54. package/dist/lib/xterm/src/common/buffer/Marker.ts +4 -4
  55. package/dist/lib/xterm/src/common/buffer/Types.ts +52 -0
  56. package/dist/lib/xterm/src/common/input/Keyboard.ts +2 -27
  57. package/dist/lib/xterm/src/common/input/UnicodeV6.ts +18 -5
  58. package/dist/lib/xterm/src/common/input/WriteBuffer.ts +9 -8
  59. package/dist/lib/xterm/src/common/parser/EscapeSequenceParser.ts +13 -13
  60. package/dist/lib/xterm/src/common/parser/Types.ts +275 -0
  61. package/dist/lib/xterm/src/common/public/AddonManager.ts +1 -1
  62. package/dist/lib/xterm/src/common/public/BufferApiView.ts +1 -1
  63. package/dist/lib/xterm/src/common/public/BufferLineApiView.ts +1 -1
  64. package/dist/lib/xterm/src/common/public/BufferNamespaceApi.ts +4 -4
  65. package/dist/lib/xterm/src/common/public/ParserApi.ts +1 -1
  66. package/dist/lib/xterm/src/common/public/UnicodeApi.ts +1 -1
  67. package/dist/lib/xterm/src/common/services/BufferService.ts +14 -11
  68. package/dist/lib/xterm/src/common/services/CoreMouseService.ts +53 -6
  69. package/dist/lib/xterm/src/common/services/CoreService.ts +13 -8
  70. package/dist/lib/xterm/src/common/services/DecorationService.ts +11 -11
  71. package/dist/lib/xterm/src/common/services/InstantiationService.ts +1 -1
  72. package/dist/lib/xterm/src/common/services/LogService.ts +2 -2
  73. package/dist/lib/xterm/src/common/services/OptionsService.ts +16 -5
  74. package/dist/lib/xterm/src/common/services/ServiceRegistry.ts +1 -1
  75. package/dist/lib/xterm/src/common/services/Services.ts +73 -19
  76. package/dist/lib/xterm/src/common/services/UnicodeService.ts +30 -5
  77. package/dist/lib/xterm/src/vs/base/browser/browser.ts +141 -0
  78. package/dist/lib/xterm/src/vs/base/browser/canIUse.ts +49 -0
  79. package/dist/lib/xterm/src/vs/base/browser/dom.ts +2369 -0
  80. package/dist/lib/xterm/src/vs/base/browser/fastDomNode.ts +316 -0
  81. package/dist/lib/xterm/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
  82. package/dist/lib/xterm/src/vs/base/browser/iframe.ts +135 -0
  83. package/dist/lib/xterm/src/vs/base/browser/keyboardEvent.ts +213 -0
  84. package/dist/lib/xterm/src/vs/base/browser/mouseEvent.ts +229 -0
  85. package/dist/lib/xterm/src/vs/base/browser/touch.ts +372 -0
  86. package/dist/lib/xterm/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
  87. package/dist/lib/xterm/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
  88. package/dist/lib/xterm/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +720 -0
  89. package/dist/lib/xterm/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
  90. package/dist/lib/xterm/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
  91. package/dist/lib/xterm/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
  92. package/dist/lib/xterm/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
  93. package/dist/lib/xterm/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
  94. package/dist/lib/xterm/src/vs/base/browser/ui/widget.ts +57 -0
  95. package/dist/lib/xterm/src/vs/base/browser/window.ts +14 -0
  96. package/dist/lib/xterm/src/vs/base/common/arrays.ts +887 -0
  97. package/dist/lib/xterm/src/vs/base/common/arraysFind.ts +202 -0
  98. package/dist/lib/xterm/src/vs/base/common/assert.ts +71 -0
  99. package/dist/lib/xterm/src/vs/base/common/async.ts +1992 -0
  100. package/dist/lib/xterm/src/vs/base/common/cancellation.ts +148 -0
  101. package/dist/lib/xterm/src/vs/base/common/charCode.ts +450 -0
  102. package/dist/lib/xterm/src/vs/base/common/collections.ts +140 -0
  103. package/dist/lib/xterm/src/vs/base/common/decorators.ts +130 -0
  104. package/dist/lib/xterm/src/vs/base/common/equals.ts +146 -0
  105. package/dist/lib/xterm/src/vs/base/common/errors.ts +303 -0
  106. package/dist/lib/xterm/src/vs/base/common/event.ts +1778 -0
  107. package/dist/lib/xterm/src/vs/base/common/functional.ts +32 -0
  108. package/dist/lib/xterm/src/vs/base/common/hash.ts +316 -0
  109. package/dist/lib/xterm/src/vs/base/common/iterator.ts +159 -0
  110. package/dist/lib/xterm/src/vs/base/common/keyCodes.ts +526 -0
  111. package/dist/lib/xterm/src/vs/base/common/keybindings.ts +284 -0
  112. package/dist/lib/xterm/src/vs/base/common/lazy.ts +47 -0
  113. package/dist/lib/xterm/src/vs/base/common/lifecycle.ts +801 -0
  114. package/dist/lib/xterm/src/vs/base/common/linkedList.ts +142 -0
  115. package/dist/lib/xterm/src/vs/base/common/map.ts +202 -0
  116. package/dist/lib/xterm/src/vs/base/common/numbers.ts +98 -0
  117. package/dist/lib/xterm/src/vs/base/common/observable.ts +76 -0
  118. package/dist/lib/xterm/src/vs/base/common/observableInternal/api.ts +31 -0
  119. package/dist/lib/xterm/src/vs/base/common/observableInternal/autorun.ts +281 -0
  120. package/dist/lib/xterm/src/vs/base/common/observableInternal/base.ts +489 -0
  121. package/dist/lib/xterm/src/vs/base/common/observableInternal/debugName.ts +145 -0
  122. package/dist/lib/xterm/src/vs/base/common/observableInternal/derived.ts +428 -0
  123. package/dist/lib/xterm/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
  124. package/dist/lib/xterm/src/vs/base/common/observableInternal/logging.ts +328 -0
  125. package/dist/lib/xterm/src/vs/base/common/observableInternal/promise.ts +209 -0
  126. package/dist/lib/xterm/src/vs/base/common/observableInternal/utils.ts +610 -0
  127. package/dist/lib/xterm/src/vs/base/common/platform.ts +281 -0
  128. package/dist/lib/xterm/src/vs/base/common/scrollable.ts +522 -0
  129. package/dist/lib/xterm/src/vs/base/common/sequence.ts +34 -0
  130. package/dist/lib/xterm/src/vs/base/common/stopwatch.ts +43 -0
  131. package/dist/lib/xterm/src/vs/base/common/strings.ts +557 -0
  132. package/dist/lib/xterm/src/vs/base/common/symbols.ts +9 -0
  133. package/dist/lib/xterm/src/vs/base/common/uint.ts +59 -0
  134. package/dist/lib/xterm/src/vs/patches/nls.ts +90 -0
  135. package/dist/lib/xterm/src/vs/typings/base-common.d.ts +20 -0
  136. package/dist/lib/xterm/src/vs/typings/require.d.ts +42 -0
  137. package/dist/lib/xterm/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  138. package/dist/lib/xterm/src/vs/typings/vscode-globals-product.d.ts +33 -0
  139. package/dist/lib/xterm/typings/xterm.d.ts +156 -43
  140. package/dist/lib/xterm-fit/README.md +5 -5
  141. package/dist/lib/xterm-fit/lib/addon-fit.js +2 -0
  142. package/dist/lib/xterm-fit/lib/addon-fit.js.map +1 -0
  143. package/dist/lib/xterm-fit/lib/addon-fit.mjs +18 -0
  144. package/dist/lib/xterm-fit/lib/addon-fit.mjs.map +7 -0
  145. package/dist/lib/xterm-fit/package.json +9 -9
  146. package/dist/lib/xterm-fit/src/FitAddon.ts +7 -4
  147. package/dist/lib/xterm-fit/typings/addon-fit.d.ts +55 -0
  148. package/dist/lib/xterm-links/README.md +5 -5
  149. package/dist/lib/xterm-links/lib/addon-web-links.js +2 -0
  150. package/dist/lib/xterm-links/lib/addon-web-links.js.map +1 -0
  151. package/dist/lib/xterm-links/lib/addon-web-links.mjs +18 -0
  152. package/dist/lib/xterm-links/lib/addon-web-links.mjs.map +7 -0
  153. package/dist/lib/xterm-links/package.json +9 -9
  154. package/dist/lib/xterm-links/src/WebLinkProvider.ts +16 -15
  155. package/dist/lib/xterm-links/src/WebLinksAddon.ts +4 -3
  156. package/dist/lib/xterm-links/typings/addon-web-links.d.ts +57 -0
  157. package/package.json +5 -6
@@ -8,10 +8,10 @@ import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
8
8
  import { WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';
9
9
  import { CellData } from 'common/buffer/CellData';
10
10
  import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';
11
- import { color, rgba } from 'common/Color';
11
+ import { channels, color } from 'common/Color';
12
12
  import { ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
13
13
  import { JoinedCellData } from 'browser/services/CharacterJoinerService';
14
- import { excludeFromContrastRatioDemands } from 'browser/renderer/shared/RendererUtils';
14
+ import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
15
15
  import { AttributeData } from 'common/buffer/AttributeData';
16
16
  import { WidthCache } from 'browser/renderer/dom/WidthCache';
17
17
  import { IColorContrastCache } from 'browser/Types';
@@ -84,6 +84,7 @@ export class DomRendererRowFactory {
84
84
  let charElement: HTMLSpanElement | undefined;
85
85
  let cellAmount = 0;
86
86
  let text = '';
87
+ let i = 0;
87
88
  let oldBg = 0;
88
89
  let oldFg = 0;
89
90
  let oldExt = 0;
@@ -91,6 +92,7 @@ export class DomRendererRowFactory {
91
92
  let oldSpacing = 0;
92
93
  let oldIsInSelection: boolean = false;
93
94
  let spacing = 0;
95
+ let skipJoinedCheckUntilX = 0;
94
96
  const classes: string[] = [];
95
97
 
96
98
  const hasHover = linkStart !== -1 && linkEnd !== -1;
@@ -106,29 +108,46 @@ export class DomRendererRowFactory {
106
108
 
107
109
  // If true, indicates that the current character(s) to draw were joined.
108
110
  let isJoined = false;
111
+
112
+ // Indicates whether this cell is part of a joined range that should be ignored as it cannot
113
+ // be rendered entirely, like the selection state differs across the range.
114
+ let isValidJoinRange = (x >= skipJoinedCheckUntilX);
115
+
109
116
  let lastCharX = x;
110
117
 
111
118
  // Process any joined character ranges as needed. Because of how the
112
119
  // ranges are produced, we know that they are valid for the characters
113
120
  // and attributes of our input.
114
121
  let cell = this._workCell;
115
- if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {
116
- isJoined = true;
122
+ if (joinedRanges.length > 0 && x === joinedRanges[0][0] && isValidJoinRange) {
117
123
  const range = joinedRanges.shift()!;
124
+ // If the ligature's selection state is not consistent, don't join it. This helps the
125
+ // selection render correctly regardless whether they should be joined.
126
+ const firstSelectionState = this._isCellInSelection(range[0], row);
127
+ for (i = range[0] + 1; i < range[1]; i++) {
128
+ isValidJoinRange &&= (firstSelectionState === this._isCellInSelection(i, row));
129
+ }
130
+ // Similarly, if the cursor is in the ligature, don't join it.
131
+ isValidJoinRange &&= !isCursorRow || cursorX < range[0] || cursorX >= range[1];
132
+ if (!isValidJoinRange) {
133
+ skipJoinedCheckUntilX = range[1];
134
+ } else {
135
+ isJoined = true;
136
+
137
+ // We already know the exact start and end column of the joined range,
138
+ // so we get the string and width representing it directly
139
+ cell = new JoinedCellData(
140
+ this._workCell,
141
+ lineData.translateToString(true, range[0], range[1]),
142
+ range[1] - range[0]
143
+ );
118
144
 
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;
145
+ // Skip over the cells occupied by this range in the loop
146
+ lastCharX = range[1] - 1;
129
147
 
130
- // Recalculate width
131
- width = cell.getWidth();
148
+ // Recalculate width
149
+ width = cell.getWidth();
150
+ }
132
151
  }
133
152
 
134
153
  const isInSelection = this._isCellInSelection(x, row);
@@ -178,9 +197,14 @@ export class DomRendererRowFactory {
178
197
  && !isCursorCell
179
198
  && !isJoined
180
199
  && !isDecorated
200
+ && isValidJoinRange
181
201
  ) {
182
202
  // no span alterations, thus only account chars skipping all code below
183
- text += chars;
203
+ if (cell.isInvisible()) {
204
+ text += WHITESPACE_CELL_CHAR;
205
+ } else {
206
+ text += chars;
207
+ }
184
208
  cellAmount++;
185
209
  continue;
186
210
  } else {
@@ -214,7 +238,7 @@ export class DomRendererRowFactory {
214
238
  }
215
239
  }
216
240
 
217
- if (!this._coreService.isCursorHidden && isCursorCell) {
241
+ if (!this._coreService.isCursorHidden && isCursorCell && this._coreService.isCursorInitialized) {
218
242
  classes.push(RowCss.CURSOR_CLASS);
219
243
  if (this._coreBrowserService.isFocused) {
220
244
  if (cursorBlink) {
@@ -372,7 +396,7 @@ export class DomRendererRowFactory {
372
396
  classes.push(`xterm-bg-${bg}`);
373
397
  break;
374
398
  case Attributes.CM_RGB:
375
- resolvedBg = rgba.toColor(bg >> 16, bg >> 8 & 0xFF, bg & 0xFF);
399
+ resolvedBg = channels.toColor(bg >> 16, bg >> 8 & 0xFF, bg & 0xFF);
376
400
  this._addStyle(charElement, `background-color:#${padStart((bg >>> 0).toString(16), '0', 6)}`);
377
401
  break;
378
402
  case Attributes.CM_DEFAULT:
@@ -404,7 +428,7 @@ export class DomRendererRowFactory {
404
428
  }
405
429
  break;
406
430
  case Attributes.CM_RGB:
407
- const color = rgba.toColor(
431
+ const color = channels.toColor(
408
432
  (fg >> 16) & 0xFF,
409
433
  (fg >> 8) & 0xFF,
410
434
  (fg ) & 0xFF
@@ -415,7 +439,7 @@ export class DomRendererRowFactory {
415
439
  break;
416
440
  case Attributes.CM_DEFAULT:
417
441
  default:
418
- if (!this._applyMinimumContrast(charElement, resolvedBg, colors.foreground, cell, bgOverride, undefined)) {
442
+ if (!this._applyMinimumContrast(charElement, resolvedBg, colors.foreground, cell, bgOverride, fgOverride)) {
419
443
  if (isInverse) {
420
444
  classes.push(`xterm-fg-${INVERTED_DEFAULT_COLOR}`);
421
445
  }
@@ -431,7 +455,7 @@ export class DomRendererRowFactory {
431
455
  }
432
456
 
433
457
  // exclude conditions for cell merging - never merge these
434
- if (!isCursorCell && !isJoined && !isDecorated) {
458
+ if (!isCursorCell && !isJoined && !isDecorated && isValidJoinRange) {
435
459
  cellAmount++;
436
460
  } else {
437
461
  charElement.textContent = text;
@@ -454,7 +478,7 @@ export class DomRendererRowFactory {
454
478
  }
455
479
 
456
480
  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())) {
481
+ if (this._optionsService.rawOptions.minimumContrastRatio === 1 || treatGlyphAsBackgroundColor(cell.getCode())) {
458
482
  return false;
459
483
  }
460
484
 
@@ -45,25 +45,28 @@ export class WidthCache implements IDisposable {
45
45
  private _container: HTMLDivElement;
46
46
  private _measureElements: HTMLSpanElement[] = [];
47
47
 
48
- constructor(_document: Document) {
48
+ constructor(_document: Document, _helperContainer: HTMLElement) {
49
49
  this._container = _document.createElement('div');
50
- this._container.style.position = 'absolute';
51
- this._container.style.top = '-50000px';
52
- this._container.style.width = '50000px';
50
+ this._container.classList.add('xterm-width-cache-measure-container');
51
+ this._container.setAttribute('aria-hidden', 'true');
53
52
  // SP should stack in spans
54
53
  this._container.style.whiteSpace = 'pre';
55
54
  // avoid undercuts in non-monospace fonts from kerning
56
55
  this._container.style.fontKerning = 'none';
57
56
 
58
57
  const regular = _document.createElement('span');
58
+ regular.classList.add('xterm-char-measure-element');
59
59
 
60
60
  const bold = _document.createElement('span');
61
+ bold.classList.add('xterm-char-measure-element');
61
62
  bold.style.fontWeight = 'bold';
62
63
 
63
64
  const italic = _document.createElement('span');
65
+ italic.classList.add('xterm-char-measure-element');
64
66
  italic.style.fontStyle = 'italic';
65
67
 
66
68
  const boldItalic = _document.createElement('span');
69
+ boldItalic.classList.add('xterm-char-measure-element');
67
70
  boldItalic.style.fontWeight = 'bold';
68
71
  boldItalic.style.fontStyle = 'italic';
69
72
 
@@ -74,7 +77,7 @@ export class WidthCache implements IDisposable {
74
77
  this._container.appendChild(italic);
75
78
  this._container.appendChild(boldItalic);
76
79
 
77
- _document.body.appendChild(this._container);
80
+ _helperContainer.appendChild(this._container);
78
81
 
79
82
  this.clear();
80
83
  }
@@ -131,9 +134,14 @@ export class WidthCache implements IDisposable {
131
134
  public get(c: string, bold: boolean | number, italic: boolean | number): number {
132
135
  let cp = 0;
133
136
  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
+ if (this._flat[cp] !== WidthCacheSettings.FLAT_UNSET) {
138
+ return this._flat[cp];
139
+ }
140
+ const width = this._measure(c, 0);
141
+ if (width > 0) {
142
+ this._flat[cp] = width;
143
+ }
144
+ return width;
137
145
  }
138
146
  let key = c;
139
147
  if (bold) key += 'B';
@@ -144,7 +152,9 @@ export class WidthCache implements IDisposable {
144
152
  if (bold) variant |= FontVariant.BOLD;
145
153
  if (italic) variant |= FontVariant.ITALIC;
146
154
  width = this._measure(c, variant);
147
- this._holey!.set(key, width);
155
+ if (width > 0) {
156
+ this._holey!.set(key, width);
157
+ }
148
158
  }
149
159
  return width;
150
160
  }
@@ -3,12 +3,4 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { isFirefox, isLegacyEdge } from 'common/Platform';
7
-
8
6
  export const INVERTED_DEFAULT_COLOR = 257;
9
-
10
- export const DIM_OPACITY = 0.5;
11
- // The text baseline is set conditionally by browser. Using 'ideographic' for Firefox or Legacy Edge
12
- // would result in truncated text (Issue 3353). Using 'bottom' for Chrome would result in slightly
13
- // unaligned Powerline fonts (PR 3356#issuecomment-850928179).
14
- export const TEXT_BASELINE: CanvasTextBaseline = isFirefox || isLegacyEdge ? 'bottom' : 'ideographic';
@@ -23,11 +23,44 @@ export function isRestrictedPowerlineGlyph(codepoint: number): boolean {
23
23
  return 0xE0B0 <= codepoint && codepoint <= 0xE0B7;
24
24
  }
25
25
 
26
+ function isNerdFontGlyph(codepoint: number): boolean {
27
+ return 0xE000 <= codepoint && codepoint <= 0xF8FF;
28
+ }
29
+
26
30
  function isBoxOrBlockGlyph(codepoint: number): boolean {
27
31
  return 0x2500 <= codepoint && codepoint <= 0x259F;
28
32
  }
29
33
 
30
- export function excludeFromContrastRatioDemands(codepoint: number): boolean {
34
+ export function isEmoji(codepoint: number): boolean {
35
+ return (
36
+ codepoint >= 0x1F600 && codepoint <= 0x1F64F || // Emoticons
37
+ codepoint >= 0x1F300 && codepoint <= 0x1F5FF || // Misc Symbols and Pictographs
38
+ codepoint >= 0x1F680 && codepoint <= 0x1F6FF || // Transport and Map
39
+ codepoint >= 0x2600 && codepoint <= 0x26FF || // Misc symbols
40
+ codepoint >= 0x2700 && codepoint <= 0x27BF || // Dingbats
41
+ codepoint >= 0xFE00 && codepoint <= 0xFE0F || // Variation Selectors
42
+ codepoint >= 0x1F900 && codepoint <= 0x1F9FF || // Supplemental Symbols and Pictographs
43
+ codepoint >= 0x1F1E6 && codepoint <= 0x1F1FF
44
+ );
45
+ }
46
+
47
+ export function allowRescaling(codepoint: number | undefined, width: number, glyphSizeX: number, deviceCellWidth: number): boolean {
48
+ return (
49
+ // Is single cell width
50
+ width === 1 &&
51
+ // Glyph exceeds cell bounds, add 50% to avoid hurting readability by rescaling glyphs that
52
+ // barely overlap
53
+ glyphSizeX > Math.ceil(deviceCellWidth * 1.5) &&
54
+ // Never rescale ascii
55
+ codepoint !== undefined && codepoint > 0xFF &&
56
+ // Never rescale emoji
57
+ !isEmoji(codepoint) &&
58
+ // Never rescale powerline or nerd fonts
59
+ !isPowerlineGlyph(codepoint) && !isNerdFontGlyph(codepoint)
60
+ );
61
+ }
62
+
63
+ export function treatGlyphAsBackgroundColor(codepoint: number): boolean {
31
64
  return isPowerlineGlyph(codepoint) || isBoxOrBlockGlyph(codepoint);
32
65
  }
33
66
 
@@ -56,3 +89,7 @@ function createDimension(): IDimensions {
56
89
  height: 0
57
90
  };
58
91
  }
92
+
93
+ export function computeNextVariantOffset(cellWidth: number, lineWidth: number, currentOffset: number = 0): number {
94
+ return (cellWidth - (Math.round(lineWidth) * 2 - currentOffset)) % (Math.round(lineWidth) * 2);
95
+ }
@@ -3,8 +3,9 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
+ import { ITerminal } from 'browser/Types';
6
7
  import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
7
- import { Terminal } from 'xterm';
8
+ import { Terminal } from '@xterm/xterm';
8
9
 
9
10
  class SelectionRenderModel implements ISelectionRenderModel {
10
11
  public hasSelection!: boolean;
@@ -35,7 +36,7 @@ class SelectionRenderModel implements ISelectionRenderModel {
35
36
  this.selectionEnd = undefined;
36
37
  }
37
38
 
38
- public update(terminal: Terminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void {
39
+ public update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void {
39
40
  this.selectionStart = start;
40
41
  this.selectionEnd = end;
41
42
  // Selection does not exist
@@ -45,8 +46,9 @@ class SelectionRenderModel implements ISelectionRenderModel {
45
46
  }
46
47
 
47
48
  // Translate from buffer position to viewport position
48
- const viewportStartRow = start[1] - terminal.buffer.active.viewportY;
49
- const viewportEndRow = end[1] - terminal.buffer.active.viewportY;
49
+ const viewportY = terminal.buffers.active.ydisp;
50
+ const viewportStartRow = start[1] - viewportY;
51
+ const viewportEndRow = end[1] - viewportY;
50
52
  const viewportCappedStartRow = Math.max(viewportStartRow, 0);
51
53
  const viewportCappedEndRow = Math.min(viewportEndRow, terminal.rows - 1);
52
54
 
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Copyright (c) 2017 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ import { Terminal } from '@xterm/xterm';
7
+ import { ITerminal } from 'browser/Types';
8
+ import { IDisposable } from 'common/Types';
9
+ import type { Event } from 'vs/base/common/event';
10
+
11
+ export interface IDimensions {
12
+ width: number;
13
+ height: number;
14
+ }
15
+
16
+ export interface IOffset {
17
+ top: number;
18
+ left: number;
19
+ }
20
+
21
+ export interface IRenderDimensions {
22
+ /**
23
+ * Dimensions measured in CSS pixels (ie. device pixels / device pixel ratio).
24
+ */
25
+ css: {
26
+ canvas: IDimensions;
27
+ cell: IDimensions;
28
+ };
29
+ /**
30
+ * Dimensions measured in actual pixels as rendered to the device.
31
+ */
32
+ device: {
33
+ canvas: IDimensions;
34
+ cell: IDimensions;
35
+ char: IDimensions & IOffset;
36
+ };
37
+ }
38
+
39
+ export interface IRequestRedrawEvent {
40
+ start: number;
41
+ end: number;
42
+ }
43
+
44
+ /**
45
+ * Note that IRenderer implementations should emit the refresh event after
46
+ * rendering rows to the screen.
47
+ */
48
+ export interface IRenderer extends IDisposable {
49
+ readonly dimensions: IRenderDimensions;
50
+
51
+ /**
52
+ * Fires when the renderer is requesting to be redrawn on the next animation
53
+ * frame but is _not_ a result of content changing (eg. selection changes).
54
+ */
55
+ readonly onRequestRedraw: Event<IRequestRedrawEvent>;
56
+
57
+ dispose(): void;
58
+ handleDevicePixelRatioChange(): void;
59
+ handleResize(cols: number, rows: number): void;
60
+ handleCharSizeChanged(): void;
61
+ handleBlur(): void;
62
+ handleFocus(): void;
63
+ handleSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void;
64
+ handleCursorMove(): void;
65
+ clear(): void;
66
+ renderRows(start: number, end: number): void;
67
+ clearTextureAtlas?(): void;
68
+ }
69
+
70
+ export interface ISelectionRenderModel {
71
+ readonly hasSelection: boolean;
72
+ readonly columnSelectMode: boolean;
73
+ readonly viewportStartRow: number;
74
+ readonly viewportEndRow: number;
75
+ readonly viewportCappedStartRow: number;
76
+ readonly viewportCappedEndRow: number;
77
+ readonly startCol: number;
78
+ readonly endCol: number;
79
+ readonly selectionStart: [number, number] | undefined;
80
+ readonly selectionEnd: [number, number] | undefined;
81
+ clear(): void;
82
+ update(terminal: ITerminal, start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode?: boolean): void;
83
+ isCellSelected(terminal: Terminal, x: number, y: number): boolean;
84
+ }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Copyright (c) 2017 The xterm.js authors. All rights reserved.
3
+ * @license MIT
4
+ */
5
+
6
+ export interface ISelectionRedrawRequestEvent {
7
+ start: [number, number] | undefined;
8
+ end: [number, number] | undefined;
9
+ columnSelectMode: boolean;
10
+ }
11
+
12
+ export interface ISelectionRequestScrollLinesEvent {
13
+ amount: number;
14
+ suppressScrollEvent: boolean;
15
+ }
@@ -4,15 +4,9 @@
4
4
  */
5
5
 
6
6
  import { IOptionsService } from 'common/services/Services';
7
- import { EventEmitter } from 'common/EventEmitter';
8
7
  import { ICharSizeService } from 'browser/services/Services';
9
- import { Disposable } from 'common/Lifecycle';
10
-
11
-
12
- const enum MeasureSettings {
13
- REPEAT = 32
14
- }
15
-
8
+ import { Disposable } from 'vs/base/common/lifecycle';
9
+ import { Emitter } from 'vs/base/common/event';
16
10
 
17
11
  export class CharSizeService extends Disposable implements ICharSizeService {
18
12
  public serviceBrand: undefined;
@@ -23,7 +17,7 @@ export class CharSizeService extends Disposable implements ICharSizeService {
23
17
 
24
18
  public get hasValidSize(): boolean { return this.width > 0 && this.height > 0; }
25
19
 
26
- private readonly _onCharSizeChange = this.register(new EventEmitter<void>());
20
+ private readonly _onCharSizeChange = this._register(new Emitter<void>());
27
21
  public readonly onCharSizeChange = this._onCharSizeChange.event;
28
22
 
29
23
  constructor(
@@ -32,8 +26,12 @@ export class CharSizeService extends Disposable implements ICharSizeService {
32
26
  @IOptionsService private readonly _optionsService: IOptionsService
33
27
  ) {
34
28
  super();
35
- this._measureStrategy = new DomMeasureStrategy(document, parentElement, this._optionsService);
36
- this.register(this._optionsService.onMultipleOptionChange(['fontFamily', 'fontSize'], () => this.measure()));
29
+ try {
30
+ this._measureStrategy = this._register(new TextMetricsMeasureStrategy(this._optionsService));
31
+ } catch {
32
+ this._measureStrategy = this._register(new DomMeasureStrategy(document, parentElement, this._optionsService));
33
+ }
34
+ this._register(this._optionsService.onMultipleOptionChange(['fontFamily', 'fontSize'], () => this.measure()));
37
35
  }
38
36
 
39
37
  public measure(): void {
@@ -47,12 +45,7 @@ export class CharSizeService extends Disposable implements ICharSizeService {
47
45
  }
48
46
 
49
47
  interface IMeasureStrategy {
50
- measure(): IReadonlyMeasureResult;
51
- }
52
-
53
- interface IReadonlyMeasureResult {
54
- readonly width: number;
55
- readonly height: number;
48
+ measure(): Readonly<IMeasureResult>;
56
49
  }
57
50
 
58
51
  interface IMeasureResult {
@@ -60,10 +53,26 @@ interface IMeasureResult {
60
53
  height: number;
61
54
  }
62
55
 
63
- // TODO: For supporting browsers we should also provide a CanvasCharDimensionsProvider that uses
64
- // ctx.measureText
65
- class DomMeasureStrategy implements IMeasureStrategy {
66
- private _result: IMeasureResult = { width: 0, height: 0 };
56
+ const enum DomMeasureStrategyConstants {
57
+ REPEAT = 32
58
+ }
59
+
60
+ abstract class BaseMeasureStategy extends Disposable implements IMeasureStrategy {
61
+ protected _result: IMeasureResult = { width: 0, height: 0 };
62
+
63
+ protected _validateAndSet(width: number | undefined, height: number | undefined): void {
64
+ // If values are 0 then the element is likely currently display:none, in which case we should
65
+ // retain the previous value.
66
+ if (width !== undefined && width > 0 && height !== undefined && height > 0) {
67
+ this._result.width = width;
68
+ this._result.height = height;
69
+ }
70
+ }
71
+
72
+ public abstract measure(): Readonly<IMeasureResult>;
73
+ }
74
+
75
+ class DomMeasureStrategy extends BaseMeasureStategy {
67
76
  private _measureElement: HTMLElement;
68
77
 
69
78
  constructor(
@@ -71,32 +80,48 @@ class DomMeasureStrategy implements IMeasureStrategy {
71
80
  private _parentElement: HTMLElement,
72
81
  private _optionsService: IOptionsService
73
82
  ) {
83
+ super();
74
84
  this._measureElement = this._document.createElement('span');
75
85
  this._measureElement.classList.add('xterm-char-measure-element');
76
- this._measureElement.textContent = 'W'.repeat(MeasureSettings.REPEAT);
86
+ this._measureElement.textContent = 'W'.repeat(DomMeasureStrategyConstants.REPEAT);
77
87
  this._measureElement.setAttribute('aria-hidden', 'true');
78
88
  this._measureElement.style.whiteSpace = 'pre';
79
89
  this._measureElement.style.fontKerning = 'none';
80
90
  this._parentElement.appendChild(this._measureElement);
81
91
  }
82
92
 
83
- public measure(): IReadonlyMeasureResult {
93
+ public measure(): Readonly<IMeasureResult> {
84
94
  this._measureElement.style.fontFamily = this._optionsService.rawOptions.fontFamily;
85
95
  this._measureElement.style.fontSize = `${this._optionsService.rawOptions.fontSize}px`;
86
96
 
87
97
  // Note that this triggers a synchronous layout
88
- const geometry = {
89
- height: Number(this._measureElement.offsetHeight),
90
- width: Number(this._measureElement.offsetWidth)
91
- };
98
+ this._validateAndSet(Number(this._measureElement.offsetWidth) / DomMeasureStrategyConstants.REPEAT, Number(this._measureElement.offsetHeight));
92
99
 
93
- // If values are 0 then the element is likely currently display:none, in which case we should
94
- // retain the previous value.
95
- if (geometry.width !== 0 && geometry.height !== 0) {
96
- this._result.width = geometry.width / MeasureSettings.REPEAT;
97
- this._result.height = Math.ceil(geometry.height);
100
+ return this._result;
101
+ }
102
+ }
103
+
104
+ class TextMetricsMeasureStrategy extends BaseMeasureStategy {
105
+ private _canvas: OffscreenCanvas;
106
+ private _ctx: OffscreenCanvasRenderingContext2D;
107
+
108
+ constructor(
109
+ private _optionsService: IOptionsService
110
+ ) {
111
+ super();
112
+ // This will throw if any required API is not supported
113
+ this._canvas = new OffscreenCanvas(100, 100);
114
+ this._ctx = this._canvas.getContext('2d')!;
115
+ const a = this._ctx.measureText('W');
116
+ if (!('width' in a && 'fontBoundingBoxAscent' in a && 'fontBoundingBoxDescent' in a)) {
117
+ throw new Error('Required font metrics not supported');
98
118
  }
119
+ }
99
120
 
121
+ public measure(): Readonly<IMeasureResult> {
122
+ this._ctx.font = `${this._optionsService.rawOptions.fontSize}px ${this._optionsService.rawOptions.fontFamily}`;
123
+ const metrics = this._ctx.measureText('W');
124
+ this._validateAndSet(metrics.width, metrics.fontBoundingBoxAscent + metrics.fontBoundingBoxDescent);
100
125
  return this._result;
101
126
  }
102
127
  }