@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,19 +8,20 @@ import { IInputHandler, IAttributeData, IDisposable, IWindowOptions, IColorEvent
8
8
  import { C0, C1 } from 'common/data/EscapeSequences';
9
9
  import { CHARSETS, DEFAULT_CHARSET } from 'common/data/Charsets';
10
10
  import { EscapeSequenceParser } from 'common/parser/EscapeSequenceParser';
11
- import { Disposable } from 'common/Lifecycle';
11
+ import { Disposable } from 'vs/base/common/lifecycle';
12
12
  import { StringToUtf32, stringFromCodePoint, Utf8ToUtf32 } from 'common/input/TextDecoder';
13
- import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
14
- import { EventEmitter } from 'common/EventEmitter';
13
+ import { BufferLine, DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
15
14
  import { IParsingState, IEscapeSequenceParser, IParams, IFunctionIdentifier } from 'common/parser/Types';
16
15
  import { NULL_CELL_CODE, NULL_CELL_WIDTH, Attributes, FgFlags, BgFlags, Content, UnderlineStyle } from 'common/buffer/Constants';
17
16
  import { CellData } from 'common/buffer/CellData';
18
17
  import { AttributeData } from 'common/buffer/AttributeData';
19
18
  import { ICoreService, IBufferService, IOptionsService, ILogService, ICoreMouseService, ICharsetService, IUnicodeService, LogLevelEnum, IOscLinkService } from 'common/services/Services';
19
+ import { UnicodeService } from 'common/services/UnicodeService';
20
20
  import { OscHandler } from 'common/parser/OscParser';
21
21
  import { DcsHandler } from 'common/parser/DcsParser';
22
22
  import { IBuffer } from 'common/buffer/Types';
23
23
  import { parseColor } from 'common/input/XParseColor';
24
+ import { Emitter } from 'vs/base/common/event';
24
25
 
25
26
  /**
26
27
  * Map collect to glevel. Used in `selectCharset`.
@@ -48,7 +49,7 @@ const GLEVEL: { [key: string]: number } = { '(': 0, ')': 1, '*': 2, '+': 3, '-':
48
49
  /**
49
50
  * Document xterm VT features here that are currently unsupported
50
51
  */
51
- // @vt: #E[Supported via xterm-addon-image.] DCS SIXEL "SIXEL Graphics" "DCS Ps ; Ps ; Ps ; q Pt ST" "Draw SIXEL image."
52
+ // @vt: #E[Supported via @xterm/addon-image.] DCS SIXEL "SIXEL Graphics" "DCS Ps ; Ps ; Ps ; q Pt ST" "Draw SIXEL image."
52
53
  // @vt: #N DCS DECUDK "User Defined Keys" "DCS Ps ; Ps \| Pt ST" "Definitions for user-defined keys."
53
54
  // @vt: #N DCS XTGETTCAP "Request Terminfo String" "DCS + q Pt ST" "Request Terminfo String."
54
55
  // @vt: #N DCS XTSETTCAP "Set Terminfo Data" "DCS + p Pt ST" "Set Terminfo Data."
@@ -118,7 +119,6 @@ export class InputHandler extends Disposable implements IInputHandler {
118
119
  private _parseBuffer: Uint32Array = new Uint32Array(4096);
119
120
  private _stringDecoder: StringToUtf32 = new StringToUtf32();
120
121
  private _utf8Decoder: Utf8ToUtf32 = new Utf8ToUtf32();
121
- private _workCell: CellData = new CellData();
122
122
  private _windowTitle = '';
123
123
  private _iconName = '';
124
124
  private _dirtyRowTracker: IDirtyRowTracker;
@@ -131,32 +131,32 @@ export class InputHandler extends Disposable implements IInputHandler {
131
131
 
132
132
  private _activeBuffer: IBuffer;
133
133
 
134
- private readonly _onRequestBell = this.register(new EventEmitter<void>());
134
+ private readonly _onRequestBell = this._register(new Emitter<void>());
135
135
  public readonly onRequestBell = this._onRequestBell.event;
136
- private readonly _onRequestRefreshRows = this.register(new EventEmitter<number, number>());
136
+ private readonly _onRequestRefreshRows = this._register(new Emitter<{ start: number, end: number } | undefined>());
137
137
  public readonly onRequestRefreshRows = this._onRequestRefreshRows.event;
138
- private readonly _onRequestReset = this.register(new EventEmitter<void>());
138
+ private readonly _onRequestReset = this._register(new Emitter<void>());
139
139
  public readonly onRequestReset = this._onRequestReset.event;
140
- private readonly _onRequestSendFocus = this.register(new EventEmitter<void>());
140
+ private readonly _onRequestSendFocus = this._register(new Emitter<void>());
141
141
  public readonly onRequestSendFocus = this._onRequestSendFocus.event;
142
- private readonly _onRequestSyncScrollBar = this.register(new EventEmitter<void>());
142
+ private readonly _onRequestSyncScrollBar = this._register(new Emitter<void>());
143
143
  public readonly onRequestSyncScrollBar = this._onRequestSyncScrollBar.event;
144
- private readonly _onRequestWindowsOptionsReport = this.register(new EventEmitter<WindowsOptionsReportType>());
144
+ private readonly _onRequestWindowsOptionsReport = this._register(new Emitter<WindowsOptionsReportType>());
145
145
  public readonly onRequestWindowsOptionsReport = this._onRequestWindowsOptionsReport.event;
146
146
 
147
- private readonly _onA11yChar = this.register(new EventEmitter<string>());
147
+ private readonly _onA11yChar = this._register(new Emitter<string>());
148
148
  public readonly onA11yChar = this._onA11yChar.event;
149
- private readonly _onA11yTab = this.register(new EventEmitter<number>());
149
+ private readonly _onA11yTab = this._register(new Emitter<number>());
150
150
  public readonly onA11yTab = this._onA11yTab.event;
151
- private readonly _onCursorMove = this.register(new EventEmitter<void>());
151
+ private readonly _onCursorMove = this._register(new Emitter<void>());
152
152
  public readonly onCursorMove = this._onCursorMove.event;
153
- private readonly _onLineFeed = this.register(new EventEmitter<void>());
153
+ private readonly _onLineFeed = this._register(new Emitter<void>());
154
154
  public readonly onLineFeed = this._onLineFeed.event;
155
- private readonly _onScroll = this.register(new EventEmitter<number>());
155
+ private readonly _onScroll = this._register(new Emitter<number>());
156
156
  public readonly onScroll = this._onScroll.event;
157
- private readonly _onTitleChange = this.register(new EventEmitter<string>());
157
+ private readonly _onTitleChange = this._register(new Emitter<string>());
158
158
  public readonly onTitleChange = this._onTitleChange.event;
159
- private readonly _onColor = this.register(new EventEmitter<IColorEvent>());
159
+ private readonly _onColor = this._register(new Emitter<IColorEvent>());
160
160
  public readonly onColor = this._onColor.event;
161
161
 
162
162
  private _parseStack: IParseStack = {
@@ -179,12 +179,12 @@ export class InputHandler extends Disposable implements IInputHandler {
179
179
  private readonly _parser: IEscapeSequenceParser = new EscapeSequenceParser()
180
180
  ) {
181
181
  super();
182
- this.register(this._parser);
182
+ this._register(this._parser);
183
183
  this._dirtyRowTracker = new DirtyRowTracker(this._bufferService);
184
184
 
185
185
  // Track properties used in performance critical code manually to avoid using slow getters
186
186
  this._activeBuffer = this._bufferService.buffer;
187
- this.register(this._bufferService.buffers.onBufferActivate(e => this._activeBuffer = e.activeBuffer));
187
+ this._register(this._bufferService.buffers.onBufferActivate(e => this._activeBuffer = e.activeBuffer));
188
188
 
189
189
  /**
190
190
  * custom fallback handlers
@@ -445,7 +445,10 @@ export class InputHandler extends Disposable implements IInputHandler {
445
445
 
446
446
  // Log debug data, the log level gate is to prevent extra work in this hot path
447
447
  if (this._logService.logLevel <= LogLevelEnum.DEBUG) {
448
- this._logService.debug(`parsing data${typeof data === 'string' ? ` "${data}"` : ` "${Array.prototype.map.call(data, e => String.fromCharCode(e)).join('')}"`}`, typeof data === 'string'
448
+ this._logService.debug(`parsing data ${typeof data === 'string' ? ` "${data}"` : ` "${Array.prototype.map.call(data, e => String.fromCharCode(e)).join('')}"`}`);
449
+ }
450
+ if (this._logService.logLevel === LogLevelEnum.TRACE) {
451
+ this._logService.trace(`parsing data (codes)`, typeof data === 'string'
449
452
  ? data.split('').map(e => e.charCodeAt(0))
450
453
  : data
451
454
  );
@@ -494,8 +497,16 @@ export class InputHandler extends Disposable implements IInputHandler {
494
497
  this._onCursorMove.fire();
495
498
  }
496
499
 
497
- // Refresh any dirty rows accumulated as part of parsing
498
- this._onRequestRefreshRows.fire(this._dirtyRowTracker.start, this._dirtyRowTracker.end);
500
+ // Refresh any dirty rows accumulated as part of parsing, fire only for rows within the
501
+ // _viewport_ which is relative to ydisp, not relative to ybase.
502
+ const viewportEnd = this._dirtyRowTracker.end + (this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
503
+ const viewportStart = this._dirtyRowTracker.start + (this._bufferService.buffer.ybase - this._bufferService.buffer.ydisp);
504
+ if (viewportStart < this._bufferService.rows) {
505
+ this._onRequestRefreshRows.fire({
506
+ start: Math.min(viewportStart, this._bufferService.rows - 1),
507
+ end: Math.min(viewportEnd, this._bufferService.rows - 1)
508
+ });
509
+ }
499
510
  }
500
511
 
501
512
  public print(data: Uint32Array, start: number, end: number): void {
@@ -513,16 +524,13 @@ export class InputHandler extends Disposable implements IInputHandler {
513
524
 
514
525
  // handle wide chars: reset start_cell-1 if we would overwrite the second cell of a wide char
515
526
  if (this._activeBuffer.x && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x - 1) === 2) {
516
- bufferRow.setCellFromCodePoint(this._activeBuffer.x - 1, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended);
527
+ bufferRow.setCellFromCodepoint(this._activeBuffer.x - 1, 0, 1, curAttr);
517
528
  }
518
529
 
530
+ let precedingJoinState = this._parser.precedingJoinState;
519
531
  for (let pos = start; pos < end; ++pos) {
520
532
  code = data[pos];
521
533
 
522
- // calculate print space
523
- // expensive call, therefore we save width in line buffer
524
- chWidth = this._unicodeService.wcwidth(code);
525
-
526
534
  // get charset replacement character
527
535
  // charset is only defined for ASCII, therefore we only
528
536
  // search for an replacement char if code < 127
@@ -533,6 +541,12 @@ export class InputHandler extends Disposable implements IInputHandler {
533
541
  }
534
542
  }
535
543
 
544
+ const currentInfo = this._unicodeService.charProperties(code, precedingJoinState);
545
+ chWidth = UnicodeService.extractWidth(currentInfo);
546
+ const shouldJoin = UnicodeService.extractShouldJoin(currentInfo);
547
+ const oldWidth = shouldJoin ? UnicodeService.extractWidth(precedingJoinState) : 0;
548
+ precedingJoinState = currentInfo;
549
+
536
550
  if (screenReaderMode) {
537
551
  this._onA11yChar.fire(stringFromCodePoint(code));
538
552
  }
@@ -540,34 +554,16 @@ export class InputHandler extends Disposable implements IInputHandler {
540
554
  this._oscLinkService.addLineToLink(this._getCurrentLinkId(), this._activeBuffer.ybase + this._activeBuffer.y);
541
555
  }
542
556
 
543
- // insert combining char at last cursor position
544
- // this._activeBuffer.x should never be 0 for a combining char
545
- // since they always follow a cell consuming char
546
- // therefore we can test for this._activeBuffer.x to avoid overflow left
547
- if (!chWidth && this._activeBuffer.x) {
548
- if (!bufferRow.getWidth(this._activeBuffer.x - 1)) {
549
- // found empty cell after fullwidth, need to go 2 cells back
550
- // it is save to step 2 cells back here
551
- // since an empty cell is only set by fullwidth chars
552
- bufferRow.addCodepointToCell(this._activeBuffer.x - 2, code);
553
- } else {
554
- bufferRow.addCodepointToCell(this._activeBuffer.x - 1, code);
555
- }
556
- continue;
557
- }
558
-
559
557
  // goto next line if ch would overflow
560
558
  // NOTE: To avoid costly width checks here,
561
559
  // the terminal does not allow a cols < 2.
562
- if (this._activeBuffer.x + chWidth - 1 >= cols) {
560
+ if (this._activeBuffer.x + chWidth - oldWidth > cols) {
563
561
  // autowrap - DECAWM
564
562
  // automatically wraps to the beginning of the next line
565
563
  if (wraparoundMode) {
566
- // clear left over cells to the right
567
- while (this._activeBuffer.x < cols) {
568
- bufferRow.setCellFromCodePoint(this._activeBuffer.x++, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended);
569
- }
570
- this._activeBuffer.x = 0;
564
+ const oldRow = bufferRow;
565
+ let oldCol = this._activeBuffer.x - oldWidth;
566
+ this._activeBuffer.x = oldWidth;
571
567
  this._activeBuffer.y++;
572
568
  if (this._activeBuffer.y === this._activeBuffer.scrollBottom + 1) {
573
569
  this._activeBuffer.y--;
@@ -582,6 +578,16 @@ export class InputHandler extends Disposable implements IInputHandler {
582
578
  }
583
579
  // row changed, get it again
584
580
  bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!;
581
+ if (oldWidth > 0 && bufferRow instanceof BufferLine) {
582
+ // Combining character widens 1 column to 2.
583
+ // Move old character to next line.
584
+ bufferRow.copyCellsFrom(oldRow as BufferLine,
585
+ oldCol, 0, oldWidth, false);
586
+ }
587
+ // clear left over cells to the right
588
+ while (oldCol < cols) {
589
+ oldRow.setCellFromCodepoint(oldCol++, 0, 1, curAttr);
590
+ }
585
591
  } else {
586
592
  this._activeBuffer.x = cols - 1;
587
593
  if (chWidth === 2) {
@@ -592,20 +598,37 @@ export class InputHandler extends Disposable implements IInputHandler {
592
598
  }
593
599
  }
594
600
 
601
+ // insert combining char at last cursor position
602
+ // this._activeBuffer.x should never be 0 for a combining char
603
+ // since they always follow a cell consuming char
604
+ // therefore we can test for this._activeBuffer.x to avoid overflow left
605
+ if (shouldJoin && this._activeBuffer.x) {
606
+ const offset = bufferRow.getWidth(this._activeBuffer.x - 1) ? 1 : 2;
607
+ // if empty cell after fullwidth, need to go 2 cells back
608
+ // it is save to step 2 cells back here
609
+ // since an empty cell is only set by fullwidth chars
610
+ bufferRow.addCodepointToCell(this._activeBuffer.x - offset,
611
+ code, chWidth);
612
+ for (let delta = chWidth - oldWidth; --delta >= 0;) {
613
+ bufferRow.setCellFromCodepoint(this._activeBuffer.x++, 0, 0, curAttr);
614
+ }
615
+ continue;
616
+ }
617
+
595
618
  // insert mode: move characters to right
596
619
  if (insertMode) {
597
620
  // right shift cells according to the width
598
- bufferRow.insertCells(this._activeBuffer.x, chWidth, this._activeBuffer.getNullCell(curAttr), curAttr);
621
+ bufferRow.insertCells(this._activeBuffer.x, chWidth - oldWidth, this._activeBuffer.getNullCell(curAttr));
599
622
  // test last cell - since the last cell has only room for
600
623
  // a halfwidth char any fullwidth shifted there is lost
601
624
  // and will be set to empty cell
602
625
  if (bufferRow.getWidth(cols - 1) === 2) {
603
- bufferRow.setCellFromCodePoint(cols - 1, NULL_CELL_CODE, NULL_CELL_WIDTH, curAttr.fg, curAttr.bg, curAttr.extended);
626
+ bufferRow.setCellFromCodepoint(cols - 1, NULL_CELL_CODE, NULL_CELL_WIDTH, curAttr);
604
627
  }
605
628
  }
606
629
 
607
630
  // write current char to buffer and advance cursor
608
- bufferRow.setCellFromCodePoint(this._activeBuffer.x++, code, chWidth, curAttr.fg, curAttr.bg, curAttr.extended);
631
+ bufferRow.setCellFromCodepoint(this._activeBuffer.x++, code, chWidth, curAttr);
609
632
 
610
633
  // fullwidth char - also set next cell to placeholder stub and advance cursor
611
634
  // for graphemes bigger than fullwidth we can simply loop to zero
@@ -613,28 +636,16 @@ export class InputHandler extends Disposable implements IInputHandler {
613
636
  if (chWidth > 0) {
614
637
  while (--chWidth) {
615
638
  // other than a regular empty cell a cell following a wide char has no width
616
- bufferRow.setCellFromCodePoint(this._activeBuffer.x++, 0, 0, curAttr.fg, curAttr.bg, curAttr.extended);
639
+ bufferRow.setCellFromCodepoint(this._activeBuffer.x++, 0, 0, curAttr);
617
640
  }
618
641
  }
619
642
  }
620
- // store last char in Parser.precedingCodepoint for REP to work correctly
621
- // This needs to check whether:
622
- // - fullwidth + surrogates: reset
623
- // - combining: only base char gets carried on (bug in xterm?)
624
- if (end - start > 0) {
625
- bufferRow.loadCell(this._activeBuffer.x - 1, this._workCell);
626
- if (this._workCell.getWidth() === 2 || this._workCell.getCode() > 0xFFFF) {
627
- this._parser.precedingCodepoint = 0;
628
- } else if (this._workCell.isCombined()) {
629
- this._parser.precedingCodepoint = this._workCell.getChars().charCodeAt(0);
630
- } else {
631
- this._parser.precedingCodepoint = this._workCell.content;
632
- }
633
- }
643
+
644
+ this._parser.precedingJoinState = precedingJoinState;
634
645
 
635
646
  // handle wide chars: reset cell to the right if it is second cell of a wide char
636
647
  if (this._activeBuffer.x < cols && end - start > 0 && bufferRow.getWidth(this._activeBuffer.x) === 0 && !bufferRow.hasContent(this._activeBuffer.x)) {
637
- bufferRow.setCellFromCodePoint(this._activeBuffer.x, 0, 1, curAttr.fg, curAttr.bg, curAttr.extended);
648
+ bufferRow.setCellFromCodepoint(this._activeBuffer.x, 0, 1, curAttr);
638
649
  }
639
650
 
640
651
  this._dirtyRowTracker.markDirty(this._activeBuffer.y);
@@ -1139,7 +1150,6 @@ export class InputHandler extends Disposable implements IInputHandler {
1139
1150
  start,
1140
1151
  end,
1141
1152
  this._activeBuffer.getNullCell(this._eraseAttrData()),
1142
- this._eraseAttrData(),
1143
1153
  respectProtect
1144
1154
  );
1145
1155
  if (clearWrap) {
@@ -1213,12 +1223,27 @@ export class InputHandler extends Disposable implements IInputHandler {
1213
1223
  this._dirtyRowTracker.markDirty(0);
1214
1224
  break;
1215
1225
  case 2:
1216
- j = this._bufferService.rows;
1217
- this._dirtyRowTracker.markDirty(j - 1);
1218
- while (j--) {
1219
- this._resetBufferLine(j, respectProtect);
1226
+ if (this._optionsService.rawOptions.scrollOnEraseInDisplay) {
1227
+ j = this._bufferService.rows;
1228
+ this._dirtyRowTracker.markRangeDirty(0, j - 1);
1229
+ while (j--) {
1230
+ const currentLine = this._activeBuffer.lines.get(this._activeBuffer.ybase + j);
1231
+ if (currentLine?.getTrimmedLength()) {
1232
+ break;
1233
+ }
1234
+ }
1235
+ for (; j >= 0; j--) {
1236
+ this._bufferService.scroll(this._eraseAttrData());
1237
+ }
1238
+ }
1239
+ else {
1240
+ j = this._bufferService.rows;
1241
+ this._dirtyRowTracker.markDirty(j - 1);
1242
+ while (j--) {
1243
+ this._resetBufferLine(j, respectProtect);
1244
+ }
1245
+ this._dirtyRowTracker.markDirty(0);
1220
1246
  }
1221
- this._dirtyRowTracker.markDirty(0);
1222
1247
  break;
1223
1248
  case 3:
1224
1249
  // Clear scrollback (everything not in viewport)
@@ -1360,8 +1385,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1360
1385
  line.insertCells(
1361
1386
  this._activeBuffer.x,
1362
1387
  params.params[0] || 1,
1363
- this._activeBuffer.getNullCell(this._eraseAttrData()),
1364
- this._eraseAttrData()
1388
+ this._activeBuffer.getNullCell(this._eraseAttrData())
1365
1389
  );
1366
1390
  this._dirtyRowTracker.markDirty(this._activeBuffer.y);
1367
1391
  }
@@ -1387,8 +1411,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1387
1411
  line.deleteCells(
1388
1412
  this._activeBuffer.x,
1389
1413
  params.params[0] || 1,
1390
- this._activeBuffer.getNullCell(this._eraseAttrData()),
1391
- this._eraseAttrData()
1414
+ this._activeBuffer.getNullCell(this._eraseAttrData())
1392
1415
  );
1393
1416
  this._dirtyRowTracker.markDirty(this._activeBuffer.y);
1394
1417
  }
@@ -1455,7 +1478,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1455
1478
  const param = params.params[0] || 1;
1456
1479
  for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
1457
1480
  const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
1458
- line.deleteCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData());
1481
+ line.deleteCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
1459
1482
  line.isWrapped = false;
1460
1483
  }
1461
1484
  this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
@@ -1488,7 +1511,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1488
1511
  const param = params.params[0] || 1;
1489
1512
  for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
1490
1513
  const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
1491
- line.insertCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData());
1514
+ line.insertCells(0, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
1492
1515
  line.isWrapped = false;
1493
1516
  }
1494
1517
  this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
@@ -1511,7 +1534,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1511
1534
  const param = params.params[0] || 1;
1512
1535
  for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
1513
1536
  const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
1514
- line.insertCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData());
1537
+ line.insertCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
1515
1538
  line.isWrapped = false;
1516
1539
  }
1517
1540
  this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
@@ -1534,7 +1557,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1534
1557
  const param = params.params[0] || 1;
1535
1558
  for (let y = this._activeBuffer.scrollTop; y <= this._activeBuffer.scrollBottom; ++y) {
1536
1559
  const line = this._activeBuffer.lines.get(this._activeBuffer.ybase + y)!;
1537
- line.deleteCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()), this._eraseAttrData());
1560
+ line.deleteCells(this._activeBuffer.x, param, this._activeBuffer.getNullCell(this._eraseAttrData()));
1538
1561
  line.isWrapped = false;
1539
1562
  }
1540
1563
  this._dirtyRowTracker.markRangeDirty(this._activeBuffer.scrollTop, this._activeBuffer.scrollBottom);
@@ -1556,8 +1579,7 @@ export class InputHandler extends Disposable implements IInputHandler {
1556
1579
  line.replaceCells(
1557
1580
  this._activeBuffer.x,
1558
1581
  this._activeBuffer.x + (params.params[0] || 1),
1559
- this._activeBuffer.getNullCell(this._eraseAttrData()),
1560
- this._eraseAttrData()
1582
+ this._activeBuffer.getNullCell(this._eraseAttrData())
1561
1583
  );
1562
1584
  this._dirtyRowTracker.markDirty(this._activeBuffer.y);
1563
1585
  }
@@ -1576,9 +1598,8 @@ export class InputHandler extends Disposable implements IInputHandler {
1576
1598
  * If the character preceding REP is a control function or part of a control function,
1577
1599
  * the effect of REP is not defined by this Standard.
1578
1600
  *
1579
- * Since we propagate the terminal as xterm-256color we have to follow xterm's behavior:
1580
- * - fullwidth + surrogate chars are ignored
1581
- * - for combining chars only the base char gets repeated
1601
+ * We extend xterm's behavior to allow repeating entire grapheme clusters.
1602
+ * This isn't 100% xterm-compatible, but it seems saner and more useful.
1582
1603
  * - text attrs are applied normally
1583
1604
  * - wrap around is respected
1584
1605
  * - any valid sequence resets the carried forward char
@@ -1592,16 +1613,29 @@ export class InputHandler extends Disposable implements IInputHandler {
1592
1613
  * (NOOP for any other sequence in between or NON ASCII characters).
1593
1614
  */
1594
1615
  public repeatPrecedingCharacter(params: IParams): boolean {
1595
- if (!this._parser.precedingCodepoint) {
1616
+ const joinState = this._parser.precedingJoinState;
1617
+ if (!joinState) {
1596
1618
  return true;
1597
1619
  }
1598
1620
  // call print to insert the chars and handle correct wrapping
1599
1621
  const length = params.params[0] || 1;
1600
- const data = new Uint32Array(length);
1601
- for (let i = 0; i < length; ++i) {
1602
- data[i] = this._parser.precedingCodepoint;
1622
+ const chWidth = UnicodeService.extractWidth(joinState);
1623
+ const x = this._activeBuffer.x - chWidth;
1624
+ const bufferRow = this._activeBuffer.lines.get(this._activeBuffer.ybase + this._activeBuffer.y)!;
1625
+ const text = bufferRow.getString(x);
1626
+ const data = new Uint32Array(text.length * length);
1627
+ let idata = 0;
1628
+ for (let itext = 0; itext < text.length;) {
1629
+ const ch = text.codePointAt(itext) || 0;
1630
+ data[idata++] = ch;
1631
+ itext += ch > 0xffff ? 2 : 1;
1632
+ }
1633
+ let tlength = idata;
1634
+ for (let i = 1; i < length; ++i) {
1635
+ data.copyWithin(tlength, 0, idata);
1636
+ tlength += idata;
1603
1637
  }
1604
- this.print(data, 0, data.length);
1638
+ this.print(data, 0, tlength);
1605
1639
  return true;
1606
1640
  }
1607
1641
 
@@ -1929,12 +1963,15 @@ export class InputHandler extends Disposable implements IInputHandler {
1929
1963
  case 1047: // alt screen buffer
1930
1964
  this._bufferService.buffers.activateAltBuffer(this._eraseAttrData());
1931
1965
  this._coreService.isCursorInitialized = true;
1932
- this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);
1966
+ this._onRequestRefreshRows.fire(undefined);
1933
1967
  this._onRequestSyncScrollBar.fire();
1934
1968
  break;
1935
1969
  case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
1936
1970
  this._coreService.decPrivateModes.bracketedPasteMode = true;
1937
1971
  break;
1972
+ case 2026: // synchronized output (https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md)
1973
+ this._coreService.decPrivateModes.synchronizedOutput = true;
1974
+ break;
1938
1975
  }
1939
1976
  }
1940
1977
  return true;
@@ -2157,12 +2194,16 @@ export class InputHandler extends Disposable implements IInputHandler {
2157
2194
  this.restoreCursor();
2158
2195
  }
2159
2196
  this._coreService.isCursorInitialized = true;
2160
- this._onRequestRefreshRows.fire(0, this._bufferService.rows - 1);
2197
+ this._onRequestRefreshRows.fire(undefined);
2161
2198
  this._onRequestSyncScrollBar.fire();
2162
2199
  break;
2163
2200
  case 2004: // bracketed paste mode (https://cirw.in/blog/bracketed-paste)
2164
2201
  this._coreService.decPrivateModes.bracketedPasteMode = false;
2165
2202
  break;
2203
+ case 2026: // synchronized output (https://github.com/contour-terminal/vt-extensions/blob/master/synchronized-output.md)
2204
+ this._coreService.decPrivateModes.synchronizedOutput = false;
2205
+ this._onRequestRefreshRows.fire(undefined);
2206
+ break;
2166
2207
  }
2167
2208
  }
2168
2209
  return true;
@@ -2257,6 +2298,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2257
2298
  if (p === 1048) return f(p, V.SET); // xterm always returns SET here
2258
2299
  if (p === 47 || p === 1047 || p === 1049) return f(p, b2v(active === alt));
2259
2300
  if (p === 2004) return f(p, b2v(dm.bracketedPasteMode));
2301
+ if (p === 2026) return f(p, b2v(dm.synchronizedOutput));
2260
2302
  return f(p, V.NOT_RECOGNIZED);
2261
2303
  }
2262
2304
 
@@ -2698,7 +2740,7 @@ export class InputHandler extends Disposable implements IInputHandler {
2698
2740
 
2699
2741
  /**
2700
2742
  * CSI Ps SP q Set cursor style (DECSCUSR, VT520).
2701
- * Ps = 0 -> blinking block.
2743
+ * Ps = 0 -> reset to option.
2702
2744
  * Ps = 1 -> blinking block (default).
2703
2745
  * Ps = 2 -> steady block.
2704
2746
  * Ps = 3 -> blinking underline.
@@ -2708,31 +2750,37 @@ export class InputHandler extends Disposable implements IInputHandler {
2708
2750
  *
2709
2751
  * @vt: #Y CSI DECSCUSR "Set Cursor Style" "CSI Ps SP q" "Set cursor style."
2710
2752
  * Supported cursor styles:
2711
- * - empty, 0 or 1: steady block
2712
- * - 2: blink block
2713
- * - 3: steady underline
2714
- * - 4: blink underline
2715
- * - 5: steady bar
2716
- * - 6: blink bar
2753
+ * - 0: reset to option
2754
+ * - empty, 1: blinking block
2755
+ * - 2: steady block
2756
+ * - 3: blinking underline
2757
+ * - 4: steady underline
2758
+ * - 5: blinking bar
2759
+ * - 6: steady bar
2717
2760
  */
2718
2761
  public setCursorStyle(params: IParams): boolean {
2719
- const param = params.params[0] || 1;
2720
- switch (param) {
2721
- case 1:
2722
- case 2:
2723
- this._optionsService.options.cursorStyle = 'block';
2724
- break;
2725
- case 3:
2726
- case 4:
2727
- this._optionsService.options.cursorStyle = 'underline';
2728
- break;
2729
- case 5:
2730
- case 6:
2731
- this._optionsService.options.cursorStyle = 'bar';
2732
- break;
2762
+ const param = params.length === 0 ? 1 : params.params[0];
2763
+ if (param === 0) {
2764
+ this._coreService.decPrivateModes.cursorStyle = undefined;
2765
+ this._coreService.decPrivateModes.cursorBlink = undefined;
2766
+ } else {
2767
+ switch (param) {
2768
+ case 1:
2769
+ case 2:
2770
+ this._coreService.decPrivateModes.cursorStyle = 'block';
2771
+ break;
2772
+ case 3:
2773
+ case 4:
2774
+ this._coreService.decPrivateModes.cursorStyle = 'underline';
2775
+ break;
2776
+ case 5:
2777
+ case 6:
2778
+ this._coreService.decPrivateModes.cursorStyle = 'bar';
2779
+ break;
2780
+ }
2781
+ const isBlinking = param % 2 === 1;
2782
+ this._coreService.decPrivateModes.cursorBlink = isBlinking;
2733
2783
  }
2734
- const isBlinking = param % 2 === 1;
2735
- this._optionsService.options.cursorBlink = isBlinking;
2736
2784
  return true;
2737
2785
  }
2738
2786
 
@@ -2958,14 +3006,18 @@ export class InputHandler extends Disposable implements IInputHandler {
2958
3006
  * feedback. Use `OSC 8 ; ; BEL` to finish the current hyperlink.
2959
3007
  */
2960
3008
  public setHyperlink(data: string): boolean {
2961
- const args = data.split(';');
2962
- if (args.length < 2) {
2963
- return false;
3009
+ // Arg parsing is special cases to support unencoded semi-colons in the URIs (#4944)
3010
+ const idx = data.indexOf(';');
3011
+ if (idx === -1) {
3012
+ // malformed sequence, just return as handled
3013
+ return true;
2964
3014
  }
2965
- if (args[1]) {
2966
- return this._createHyperlink(args[0], args[1]);
3015
+ const id = data.slice(0, idx).trim();
3016
+ const uri = data.slice(idx + 1);
3017
+ if (uri) {
3018
+ return this._createHyperlink(id, uri);
2967
3019
  }
2968
- if (args[0]) {
3020
+ if (id.trim()) {
2969
3021
  return false;
2970
3022
  }
2971
3023
  return this._finishHyperlink();
@@ -3438,6 +3490,6 @@ class DirtyRowTracker implements IDirtyRowTracker {
3438
3490
  }
3439
3491
  }
3440
3492
 
3441
- function isValidColorIndex(value: number): value is ColorIndex {
3493
+ export function isValidColorIndex(value: number): value is ColorIndex {
3442
3494
  return 0 <= value && value < 256;
3443
3495
  }
@@ -12,8 +12,9 @@ interface INavigator {
12
12
  // We're declaring a navigator global here as we expect it in all runtimes (node and browser), but
13
13
  // we want this module to live in common.
14
14
  declare const navigator: INavigator;
15
+ declare const process: unknown;
15
16
 
16
- export const isNode = (typeof navigator === 'undefined') ? true : false;
17
+ export const isNode = (typeof process !== 'undefined' && 'title' in (process as any)) ? true : false;
17
18
  const userAgent = (isNode) ? 'node' : navigator.userAgent;
18
19
  const platform = (isNode) ? 'node' : navigator.platform;
19
20