@xterm/xterm 5.5.0-beta.9 → 5.6.0-beta.1

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.5.0-beta.9",
4
+ "version": "5.6.0-beta.1",
5
5
  "main": "lib/xterm.js",
6
6
  "style": "css/xterm.css",
7
7
  "types": "typings/xterm.d.ts",
@@ -159,8 +159,9 @@ export class CompositionHelper {
159
159
  // otherwise input characters can be duplicated. (Issue #3191)
160
160
  currentCompositionPosition.start += this._dataAlreadySent.length;
161
161
  if (this._isComposing) {
162
- // Use the end position to get the string if a new composition has started.
163
- input = this._textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end);
162
+ // Use the start position of the new composition to get the string
163
+ // if a new composition has started.
164
+ input = this._textarea.value.substring(currentCompositionPosition.start, this._compositionPosition.start);
164
165
  } else {
165
166
  // Don't use the end position here in order to pick up any characters after the
166
167
  // composition has finished, for example when typing a non-composition character
@@ -183,14 +183,23 @@ export class DomRenderer extends Disposable implements IRenderer {
183
183
  ` font-style: italic;` +
184
184
  `}`;
185
185
  // Blink animation
186
+ const blinkAnimationUnderlineId = `blink_underline_${this._terminalClass}`;
187
+ const blinkAnimationBarId = `blink_bar_${this._terminalClass}`;
188
+ const blinkAnimationBlockId = `blink_block_${this._terminalClass}`;
186
189
  styles +=
187
- `@keyframes blink_box_shadow` + `_` + this._terminalClass + ` {` +
190
+ `@keyframes ${blinkAnimationUnderlineId} {` +
188
191
  ` 50% {` +
189
192
  ` border-bottom-style: hidden;` +
190
193
  ` }` +
191
194
  `}`;
192
195
  styles +=
193
- `@keyframes blink_block` + `_` + this._terminalClass + ` {` +
196
+ `@keyframes ${blinkAnimationBarId} {` +
197
+ ` 50% {` +
198
+ ` box-shadow: none;` +
199
+ ` }` +
200
+ `}`;
201
+ styles +=
202
+ `@keyframes ${blinkAnimationBlockId} {` +
194
203
  ` 0% {` +
195
204
  ` background-color: ${colors.cursor.css};` +
196
205
  ` color: ${colors.cursorAccent.css};` +
@@ -202,13 +211,23 @@ export class DomRenderer extends Disposable implements IRenderer {
202
211
  `}`;
203
212
  // Cursor
204
213
  styles +=
205
- `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}:not(.${RowCss.CURSOR_STYLE_BLOCK_CLASS}) {` +
206
- ` animation: blink_box_shadow` + `_` + this._terminalClass + ` 1s step-end infinite;` +
214
+ `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
215
+ ` animation: ${blinkAnimationUnderlineId} 1s step-end infinite;` +
216
+ `}` +
217
+ `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
218
+ ` animation: ${blinkAnimationBarId} 1s step-end infinite;` +
207
219
  `}` +
208
220
  `${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
209
- ` animation: blink_block` + `_` + this._terminalClass + ` 1s step-end infinite;` +
221
+ ` animation: ${blinkAnimationBlockId} 1s step-end infinite;` +
210
222
  `}` +
223
+ // !important helps fix an issue where the cursor will not render on top of the selection,
224
+ // however it's very hard to fix this issue and retain the blink animation without the use of
225
+ // !important. So this edge case fails when cursor blink is on.
211
226
  `${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
227
+ ` background-color: ${colors.cursor.css};` +
228
+ ` color: ${colors.cursorAccent.css};` +
229
+ `}` +
230
+ `${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS}:not(.${RowCss.CURSOR_BLINK_CLASS}) {` +
212
231
  ` background-color: ${colors.cursor.css} !important;` +
213
232
  ` color: ${colors.cursorAccent.css} !important;` +
214
233
  `}` +
@@ -48,11 +48,13 @@ export function allowRescaling(codepoint: number | undefined, width: number, gly
48
48
  return (
49
49
  // Is single cell width
50
50
  width === 1 &&
51
- // Glyph exceeds cell bounds, add 25% to avoid hurting readability by rescaling glyphs that
51
+ // Glyph exceeds cell bounds, add 50% to avoid hurting readability by rescaling glyphs that
52
52
  // barely overlap
53
- glyphSizeX > deviceCellWidth * 1.25 &&
53
+ glyphSizeX > Math.ceil(deviceCellWidth * 1.5) &&
54
+ // Never rescale ascii
55
+ codepoint !== undefined && codepoint > 0xFF &&
54
56
  // Never rescale emoji
55
- codepoint !== undefined && !isEmoji(codepoint) &&
57
+ !isEmoji(codepoint) &&
56
58
  // Never rescale powerline or nerd fonts
57
59
  !isPowerlineGlyph(codepoint) && !isNerdFontGlyph(codepoint)
58
60
  );
@@ -1 +0,0 @@
1
- This folder contains files that are shared between the renderer addons, but not necessarily bundled into the `xterm` module.
@@ -1,140 +0,0 @@
1
- /**
2
- * Copyright (c) 2014 The xterm.js authors. All rights reserved.
3
- * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
4
- * @license MIT
5
- *
6
- * Originally forked from (with the author's permission):
7
- * Fabrice Bellard's javascript vt100 for jslinux:
8
- * http://bellard.org/jslinux/
9
- * Copyright (c) 2011 Fabrice Bellard
10
- * The original design remains. The terminal itself
11
- * has been extended to include xterm CSI codes, among
12
- * other features.
13
- *
14
- * Terminal Emulation References:
15
- * http://vt100.net/
16
- * http://invisible-island.net/xterm/ctlseqs/ctlseqs.txt
17
- * http://invisible-island.net/xterm/ctlseqs/ctlseqs.html
18
- * http://invisible-island.net/vttest/
19
- * http://www.inwap.com/pdp10/ansicode.txt
20
- * http://linux.die.net/man/4/console_codes
21
- * http://linux.die.net/man/7/urxvt
22
- */
23
-
24
- import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
25
- import { IBuffer } from 'common/buffer/Types';
26
- import { CoreTerminal } from 'common/CoreTerminal';
27
- import { EventEmitter, forwardEvent } from 'common/EventEmitter';
28
- import { IMarker, ITerminalOptions, ScrollSource } from 'common/Types';
29
-
30
- export class Terminal extends CoreTerminal {
31
- private readonly _onBell = this.register(new EventEmitter<void>());
32
- public readonly onBell = this._onBell.event;
33
- private readonly _onCursorMove = this.register(new EventEmitter<void>());
34
- public readonly onCursorMove = this._onCursorMove.event;
35
- private readonly _onTitleChange = this.register(new EventEmitter<string>());
36
- public readonly onTitleChange = this._onTitleChange.event;
37
- private readonly _onA11yCharEmitter = this.register(new EventEmitter<string>());
38
- public readonly onA11yChar = this._onA11yCharEmitter.event;
39
- private readonly _onA11yTabEmitter = this.register(new EventEmitter<number>());
40
- public readonly onA11yTab = this._onA11yTabEmitter.event;
41
-
42
- constructor(
43
- options: ITerminalOptions = {}
44
- ) {
45
- super(options);
46
-
47
- this._setup();
48
-
49
- // Setup InputHandler listeners
50
- this.register(this._inputHandler.onRequestBell(() => this.bell()));
51
- this.register(this._inputHandler.onRequestReset(() => this.reset()));
52
- this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove));
53
- this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange));
54
- this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
55
- this.register(forwardEvent(this._inputHandler.onA11yTab, this._onA11yTabEmitter));
56
- }
57
-
58
- /**
59
- * Convenience property to active buffer.
60
- */
61
- public get buffer(): IBuffer {
62
- return this.buffers.active;
63
- }
64
-
65
- // TODO: Support paste here?
66
-
67
- public get markers(): IMarker[] {
68
- return this.buffer.markers;
69
- }
70
-
71
- public addMarker(cursorYOffset: number): IMarker | undefined {
72
- // Disallow markers on the alt buffer
73
- if (this.buffer !== this.buffers.normal) {
74
- return;
75
- }
76
-
77
- return this.buffer.addMarker(this.buffer.ybase + this.buffer.y + cursorYOffset);
78
- }
79
-
80
- public bell(): void {
81
- this._onBell.fire();
82
- }
83
-
84
- public input(data: string, wasUserInput: boolean = true): void {
85
- this.coreService.triggerDataEvent(data, wasUserInput);
86
- }
87
-
88
- /**
89
- * Resizes the terminal.
90
- *
91
- * @param x The number of columns to resize to.
92
- * @param y The number of rows to resize to.
93
- */
94
- public resize(x: number, y: number): void {
95
- if (x === this.cols && y === this.rows) {
96
- return;
97
- }
98
-
99
- super.resize(x, y);
100
- }
101
-
102
- /**
103
- * Clear the entire buffer, making the prompt line the new first line.
104
- */
105
- public clear(): void {
106
- if (this.buffer.ybase === 0 && this.buffer.y === 0) {
107
- // Don't clear if it's already clear
108
- return;
109
- }
110
- this.buffer.lines.set(0, this.buffer.lines.get(this.buffer.ybase + this.buffer.y)!);
111
- this.buffer.lines.length = 1;
112
- this.buffer.ydisp = 0;
113
- this.buffer.ybase = 0;
114
- this.buffer.y = 0;
115
- for (let i = 1; i < this.rows; i++) {
116
- this.buffer.lines.push(this.buffer.getBlankLine(DEFAULT_ATTR_DATA));
117
- }
118
- this._onScroll.fire({ position: this.buffer.ydisp, source: ScrollSource.TERMINAL });
119
- }
120
-
121
- /**
122
- * Reset terminal.
123
- * Note: Calling this directly from JS is synchronous but does not clear
124
- * input buffers and does not reset the parser, thus the terminal will
125
- * continue to apply pending input data.
126
- * If you need in band reset (synchronous with input data) consider
127
- * using DECSTR (soft reset, CSI ! p) or RIS instead (hard reset, ESC c).
128
- */
129
- public reset(): void {
130
- /**
131
- * Since _setup handles a full terminal creation, we have to carry forward
132
- * a few things that should not reset.
133
- */
134
- this.options.rows = this.rows;
135
- this.options.cols = this.cols;
136
-
137
- this._setup();
138
- super.reset();
139
- }
140
- }
@@ -1,198 +0,0 @@
1
- /**
2
- * Copyright (c) 2018 The xterm.js authors. All rights reserved.
3
- * @license MIT
4
- */
5
-
6
- import { IEvent } from 'common/EventEmitter';
7
- import { BufferNamespaceApi } from 'common/public/BufferNamespaceApi';
8
- import { ParserApi } from 'common/public/ParserApi';
9
- import { UnicodeApi } from 'common/public/UnicodeApi';
10
- import { IBufferNamespace as IBufferNamespaceApi, IMarker, IModes, IParser, ITerminalAddon, ITerminalInitOnlyOptions, IUnicodeHandling, Terminal as ITerminalApi } from '@xterm/headless';
11
- import { Terminal as TerminalCore } from 'headless/Terminal';
12
- import { AddonManager } from 'common/public/AddonManager';
13
- import { ITerminalOptions } from 'common/Types';
14
- import { Disposable } from 'common/Lifecycle';
15
- /**
16
- * The set of options that only have an effect when set in the Terminal constructor.
17
- */
18
- const CONSTRUCTOR_ONLY_OPTIONS = ['cols', 'rows'];
19
-
20
- export class Terminal extends Disposable implements ITerminalApi {
21
- private _core: TerminalCore;
22
- private _addonManager: AddonManager;
23
- private _parser: IParser | undefined;
24
- private _buffer: BufferNamespaceApi | undefined;
25
- private _publicOptions: Required<ITerminalOptions>;
26
-
27
- constructor(options?: ITerminalOptions & ITerminalInitOnlyOptions) {
28
- super();
29
-
30
- this._core = this.register(new TerminalCore(options));
31
- this._addonManager = this.register(new AddonManager());
32
-
33
- this._publicOptions = { ... this._core.options };
34
- const getter = (propName: string): any => {
35
- return this._core.options[propName];
36
- };
37
- const setter = (propName: string, value: any): void => {
38
- this._checkReadonlyOptions(propName);
39
- this._core.options[propName] = value;
40
- };
41
-
42
- for (const propName in this._core.options) {
43
- Object.defineProperty(this._publicOptions, propName, {
44
- get: () => {
45
- return this._core.options[propName];
46
- },
47
- set: (value: any) => {
48
- this._checkReadonlyOptions(propName);
49
- this._core.options[propName] = value;
50
- }
51
- });
52
- const desc = {
53
- get: getter.bind(this, propName),
54
- set: setter.bind(this, propName)
55
- };
56
- Object.defineProperty(this._publicOptions, propName, desc);
57
- }
58
- }
59
-
60
- private _checkReadonlyOptions(propName: string): void {
61
- // Throw an error if any constructor only option is modified
62
- // from terminal.options
63
- // Modifications from anywhere else are allowed
64
- if (CONSTRUCTOR_ONLY_OPTIONS.includes(propName)) {
65
- throw new Error(`Option "${propName}" can only be set in the constructor`);
66
- }
67
- }
68
-
69
- private _checkProposedApi(): void {
70
- if (!this._core.optionsService.options.allowProposedApi) {
71
- throw new Error('You must set the allowProposedApi option to true to use proposed API');
72
- }
73
- }
74
-
75
- public get onBell(): IEvent<void> { return this._core.onBell; }
76
- public get onBinary(): IEvent<string> { return this._core.onBinary; }
77
- public get onCursorMove(): IEvent<void> { return this._core.onCursorMove; }
78
- public get onData(): IEvent<string> { return this._core.onData; }
79
- public get onLineFeed(): IEvent<void> { return this._core.onLineFeed; }
80
- public get onResize(): IEvent<{ cols: number, rows: number }> { return this._core.onResize; }
81
- public get onScroll(): IEvent<number> { return this._core.onScroll; }
82
- public get onTitleChange(): IEvent<string> { return this._core.onTitleChange; }
83
-
84
- public get parser(): IParser {
85
- this._checkProposedApi();
86
- if (!this._parser) {
87
- this._parser = new ParserApi(this._core);
88
- }
89
- return this._parser;
90
- }
91
- public get unicode(): IUnicodeHandling {
92
- this._checkProposedApi();
93
- return new UnicodeApi(this._core);
94
- }
95
- public get rows(): number { return this._core.rows; }
96
- public get cols(): number { return this._core.cols; }
97
- public get buffer(): IBufferNamespaceApi {
98
- this._checkProposedApi();
99
- if (!this._buffer) {
100
- this._buffer = this.register(new BufferNamespaceApi(this._core));
101
- }
102
- return this._buffer;
103
- }
104
- public get markers(): ReadonlyArray<IMarker> {
105
- this._checkProposedApi();
106
- return this._core.markers;
107
- }
108
- public get modes(): IModes {
109
- const m = this._core.coreService.decPrivateModes;
110
- let mouseTrackingMode: 'none' | 'x10' | 'vt200' | 'drag' | 'any' = 'none';
111
- switch (this._core.coreMouseService.activeProtocol) {
112
- case 'X10': mouseTrackingMode = 'x10'; break;
113
- case 'VT200': mouseTrackingMode = 'vt200'; break;
114
- case 'DRAG': mouseTrackingMode = 'drag'; break;
115
- case 'ANY': mouseTrackingMode = 'any'; break;
116
- }
117
- return {
118
- applicationCursorKeysMode: m.applicationCursorKeys,
119
- applicationKeypadMode: m.applicationKeypad,
120
- bracketedPasteMode: m.bracketedPasteMode,
121
- insertMode: this._core.coreService.modes.insertMode,
122
- mouseTrackingMode: mouseTrackingMode,
123
- originMode: m.origin,
124
- reverseWraparoundMode: m.reverseWraparound,
125
- sendFocusMode: m.sendFocus,
126
- wraparoundMode: m.wraparound
127
- };
128
- }
129
- public get options(): Required<ITerminalOptions> {
130
- return this._publicOptions;
131
- }
132
- public set options(options: ITerminalOptions) {
133
- for (const propName in options) {
134
- this._publicOptions[propName] = options[propName];
135
- }
136
- }
137
- public input(data: string, wasUserInput: boolean = true): void {
138
- this._core.input(data, wasUserInput);
139
- }
140
- public resize(columns: number, rows: number): void {
141
- this._verifyIntegers(columns, rows);
142
- this._core.resize(columns, rows);
143
- }
144
- public registerMarker(cursorYOffset: number = 0): IMarker | undefined {
145
- this._checkProposedApi();
146
- this._verifyIntegers(cursorYOffset);
147
- return this._core.addMarker(cursorYOffset);
148
- }
149
- public addMarker(cursorYOffset: number): IMarker | undefined {
150
- return this.registerMarker(cursorYOffset);
151
- }
152
- public dispose(): void {
153
- super.dispose();
154
- }
155
- public scrollLines(amount: number): void {
156
- this._verifyIntegers(amount);
157
- this._core.scrollLines(amount);
158
- }
159
- public scrollPages(pageCount: number): void {
160
- this._verifyIntegers(pageCount);
161
- this._core.scrollPages(pageCount);
162
- }
163
- public scrollToTop(): void {
164
- this._core.scrollToTop();
165
- }
166
- public scrollToBottom(): void {
167
- this._core.scrollToBottom();
168
- }
169
- public scrollToLine(line: number): void {
170
- this._verifyIntegers(line);
171
- this._core.scrollToLine(line);
172
- }
173
- public clear(): void {
174
- this._core.clear();
175
- }
176
- public write(data: string | Uint8Array, callback?: () => void): void {
177
- this._core.write(data, callback);
178
- }
179
- public writeln(data: string | Uint8Array, callback?: () => void): void {
180
- this._core.write(data);
181
- this._core.write('\r\n', callback);
182
- }
183
- public reset(): void {
184
- this._core.reset();
185
- }
186
- public loadAddon(addon: ITerminalAddon): void {
187
- // TODO: This could cause issues if the addon calls renderer apis
188
- this._addonManager.loadAddon(this as any, addon);
189
- }
190
-
191
- private _verifyIntegers(...values: number[]): void {
192
- for (const value of values) {
193
- if (value === Infinity || isNaN(value) || value % 1 !== 0) {
194
- throw new Error('This API only accepts integers');
195
- }
196
- }
197
- }
198
- }