@xterm/addon-image 0.10.0-beta.25 → 0.10.0-beta.250
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/README.md +5 -3
- package/lib/addon-image.js +1 -1
- package/lib/addon-image.js.map +1 -1
- package/lib/addon-image.mjs +1 -22
- package/lib/addon-image.mjs.map +4 -4
- package/package.json +5 -5
- package/src/IIPHandler.ts +53 -39
- package/src/IIPHeaderParser.ts +3 -2
- package/src/IIPImageStorage.ts +26 -0
- package/src/IIPMetrics.ts +9 -1
- package/src/ImageAddon.ts +73 -7
- package/src/ImageRenderer.ts +99 -53
- package/src/ImageStorage.ts +128 -64
- package/src/SixelHandler.ts +4 -4
- package/src/SixelImageStorage.ts +50 -0
- package/src/Types.ts +8 -2
- package/src/kitty/KittyGraphicsHandler.ts +819 -0
- package/src/kitty/KittyGraphicsTypes.ts +195 -0
- package/src/kitty/KittyImageStorage.ts +151 -0
- package/typings/addon-image.d.ts +15 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xterm/addon-image",
|
|
3
|
-
"version": "0.10.0-beta.
|
|
3
|
+
"version": "0.10.0-beta.250",
|
|
4
4
|
"author": {
|
|
5
5
|
"name": "The xterm.js authors",
|
|
6
6
|
"url": "https://xtermjs.org/"
|
|
@@ -18,17 +18,17 @@
|
|
|
18
18
|
"xterm.js"
|
|
19
19
|
],
|
|
20
20
|
"scripts": {
|
|
21
|
-
"prepackage": "../../node_modules/.bin/
|
|
21
|
+
"prepackage": "../../node_modules/.bin/tsgo -p .",
|
|
22
22
|
"package": "../../node_modules/.bin/webpack",
|
|
23
23
|
"prepublishOnly": "npm run package",
|
|
24
24
|
"start": "node ../../demo/start"
|
|
25
25
|
},
|
|
26
26
|
"devDependencies": {
|
|
27
27
|
"sixel": "^0.16.0",
|
|
28
|
-
"xterm-wasm-parts": "^0.1
|
|
28
|
+
"xterm-wasm-parts": "^0.4.1"
|
|
29
29
|
},
|
|
30
|
-
"commit": "
|
|
30
|
+
"commit": "56564431633cc0e7b445292ad2e6b4c9cf0e66ba",
|
|
31
31
|
"peerDependencies": {
|
|
32
|
-
"@xterm/xterm": "^6.1.0-beta.
|
|
32
|
+
"@xterm/xterm": "^6.1.0-beta.250"
|
|
33
33
|
}
|
|
34
34
|
}
|
package/src/IIPHandler.ts
CHANGED
|
@@ -4,17 +4,22 @@
|
|
|
4
4
|
*/
|
|
5
5
|
import { IImageAddonOptions, IOscHandler, IResetHandler, ITerminalExt } from './Types';
|
|
6
6
|
import { ImageRenderer } from './ImageRenderer';
|
|
7
|
-
import {
|
|
7
|
+
import { IIPImageStorage } from './IIPImageStorage';
|
|
8
|
+
import { CELL_SIZE_DEFAULT } from './ImageStorage';
|
|
8
9
|
import Base64Decoder from 'xterm-wasm-parts/lib/base64/Base64Decoder.wasm';
|
|
10
|
+
import QoiDecoder from 'xterm-wasm-parts/lib/qoi/QoiDecoder.wasm';
|
|
9
11
|
import { HeaderParser, IHeaderFields, HeaderState } from './IIPHeaderParser';
|
|
10
12
|
import { imageType, UNSUPPORTED_TYPE } from './IIPMetrics';
|
|
11
13
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
//
|
|
17
|
-
|
|
14
|
+
// Local const enum mirror - esbuild can't inline const enums from external packages
|
|
15
|
+
const enum DecoderConst {
|
|
16
|
+
// Limit held memory in base64 decoder (encoded bytes).
|
|
17
|
+
KEEP_DATA = 4194304,
|
|
18
|
+
// Initial buffer allocation for the decoder.
|
|
19
|
+
INITIAL_DATA = 1048576,
|
|
20
|
+
// Local mirror of const enum (esbuild can't inline const enums from external packages)
|
|
21
|
+
OK = 0
|
|
22
|
+
}
|
|
18
23
|
|
|
19
24
|
// default IIP header values
|
|
20
25
|
const DEFAULT_HEADER: IHeaderFields = {
|
|
@@ -31,15 +36,21 @@ export class IIPHandler implements IOscHandler, IResetHandler {
|
|
|
31
36
|
private _aborted = false;
|
|
32
37
|
private _hp = new HeaderParser();
|
|
33
38
|
private _header: IHeaderFields = DEFAULT_HEADER;
|
|
34
|
-
private _dec
|
|
39
|
+
private _dec: Base64Decoder;
|
|
40
|
+
private _qoiDec: QoiDecoder;
|
|
35
41
|
private _metrics = UNSUPPORTED_TYPE;
|
|
36
42
|
|
|
37
43
|
constructor(
|
|
38
44
|
private readonly _opts: IImageAddonOptions,
|
|
39
45
|
private readonly _renderer: ImageRenderer,
|
|
40
|
-
private readonly _storage:
|
|
46
|
+
private readonly _storage: IIPImageStorage,
|
|
41
47
|
private readonly _coreTerminal: ITerminalExt
|
|
42
|
-
) {
|
|
48
|
+
) {
|
|
49
|
+
const maxEncodedBytes = Math.ceil(this._opts.iipSizeLimit * 4 / 3);
|
|
50
|
+
const initialBytes = Math.min(DecoderConst.INITIAL_DATA, maxEncodedBytes);
|
|
51
|
+
this._dec = new Base64Decoder(DecoderConst.KEEP_DATA, maxEncodedBytes, initialBytes);
|
|
52
|
+
this._qoiDec = new QoiDecoder(DecoderConst.KEEP_DATA);
|
|
53
|
+
}
|
|
43
54
|
|
|
44
55
|
public reset(): void {}
|
|
45
56
|
|
|
@@ -54,7 +65,7 @@ export class IIPHandler implements IOscHandler, IResetHandler {
|
|
|
54
65
|
if (this._aborted) return;
|
|
55
66
|
|
|
56
67
|
if (this._hp.state === HeaderState.END) {
|
|
57
|
-
if (this._dec.put(data
|
|
68
|
+
if ((this._dec.put(data.subarray(start, end)) as number) !== DecoderConst.OK) {
|
|
58
69
|
this._dec.release();
|
|
59
70
|
this._aborted = true;
|
|
60
71
|
}
|
|
@@ -70,8 +81,8 @@ export class IIPHandler implements IOscHandler, IResetHandler {
|
|
|
70
81
|
this._aborted = true;
|
|
71
82
|
return;
|
|
72
83
|
}
|
|
73
|
-
this._dec.init(
|
|
74
|
-
if (this._dec.put(data
|
|
84
|
+
this._dec.init();
|
|
85
|
+
if ((this._dec.put(data.subarray(dataPos, end)) as number) !== DecoderConst.OK) {
|
|
75
86
|
this._dec.release();
|
|
76
87
|
this._aborted = true;
|
|
77
88
|
}
|
|
@@ -89,13 +100,15 @@ export class IIPHandler implements IOscHandler, IResetHandler {
|
|
|
89
100
|
let cond: number | boolean = true;
|
|
90
101
|
if (cond = success) {
|
|
91
102
|
if (cond = !this._dec.end()) {
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
103
|
+
if (cond = this._dec.data8.length === this._header.size) {
|
|
104
|
+
this._metrics = imageType(this._dec.data8);
|
|
105
|
+
if (cond = this._metrics.mime !== 'unsupported') {
|
|
106
|
+
w = this._metrics.width;
|
|
107
|
+
h = this._metrics.height;
|
|
108
|
+
if (cond = w && h && w * h < this._opts.pixelLimit) {
|
|
109
|
+
[w, h] = this._resize(w, h).map(Math.floor);
|
|
110
|
+
cond = w && h && w * h < this._opts.pixelLimit;
|
|
111
|
+
}
|
|
99
112
|
}
|
|
100
113
|
}
|
|
101
114
|
}
|
|
@@ -105,26 +118,27 @@ export class IIPHandler implements IOscHandler, IResetHandler {
|
|
|
105
118
|
return true;
|
|
106
119
|
}
|
|
107
120
|
|
|
108
|
-
|
|
109
|
-
this.
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
});
|
|
121
|
+
let blob: Blob | ImageData;
|
|
122
|
+
if (this._metrics.mime === 'image/qoi') {
|
|
123
|
+
const data = this._qoiDec.decode(this._dec.data8);
|
|
124
|
+
blob = new ImageData(
|
|
125
|
+
new Uint8ClampedArray(data.buffer, data.byteOffset, data.byteLength),
|
|
126
|
+
this._qoiDec.width,
|
|
127
|
+
this._qoiDec.height
|
|
128
|
+
);
|
|
129
|
+
this._qoiDec.release();
|
|
130
|
+
if (w === this._qoiDec.width && h === this._qoiDec.height) {
|
|
131
|
+
// use fast-path if we don't need to rescale
|
|
132
|
+
this._dec.release();
|
|
133
|
+
const canvas = ImageRenderer.createCanvas(undefined, this._qoiDec.width, this._qoiDec.height);
|
|
134
|
+
canvas.getContext('2d')?.putImageData(blob, 0, 0);
|
|
135
|
+
this._storage.addImage(canvas);
|
|
136
|
+
return true;
|
|
137
|
+
}
|
|
138
|
+
} else {
|
|
139
|
+
blob = new Blob([this._dec.data8], { type: this._metrics.mime });
|
|
127
140
|
}
|
|
141
|
+
this._dec.release();
|
|
128
142
|
return createImageBitmap(blob, { resizeWidth: w, resizeHeight: h })
|
|
129
143
|
.then(bm => {
|
|
130
144
|
this._storage.addImage(bm);
|
package/src/IIPHeaderParser.ts
CHANGED
|
@@ -8,6 +8,7 @@ declare const Buffer: any;
|
|
|
8
8
|
|
|
9
9
|
|
|
10
10
|
export interface IHeaderFields {
|
|
11
|
+
[key: string]: number | string | Uint32Array | null | undefined;
|
|
11
12
|
// base-64 encoded filename. Defaults to "Unnamed file".
|
|
12
13
|
name: string;
|
|
13
14
|
// File size in bytes. The file transfer will be canceled if this size is exceeded.
|
|
@@ -81,7 +82,7 @@ function toName(data: Uint32Array): string {
|
|
|
81
82
|
return new TextDecoder().decode(b);
|
|
82
83
|
}
|
|
83
84
|
|
|
84
|
-
const DECODERS: {[key: string]: (v: Uint32Array) =>
|
|
85
|
+
const DECODERS: {[key: string]: (v: Uint32Array) => number | string} = {
|
|
85
86
|
inline: toInt,
|
|
86
87
|
size: toInt,
|
|
87
88
|
name: toName,
|
|
@@ -100,7 +101,7 @@ export class HeaderParser {
|
|
|
100
101
|
private _buffer = new Uint32Array(MAX_FIELDCHARS);
|
|
101
102
|
private _position = 0;
|
|
102
103
|
private _key = '';
|
|
103
|
-
public fields: {[key: string]:
|
|
104
|
+
public fields: {[key: string]: number | string | Uint32Array | null | undefined} = {};
|
|
104
105
|
|
|
105
106
|
public reset(): void {
|
|
106
107
|
this._buffer.fill(0);
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2023 The xterm.js authors. All rights reserved.
|
|
3
|
+
* @license MIT
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ImageStorage } from './ImageStorage';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* IIP (iTerm Image Protocol) specific image storage controller.
|
|
10
|
+
*
|
|
11
|
+
* Wraps the shared ImageStorage with IIP protocol semantics:
|
|
12
|
+
* - Always uses scrolling mode (cursor advances with image)
|
|
13
|
+
*/
|
|
14
|
+
export class IIPImageStorage {
|
|
15
|
+
constructor(
|
|
16
|
+
private readonly _storage: ImageStorage
|
|
17
|
+
) {}
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Add an IIP image to storage.
|
|
21
|
+
* Always uses scrolling mode — cursor advances past the image.
|
|
22
|
+
*/
|
|
23
|
+
public addImage(img: HTMLCanvasElement | ImageBitmap): void {
|
|
24
|
+
this._storage.addImage(img, true);
|
|
25
|
+
}
|
|
26
|
+
}
|
package/src/IIPMetrics.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
export type ImageType = 'image/png' | 'image/jpeg' | 'image/gif' | 'unsupported' | '';
|
|
7
|
+
export type ImageType = 'image/png' | 'image/jpeg' | 'image/gif' | 'image/qoi' | 'unsupported' | '';
|
|
8
8
|
|
|
9
9
|
export interface IMetrics {
|
|
10
10
|
mime: ImageType;
|
|
@@ -45,6 +45,14 @@ export function imageType(d: Uint8Array): IMetrics {
|
|
|
45
45
|
height: d[9] << 8 | d[8]
|
|
46
46
|
};
|
|
47
47
|
}
|
|
48
|
+
// QOI: qoif
|
|
49
|
+
if (d32[0] === 0x66696F71) {
|
|
50
|
+
return {
|
|
51
|
+
mime: 'image/qoi',
|
|
52
|
+
width: d[4] << 24 | d[5] << 16 | d[6] << 8 | d[7],
|
|
53
|
+
height: d[8] << 24 | d[9] << 16 | d[10] << 8 | d[11]
|
|
54
|
+
};
|
|
55
|
+
}
|
|
48
56
|
return UNSUPPORTED_TYPE;
|
|
49
57
|
}
|
|
50
58
|
|
package/src/ImageAddon.ts
CHANGED
|
@@ -5,24 +5,72 @@
|
|
|
5
5
|
|
|
6
6
|
import type { ITerminalAddon, IDisposable } from '@xterm/xterm';
|
|
7
7
|
import type { ImageAddon as IImageApi } from '@xterm/addon-image';
|
|
8
|
+
import { Emitter, type IEvent } from 'common/Event';
|
|
8
9
|
import { IIPHandler } from './IIPHandler';
|
|
9
10
|
import { ImageRenderer } from './ImageRenderer';
|
|
10
11
|
import { ImageStorage, CELL_SIZE_DEFAULT } from './ImageStorage';
|
|
12
|
+
import { KittyGraphicsHandler } from './kitty/KittyGraphicsHandler';
|
|
13
|
+
import { KittyImageStorage } from './kitty/KittyImageStorage';
|
|
11
14
|
import { SixelHandler } from './SixelHandler';
|
|
15
|
+
import { SixelImageStorage } from './SixelImageStorage';
|
|
16
|
+
import { IIPImageStorage } from './IIPImageStorage';
|
|
12
17
|
import { ITerminalExt, IImageAddonOptions, IResetHandler } from './Types';
|
|
13
18
|
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Document VT features provided by this addon.
|
|
22
|
+
*
|
|
23
|
+
* @vt: #E[Supported via @xterm/addon-image.] DCS SIXEL "SIXEL Graphics" "DCS Ps ; Ps ; Ps ; q Pt ST" "Draw SIXEL image."
|
|
24
|
+
*
|
|
25
|
+
* Sixel support is provided by the addon @xterm/addon-image with these limitations:
|
|
26
|
+
* - immediate coloring (no shared palette, allows high color settings of `img2sixel`)
|
|
27
|
+
* - max. palette size of 4096 colors
|
|
28
|
+
* - max. pixel width of 16K
|
|
29
|
+
* - max. 25 MB per sixel sequence
|
|
30
|
+
* - VT340 cursor positioning (begin of last sixel data row)
|
|
31
|
+
*
|
|
32
|
+
* See [addon readme](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-image) for more details.
|
|
33
|
+
*
|
|
34
|
+
*
|
|
35
|
+
* @vt: #E[Supported via @xterm/addon-image.] OSC 1337 "iTerm2 Commands" "OSC 1337 ; Pt BEL" "Custom iTerm2 commands."
|
|
36
|
+
*
|
|
37
|
+
* Only the inline image protocol (IIP) is supported by the addon @xterm/addon-image with
|
|
38
|
+
* the following limitations:
|
|
39
|
+
* - sequence:
|
|
40
|
+
* - format: `OSC 1337 ; File=inline=1 ; size=<unencoded size> ; ... : <base64 payload> BEL`
|
|
41
|
+
* - size param must be set and payload may not exceed CEIL(size * 4 / 3)
|
|
42
|
+
* - strict base64 handling as of RFC4648 §4 (standard alphabet, optional padding,
|
|
43
|
+
* no separator bytes allowed)
|
|
44
|
+
* - supported params: size, name, width, height, preserveAspectRatio
|
|
45
|
+
* - image formats: PNG, JPEG and GIF
|
|
46
|
+
* - no animation support (renders first image of a GIF)
|
|
47
|
+
* - no multipart support
|
|
48
|
+
* - VT340 cursor positioning (begin of last sixel data row)
|
|
49
|
+
*
|
|
50
|
+
* See [addon readme](https://github.com/xtermjs/xterm.js/tree/master/addons/addon-image)
|
|
51
|
+
* and [iTerm2 IIP docs](https://iterm2.com/documentation-images.html) for more details.
|
|
52
|
+
*
|
|
53
|
+
*
|
|
54
|
+
* @vt: #E[Supported via @xterm/addon-image.] APC KITTY_GRAPHICS "Kitty Graphics" "APC G Pt ST" "Kitty Graphics Protocol."
|
|
55
|
+
*
|
|
56
|
+
* Kitty graphics support is provided by the addon @xterm/addon-image.
|
|
57
|
+
* Note that while basic image output already works, this is still work in progress.
|
|
58
|
+
*/
|
|
59
|
+
|
|
14
60
|
// default values of addon ctor options
|
|
15
61
|
const DEFAULT_OPTIONS: IImageAddonOptions = {
|
|
16
62
|
enableSizeReports: true,
|
|
17
63
|
pixelLimit: 16777216, // limit to 4096 * 4096 pixels
|
|
18
64
|
sixelSupport: true,
|
|
19
65
|
sixelScrolling: true,
|
|
20
|
-
sixelPaletteLimit:
|
|
21
|
-
sixelSizeLimit:
|
|
66
|
+
sixelPaletteLimit: 4096,
|
|
67
|
+
sixelSizeLimit: 33554432,
|
|
22
68
|
storageLimit: 128,
|
|
23
69
|
showPlaceholder: true,
|
|
24
70
|
iipSupport: true,
|
|
25
|
-
iipSizeLimit:
|
|
71
|
+
iipSizeLimit: 33554432,
|
|
72
|
+
kittySupport: true,
|
|
73
|
+
kittySizeLimit: 33554432
|
|
26
74
|
};
|
|
27
75
|
|
|
28
76
|
// max palette size supported by the sixel lib (compile time setting)
|
|
@@ -48,7 +96,7 @@ const enum GaStatus {
|
|
|
48
96
|
}
|
|
49
97
|
|
|
50
98
|
|
|
51
|
-
export class ImageAddon implements ITerminalAddon
|
|
99
|
+
export class ImageAddon implements ITerminalAddon, IImageApi {
|
|
52
100
|
private _opts: IImageAddonOptions;
|
|
53
101
|
private _defaultOpts: IImageAddonOptions;
|
|
54
102
|
private _storage: ImageStorage | undefined;
|
|
@@ -56,6 +104,8 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
|
|
|
56
104
|
private _disposables: IDisposable[] = [];
|
|
57
105
|
private _terminal: ITerminalExt | undefined;
|
|
58
106
|
private _handlers: Map<String, IResetHandler> = new Map();
|
|
107
|
+
private readonly _onImageAdded = new Emitter<void>();
|
|
108
|
+
public readonly onImageAdded: IEvent<void> = this._onImageAdded.event;
|
|
59
109
|
|
|
60
110
|
constructor(opts?: Partial<IImageAddonOptions>) {
|
|
61
111
|
this._opts = Object.assign({}, DEFAULT_OPTIONS, opts);
|
|
@@ -68,6 +118,7 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
|
|
|
68
118
|
}
|
|
69
119
|
this._disposables.length = 0;
|
|
70
120
|
this._handlers.clear();
|
|
121
|
+
this._onImageAdded.dispose();
|
|
71
122
|
}
|
|
72
123
|
|
|
73
124
|
private _disposeLater(...args: IDisposable[]): void {
|
|
@@ -82,6 +133,7 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
|
|
|
82
133
|
// internal data structures
|
|
83
134
|
this._renderer = new ImageRenderer(terminal);
|
|
84
135
|
this._storage = new ImageStorage(terminal, this._renderer, this._opts);
|
|
136
|
+
this._storage.onImageAdded = () => this._onImageAdded.fire();
|
|
85
137
|
|
|
86
138
|
// enable size reports
|
|
87
139
|
if (this._opts.enableSizeReports) {
|
|
@@ -90,7 +142,7 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
|
|
|
90
142
|
// windowOptions.getCellSizePixels = true;
|
|
91
143
|
// windowOptions.getWinSizeChars = true;
|
|
92
144
|
// terminal.setOption('windowOptions', windowOptions);
|
|
93
|
-
const windowOps = terminal.options.windowOptions
|
|
145
|
+
const windowOps = terminal.options.windowOptions ?? {};
|
|
94
146
|
windowOps.getWinSizePixels = true;
|
|
95
147
|
windowOps.getCellSizePixels = true;
|
|
96
148
|
windowOps.getWinSizeChars = true;
|
|
@@ -129,7 +181,8 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
|
|
|
129
181
|
|
|
130
182
|
// SIXEL handler
|
|
131
183
|
if (this._opts.sixelSupport) {
|
|
132
|
-
const
|
|
184
|
+
const sixelStorage = new SixelImageStorage(this._storage!, this._opts, this._renderer!, terminal);
|
|
185
|
+
const sixelHandler = new SixelHandler(this._opts, sixelStorage, terminal);
|
|
133
186
|
this._handlers.set('sixel', sixelHandler);
|
|
134
187
|
this._disposeLater(
|
|
135
188
|
terminal._core._inputHandler._parser.registerDcsHandler({ final: 'q' }, sixelHandler)
|
|
@@ -138,12 +191,25 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
|
|
|
138
191
|
|
|
139
192
|
// iTerm IIP handler
|
|
140
193
|
if (this._opts.iipSupport) {
|
|
141
|
-
const
|
|
194
|
+
const iipStorage = new IIPImageStorage(this._storage!);
|
|
195
|
+
const iipHandler = new IIPHandler(this._opts, this._renderer!, iipStorage, terminal);
|
|
142
196
|
this._handlers.set('iip', iipHandler);
|
|
143
197
|
this._disposeLater(
|
|
144
198
|
terminal._core._inputHandler._parser.registerOscHandler(1337, iipHandler)
|
|
145
199
|
);
|
|
146
200
|
}
|
|
201
|
+
|
|
202
|
+
// Kitty graphics handler
|
|
203
|
+
if (this._opts.kittySupport) {
|
|
204
|
+
const kittyStorage = new KittyImageStorage(this._storage!);
|
|
205
|
+
const kittyHandler = new KittyGraphicsHandler(this._opts, this._renderer!, kittyStorage, terminal);
|
|
206
|
+
this._handlers.set('kitty', kittyHandler);
|
|
207
|
+
this._disposeLater(
|
|
208
|
+
kittyStorage,
|
|
209
|
+
kittyHandler,
|
|
210
|
+
terminal._core._inputHandler._parser.registerApcHandler({ final: 'G' }, kittyHandler)
|
|
211
|
+
);
|
|
212
|
+
}
|
|
147
213
|
}
|
|
148
214
|
|
|
149
215
|
// Note: storageLimit is skipped here to not intoduce a surprising side effect.
|