@xterm/xterm 5.4.0-beta.20 → 5.4.0-beta.22

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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@xterm/xterm",
3
3
  "description": "Full xterm terminal, in your browser",
4
- "version": "5.4.0-beta.20",
4
+ "version": "5.4.0-beta.22",
5
5
  "main": "lib/xterm.js",
6
6
  "style": "css/xterm.css",
7
7
  "types": "typings/xterm.d.ts",
@@ -4,18 +4,14 @@
4
4
  */
5
5
 
6
6
  import { addDisposableDomListener } from 'browser/Lifecycle';
7
- import { IBufferCellPosition, ILink, ILinkDecorations, ILinkProvider, ILinkWithState, ILinkifier2, ILinkifierEvent } from 'browser/Types';
7
+ import { IBufferCellPosition, ILink, ILinkDecorations, ILinkWithState, ILinkifier2, ILinkifierEvent } from 'browser/Types';
8
8
  import { EventEmitter } from 'common/EventEmitter';
9
9
  import { Disposable, disposeArray, getDisposeArrayDisposable, toDisposable } from 'common/Lifecycle';
10
10
  import { IDisposable } from 'common/Types';
11
11
  import { IBufferService } from 'common/services/Services';
12
- import { IMouseService, IRenderService } from './services/Services';
12
+ import { ILinkProviderService, IMouseService, IRenderService } from './services/Services';
13
13
 
14
- export class Linkifier2 extends Disposable implements ILinkifier2 {
15
- private _element: HTMLElement | undefined;
16
- private _mouseService: IMouseService | undefined;
17
- private _renderService: IRenderService | undefined;
18
- private _linkProviders: ILinkProvider[] = [];
14
+ export class Linkifier extends Disposable implements ILinkifier2 {
19
15
  public get currentLink(): ILinkWithState | undefined { return this._currentLink; }
20
16
  protected _currentLink: ILinkWithState | undefined;
21
17
  private _mouseDownLink: ILinkWithState | undefined;
@@ -33,14 +29,17 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
33
29
  public readonly onHideLinkUnderline = this._onHideLinkUnderline.event;
34
30
 
35
31
  constructor(
36
- @IBufferService private readonly _bufferService: IBufferService
32
+ private readonly _element: HTMLElement,
33
+ @IMouseService private readonly _mouseService: IMouseService,
34
+ @IRenderService private readonly _renderService: IRenderService,
35
+ @IBufferService private readonly _bufferService: IBufferService,
36
+ @ILinkProviderService private readonly _linkProviderService: ILinkProviderService
37
37
  ) {
38
38
  super();
39
39
  this.register(getDisposeArrayDisposable(this._linkCacheDisposables));
40
40
  this.register(toDisposable(() => {
41
41
  this._lastMouseEvent = undefined;
42
42
  // Clear out link providers as they could easily cause an embedder memory leak
43
- this._linkProviders.length = 0;
44
43
  this._activeProviderReplies?.clear();
45
44
  }));
46
45
  // Listen to resize to catch the case where it's resized and the cursor is out of the viewport.
@@ -48,27 +47,6 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
48
47
  this._clearCurrentLink();
49
48
  this._wasResized = true;
50
49
  }));
51
- }
52
-
53
- public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
54
- this._linkProviders.push(linkProvider);
55
- return {
56
- dispose: () => {
57
- // Remove the link provider from the list
58
- const providerIndex = this._linkProviders.indexOf(linkProvider);
59
-
60
- if (providerIndex !== -1) {
61
- this._linkProviders.splice(providerIndex, 1);
62
- }
63
- }
64
- };
65
- }
66
-
67
- public attachToDom(element: HTMLElement, mouseService: IMouseService, renderService: IRenderService): void {
68
- this._element = element;
69
- this._mouseService = mouseService;
70
- this._renderService = renderService;
71
-
72
50
  this.register(addDisposableDomListener(this._element, 'mouseleave', () => {
73
51
  this._isMouseOut = true;
74
52
  this._clearCurrentLink();
@@ -81,10 +59,6 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
81
59
  private _handleMouseMove(event: MouseEvent): void {
82
60
  this._lastMouseEvent = event;
83
61
 
84
- if (!this._element || !this._mouseService) {
85
- return;
86
- }
87
-
88
62
  const position = this._positionFromMouseEvent(event, this._element, this._mouseService);
89
63
  if (!position) {
90
64
  return;
@@ -145,7 +119,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
145
119
  let linkProvided = false;
146
120
 
147
121
  // There is no link cached, so ask for one
148
- for (const [i, linkProvider] of this._linkProviders.entries()) {
122
+ for (const [i, linkProvider] of this._linkProviderService.linkProviders.entries()) {
149
123
  if (useLineCache) {
150
124
  const existingReply = this._activeProviderReplies?.get(i);
151
125
  // If there isn't a reply, the provider hasn't responded yet.
@@ -167,7 +141,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
167
141
 
168
142
  // If all providers have responded, remove lower priority links that intersect ranges of
169
143
  // higher priority links
170
- if (this._activeProviderReplies?.size === this._linkProviders.length) {
144
+ if (this._activeProviderReplies?.size === this._linkProviderService.linkProviders.length) {
171
145
  this._removeIntersectingLinks(position.y, this._activeProviderReplies);
172
146
  }
173
147
  });
@@ -223,7 +197,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
223
197
  }
224
198
 
225
199
  // Check if all the providers have responded
226
- if (this._activeProviderReplies.size === this._linkProviders.length && !linkProvided) {
200
+ if (this._activeProviderReplies.size === this._linkProviderService.linkProviders.length && !linkProvided) {
227
201
  // Respect the order of the link providers
228
202
  for (let j = 0; j < this._activeProviderReplies.size; j++) {
229
203
  const currentLink = this._activeProviderReplies.get(j)?.find(link => this._linkAtPosition(link.link, position));
@@ -243,7 +217,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
243
217
  }
244
218
 
245
219
  private _handleMouseUp(event: MouseEvent): void {
246
- if (!this._element || !this._mouseService || !this._currentLink) {
220
+ if (!this._currentLink) {
247
221
  return;
248
222
  }
249
223
 
@@ -258,7 +232,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
258
232
  }
259
233
 
260
234
  private _clearCurrentLink(startRow?: number, endRow?: number): void {
261
- if (!this._element || !this._currentLink || !this._lastMouseEvent) {
235
+ if (!this._currentLink || !this._lastMouseEvent) {
262
236
  return;
263
237
  }
264
238
 
@@ -271,7 +245,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
271
245
  }
272
246
 
273
247
  private _handleNewLink(linkWithState: ILinkWithState): void {
274
- if (!this._element || !this._lastMouseEvent || !this._mouseService) {
248
+ if (!this._lastMouseEvent) {
275
249
  return;
276
250
  }
277
251
 
@@ -302,7 +276,7 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
302
276
  if (this._currentLink?.state && this._currentLink.state.decorations.pointerCursor !== v) {
303
277
  this._currentLink.state.decorations.pointerCursor = v;
304
278
  if (this._currentLink.state.isHovered) {
305
- this._element?.classList.toggle('xterm-cursor-pointer', v);
279
+ this._element.classList.toggle('xterm-cursor-pointer', v);
306
280
  }
307
281
  }
308
282
  }
@@ -322,29 +296,27 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
322
296
 
323
297
  // Listen to viewport changes to re-render the link under the cursor (only when the line the
324
298
  // link is on changes)
325
- if (this._renderService) {
326
- this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange(e => {
327
- // Sanity check, this shouldn't happen in practice as this listener would be disposed
328
- if (!this._currentLink) {
329
- return;
330
- }
331
- // When start is 0 a scroll most likely occurred, make sure links above the fold also get
332
- // cleared.
333
- const start = e.start === 0 ? 0 : e.start + 1 + this._bufferService.buffer.ydisp;
334
- const end = this._bufferService.buffer.ydisp + 1 + e.end;
335
- // Only clear the link if the viewport change happened on this line
336
- if (this._currentLink.link.range.start.y >= start && this._currentLink.link.range.end.y <= end) {
337
- this._clearCurrentLink(start, end);
338
- if (this._lastMouseEvent && this._element) {
339
- // re-eval previously active link after changes
340
- const position = this._positionFromMouseEvent(this._lastMouseEvent, this._element, this._mouseService!);
341
- if (position) {
342
- this._askForLink(position, false);
343
- }
299
+ this._linkCacheDisposables.push(this._renderService.onRenderedViewportChange(e => {
300
+ // Sanity check, this shouldn't happen in practice as this listener would be disposed
301
+ if (!this._currentLink) {
302
+ return;
303
+ }
304
+ // When start is 0 a scroll most likely occurred, make sure links above the fold also get
305
+ // cleared.
306
+ const start = e.start === 0 ? 0 : e.start + 1 + this._bufferService.buffer.ydisp;
307
+ const end = this._bufferService.buffer.ydisp + 1 + e.end;
308
+ // Only clear the link if the viewport change happened on this line
309
+ if (this._currentLink.link.range.start.y >= start && this._currentLink.link.range.end.y <= end) {
310
+ this._clearCurrentLink(start, end);
311
+ if (this._lastMouseEvent) {
312
+ // re-eval previously active link after changes
313
+ const position = this._positionFromMouseEvent(this._lastMouseEvent, this._element, this._mouseService!);
314
+ if (position) {
315
+ this._askForLink(position, false);
344
316
  }
345
317
  }
346
- }));
347
- }
318
+ }
319
+ }));
348
320
  }
349
321
  }
350
322
 
@@ -3,7 +3,8 @@
3
3
  * @license MIT
4
4
  */
5
5
 
6
- import { IBufferRange, ILink, ILinkProvider } from 'browser/Types';
6
+ import { IBufferRange, ILink } from 'browser/Types';
7
+ import { ILinkProvider } from 'browser/services/Services';
7
8
  import { CellData } from 'common/buffer/CellData';
8
9
  import { IBufferService, IOptionsService, IOscLinkService } from 'common/services/Services';
9
10
 
@@ -23,7 +23,7 @@
23
23
 
24
24
  import { copyHandler, handlePasteEvent, moveTextAreaUnderMouseCursor, paste, rightClickHandler } from 'browser/Clipboard';
25
25
  import { addDisposableDomListener } from 'browser/Lifecycle';
26
- import { Linkifier2 } from 'browser/Linkifier2';
26
+ import { Linkifier } from './Linkifier';
27
27
  import * as Strings from 'browser/LocalizableStrings';
28
28
  import { OscLinkProvider } from 'browser/OscLinkProvider';
29
29
  import { CharacterJoinerHandler, CustomKeyEventHandler, CustomWheelEventHandler, IBrowser, IBufferRange, ICompositionHelper, ILinkifier2, ITerminal, IViewport } from 'browser/Types';
@@ -39,9 +39,9 @@ import { CoreBrowserService } from 'browser/services/CoreBrowserService';
39
39
  import { MouseService } from 'browser/services/MouseService';
40
40
  import { RenderService } from 'browser/services/RenderService';
41
41
  import { SelectionService } from 'browser/services/SelectionService';
42
- import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services';
42
+ import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, ILinkProviderService, IMouseService, IRenderService, ISelectionService, IThemeService } from 'browser/services/Services';
43
43
  import { ThemeService } from 'browser/services/ThemeService';
44
- import { color, rgba } from 'common/Color';
44
+ import { channels, color } from 'common/Color';
45
45
  import { CoreTerminal } from 'common/CoreTerminal';
46
46
  import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
47
47
  import { MutableDisposable, toDisposable } from 'common/Lifecycle';
@@ -57,6 +57,7 @@ import { IDecorationService } from 'common/services/Services';
57
57
  import { IDecoration, IDecorationOptions, IDisposable, ILinkProvider, IMarker } from '@xterm/xterm';
58
58
  import { WindowsOptionsReportType } from '../common/InputHandler';
59
59
  import { AccessibilityManager } from './AccessibilityManager';
60
+ import { LinkProviderService } from 'browser/services/LinkProviderService';
60
61
 
61
62
  export class Terminal extends CoreTerminal implements ITerminal {
62
63
  public textarea: HTMLTextAreaElement | undefined;
@@ -69,6 +70,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
69
70
  private _helperContainer: HTMLElement | undefined;
70
71
  private _compositionView: HTMLElement | undefined;
71
72
 
73
+ public linkifier: ILinkifier2 | undefined;
72
74
  private _overviewRulerRenderer: OverviewRulerRenderer | undefined;
73
75
 
74
76
  public browser: IBrowser = Browser as any;
@@ -76,8 +78,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
76
78
  private _customKeyEventHandler: CustomKeyEventHandler | undefined;
77
79
  private _customWheelEventHandler: CustomWheelEventHandler | undefined;
78
80
 
79
- // browser services
81
+ // Browser services
80
82
  private _decorationService: DecorationService;
83
+ private _linkProviderService: ILinkProviderService;
84
+
85
+ // Optional browser services
81
86
  private _charSizeService: ICharSizeService | undefined;
82
87
  private _coreBrowserService: ICoreBrowserService | undefined;
83
88
  private _mouseService: IMouseService | undefined;
@@ -113,7 +118,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
113
118
  */
114
119
  private _unprocessedDeadKey: boolean = false;
115
120
 
116
- public linkifier2: ILinkifier2;
117
121
  public viewport: IViewport | undefined;
118
122
  private _compositionHelper: ICompositionHelper | undefined;
119
123
  private _accessibilityManager: MutableDisposable<AccessibilityManager> = this.register(new MutableDisposable());
@@ -149,10 +153,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
149
153
 
150
154
  this._setup();
151
155
 
152
- this.linkifier2 = this.register(this._instantiationService.createInstance(Linkifier2));
153
- this.linkifier2.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
154
156
  this._decorationService = this._instantiationService.createInstance(DecorationService);
155
157
  this._instantiationService.setService(IDecorationService, this._decorationService);
158
+ this._linkProviderService = this._instantiationService.createInstance(LinkProviderService);
159
+ this._instantiationService.setService(ILinkProviderService, this._linkProviderService);
160
+ this._linkProviderService.registerLinkProvider(this._instantiationService.createInstance(OscLinkProvider));
156
161
 
157
162
  // Setup InputHandler listeners
158
163
  this.register(this._inputHandler.onRequestBell(() => this._onBell.fire()));
@@ -206,17 +211,17 @@ export class Terminal extends CoreTerminal implements ITerminal {
206
211
  }
207
212
  switch (req.type) {
208
213
  case ColorRequestType.REPORT:
209
- const channels = color.toColorRGB(acc === 'ansi'
214
+ const colorRgb = color.toColorRGB(acc === 'ansi'
210
215
  ? this._themeService.colors.ansi[req.index]
211
216
  : this._themeService.colors[acc]);
212
- this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(channels)}${C1_ESCAPED.ST}`);
217
+ this.coreService.triggerDataEvent(`${C0.ESC}]${ident};${toRgbString(colorRgb)}${C1_ESCAPED.ST}`);
213
218
  break;
214
219
  case ColorRequestType.SET:
215
220
  if (acc === 'ansi') {
216
- this._themeService.modifyColors(colors => colors.ansi[req.index] = rgba.toColor(...req.color));
221
+ this._themeService.modifyColors(colors => colors.ansi[req.index] = channels.toColor(...req.color));
217
222
  } else {
218
223
  const narrowedAcc = acc;
219
- this._themeService.modifyColors(colors => colors[narrowedAcc] = rgba.toColor(...req.color));
224
+ this._themeService.modifyColors(colors => colors[narrowedAcc] = channels.toColor(...req.color));
220
225
  }
221
226
  break;
222
227
  case ColorRequestType.RESTORE:
@@ -482,6 +487,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
482
487
  this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
483
488
  this._helperContainer.appendChild(this._compositionView);
484
489
 
490
+ this._mouseService = this._instantiationService.createInstance(MouseService);
491
+ this._instantiationService.setService(IMouseService, this._mouseService);
492
+
493
+ this.linkifier = this.register(this._instantiationService.createInstance(Linkifier, this.screenElement));
494
+
485
495
  // Performance: Add viewport and helper elements from the fragment
486
496
  this.element.appendChild(fragment);
487
497
 
@@ -493,9 +503,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
493
503
  this._renderService.setRenderer(this._createRenderer());
494
504
  }
495
505
 
496
- this._mouseService = this._instantiationService.createInstance(MouseService);
497
- this._instantiationService.setService(IMouseService, this._mouseService);
498
-
499
506
  this.viewport = this._instantiationService.createInstance(Viewport, this._viewportElement, this._viewportScrollArea);
500
507
  this.viewport.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent, ScrollSource.VIEWPORT)),
501
508
  this.register(this._inputHandler.onRequestSyncScrollBar(() => this.viewport!.syncScrollArea()));
@@ -513,7 +520,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
513
520
  this._selectionService = this.register(this._instantiationService.createInstance(SelectionService,
514
521
  this.element,
515
522
  this.screenElement,
516
- this.linkifier2
523
+ this.linkifier
517
524
  ));
518
525
  this._instantiationService.setService(ISelectionService, this._selectionService);
519
526
  this.register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
@@ -533,7 +540,6 @@ export class Terminal extends CoreTerminal implements ITerminal {
533
540
  }));
534
541
  this.register(addDisposableDomListener(this._viewportElement, 'scroll', () => this._selectionService!.refresh()));
535
542
 
536
- this.linkifier2.attachToDom(this.screenElement, this._mouseService, this._renderService);
537
543
  this.register(this._instantiationService.createInstance(BufferDecorationRenderer, this.screenElement));
538
544
  this.register(addDisposableDomListener(this.element, 'mousedown', (e: MouseEvent) => this._selectionService!.handleMouseDown(e)));
539
545
 
@@ -575,7 +581,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
575
581
  }
576
582
 
577
583
  private _createRenderer(): IRenderer {
578
- return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier2);
584
+ return this._instantiationService.createInstance(DomRenderer, this, this._document!, this.element!, this.screenElement!, this._viewportElement!, this._helperContainer!, this.linkifier!);
579
585
  }
580
586
 
581
587
  /**
@@ -894,7 +900,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
894
900
  }
895
901
 
896
902
  public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
897
- return this.linkifier2.registerLinkProvider(linkProvider);
903
+ return this._linkProviderService.registerLinkProvider(linkProvider);
898
904
  }
899
905
 
900
906
  public registerCharacterJoiner(handler: CharacterJoinerHandler): number {
@@ -7,7 +7,6 @@ import { IEvent } from 'common/EventEmitter';
7
7
  import { CharData, IColor, ICoreTerminal, ITerminalOptions } from 'common/Types';
8
8
  import { IBuffer } from 'common/buffer/Types';
9
9
  import { IDisposable, Terminal as ITerminalApi } from '@xterm/xterm';
10
- import { IMouseService, IRenderService } from './services/Services';
11
10
 
12
11
  /**
13
12
  * A portion of the public API that are implemented identially internally and simply passed through.
@@ -18,9 +17,9 @@ export interface ITerminal extends InternalPassthroughApis, ICoreTerminal {
18
17
  screenElement: HTMLElement | undefined;
19
18
  browser: IBrowser;
20
19
  buffer: IBuffer;
20
+ linkifier: ILinkifier2 | undefined;
21
21
  viewport: IViewport | undefined;
22
22
  options: Required<ITerminalOptions>;
23
- linkifier2: ILinkifier2;
24
23
 
25
24
  onBlur: IEvent<void>;
26
25
  onFocus: IEvent<void>;
@@ -128,13 +127,6 @@ export interface ILinkifier2 extends IDisposable {
128
127
  onShowLinkUnderline: IEvent<ILinkifierEvent>;
129
128
  onHideLinkUnderline: IEvent<ILinkifierEvent>;
130
129
  readonly currentLink: ILinkWithState | undefined;
131
-
132
- attachToDom(element: HTMLElement, mouseService: IMouseService, renderService: IRenderService): void;
133
- registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
134
- }
135
-
136
- interface ILinkProvider {
137
- provideLinks(y: number, callback: (links: ILink[] | undefined) => void): void;
138
130
  }
139
131
 
140
132
  interface ILink {
@@ -8,7 +8,7 @@ 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
14
  import { treatGlyphAsBackgroundColor } from 'browser/renderer/shared/RendererUtils';
@@ -376,7 +376,7 @@ export class DomRendererRowFactory {
376
376
  classes.push(`xterm-bg-${bg}`);
377
377
  break;
378
378
  case Attributes.CM_RGB:
379
- resolvedBg = rgba.toColor(bg >> 16, bg >> 8 & 0xFF, bg & 0xFF);
379
+ resolvedBg = channels.toColor(bg >> 16, bg >> 8 & 0xFF, bg & 0xFF);
380
380
  this._addStyle(charElement, `background-color:#${padStart((bg >>> 0).toString(16), '0', 6)}`);
381
381
  break;
382
382
  case Attributes.CM_DEFAULT:
@@ -408,7 +408,7 @@ export class DomRendererRowFactory {
408
408
  }
409
409
  break;
410
410
  case Attributes.CM_RGB:
411
- const color = rgba.toColor(
411
+ const color = channels.toColor(
412
412
  (fg >> 16) & 0xFF,
413
413
  (fg >> 8) & 0xFF,
414
414
  (fg ) & 0xFF
@@ -8,7 +8,7 @@ import { DIM_OPACITY, TEXT_BASELINE } from 'browser/renderer/shared/Constants';
8
8
  import { tryDrawCustomChar } from 'browser/renderer/shared/CustomGlyphs';
9
9
  import { computeNextVariantOffset, treatGlyphAsBackgroundColor, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
10
10
  import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from 'browser/renderer/shared/Types';
11
- import { NULL_COLOR, color, rgba } from 'common/Color';
11
+ import { NULL_COLOR, channels, color, rgba } from 'common/Color';
12
12
  import { EventEmitter } from 'common/EventEmitter';
13
13
  import { FourKeyMap } from 'common/MultiKeyMap';
14
14
  import { IdleTaskQueue } from 'common/TaskQueue';
@@ -291,8 +291,7 @@ export class TextureAtlas implements ITextureAtlas {
291
291
  break;
292
292
  case Attributes.CM_RGB:
293
293
  const arr = AttributeData.toColorRGB(bgColor);
294
- // TODO: This object creation is slow
295
- result = rgba.toColor(arr[0], arr[1], arr[2]);
294
+ result = channels.toColor(arr[0], arr[1], arr[2]);
296
295
  break;
297
296
  case Attributes.CM_DEFAULT:
298
297
  default:
@@ -324,7 +323,7 @@ export class TextureAtlas implements ITextureAtlas {
324
323
  break;
325
324
  case Attributes.CM_RGB:
326
325
  const arr = AttributeData.toColorRGB(fgColor);
327
- result = rgba.toColor(arr[0], arr[1], arr[2]);
326
+ result = channels.toColor(arr[0], arr[1], arr[2]);
328
327
  break;
329
328
  case Attributes.CM_DEFAULT:
330
329
  default:
@@ -406,7 +405,7 @@ export class TextureAtlas implements ITextureAtlas {
406
405
  return undefined;
407
406
  }
408
407
 
409
- const color = rgba.toColor(
408
+ const color = channels.toColor(
410
409
  (result >> 24) & 0xFF,
411
410
  (result >> 16) & 0xFF,
412
411
  (result >> 8) & 0xFF
@@ -0,0 +1,28 @@
1
+ import { ILinkProvider, ILinkProviderService } from 'browser/services/Services';
2
+ import { Disposable, toDisposable } from 'common/Lifecycle';
3
+ import { IDisposable } from 'common/Types';
4
+
5
+ export class LinkProviderService extends Disposable implements ILinkProviderService {
6
+ declare public serviceBrand: undefined;
7
+
8
+ public readonly linkProviders: ILinkProvider[] = [];
9
+
10
+ constructor() {
11
+ super();
12
+ this.register(toDisposable(() => this.linkProviders.length = 0));
13
+ }
14
+
15
+ public registerLinkProvider(linkProvider: ILinkProvider): IDisposable {
16
+ this.linkProviders.push(linkProvider);
17
+ return {
18
+ dispose: () => {
19
+ // Remove the link provider from the list
20
+ const providerIndex = this.linkProviders.indexOf(linkProvider);
21
+
22
+ if (providerIndex !== -1) {
23
+ this.linkProviders.splice(providerIndex, 1);
24
+ }
25
+ }
26
+ };
27
+ }
28
+ }
@@ -5,7 +5,7 @@
5
5
 
6
6
  import { IEvent } from 'common/EventEmitter';
7
7
  import { IRenderDimensions, IRenderer } from 'browser/renderer/shared/Types';
8
- import { IColorSet, ReadonlyColorSet } from 'browser/Types';
8
+ import { IColorSet, ILink, ReadonlyColorSet } from 'browser/Types';
9
9
  import { ISelectionRedrawRequestEvent as ISelectionRequestRedrawEvent, ISelectionRequestScrollLinesEvent } from 'browser/selection/Types';
10
10
  import { createDecorator } from 'common/services/ServiceRegistry';
11
11
  import { AllColorIndex, IDisposable } from 'common/Types';
@@ -145,3 +145,14 @@ export interface IThemeService {
145
145
  */
146
146
  modifyColors(callback: (colors: IColorSet) => void): void;
147
147
  }
148
+
149
+
150
+ export const ILinkProviderService = createDecorator<ILinkProviderService>('LinkProviderService');
151
+ export interface ILinkProviderService extends IDisposable {
152
+ serviceBrand: undefined;
153
+ readonly linkProviders: ReadonlyArray<ILinkProvider>;
154
+ registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
155
+ }
156
+ export interface ILinkProvider {
157
+ provideLinks(y: number, callback: (links: ILink[] | undefined) => void): void;
158
+ }
@@ -33,6 +33,13 @@ export namespace channels {
33
33
  // >>> 0 forces an unsigned int
34
34
  return (r << 24 | g << 16 | b << 8 | a) >>> 0;
35
35
  }
36
+
37
+ export function toColor(r: number, g: number, b: number, a?: number): IColor {
38
+ return {
39
+ css: channels.toCss(r, g, b, a),
40
+ rgba: channels.toRgba(r, g, b, a)
41
+ };
42
+ }
36
43
  }
37
44
 
38
45
  /**
@@ -70,7 +77,7 @@ export namespace color {
70
77
  if (!result) {
71
78
  return undefined;
72
79
  }
73
- return rgba.toColor(
80
+ return channels.toColor(
74
81
  (result >> 24 & 0xFF),
75
82
  (result >> 16 & 0xFF),
76
83
  (result >> 8 & 0xFF)
@@ -142,14 +149,14 @@ export namespace css {
142
149
  $r = parseInt(css.slice(1, 2).repeat(2), 16);
143
150
  $g = parseInt(css.slice(2, 3).repeat(2), 16);
144
151
  $b = parseInt(css.slice(3, 4).repeat(2), 16);
145
- return rgba.toColor($r, $g, $b);
152
+ return channels.toColor($r, $g, $b);
146
153
  }
147
154
  case 5: { // #rgba
148
155
  $r = parseInt(css.slice(1, 2).repeat(2), 16);
149
156
  $g = parseInt(css.slice(2, 3).repeat(2), 16);
150
157
  $b = parseInt(css.slice(3, 4).repeat(2), 16);
151
158
  $a = parseInt(css.slice(4, 5).repeat(2), 16);
152
- return rgba.toColor($r, $g, $b, $a);
159
+ return channels.toColor($r, $g, $b, $a);
153
160
  }
154
161
  case 7: // #rrggbb
155
162
  return {
@@ -171,7 +178,7 @@ export namespace css {
171
178
  $g = parseInt(rgbaMatch[2]);
172
179
  $b = parseInt(rgbaMatch[3]);
173
180
  $a = Math.round((rgbaMatch[5] === undefined ? 1 : parseFloat(rgbaMatch[5])) * 0xFF);
174
- return rgba.toColor($r, $g, $b, $a);
181
+ return channels.toColor($r, $g, $b, $a);
175
182
  }
176
183
 
177
184
  // Validate the context is available for canvas-based color parsing
@@ -342,17 +349,9 @@ export namespace rgba {
342
349
  return (fgR << 24 | fgG << 16 | fgB << 8 | 0xFF) >>> 0;
343
350
  }
344
351
 
345
- // FIXME: Move this to channels NS?
346
352
  export function toChannels(value: number): [number, number, number, number] {
347
353
  return [(value >> 24) & 0xFF, (value >> 16) & 0xFF, (value >> 8) & 0xFF, value & 0xFF];
348
354
  }
349
-
350
- export function toColor(r: number, g: number, b: number, a?: number): IColor {
351
- return {
352
- css: channels.toCss(r, g, b, a),
353
- rgba: channels.toRgba(r, g, b, a)
354
- };
355
- }
356
355
  }
357
356
 
358
357
  export function toPaddedHex(c: number): string {
@@ -120,6 +120,7 @@ export abstract class CoreTerminal extends Disposable implements ICoreTerminal {
120
120
  this._oscLinkService = this._instantiationService.createInstance(OscLinkService);
121
121
  this._instantiationService.setService(IOscLinkService, this._oscLinkService);
122
122
 
123
+
123
124
  // Register input handler and handle/forward events
124
125
  this._inputHandler = this.register(new InputHandler(this._bufferService, this._charsetService, this.coreService, this._logService, this.optionsService, this._oscLinkService, this.coreMouseService, this.unicodeService));
125
126
  this.register(forwardEvent(this._inputHandler.onLineFeed, this._onLineFeed));
@@ -110,8 +110,8 @@ export interface ICharset {
110
110
  export type CharData = [number, string, number, number];
111
111
 
112
112
  export interface IColor {
113
- css: string;
114
- rgba: number; // 32-bit int with rgba in each byte
113
+ readonly css: string;
114
+ readonly rgba: number; // 32-bit int with rgba in each byte
115
115
  }
116
116
  export type IColorRGB = [number, number, number];
117
117