@hex1b/web-terminal 0.172.0 → 0.173.0-alpha.1801.1.3dc2d9b

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/dist/index.js CHANGED
@@ -557,6 +557,11 @@ function validateMetadata(metadata2) {
557
557
  if (commandMark !== null) validateCommandMark(commandMark);
558
558
  const columns = integer(metadata2.columns, "columns", 1, 1024);
559
559
  const rows = integer(metadata2.rows, "rows", 1, 512);
560
+ if (metadata2.lineRenditions !== void 0) {
561
+ array(metadata2.lineRenditions, "line renditions", rows);
562
+ if (metadata2.lineRenditions.length !== rows) throw new Error("Invalid line rendition count");
563
+ for (const rendition of metadata2.lineRenditions) integer(rendition, "line rendition", 0, 3);
564
+ }
560
565
  if (typeof metadata2.mouseTracking !== "number" || ![0, 9, 1e3, 1002, 1003].includes(metadata2.mouseTracking)) {
561
566
  throw new Error("Unsupported mouse tracking mode");
562
567
  }
@@ -2154,32 +2159,45 @@ var init_renderer = __esm({
2154
2159
  [left, top, Math.max(0, right - left), Math.max(0, bottom - top)]
2155
2160
  );
2156
2161
  }
2157
- decorations(cell, x, y, width, foreground, underline = cell.underlineColor, clip) {
2158
- if (cell.attributes & 128) this.solid(x, y + 10, width, 1, foreground, clip);
2159
- if (cell.attributes & 256) this.solid(x, y + 1, width, 1, foreground, clip);
2162
+ decorations(cell, x, y, width, foreground, underline = cell.underlineColor, clip, scaleY = 1) {
2163
+ if (cell.attributes & 128) this.solid(x, y + 10 * scaleY, width, scaleY, foreground, clip);
2164
+ if (cell.attributes & 256) this.solid(x, y + scaleY, width, scaleY, foreground, clip);
2160
2165
  const style = cell.underlineStyle || (cell.attributes & 8 ? 1 : 0);
2161
- this.underline(style, x, y, width, rgba(underline), clip);
2166
+ this.underline(style, x, y, width, rgba(underline), clip, scaleY);
2162
2167
  }
2163
- underline(style, x, y, width, color2, clip) {
2164
- if (style === 1) this.solid(x, y + 18, width, 1, color2, clip);
2168
+ underline(style, x, y, width, color2, clip, scaleY = 1) {
2169
+ if (style === 1) this.solid(x, y + 18 * scaleY, width, scaleY, color2, clip);
2165
2170
  else if (style === 2) {
2166
- this.solid(x, y + 16, width, 1, color2, clip);
2167
- this.solid(x, y + 18, width, 1, color2, clip);
2171
+ this.solid(x, y + 16 * scaleY, width, scaleY, color2, clip);
2172
+ this.solid(x, y + 18 * scaleY, width, scaleY, color2, clip);
2168
2173
  } else if (style === 3) {
2169
2174
  for (let dx = 0; dx < width; dx++) {
2170
- this.solid(x + dx, y + 17 + Math.round(Math.sin((x + dx) * Math.PI / 4)), 1, 1, color2, clip);
2175
+ this.solid(x + dx, y + (17 + Math.round(Math.sin((x + dx) * Math.PI / 4))) * scaleY, 1, scaleY, color2, clip);
2171
2176
  }
2172
2177
  } else if (style === 4 || style === 5) {
2173
2178
  const step = style === 4 ? 2 : 5;
2174
2179
  const segment = style === 4 ? 1 : 3;
2175
- for (let dx = 0; dx < width; dx += step) this.solid(x + dx, y + 18, Math.min(segment, width - dx), 1, color2, clip);
2180
+ for (let dx = 0; dx < width; dx += step) this.solid(x + dx, y + 18 * scaleY, Math.min(segment, width - dx), scaleY, color2, clip);
2176
2181
  }
2177
2182
  }
2178
2183
  renderCell(cell, index, metadata2, blinkOn, palette2, linkDecoration, selectionClip) {
2179
2184
  if (!cell.width || cell.attributes & 64 || cell.attributes & 16 && !blinkOn) return;
2180
- const x = index % this.columns * CELL_WIDTH;
2181
- const y = Math.floor(index / this.columns) * CELL_HEIGHT;
2182
- const width = Math.min(cell.width * CELL_WIDTH, this.width - x);
2185
+ const row = Math.floor(index / this.columns);
2186
+ const rendition = metadata2.lineRenditions?.[row] ?? 0;
2187
+ const scaleX = rendition ? 2 : 1;
2188
+ const scaleY = rendition >= 2 ? 2 : 1;
2189
+ const column = index % this.columns;
2190
+ if (column >= Math.max(1, Math.floor(this.columns / scaleX))) return;
2191
+ const x = column * CELL_WIDTH * scaleX;
2192
+ const rowY = row * CELL_HEIGHT;
2193
+ const y = rowY - (rendition === 3 ? CELL_HEIGHT : 0);
2194
+ const width = Math.min(cell.width * CELL_WIDTH * scaleX, this.width - x);
2195
+ const clip = !rendition ? selectionClip : selectionClip ? [
2196
+ selectionClip[0],
2197
+ Math.max(rowY, selectionClip[1]),
2198
+ selectionClip[2],
2199
+ Math.min(rowY + CELL_HEIGHT, selectionClip[1] + selectionClip[3]) - Math.max(rowY, selectionClip[1])
2200
+ ] : [0, rowY, this.width, CELL_HEIGHT];
2183
2201
  const foreground = rgba(selectionClip ? palette2.selectionForeground : foregroundColor(cell, metadata2, palette2));
2184
2202
  const glyph = isKgpPlaceholder(cell) ? void 0 : this.glyphs.get(glyphKey(cell));
2185
2203
  if (glyph) {
@@ -2188,12 +2206,12 @@ var init_renderer = __esm({
2188
2206
  this.atlas,
2189
2207
  x,
2190
2208
  y,
2191
- cell.width * CELL_WIDTH,
2192
- CELL_HEIGHT,
2209
+ cell.width * CELL_WIDTH * scaleX,
2210
+ CELL_HEIGHT * scaleY,
2193
2211
  tint,
2194
2212
  glyph.colored ? 2 : 1,
2195
2213
  [glyph.u0, glyph.v0, glyph.u1, glyph.v1],
2196
- selectionClip
2214
+ clip
2197
2215
  );
2198
2216
  }
2199
2217
  this.decorations(
@@ -2203,10 +2221,11 @@ var init_renderer = __esm({
2203
2221
  width,
2204
2222
  foreground,
2205
2223
  selectionClip ? palette2.selectionForeground : underlineColor(cell, metadata2, palette2),
2206
- selectionClip
2224
+ clip,
2225
+ scaleY
2207
2226
  );
2208
2227
  if (linkDecoration && !cell.underlineStyle && !(cell.attributes & 8) && !isKgpPlaceholder(cell)) {
2209
- this.underline(linkDecoration, x, y, width, foreground, selectionClip);
2228
+ this.underline(linkDecoration, x, y, width, foreground, clip, scaleY);
2210
2229
  }
2211
2230
  }
2212
2231
  render(cells2, metadata2, blinkOn, linkDecorations, palette2 = DEFAULT_PALETTE) {
@@ -2222,10 +2241,13 @@ var init_renderer = __esm({
2222
2241
  for (let i = 0; i < cells2.length; i++) {
2223
2242
  const cell = cells2[i];
2224
2243
  if (!cell) continue;
2244
+ const row = Math.floor(i / this.columns);
2245
+ const scaleX = metadata2.lineRenditions?.[row] ? 2 : 1;
2246
+ if (i % this.columns >= Math.max(1, Math.floor(this.columns / scaleX))) continue;
2225
2247
  this.solid(
2226
- i % this.columns * CELL_WIDTH,
2227
- Math.floor(i / this.columns) * CELL_HEIGHT,
2228
- CELL_WIDTH,
2248
+ i % this.columns * CELL_WIDTH * scaleX,
2249
+ row * CELL_HEIGHT,
2250
+ CELL_WIDTH * scaleX,
2229
2251
  CELL_HEIGHT,
2230
2252
  rgba(backgroundColor(cell, metadata2, palette2))
2231
2253
  );
@@ -2239,10 +2261,11 @@ var init_renderer = __esm({
2239
2261
  const selection = metadata2.history?.selection;
2240
2262
  if (selection?.status === "valid") {
2241
2263
  for (const range of selection.ranges) {
2264
+ const scaleX = metadata2.lineRenditions?.[range.row] ? 2 : 1;
2242
2265
  const clip = [
2243
- range.startColumn * CELL_WIDTH,
2266
+ range.startColumn * CELL_WIDTH * scaleX,
2244
2267
  range.row * CELL_HEIGHT,
2245
- (range.endColumn - range.startColumn) * CELL_WIDTH,
2268
+ (range.endColumn - range.startColumn) * CELL_WIDTH * scaleX,
2246
2269
  CELL_HEIGHT
2247
2270
  ];
2248
2271
  this.solid(...clip, rgba(palette2.selectionBackground));
@@ -2260,13 +2283,14 @@ var init_renderer = __esm({
2260
2283
  if (cursor.visible && (!cursorBlink || blinkOn) && cursor.x >= 0 && cursor.x < this.columns && cursor.y >= 0 && cursor.y < this.rows) {
2261
2284
  const cell = cells2[cursor.y * this.columns + cursor.x];
2262
2285
  const color2 = rgba(palette2.cursor ?? (cell ? foregroundColor(cell, metadata2, palette2) : palette2.foreground));
2263
- const x = cursor.x * CELL_WIDTH;
2286
+ const scaleX = metadata2.lineRenditions?.[cursor.y] ? 2 : 1;
2287
+ const x = cursor.x * CELL_WIDTH * scaleX;
2264
2288
  const y = cursor.y * CELL_HEIGHT;
2265
- if (cursor.shape === 3 || cursor.shape === 4) this.solid(x, y + 18, CELL_WIDTH, 2, color2);
2289
+ if (cursor.shape === 3 || cursor.shape === 4) this.solid(x, y + 18, CELL_WIDTH * scaleX, 2, color2);
2266
2290
  else if (cursor.shape === 5 || cursor.shape === 6) this.solid(x, y, 2, CELL_HEIGHT, color2);
2267
2291
  else {
2268
2292
  color2[3] *= 0.55;
2269
- this.solid(x, y, CELL_WIDTH, CELL_HEIGHT, color2);
2293
+ this.solid(x, y, CELL_WIDTH * scaleX, CELL_HEIGHT, color2);
2270
2294
  }
2271
2295
  }
2272
2296
  const base = rgba(metadata2.colorEncoding === "indexed-v1" ? palette2.background : metadata2.defaultBackground ?? cells2[0]?.background ?? 4278190080);
@@ -2562,6 +2586,7 @@ async function drawFrame() {
2562
2586
  commandMark: metadata.commandMark,
2563
2587
  text,
2564
2588
  hyperlinks: metadata.hyperlinks,
2589
+ lineRenditions: metadata.lineRenditions,
2565
2590
  ...links.present(cells, metadata)
2566
2591
  });
2567
2592
  send({ type: "ack", revision: frame.revision });
@@ -3199,7 +3224,10 @@ function captureMouse(canvas, send2, focus, inspection = {}) {
3199
3224
  const originalCursor = canvas.style.cursor;
3200
3225
  const state = () => ({ tracking, ...inspection.state?.() });
3201
3226
  function point(event, clamp2 = false) {
3202
- return cellPoint(event, canvas.getBoundingClientRect(), columns, rows, clamp2);
3227
+ const position = cellPoint(event, canvas.getBoundingClientRect(), columns, rows, clamp2);
3228
+ if (position && inspection.lineRenditions?.()[position.y])
3229
+ position.x = Math.min(Math.max(0, Math.floor(columns / 2) - 1), Math.floor(position.x / 2));
3230
+ return position;
3203
3231
  }
3204
3232
  function refreshHover(modifiers = hoverModifiers) {
3205
3233
  if (!inspection.hyperlink) return;
@@ -5508,6 +5536,7 @@ var WebTerminal = class _WebTerminal {
5508
5536
  #selectionUIError = "";
5509
5537
  #canvasSize = { width: 0, height: 0 };
5510
5538
  #hyperlinks = new Hyperlinks();
5539
+ #lineRenditions = [];
5511
5540
  #links;
5512
5541
  #linkDetector;
5513
5542
  #linkGeneration = 1;
@@ -5796,6 +5825,7 @@ var WebTerminal = class _WebTerminal {
5796
5825
  }
5797
5826
  };
5798
5827
  this.#mouse = captureMouse(this.#canvas, (command) => this.#inputCommand(command), () => this.focus(), {
5828
+ lineRenditions: () => this.#lineRenditions,
5799
5829
  state: () => ({
5800
5830
  historical: !this.viewport.following || this.viewport.pending,
5801
5831
  readOnly: this.#readOnly,
@@ -5914,6 +5944,7 @@ var WebTerminal = class _WebTerminal {
5914
5944
  }
5915
5945
  this.#options.onStatus?.(message.message, message.level);
5916
5946
  } else if (message.type === "geometry") {
5947
+ this.#lineRenditions = message.lineRenditions ?? [];
5917
5948
  this.#linkRevision = message.revision;
5918
5949
  this.#osc8Rows.clear();
5919
5950
  for (const range of message.hyperlinks) {
@@ -6075,7 +6106,8 @@ var WebTerminal = class _WebTerminal {
6075
6106
  const element = document.createElement("span");
6076
6107
  element.className = "highlight";
6077
6108
  element.setAttribute("part", "selection-highlight");
6078
- element.style.cssText = `left:${range.startColumn / this.#geometry.columns * 100}%;top:${range.row / this.#geometry.rows * 100}%;width:${(range.endColumn - range.startColumn) / this.#geometry.columns * 100}%;height:${100 / this.#geometry.rows}%`;
6109
+ const scaleX = this.#lineRenditions[range.row] ? 2 : 1;
6110
+ element.style.cssText = `left:${range.startColumn * scaleX / this.#geometry.columns * 100}%;top:${range.row / this.#geometry.rows * 100}%;width:${(range.endColumn - range.startColumn) * scaleX / this.#geometry.columns * 100}%;height:${100 / this.#geometry.rows}%`;
6079
6111
  return element;
6080
6112
  }));
6081
6113
  const live = requiredElement(this.#inspection, ".return-live", HTMLButtonElement);