mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' into 5626
This commit is contained in:
@@ -12,7 +12,7 @@ interface IAttachOptions {
|
||||
bidirectional?: boolean;
|
||||
}
|
||||
|
||||
export class AttachAddon implements ITerminalAddon , IAttachApi {
|
||||
export class AttachAddon implements ITerminalAddon, IAttachApi {
|
||||
private _socket: WebSocket;
|
||||
private _bidirectional: boolean;
|
||||
private _disposables: IDisposable[] = [];
|
||||
|
||||
@@ -33,7 +33,7 @@ function _getComputedStyle(el: HTMLElement): CSSStyleDeclaration {
|
||||
return getWindow(el).getComputedStyle(el, null);
|
||||
}
|
||||
|
||||
export class FitAddon implements ITerminalAddon , IFitApi {
|
||||
export class FitAddon implements ITerminalAddon, IFitApi {
|
||||
private _terminal: Terminal | undefined;
|
||||
|
||||
public activate(terminal: Terminal): void {
|
||||
|
||||
@@ -48,7 +48,7 @@ const enum GaStatus {
|
||||
}
|
||||
|
||||
|
||||
export class ImageAddon implements ITerminalAddon , IImageApi {
|
||||
export class ImageAddon implements ITerminalAddon, IImageApi {
|
||||
private _opts: IImageAddonOptions;
|
||||
private _defaultOpts: IImageAddonOptions;
|
||||
private _storage: ImageStorage | undefined;
|
||||
@@ -90,7 +90,7 @@ export class ImageAddon implements ITerminalAddon , IImageApi {
|
||||
// windowOptions.getCellSizePixels = true;
|
||||
// windowOptions.getWinSizeChars = true;
|
||||
// terminal.setOption('windowOptions', windowOptions);
|
||||
const windowOps = terminal.options.windowOptions || {};
|
||||
const windowOps = terminal.options.windowOptions ?? {};
|
||||
windowOps.getWinSizePixels = true;
|
||||
windowOps.getCellSizePixels = true;
|
||||
windowOps.getWinSizeChars = true;
|
||||
|
||||
@@ -38,7 +38,7 @@ export class ImageRenderer extends Disposable implements IDisposable {
|
||||
* Only the DOM output canvas should be on the terminal's document,
|
||||
* which gets explicitly checked in `insertLayerToDom`.
|
||||
*/
|
||||
const canvas = (localDocument || document).createElement('canvas');
|
||||
const canvas = (localDocument ?? document).createElement('canvas');
|
||||
canvas.width = width | 0;
|
||||
canvas.height = height | 0;
|
||||
return canvas;
|
||||
@@ -242,7 +242,7 @@ export class ImageRenderer extends Disposable implements IDisposable {
|
||||
}
|
||||
if (!this._placeholder) return;
|
||||
this._ctx.drawImage(
|
||||
this._placeholderBitmap || this._placeholder!,
|
||||
this._placeholderBitmap ?? this._placeholder!,
|
||||
col * width,
|
||||
(row * height) % 2 ? 0 : 1, // needs %2 offset correction
|
||||
width * count,
|
||||
|
||||
@@ -381,7 +381,7 @@ export class ImageStorage implements IDisposable {
|
||||
if (!line) return;
|
||||
for (let col = 0; col < cols; ++col) {
|
||||
if (line.getBg(col) & BgFlags.HAS_EXTENDED) {
|
||||
let e: IExtendedAttrsImage = line._extendedAttrs[col] || EMPTY_ATTRS;
|
||||
let e: IExtendedAttrsImage = line._extendedAttrs[col] ?? EMPTY_ATTRS;
|
||||
const imageId = e.imageId;
|
||||
if (imageId === undefined || imageId === -1) {
|
||||
continue;
|
||||
@@ -400,7 +400,7 @@ export class ImageStorage implements IDisposable {
|
||||
while (
|
||||
++col < cols
|
||||
&& (line.getBg(col) & BgFlags.HAS_EXTENDED)
|
||||
&& (e = line._extendedAttrs[col] || EMPTY_ATTRS)
|
||||
&& (e = line._extendedAttrs[col] ?? EMPTY_ATTRS)
|
||||
&& (e.imageId === imageId)
|
||||
&& (e.tileId === startTile + count)
|
||||
) {
|
||||
@@ -442,7 +442,7 @@ export class ImageStorage implements IDisposable {
|
||||
for (let row = 0; row < rows; ++row) {
|
||||
const line = buffer.lines.get(row) as IBufferLineExt;
|
||||
if (line.getBg(oldCol) & BgFlags.HAS_EXTENDED) {
|
||||
const e: IExtendedAttrsImage = line._extendedAttrs[oldCol] || EMPTY_ATTRS;
|
||||
const e: IExtendedAttrsImage = line._extendedAttrs[oldCol] ?? EMPTY_ATTRS;
|
||||
const imageId = e.imageId;
|
||||
if (imageId === undefined || imageId === -1) {
|
||||
continue;
|
||||
@@ -487,7 +487,7 @@ export class ImageStorage implements IDisposable {
|
||||
const buffer = this._terminal._core.buffer;
|
||||
const line = buffer.lines.get(y) as IBufferLineExt;
|
||||
if (line && line.getBg(x) & BgFlags.HAS_EXTENDED) {
|
||||
const e: IExtendedAttrsImage = line._extendedAttrs[x] || EMPTY_ATTRS;
|
||||
const e: IExtendedAttrsImage = line._extendedAttrs[x] ?? EMPTY_ATTRS;
|
||||
if (e.imageId && e.imageId !== -1) {
|
||||
const orig = this._images.get(e.imageId)?.orig;
|
||||
if (window.ImageBitmap && orig instanceof ImageBitmap) {
|
||||
@@ -507,7 +507,7 @@ export class ImageStorage implements IDisposable {
|
||||
const buffer = this._terminal._core.buffer;
|
||||
const line = buffer.lines.get(y) as IBufferLineExt;
|
||||
if (line && line.getBg(x) & BgFlags.HAS_EXTENDED) {
|
||||
const e: IExtendedAttrsImage = line._extendedAttrs[x] || EMPTY_ATTRS;
|
||||
const e: IExtendedAttrsImage = line._extendedAttrs[x] ?? EMPTY_ATTRS;
|
||||
if (e.imageId && e.imageId !== -1 && e.tileId !== -1) {
|
||||
const spec = this._images.get(e.imageId);
|
||||
if (spec) {
|
||||
|
||||
@@ -13,7 +13,7 @@ export interface ITerminalAddon {
|
||||
dispose(): void;
|
||||
}
|
||||
|
||||
export class LigaturesAddon implements ITerminalAddon , ILigaturesApi {
|
||||
export class LigaturesAddon implements ITerminalAddon, ILigaturesApi {
|
||||
private readonly _fallbackLigatures: string[];
|
||||
private readonly _fontFeatureSettings?: string;
|
||||
|
||||
@@ -22,7 +22,7 @@ export class LigaturesAddon implements ITerminalAddon , ILigaturesApi {
|
||||
|
||||
constructor(options?: Partial<ILigatureOptions>) {
|
||||
// Source: calt set from https://github.com/be5invis/Iosevka?tab=readme-ov-file#ligations
|
||||
this._fallbackLigatures = (options?.fallbackLigatures || [
|
||||
this._fallbackLigatures = (options?.fallbackLigatures ?? [
|
||||
'<--', '<---', '<<-', '<-', '->', '->>', '-->', '--->',
|
||||
'<==', '<===', '<<=', '<=', '=>', '=>>', '==>', '===>', '>=', '>>=',
|
||||
'<->', '<-->', '<--->', '<---->', '<=>', '<==>', '<===>', '<====>', '::', ':::',
|
||||
|
||||
@@ -80,9 +80,7 @@ export default async function load(fontFamily: string, cacheSize: number): Promi
|
||||
console.error(err.name, err.message);
|
||||
}
|
||||
}
|
||||
if (!fontsPromise) {
|
||||
fontsPromise = Promise.resolve({});
|
||||
}
|
||||
fontsPromise ??= Promise.resolve({});
|
||||
}
|
||||
|
||||
const fonts = await fontsPromise;
|
||||
|
||||
@@ -52,12 +52,10 @@ export function processLookaheadPosition(
|
||||
}
|
||||
processedEntries.add(currentEntry.entry);
|
||||
|
||||
if (!currentEntry.entry.forward) {
|
||||
currentEntry.entry.forward = {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
}
|
||||
currentEntry.entry.forward ??= {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
|
||||
// All glyphs at this position share ONE entry - lookahead just needs to match,
|
||||
// all paths lead to the same result
|
||||
@@ -97,12 +95,10 @@ export function processBacktrackPosition(
|
||||
}
|
||||
processedEntries.add(currentEntry.entry);
|
||||
|
||||
if (!currentEntry.entry.reverse) {
|
||||
currentEntry.entry.reverse = {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
}
|
||||
currentEntry.entry.reverse ??= {
|
||||
individual: {},
|
||||
range: []
|
||||
};
|
||||
|
||||
// All glyphs at this position share ONE entry - backtrack just needs to match,
|
||||
// all paths lead to the same result
|
||||
|
||||
@@ -54,9 +54,6 @@ export function getIndividualSubstitutionGlyph(table: SubstitutionTable, glyphId
|
||||
return (glyphId + table.deltaGlyphId) % (2 ** 16);
|
||||
// https://docs.microsoft.com/en-us/typography/opentype/spec/gsub#12-single-substitution-format-2
|
||||
case 2:
|
||||
// eslint-disable-next-line eqeqeq
|
||||
return table.substitute[coverageIndex] != null
|
||||
? table.substitute[coverageIndex]
|
||||
: null;
|
||||
return table.substitute[coverageIndex] ?? null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -198,9 +198,7 @@ export class SearchEngine {
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
result = this._findInLine(term, searchPosition, searchOptions, isReverseSearch);
|
||||
}
|
||||
result ??= this._findInLine(term, searchPosition, searchOptions, isReverseSearch);
|
||||
|
||||
// Search from startRow - 1 to top
|
||||
if (!result) {
|
||||
|
||||
@@ -228,7 +228,7 @@ describe('SerializeAddon', () => {
|
||||
it('empty terminal with selection turned off', () => {
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.notEqual(output, '');
|
||||
assert.equal((output.match(/<div><span> {10}<\/span><\/div>/g) || []).length, 2);
|
||||
assert.equal((output.match(/<div><span> {10}<\/span><\/div>/g) ?? []).length, 2);
|
||||
});
|
||||
|
||||
it('empty terminal with no selection', () => {
|
||||
@@ -245,7 +245,7 @@ describe('SerializeAddon', () => {
|
||||
const output = serializeAddon.serializeAsHTML({
|
||||
onlySelection: true
|
||||
});
|
||||
assert.equal((output.match(/<div><span>terminal<\/span><\/div>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<div><span>terminal<\/span><\/div>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('basic terminal with html unsafe chars', async () => {
|
||||
@@ -255,7 +255,7 @@ describe('SerializeAddon', () => {
|
||||
const output = serializeAddon.serializeAsHTML({
|
||||
onlySelection: true
|
||||
});
|
||||
assert.equal((output.match(/<div><span><a>&pi;<\/span><\/div>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<div><span><a>&pi;<\/span><\/div>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('serializes rows within a provided range', async () => {
|
||||
@@ -267,7 +267,7 @@ describe('SerializeAddon', () => {
|
||||
startCol: 4
|
||||
}
|
||||
});
|
||||
const rowMatches = output.match(/<div><span>.*?<\/span><\/div>/g) || [];
|
||||
const rowMatches = output.match(/<div><span>.*?<\/span><\/div>/g) ?? [];
|
||||
assert.equal(rowMatches.length, 1, output);
|
||||
assert.ok(rowMatches[0]?.includes('hello'));
|
||||
assert.ok(!output.includes('bye'));
|
||||
@@ -278,56 +278,56 @@ describe('SerializeAddon', () => {
|
||||
await writeP(terminal, ' ' + sgr('1') + 'terminal' + sgr('22') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='font-weight: bold;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='font-weight: bold;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with italic styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('3') + 'terminal' + sgr('23') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='font-style: italic;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='font-style: italic;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with inverse styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('7') + 'terminal' + sgr('27') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='color: #000000; background-color: #BFBFBF;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='color: #000000; background-color: #BFBFBF;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with underline styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('4') + 'terminal' + sgr('24') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='text-decoration: underline;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='text-decoration: underline;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with double underline styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('4:2') + 'terminal' + sgr('24') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='text-decoration: underline double;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='text-decoration: underline double;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with curly underline styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('4:3') + 'terminal' + sgr('24') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='text-decoration: underline wavy;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='text-decoration: underline wavy;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with dotted underline styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('4:4') + 'terminal' + sgr('24') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='text-decoration: underline dotted;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='text-decoration: underline dotted;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with dashed underline styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('4:5') + 'terminal' + sgr('24') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='text-decoration: underline dashed;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='text-decoration: underline dashed;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with underline color (palette)', async () => {
|
||||
@@ -350,49 +350,49 @@ describe('SerializeAddon', () => {
|
||||
await writeP(terminal, ' ' + sgr('8') + 'terminal' + sgr('28') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='visibility: hidden;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='visibility: hidden;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with dim styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('2') + 'terminal' + sgr('22') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='opacity: 0.5;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='opacity: 0.5;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with strikethrough styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('9') + 'terminal' + sgr('29') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='text-decoration: line-through;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='text-decoration: line-through;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with combined styling', async () => {
|
||||
await writeP(terminal, sgr('1') + ' ' + sgr('9') + 'termi' + sgr('22') + 'nal' + sgr('29') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='font-weight: bold;'> <\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='font-weight: bold; text-decoration: line-through;'>termi<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='text-decoration: line-through;'>nal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='font-weight: bold;'> <\/span>/g) ?? []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='font-weight: bold; text-decoration: line-through;'>termi<\/span>/g) ?? []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='text-decoration: line-through;'>nal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with color styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('38;5;46') + 'terminal' + sgr('39') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='color: #00ff00;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='color: #00ff00;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with background styling', async () => {
|
||||
await writeP(terminal, ' ' + sgr('48;5;46') + 'terminal' + sgr('49') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='background-color: #00ff00;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='background-color: #00ff00;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('empty terminal with default options', async () => {
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/color: #000000; background-color: #ffffff; font-family: monospace; font-size: 15px;/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/color: #000000; background-color: #ffffff; font-family: monospace; font-size: 15px;/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('empty terminal with custom options', async () => {
|
||||
@@ -405,14 +405,14 @@ describe('SerializeAddon', () => {
|
||||
const output = serializeAddon.serializeAsHTML({
|
||||
includeGlobalBackground: true
|
||||
});
|
||||
assert.equal((output.match(/color: #ff00ff; background-color: #00ff00; font-family: verdana; font-size: 20px;/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/color: #ff00ff; background-color: #00ff00; font-family: verdana; font-size: 20px;/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('empty terminal with background included', async () => {
|
||||
const output = serializeAddon.serializeAsHTML({
|
||||
includeGlobalBackground: true
|
||||
});
|
||||
assert.equal((output.match(/color: #ffffff; background-color: #000000; font-family: monospace; font-size: 15px;/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/color: #ffffff; background-color: #000000; font-family: monospace; font-size: 15px;/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with custom color styling', async () => {
|
||||
@@ -422,7 +422,7 @@ describe('SerializeAddon', () => {
|
||||
await writeP(terminal, ' ' + sgr('38;5;0') + 'terminal' + sgr('39') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='color: #ffa500;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='color: #ffa500;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
|
||||
it('cells with color styling - xterm headless', async () => {
|
||||
@@ -432,7 +432,7 @@ describe('SerializeAddon', () => {
|
||||
await writeP(terminal, ' ' + sgr('38;5;46') + 'terminal' + sgr('39') + ' ');
|
||||
|
||||
const output = serializeAddon.serializeAsHTML();
|
||||
assert.equal((output.match(/<span style='color: #00ff00;'>terminal<\/span>/g) || []).length, 1, output);
|
||||
assert.equal((output.match(/<span style='color: #00ff00;'>terminal<\/span>/g) ?? []).length, 1, output);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -457,7 +457,7 @@ class StringSerializeHandler extends BaseSerializeHandler {
|
||||
}
|
||||
}
|
||||
|
||||
export class SerializeAddon implements ITerminalAddon , ISerializeApi {
|
||||
export class SerializeAddon implements ITerminalAddon, ISerializeApi {
|
||||
private _terminal: Terminal | undefined;
|
||||
|
||||
public activate(terminal: Terminal): void {
|
||||
@@ -601,7 +601,7 @@ export class SerializeAddon implements ITerminalAddon , ISerializeApi {
|
||||
throw new Error('Cannot use addon until it has been loaded');
|
||||
}
|
||||
|
||||
return this._serializeBufferAsHTML(this._terminal, options || {});
|
||||
return this._serializeBufferAsHTML(this._terminal, options ?? {});
|
||||
}
|
||||
|
||||
public dispose(): void { }
|
||||
|
||||
@@ -9,19 +9,15 @@ import type { Terminal, ITerminalAddon, IUnicodeHandling } from '@xterm/xterm';
|
||||
import type { UnicodeGraphemesAddon as IUnicodeGraphemesApi } from '@xterm/addon-unicode-graphemes';
|
||||
import { UnicodeGraphemeProvider } from './UnicodeGraphemeProvider';
|
||||
|
||||
export class UnicodeGraphemesAddon implements ITerminalAddon , IUnicodeGraphemesApi {
|
||||
export class UnicodeGraphemesAddon implements ITerminalAddon, IUnicodeGraphemesApi {
|
||||
private _provider15Graphemes?: UnicodeGraphemeProvider;
|
||||
private _provider15?: UnicodeGraphemeProvider;
|
||||
private _unicode?: IUnicodeHandling;
|
||||
private _oldVersion: string = '';
|
||||
|
||||
public activate(terminal: Terminal): void {
|
||||
if (! this._provider15) {
|
||||
this._provider15 = new UnicodeGraphemeProvider(false);
|
||||
}
|
||||
if (! this._provider15Graphemes) {
|
||||
this._provider15Graphemes = new UnicodeGraphemeProvider(true);
|
||||
}
|
||||
this._provider15 ??= new UnicodeGraphemeProvider(false);
|
||||
this._provider15Graphemes ??= new UnicodeGraphemeProvider(true);
|
||||
const unicode = terminal.unicode;
|
||||
this._unicode = unicode;
|
||||
unicode.register(this._provider15);
|
||||
|
||||
@@ -9,7 +9,7 @@ import type { Terminal, ITerminalAddon } from '@xterm/xterm';
|
||||
import type { Unicode11Addon as IUnicode11Api } from '@xterm/addon-unicode11';
|
||||
import { UnicodeV11 } from './UnicodeV11';
|
||||
|
||||
export class Unicode11Addon implements ITerminalAddon , IUnicode11Api {
|
||||
export class Unicode11Addon implements ITerminalAddon, IUnicode11Api {
|
||||
public activate(terminal: Terminal): void {
|
||||
terminal.unicode.register(new UnicodeV11());
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ function handleLink(event: MouseEvent, uri: string): void {
|
||||
}
|
||||
}
|
||||
|
||||
export class WebLinksAddon implements ITerminalAddon , IWebLinksApi {
|
||||
export class WebLinksAddon implements ITerminalAddon, IWebLinksApi {
|
||||
private _terminal: Terminal | undefined;
|
||||
private _linkProvider: IDisposable | undefined;
|
||||
|
||||
@@ -48,7 +48,7 @@ export class WebLinksAddon implements ITerminalAddon , IWebLinksApi {
|
||||
public activate(terminal: Terminal): void {
|
||||
this._terminal = terminal;
|
||||
const options = this._options as ILinkProviderOptions;
|
||||
const regex = options.urlRegex || strictUrlRegex;
|
||||
const regex = options.urlRegex ?? strictUrlRegex;
|
||||
this._linkProvider = this._terminal.registerLinkProvider(new WebLinkProvider(this._terminal, regex, this._handler, options));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
* @license MIT
|
||||
*/
|
||||
|
||||
import { toDisposable, IDisposable } from 'vs/base/common/lifecycle';
|
||||
import { toDisposable, IDisposable } from 'common/Lifecycle';
|
||||
|
||||
export function observeDevicePixelDimensions(element: HTMLElement, parentWindow: Window & typeof globalThis, callback: (deviceWidth: number, deviceHeight: number) => void): IDisposable {
|
||||
// Observe any resizes to the element and extract the actual pixel size of the element if the
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import { TextureAtlas } from './TextureAtlas';
|
||||
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||
import { NULL_CELL_CODE } from 'common/buffer/Constants';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject, type IRasterizedGlyph, type ITextureAtlas } from './Types';
|
||||
import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils';
|
||||
|
||||
@@ -7,7 +7,7 @@ import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||
import { IThemeService } from 'browser/services/Services';
|
||||
import { ReadonlyColorSet } from 'browser/Types';
|
||||
import { Attributes, FgFlags } from 'common/buffer/Constants';
|
||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||
import { Disposable, toDisposable } from 'common/Lifecycle';
|
||||
import { IColor } from 'common/Types';
|
||||
import { Terminal } from '@xterm/xterm';
|
||||
import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
|
||||
|
||||
@@ -15,7 +15,7 @@ import { IColor } from 'common/Types';
|
||||
import { AttributeData } from 'common/buffer/AttributeData';
|
||||
import { Attributes, DEFAULT_COLOR, DEFAULT_EXT, UnderlineStyle } from 'common/buffer/Constants';
|
||||
import { IUnicodeService } from 'common/services/Services';
|
||||
import { Emitter } from 'vs/base/common/event';
|
||||
import { Emitter } from 'common/Event';
|
||||
|
||||
/**
|
||||
* A shared object which is used to draw nothing for a particular cell.
|
||||
@@ -176,6 +176,17 @@ export class TextureAtlas implements ITextureAtlas {
|
||||
|
||||
// Gather details of the merge
|
||||
const mergingPages = pagesBySize.slice(sameSizeI, sameSizeI + 4);
|
||||
|
||||
// Only proceed with merge if we have exactly 4 same-sized pages. If not, we cannot
|
||||
// effectively reduce page count and merging would cause issues.
|
||||
if (mergingPages.length < 4 || mergingPages.some(p => p.canvas.width !== mergingPages[0].canvas.width)) {
|
||||
const newPage = new AtlasPage(this._document, this._textureSize);
|
||||
this._pages.push(newPage);
|
||||
this._activePages.push(newPage);
|
||||
this._onAddTextureAtlasCanvas.fire(newPage.canvas);
|
||||
return newPage;
|
||||
}
|
||||
|
||||
const sortedMergingPagesIndexes = mergingPages.map(e => e.glyphs[0].texturePage).sort((a, b) => a > b ? 1 : -1);
|
||||
const mergedPageIndex = this.pages.length - mergingPages.length;
|
||||
|
||||
@@ -399,7 +410,7 @@ export class TextureAtlas implements ITextureAtlas {
|
||||
const cache = this._getContrastCache(dim);
|
||||
const adjustedColor = cache.getColor(bg, fg);
|
||||
if (adjustedColor !== undefined) {
|
||||
return adjustedColor || undefined;
|
||||
return adjustedColor ?? undefined;
|
||||
}
|
||||
|
||||
const bgRgba = this._resolveBackgroundRgba(bgColorMode, bgColor, inverse);
|
||||
|
||||
@@ -7,7 +7,7 @@ import { FontWeight } from '@xterm/xterm';
|
||||
import { IColorSet } from 'browser/Types';
|
||||
import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
|
||||
import { CursorInactiveStyle, CursorStyle, type IDisposable } from 'common/Types';
|
||||
import type { Event } from 'vs/base/common/event';
|
||||
import type { IEvent } from 'common/Event';
|
||||
|
||||
export interface IRenderModel {
|
||||
cells: Uint32Array;
|
||||
@@ -58,8 +58,8 @@ export interface ICharAtlasConfig {
|
||||
export interface ITextureAtlas extends IDisposable {
|
||||
readonly pages: { canvas: HTMLCanvasElement, version: number }[];
|
||||
|
||||
onAddTextureAtlasCanvas: Event<HTMLCanvasElement>;
|
||||
onRemoveTextureAtlasCanvas: Event<HTMLCanvasElement>;
|
||||
onAddTextureAtlasCanvas: IEvent<HTMLCanvasElement>;
|
||||
onRemoveTextureAtlasCanvas: IEvent<HTMLCanvasElement>;
|
||||
|
||||
/**
|
||||
* Warm up the texture atlas, adding common glyphs to avoid slowing early frame.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user