Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

xterm

Package Overview
Dependencies
Maintainers
2
Versions
1092
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

xterm - npm Package Compare versions

Comparing version 5.3.0-beta.20 to 5.3.0-beta.21

src/browser/renderer/dom/WidthCache.ts

2

package.json
{
"name": "xterm",
"description": "Full xterm terminal, in your browser",
"version": "5.3.0-beta.20",
"version": "5.3.0-beta.21",
"main": "lib/xterm.js",

@@ -6,0 +6,0 @@ "style": "css/xterm.css",

@@ -6,3 +6,4 @@ /**

import { BOLD_CLASS, CURSOR_BLINK_CLASS, CURSOR_CLASS, CURSOR_STYLE_BAR_CLASS, CURSOR_STYLE_BLOCK_CLASS, CURSOR_STYLE_UNDERLINE_CLASS, DIM_CLASS, DomRendererRowFactory, ITALIC_CLASS } from 'browser/renderer/dom/DomRendererRowFactory';
import { DomRendererRowFactory, RowCss } from 'browser/renderer/dom/DomRendererRowFactory';
import { WidthCache } from 'browser/renderer/dom/WidthCache';
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';

@@ -19,2 +20,3 @@ import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';

const TERMINAL_CLASS_PREFIX = 'xterm-dom-renderer-owner-';

@@ -29,2 +31,3 @@ const ROW_CONTAINER_CLASS = 'xterm-rows';

/**

@@ -44,3 +47,3 @@ * A fallback renderer for when canvas is slow. This is not meant to be

private _selectionContainer: HTMLElement;
private _cellToRowElements: Int16Array[] = [];
private _widthCache: WidthCache;

@@ -98,3 +101,13 @@ public dimensions: IRenderDimensions;

this._dimensionsStyle.dispose();
this._widthCache.dispose();
}));
this._widthCache = new WidthCache(document);
this._widthCache.setFont(
this._optionsService.rawOptions.fontFamily,
this._optionsService.rawOptions.fontSize,
this._optionsService.rawOptions.fontWeight,
this._optionsService.rawOptions.fontWeightBold
);
this._setDefaultSpacing();
}

@@ -131,6 +144,5 @@

`${this._terminalSelector} .${ROW_CONTAINER_CLASS} span {` +
` display: inline-block;` +
` display: inline-block;` + // TODO: find workaround for inline-block (creates ~20% render penalty)
` height: 100%;` +
` vertical-align: top;` +
` width: ${this.dimensions.css.cell.width}px` +
`}`;

@@ -156,2 +168,4 @@

` font-size: ${this._optionsService.rawOptions.fontSize}px;` +
` font-kerning: none;` +
` white-space: pre` +
`}`;

@@ -164,9 +178,9 @@ styles +=

styles +=
`${this._terminalSelector} span:not(.${BOLD_CLASS}) {` +
`${this._terminalSelector} span:not(.${RowCss.BOLD_CLASS}) {` +
` font-weight: ${this._optionsService.rawOptions.fontWeight};` +
`}` +
`${this._terminalSelector} span.${BOLD_CLASS} {` +
`${this._terminalSelector} span.${RowCss.BOLD_CLASS} {` +
` font-weight: ${this._optionsService.rawOptions.fontWeightBold};` +
`}` +
`${this._terminalSelector} span.${ITALIC_CLASS} {` +
`${this._terminalSelector} span.${RowCss.ITALIC_CLASS} {` +
` font-style: italic;` +

@@ -188,3 +202,3 @@ `}`;

` 50% {` +
` background-color: ${colors.cursorAccent.css};` +
` background-color: inherit;` +
` color: ${colors.cursor.css};` +

@@ -195,5 +209,5 @@ ` }` +

styles +=
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${CURSOR_CLASS}.${CURSOR_STYLE_BLOCK_CLASS} ,` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${CURSOR_CLASS}.${CURSOR_STYLE_BAR_CLASS} ,` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${CURSOR_CLASS}.${CURSOR_STYLE_UNDERLINE_CLASS} ` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} ,` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} ,` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}:not(.${FOCUS_CLASS}) .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} ` +
`{` +

@@ -203,16 +217,16 @@ ` outline: 1px solid ${colors.cursor.css};` +

`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS}.${CURSOR_BLINK_CLASS}:not(.${CURSOR_STYLE_BLOCK_CLASS}) {` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}:not(.${RowCss.CURSOR_STYLE_BLOCK_CLASS}) {` +
` animation: blink_box_shadow` + `_` + this._terminalClass + ` 1s step-end infinite;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS}.${CURSOR_BLINK_CLASS}.${CURSOR_STYLE_BLOCK_CLASS} {` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_BLINK_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
` animation: blink_block` + `_` + this._terminalClass + ` 1s step-end infinite;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_BLOCK_CLASS} {` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS}.${FOCUS_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BLOCK_CLASS} {` +
` background-color: ${colors.cursor.css};` +
` color: ${colors.cursorAccent.css};` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_BAR_CLASS} {` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_BAR_CLASS} {` +
` box-shadow: ${this._optionsService.rawOptions.cursorWidth}px 0 0 ${colors.cursor.css} inset;` +
`}` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${CURSOR_CLASS}.${CURSOR_STYLE_UNDERLINE_CLASS} {` +
`${this._terminalSelector} .${ROW_CONTAINER_CLASS} .${RowCss.CURSOR_CLASS}.${RowCss.CURSOR_STYLE_UNDERLINE_CLASS} {` +
` border-bottom: 1px ${colors.cursor.css};` +

@@ -243,3 +257,3 @@ ` border-bottom-style: solid;` +

`${this._terminalSelector} .${FG_CLASS_PREFIX}${i} { color: ${c.css}; }` +
`${this._terminalSelector} .${FG_CLASS_PREFIX}${i}.${DIM_CLASS} { color: ${color.multiplyOpacity(c, 0.5).css}; }` +
`${this._terminalSelector} .${FG_CLASS_PREFIX}${i}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(c, 0.5).css}; }` +
`${this._terminalSelector} .${BG_CLASS_PREFIX}${i} { background-color: ${c.css}; }`;

@@ -249,3 +263,3 @@ }

`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { color: ${color.opaque(colors.background).css}; }` +
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR}.${DIM_CLASS} { color: ${color.multiplyOpacity(color.opaque(colors.background), 0.5).css}; }` +
`${this._terminalSelector} .${FG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR}.${RowCss.DIM_CLASS} { color: ${color.multiplyOpacity(color.opaque(colors.background), 0.5).css}; }` +
`${this._terminalSelector} .${BG_CLASS_PREFIX}${INVERTED_DEFAULT_COLOR} { background-color: ${colors.foreground.css}; }`;

@@ -256,4 +270,21 @@

/**
* default letter spacing
* Due to rounding issues in dimensions dpr calc glyph might render
* slightly too wide or too narrow. The method corrects the stacking offsets
* by applying a default letter-spacing for all chars.
* The value gets passed to the row factory to avoid setting this value again
* (render speedup is roughly 10%).
*/
private _setDefaultSpacing(): void {
// measure same char as in CharSizeService to get the base deviation
const spacing = this.dimensions.css.cell.width - this._widthCache.get('W', false, false);
this._rowContainer.style.letterSpacing = `${spacing}px`;
this._rowFactory.defaultSpacing = spacing;
}
public handleDevicePixelRatioChange(): void {
this._updateDimensions();
this._widthCache.clear();
this._setDefaultSpacing();
}

@@ -281,2 +312,4 @@

this._updateDimensions();
this._widthCache.clear();
this._setDefaultSpacing();
}

@@ -294,6 +327,3 @@

// Remove all selections
while (this._selectionContainer.children.length) {
this._selectionContainer.removeChild(this._selectionContainer.children[0]);
}
this._selectionContainer.replaceChildren();
this._rowFactory.handleSelectionChanged(start, end, columnSelectMode);

@@ -368,2 +398,10 @@ this.renderRows(0, this._bufferService.rows - 1);

this._injectCss(this._themeService.colors);
// update spacing cache
this._widthCache.setFont(
this._optionsService.rawOptions.fontFamily,
this._optionsService.rawOptions.fontSize,
this._optionsService.rawOptions.fontWeight,
this._optionsService.rawOptions.fontWeightBold
);
this._setDefaultSpacing();
}

@@ -385,15 +423,29 @@

public renderRows(start: number, end: number): void {
const cursorAbsoluteY = this._bufferService.buffer.ybase + this._bufferService.buffer.y;
const cursorX = Math.min(this._bufferService.buffer.x, this._bufferService.cols - 1);
const buffer = this._bufferService.buffer;
const cursorAbsoluteY = buffer.ybase + buffer.y;
const cursorX = Math.min(buffer.x, this._bufferService.cols - 1);
const cursorBlink = this._optionsService.rawOptions.cursorBlink;
const cursorStyle = this._optionsService.rawOptions.cursorStyle;
for (let y = start; y <= end; y++) {
const row = y + buffer.ydisp;
const rowElement = this._rowElements[y];
const row = y + this._bufferService.buffer.ydisp;
const lineData = this._bufferService.buffer.lines.get(row);
const cursorStyle = this._optionsService.rawOptions.cursorStyle;
if (!this._cellToRowElements[y] || this._cellToRowElements[y].length !== this._bufferService.cols) {
this._cellToRowElements[y] = new Int16Array(this._bufferService.cols);
const lineData = buffer.lines.get(row);
if (!rowElement || !lineData) {
break;
}
rowElement.replaceChildren(this._rowFactory.createRow(lineData!, row, row === cursorAbsoluteY, cursorStyle, cursorX, cursorBlink, this.dimensions.css.cell.width, this._bufferService.cols, this._cellToRowElements[y]));
rowElement.replaceChildren(
...this._rowFactory.createRow(
lineData,
row,
row === cursorAbsoluteY,
cursorStyle,
cursorX,
cursorBlink,
this.dimensions.css.cell.width,
this._widthCache,
-1,
-1
)
);
}

@@ -430,38 +482,40 @@ }

*/
// clip coords into viewport
if (y < 0) x = 0;
if (y2 < 0) x2 = 0;
// avoid out-of-sync y-values, simply clamp into valid area
const maxY = this._cellToRowElements.length - 1;
const maxY = this._bufferService.rows - 1;
y = Math.max(Math.min(y, maxY), 0);
y2 = Math.max(Math.min(y2, maxY), 0);
const elemY = this._cellToRowElements[y];
const elemY2 = this._cellToRowElements[y2];
if (x >= elemY.length || x2 >= elemY2.length) {
// avoid out-of-sync x-values
// simply exit early, gets fixed by the next render update
return;
}
x = elemY[x];
x2 = elemY2[x2];
if (x === -1 || x2 === -1) {
return;
}
cols = Math.min(cols, this._bufferService.cols);
const buffer = this._bufferService.buffer;
const cursorAbsoluteY = buffer.ybase + buffer.y;
const cursorX = Math.min(buffer.x, cols - 1);
const cursorBlink = this._optionsService.rawOptions.cursorBlink;
const cursorStyle = this._optionsService.rawOptions.cursorStyle;
while (x !== x2 || y !== y2) {
const row = this._rowElements[y];
if (!row) {
return;
// refresh rows within link range
for (let i = y; i <= y2; ++i) {
const row = i + buffer.ydisp;
const rowElement = this._rowElements[i];
const bufferline = buffer.lines.get(row);
if (!rowElement || !bufferline) {
break;
}
const span = row.children[x] as HTMLElement;
if (span) {
span.style.textDecoration = enabled ? 'underline' : 'none';
}
if (++x >= cols) {
x = 0;
y++;
}
rowElement.replaceChildren(
...this._rowFactory.createRow(
bufferline,
row,
row === cursorAbsoluteY,
cursorStyle,
cursorX,
cursorBlink,
this.dimensions.css.cell.width,
this._widthCache,
enabled ? (i === y ? x : 0) : -1,
enabled ? ((i === y2 ? x2 : cols) - 1) : -1
)
);
}
}
}
/**
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
* Copyright (c) 2018, 2023 The xterm.js authors. All rights reserved.
* @license MIT

@@ -8,3 +8,3 @@ */

import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
import { NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';
import { WHITESPACE_CELL_CHAR, Attributes } from 'common/buffer/Constants';
import { CellData } from 'common/buffer/CellData';

@@ -17,15 +17,20 @@ import { ICoreService, IDecorationService, IOptionsService } from 'common/services/Services';

import { AttributeData } from 'common/buffer/AttributeData';
import { WidthCache } from 'browser/renderer/dom/WidthCache';
export const BOLD_CLASS = 'xterm-bold';
export const DIM_CLASS = 'xterm-dim';
export const ITALIC_CLASS = 'xterm-italic';
export const UNDERLINE_CLASS = 'xterm-underline';
export const OVERLINE_CLASS = 'xterm-overline';
export const STRIKETHROUGH_CLASS = 'xterm-strikethrough';
export const CURSOR_CLASS = 'xterm-cursor';
export const CURSOR_BLINK_CLASS = 'xterm-cursor-blink';
export const CURSOR_STYLE_BLOCK_CLASS = 'xterm-cursor-block';
export const CURSOR_STYLE_BAR_CLASS = 'xterm-cursor-bar';
export const CURSOR_STYLE_UNDERLINE_CLASS = 'xterm-cursor-underline';
export const enum RowCss {
BOLD_CLASS = 'xterm-bold',
DIM_CLASS = 'xterm-dim',
ITALIC_CLASS = 'xterm-italic',
UNDERLINE_CLASS = 'xterm-underline',
OVERLINE_CLASS = 'xterm-overline',
STRIKETHROUGH_CLASS = 'xterm-strikethrough',
CURSOR_CLASS = 'xterm-cursor',
CURSOR_BLINK_CLASS = 'xterm-cursor-blink',
CURSOR_STYLE_BLOCK_CLASS = 'xterm-cursor-block',
CURSOR_STYLE_BAR_CLASS = 'xterm-cursor-bar',
CURSOR_STYLE_UNDERLINE_CLASS = 'xterm-cursor-underline'
}
export class DomRendererRowFactory {

@@ -38,2 +43,4 @@ private _workCell: CellData = new CellData();

public defaultSpacing = 0;
constructor(

@@ -55,28 +62,38 @@ private readonly _document: Document,

public createRow(lineData: IBufferLine, row: number, isCursorRow: boolean, cursorStyle: string | undefined, cursorX: number, cursorBlink: boolean, cellWidth: number, cols: number, cellMap: Int16Array): DocumentFragment {
// NOTE: `cellMap` maps cell positions to a span element index in a row.
// All positions should be updated, even skipped ones after wide chars or left overs at the end,
// otherwise the mouse hover logic might mark the wrong elements as underlined.
public createRow(
lineData: IBufferLine,
row: number,
isCursorRow: boolean,
cursorStyle: string | undefined,
cursorX: number,
cursorBlink: boolean,
cellWidth: number,
widthCache: WidthCache,
linkStart: number,
linkEnd: number
): HTMLSpanElement[] {
const fragment = this._document.createDocumentFragment();
const elements: HTMLSpanElement[] = [];
const joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
const colors = this._themeService.colors;
const joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
// Find the line length first, this prevents the need to output a bunch of
// empty cells at the end. This cannot easily be integrated into the main
// loop below because of the colCount feature (which can be removed after we
// properly support reflow and disallow data to go beyond the right-side of
// the viewport).
let lineLength = 0;
for (let x = Math.min(lineData.length, cols) - 1; x >= 0; x--) {
if (lineData.loadCell(x, this._workCell).getCode() !== NULL_CELL_CODE || (isCursorRow && x === cursorX)) {
lineLength = x + 1;
break;
}
let lineLength = lineData.getNoBgTrimmedLength();
if (isCursorRow && lineLength < cursorX + 1) {
lineLength = cursorX + 1;
}
const colors = this._themeService.colors;
let elemIndex = -1;
let charElement: HTMLSpanElement | undefined;
let cellAmount = 0;
let text = '';
let oldBg = 0;
let oldFg = 0;
let oldExt = 0;
let oldLinkHover: number | boolean = false;
let oldSpacing = 0;
let spacing = 0;
const classes: string[] = [];
let x = 0;
for (; x < lineLength; x++) {
const hasHover = linkStart !== -1 && linkEnd !== -1;
for (let x = 0; x < lineLength; x++) {
lineData.loadCell(x, this._workCell);

@@ -86,5 +103,3 @@ let width = this._workCell.getWidth();

// The character to the left is a wide character, drawing is owned by the char at x-1
// still have to update cellMap with current element index
if (width === 0) {
cellMap[x] = elemIndex;
continue;

@@ -120,12 +135,62 @@ }

const charElement = this._document.createElement('span');
if (width > 1) {
charElement.style.width = `${cellWidth * width}px`;
const isInSelection = this._isCellInSelection(x, row);
const isCursorCell = isCursorRow && x === cursorX;
const isLinkHover = hasHover && x >= linkStart && x <= linkEnd;
// get chars to render for this cell
let chars = cell.getChars() || WHITESPACE_CELL_CHAR;
if (chars === ' ' && (cell.isUnderline() || cell.isOverline())) {
chars = '\xa0';
}
// lookup char render width and calc spacing
spacing = width * cellWidth - widthCache.get(chars, cell.isBold(), cell.isItalic());
if (!charElement) {
charElement = this._document.createElement('span');
} else {
/**
* chars can only be merged on existing span if:
* - existing span only contains mergeable chars (cellAmount != 0)
* - fg/bg/ul did not change
* - char not part of a selection
* - underline from hover state did not change
* - cell content renders to same letter-spacing
* - cell is not cursor
*/
if (
cellAmount
&& cell.bg === oldBg && cell.fg === oldFg && cell.extended.ext === oldExt
&& !isInSelection
&& isLinkHover === oldLinkHover
&& spacing === oldSpacing
&& !isCursorCell
&& !isJoined
) {
// no span alterations, thus only account chars skipping all code below
text += chars;
cellAmount++;
continue;
} else {
/**
* cannot merge:
* - apply left-over text to old span
* - create new span, reset state holders cellAmount & text
*/
if (cellAmount) {
charElement.textContent = text;
}
charElement = this._document.createElement('span');
cellAmount = 0;
text = '';
}
}
// preserve conditions for next merger eval round
oldBg = cell.bg;
oldFg = cell.fg;
oldExt = cell.extended.ext;
oldLinkHover = isLinkHover;
oldSpacing = spacing;
if (isJoined) {
// Ligatures in the DOM renderer must use display inline, as they may not show with
// inline-block if they are outside the bounds of the element
charElement.style.display = 'inline';
// The DOM renderer colors the background of the cursor but for ligatures all cells are

@@ -139,44 +204,38 @@ // joined. The workaround here is to show a cursor around the whole ligature so it shows up,

if (!this._coreService.isCursorHidden && isCursorRow && x === cursorX) {
charElement.classList.add(CURSOR_CLASS);
if (!this._coreService.isCursorHidden && isCursorCell) {
classes.push(RowCss.CURSOR_CLASS);
if (cursorBlink) {
charElement.classList.add(CURSOR_BLINK_CLASS);
classes.push(RowCss.CURSOR_BLINK_CLASS);
}
switch (cursorStyle) {
case 'bar':
charElement.classList.add(CURSOR_STYLE_BAR_CLASS);
break;
case 'underline':
charElement.classList.add(CURSOR_STYLE_UNDERLINE_CLASS);
break;
default:
charElement.classList.add(CURSOR_STYLE_BLOCK_CLASS);
break;
}
classes.push(
cursorStyle === 'bar'
? RowCss.CURSOR_STYLE_BAR_CLASS
: cursorStyle === 'underline'
? RowCss.CURSOR_STYLE_UNDERLINE_CLASS
: RowCss.CURSOR_STYLE_BLOCK_CLASS
);
}
if (cell.isBold()) {
charElement.classList.add(BOLD_CLASS);
classes.push(RowCss.BOLD_CLASS);
}
if (cell.isItalic()) {
charElement.classList.add(ITALIC_CLASS);
classes.push(RowCss.ITALIC_CLASS);
}
if (cell.isDim()) {
charElement.classList.add(DIM_CLASS);
classes.push(RowCss.DIM_CLASS);
}
if (cell.isInvisible()) {
charElement.textContent = WHITESPACE_CELL_CHAR;
text = WHITESPACE_CELL_CHAR;
} else {
charElement.textContent = cell.getChars() || WHITESPACE_CELL_CHAR;
text = cell.getChars() || WHITESPACE_CELL_CHAR;
}
if (cell.isUnderline()) {
charElement.classList.add(`${UNDERLINE_CLASS}-${cell.extended.underlineStyle}`);
if (charElement.textContent === ' ') {
charElement.textContent = '\xa0'; // = &nbsp;
classes.push(`${RowCss.UNDERLINE_CLASS}-${cell.extended.underlineStyle}`);
if (text === ' ') {
text = '\xa0'; // = &nbsp;
}

@@ -197,5 +256,5 @@ if (!cell.isUnderlineColorDefault()) {

if (cell.isOverline()) {
charElement.classList.add(OVERLINE_CLASS);
if (charElement.textContent === ' ') {
charElement.textContent = '\xa0'; // = &nbsp;
classes.push(RowCss.OVERLINE_CLASS);
if (text === ' ') {
text = '\xa0'; // = &nbsp;
}

@@ -205,5 +264,10 @@ }

if (cell.isStrikethrough()) {
charElement.classList.add(STRIKETHROUGH_CLASS);
classes.push(RowCss.STRIKETHROUGH_CLASS);
}
// apply link hover underline late, effectively overrides any previous text-decoration settings
if (isLinkHover) {
charElement.style.textDecoration = 'underline';
}
let fg = cell.getFgColor();

@@ -246,3 +310,2 @@ let fgColorMode = cell.getFgColorMode();

// Apply selection foreground if applicable
const isInSelection = this._isCellInSelection(x, row);
if (!isTop) {

@@ -265,3 +328,3 @@ if (colors.selectionForeground && isInSelection) {

if (isTop) {
charElement.classList.add(`xterm-decoration-top`);
classes.push('xterm-decoration-top');
}

@@ -275,3 +338,3 @@

resolvedBg = colors.ansi[bg];
charElement.classList.add(`xterm-bg-${bg}`);
classes.push(`xterm-bg-${bg}`);
break;

@@ -286,3 +349,3 @@ case Attributes.CM_RGB:

resolvedBg = colors.foreground;
charElement.classList.add(`xterm-bg-${INVERTED_DEFAULT_COLOR}`);
classes.push(`xterm-bg-${INVERTED_DEFAULT_COLOR}`);
} else {

@@ -308,3 +371,3 @@ resolvedBg = colors.background;

if (!this._applyMinimumContrast(charElement, resolvedBg, colors.ansi[fg], cell, bgOverride, undefined)) {
charElement.classList.add(`xterm-fg-${fg}`);
classes.push(`xterm-fg-${fg}`);
}

@@ -326,3 +389,3 @@ break;

if (isInverse) {
charElement.classList.add(`xterm-fg-${INVERTED_DEFAULT_COLOR}`);
classes.push(`xterm-fg-${INVERTED_DEFAULT_COLOR}`);
}

@@ -332,15 +395,31 @@ }

fragment.appendChild(charElement);
cellMap[x] = ++elemIndex;
// apply CSS classes
// slightly faster than using classList by omitting
// checks for doubled entries (code above should not have doublets)
if (classes.length) {
charElement.className = classes.join(' ');
classes.length = 0;
}
// exclude conditions for cell merging - never merge these
if (!isCursorCell && !isInSelection && !isJoined) {
cellAmount++;
} else {
charElement.textContent = text;
}
// apply letter-spacing rule
if (spacing !== this.defaultSpacing) {
charElement.style.letterSpacing = `${spacing}px`;
}
elements.push(charElement);
x = lastCharX;
}
// since the loop above might exit early not handling all cells,
// also set remaining cell positions to last element index
if (x < cols - 1) {
cellMap.subarray(x).fill(++elemIndex);
// postfix text of last merged span
if (charElement && cellAmount) {
charElement.textContent = text;
}
return fragment;
return elements;
}

@@ -347,0 +426,0 @@

@@ -10,4 +10,9 @@ /**

import { Disposable } from 'common/Lifecycle';
import { ITerminalOptions } from 'common/Types';
const enum MeasureSettings {
REPEAT = 32
}
export class CharSizeService extends Disposable implements ICharSizeService {

@@ -71,4 +76,6 @@ public serviceBrand: undefined;

this._measureElement.classList.add('xterm-char-measure-element');
this._measureElement.textContent = 'W';
this._measureElement.textContent = 'W'.repeat(MeasureSettings.REPEAT);
this._measureElement.setAttribute('aria-hidden', 'true');
this._measureElement.style.whiteSpace = 'pre';
this._measureElement.style.fontKerning = 'none';
this._parentElement.appendChild(this._measureElement);

@@ -90,3 +97,3 @@ }

if (geometry.width !== 0 && geometry.height !== 0) {
this._result.width = geometry.width;
this._result.width = geometry.width / MeasureSettings.REPEAT;
this._result.height = Math.ceil(geometry.height);

@@ -93,0 +100,0 @@ }

@@ -8,3 +8,3 @@ /**

import { stringFromCodePoint } from 'common/input/TextDecoder';
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Content, BgFlags, FgFlags } from 'common/buffer/Constants';
import { CHAR_DATA_CHAR_INDEX, CHAR_DATA_WIDTH_INDEX, CHAR_DATA_ATTR_INDEX, NULL_CELL_CHAR, NULL_CELL_WIDTH, NULL_CELL_CODE, WHITESPACE_CELL_CHAR, Content, BgFlags, FgFlags, Attributes } from 'common/buffer/Constants';
import { CellData } from 'common/buffer/CellData';

@@ -467,2 +467,11 @@ import { AttributeData, ExtendedAttrs } from 'common/buffer/AttributeData';

public getNoBgTrimmedLength(): number {
for (let i = this.length - 1; i >= 0; --i) {
if ((this._data[i * CELL_SIZE + Cell.CONTENT] & Content.HAS_CONTENT_MASK) || (this._data[i * CELL_SIZE + Cell.BG] & Attributes.CM_MASK)) {
return i + (this._data[i * CELL_SIZE + Cell.CONTENT] >> Content.WIDTH_SHIFT);
}
}
return 0;
}
public copyCellsFrom(src: BufferLine, srcCol: number, destCol: number, length: number, applyInReverse: boolean): void {

@@ -469,0 +478,0 @@ const srcData = src._data;

@@ -245,2 +245,3 @@ /**

getTrimmedLength(): number;
getNoBgTrimmedLength(): number;
translateToString(trimRight?: boolean, startCol?: number, endCol?: number): string;

@@ -247,0 +248,0 @@

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc