Merge branch 'master' into progress-addon
This commit is contained in:
@@ -226,6 +226,9 @@ Xterm.js is used in several world-class applications to provide great terminal e
|
|||||||
- [**OpenSFTP**](https://opensftp.com): Super beautiful SSH and SFTP integrated workspace client.
|
- [**OpenSFTP**](https://opensftp.com): Super beautiful SSH and SFTP integrated workspace client.
|
||||||
- [**balena**](https://www.balena.io/): Balena is a full-stack solution for developing, deploying, updating, and troubleshooting IoT Edge devices. We use xterm.js to manage & debug devices on [balenaCloud](https://www.balena.io/cloud).
|
- [**balena**](https://www.balena.io/): Balena is a full-stack solution for developing, deploying, updating, and troubleshooting IoT Edge devices. We use xterm.js to manage & debug devices on [balenaCloud](https://www.balena.io/cloud).
|
||||||
- [**Filet Cloud**](https://github.com/fuglaro/filet-cloud): The lean and powerful personal cloud ⛅.
|
- [**Filet Cloud**](https://github.com/fuglaro/filet-cloud): The lean and powerful personal cloud ⛅.
|
||||||
|
- [**pyTermTk**](https://github.com/ceccopierangiolieugenio/pyTermTk): Python Terminal Toolkit - a Spiced Up Cross Compatible TUI Library 🌶️, use xterm.js for the [HTML5 exporter](https://ceccopierangiolieugenio.github.io/pyTermTk/sandbox/sandbox.html).
|
||||||
|
- [**ecmaOS**](https://ecmaos.sh): A kernel and suite of applications tying modern web technologies into a browser-based operating system.
|
||||||
|
- [**LabEx**](https://labex.io): Interactive learning platform with hands-on labs and xterm.js-based online terminals, focused on learn-by-doing approach.
|
||||||
- [And much more...](https://github.com/xtermjs/xterm.js/network/dependents?package_id=UGFja2FnZS0xNjYzMjc4OQ%3D%3D)
|
- [And much more...](https://github.com/xtermjs/xterm.js/network/dependents?package_id=UGFja2FnZS0xNjYzMjc4OQ%3D%3D)
|
||||||
|
|
||||||
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it on our list. Note: Please add any new contributions to the end of the list only.
|
Do you use xterm.js in your application as well? Please [open a Pull Request](https://github.com/sourcelair/xterm.js/pulls) to include it here. We would love to have it on our list. Note: Please add any new contributions to the end of the list only.
|
||||||
|
|||||||
+1
-1
@@ -39,7 +39,7 @@ declare module '@xterm/addon-fit' {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reprepresents the dimensions of a terminal.
|
* Represents the dimensions of a terminal.
|
||||||
*/
|
*/
|
||||||
export interface ITerminalDimensions {
|
export interface ITerminalDimensions {
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -15,19 +15,22 @@ export interface ITerminalAddon {
|
|||||||
|
|
||||||
export class LigaturesAddon implements ITerminalAddon , ILigaturesApi {
|
export class LigaturesAddon implements ITerminalAddon , ILigaturesApi {
|
||||||
private readonly _fallbackLigatures: string[];
|
private readonly _fallbackLigatures: string[];
|
||||||
|
private readonly _fontFeatureSettings?: string;
|
||||||
|
|
||||||
private _terminal: Terminal | undefined;
|
private _terminal: Terminal | undefined;
|
||||||
private _characterJoinerId: number | undefined;
|
private _characterJoinerId: number | undefined;
|
||||||
|
|
||||||
constructor(options?: Partial<ILigatureOptions>) {
|
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 || [
|
||||||
'<--', '<---', '<<-', '<-', '->', '->>', '-->', '--->',
|
'<--', '<---', '<<-', '<-', '->', '->>', '-->', '--->',
|
||||||
'<==', '<===', '<<=', '<=', '=>', '=>>', '==>', '===>', '>=', '>>=',
|
'<==', '<===', '<<=', '<=', '=>', '=>>', '==>', '===>', '>=', '>>=',
|
||||||
'<->', '<-->', '<--->', '<---->', '<=>', '<==>', '<===>', '<====>', '-------->',
|
'<->', '<-->', '<--->', '<---->', '<=>', '<==>', '<===>', '<====>', '::', ':::',
|
||||||
'<~~', '<~', '~>', '~~>', '::', ':::', '==', '!=', '===', '!==',
|
'<~~', '</', '</>', '/>', '~~>', '==', '!=', '/=', '~=', '<>', '===', '!==', '!===',
|
||||||
':=', ':-', ':+', '<*', '<*>', '*>', '<|', '<|>', '|>', '+:', '-:', '=:', ':>',
|
'<:', ':=', '*=', '*+', '<*', '<*>', '*>', '<|', '<|>', '|>', '+*', '=*', '=:', ':>',
|
||||||
'++', '+++', '<!--', '<!---', '<***>'
|
'/*', '*/', '+++', '<!--', '<!---'
|
||||||
]).sort((a, b) => b.length - a.length);
|
]).sort((a, b) => b.length - a.length);
|
||||||
|
this._fontFeatureSettings = options?.fontFeatureSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public activate(terminal: Terminal): void {
|
public activate(terminal: Terminal): void {
|
||||||
@@ -36,7 +39,7 @@ export class LigaturesAddon implements ITerminalAddon , ILigaturesApi {
|
|||||||
}
|
}
|
||||||
this._terminal = terminal;
|
this._terminal = terminal;
|
||||||
this._characterJoinerId = enableLigatures(terminal, this._fallbackLigatures);
|
this._characterJoinerId = enableLigatures(terminal, this._fallbackLigatures);
|
||||||
terminal.element.style.fontFeatureSettings = '"liga" on, "calt" on';
|
terminal.element.style.fontFeatureSettings = this._fontFeatureSettings ?? '"calt" on';
|
||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
|
|||||||
@@ -5,4 +5,5 @@
|
|||||||
|
|
||||||
export interface ILigatureOptions {
|
export interface ILigatureOptions {
|
||||||
fallbackLigatures: string[];
|
fallbackLigatures: string[];
|
||||||
|
fontFeatureSettings: string;
|
||||||
}
|
}
|
||||||
|
|||||||
+21
-9
@@ -23,7 +23,10 @@ declare module '@xterm/addon-ligatures' {
|
|||||||
constructor(options?: Partial<ILigatureOptions>);
|
constructor(options?: Partial<ILigatureOptions>);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Activates the addon
|
* Activates the addon. Note that if webgl is also being used, that addon
|
||||||
|
* should be reactivated after ligatures is activated in order to apply
|
||||||
|
* {@link ILigatureOptions.fontFeatureSettings} to the texture atlas.
|
||||||
|
*
|
||||||
*
|
*
|
||||||
* @param terminal The terminal the addon is being loaded in.
|
* @param terminal The terminal the addon is being loaded in.
|
||||||
*/
|
*/
|
||||||
@@ -40,19 +43,28 @@ declare module '@xterm/addon-ligatures' {
|
|||||||
*/
|
*/
|
||||||
export interface ILigatureOptions {
|
export interface ILigatureOptions {
|
||||||
/**
|
/**
|
||||||
* Fallback ligatures to use when the font access API is either not supported by the browser or
|
* Fallback ligatures to use when the font access API is either not
|
||||||
* access is denied. The default set of ligatures is taken from Iosevka's default "calt"
|
* supported by the browser or access is denied. The default set of
|
||||||
* ligation set: https://typeof.net/Iosevka/
|
* ligatures is taken from Iosevka's default "calt" ligation set:
|
||||||
|
* https://typeof.net/Iosevka/
|
||||||
*
|
*
|
||||||
* ```
|
* ```
|
||||||
* <-- <--- <<- <- -> ->> --> --->
|
* <-- <--- <<- <- -> ->> --> --->
|
||||||
* <== <=== <<= <= => =>> ==> ===> >= >>=
|
* <== <=== <<= <= => =>> ==> ===> >= >>=
|
||||||
* <-> <--> <---> <----> <=> <==> <===> <====> -------->
|
* <-> <--> <---> <----> <=> <==> <===> <====> :: :::
|
||||||
* <~~ <~ ~> ~~> :: ::: == != === !==
|
* <~~ </ </> /> ~~> == != /= ~= <> === !== !===
|
||||||
* := :- :+ <* <*> *> <| <|> |> +: -: =: :>
|
* <: := *= *+ <* <*> *> <| <|> |> +* =* =: :>
|
||||||
* ++ +++ <!-- <!--- <***>
|
* /* <close block comment> +++ <!-- <!---
|
||||||
* ```
|
|
||||||
*/
|
*/
|
||||||
fallbackLigatures: string[]
|
fallbackLigatures: string[]
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The CSS `font-feature-settings` value to use for enabling ligatures. This
|
||||||
|
* also supports font variants for example with a value like
|
||||||
|
* `"calt" on, "ss03"`.
|
||||||
|
*
|
||||||
|
* The default value is `"calt" on`.
|
||||||
|
*/
|
||||||
|
fontFeatureSettings: string;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-3
@@ -3,11 +3,11 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas';
|
import { TextureAtlas } from './TextureAtlas';
|
||||||
import { ITerminalOptions, Terminal } from '@xterm/xterm';
|
import { ITerminalOptions, Terminal } from '@xterm/xterm';
|
||||||
import { ITerminal, ReadonlyColorSet } from 'browser/Types';
|
import { ITerminal, ReadonlyColorSet } from 'browser/Types';
|
||||||
import { ICharAtlasConfig, ITextureAtlas } from 'browser/renderer/shared/Types';
|
import { ICharAtlasConfig, ITextureAtlas } from './Types';
|
||||||
import { generateConfig, configEquals } from 'browser/renderer/shared/CharAtlasUtils';
|
import { generateConfig, configEquals } from './CharAtlasUtils';
|
||||||
|
|
||||||
interface ITextureAtlasCacheEntry {
|
interface ITextureAtlasCacheEntry {
|
||||||
atlas: ITextureAtlas;
|
atlas: ITextureAtlas;
|
||||||
@@ -0,0 +1,12 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2017 The xterm.js authors. All rights reserved.
|
||||||
|
* @license MIT
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { isFirefox, isLegacyEdge } from 'common/Platform';
|
||||||
|
|
||||||
|
export const DIM_OPACITY = 0.5;
|
||||||
|
// The text baseline is set conditionally by browser. Using 'ideographic' for Firefox or Legacy Edge
|
||||||
|
// would result in truncated text (Issue 3353). Using 'bottom' for Chrome would result in slightly
|
||||||
|
// unaligned Powerline fonts (PR 3356#issuecomment-850928179).
|
||||||
|
export const TEXT_BASELINE: CanvasTextBaseline = isFirefox || isLegacyEdge ? 'bottom' : 'ideographic';
|
||||||
@@ -2,16 +2,15 @@
|
|||||||
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
* Copyright (c) 2018 The xterm.js authors. All rights reserved.
|
||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
import { TextureAtlas } from './TextureAtlas';
|
||||||
import { allowRescaling, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||||
import { TextureAtlas } from 'browser/renderer/shared/TextureAtlas';
|
|
||||||
import { IRasterizedGlyph, IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types';
|
|
||||||
import { NULL_CELL_CODE } from 'common/buffer/Constants';
|
import { NULL_CELL_CODE } from 'common/buffer/Constants';
|
||||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { Terminal } from '@xterm/xterm';
|
import { Terminal } from '@xterm/xterm';
|
||||||
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types';
|
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject, type IRasterizedGlyph, type ITextureAtlas } from './Types';
|
||||||
import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils';
|
import { createProgram, GLTexture, PROJECTION_MATRIX } from './WebglUtils';
|
||||||
import type { IOptionsService } from 'common/services/Services';
|
import type { IOptionsService } from 'common/services/Services';
|
||||||
|
import { allowRescaling, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||||
|
|
||||||
interface IVertices {
|
interface IVertices {
|
||||||
attributes: Float32Array;
|
attributes: Float32Array;
|
||||||
@@ -238,9 +237,9 @@ export class GlyphRenderer extends Disposable {
|
|||||||
|
|
||||||
// Get the glyph
|
// Get the glyph
|
||||||
if (chars && chars.length > 1) {
|
if (chars && chars.length > 1) {
|
||||||
$glyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg, ext, false);
|
$glyph = this._atlas.getRasterizedGlyphCombinedChar(chars, bg, fg, ext, false, this._terminal.element);
|
||||||
} else {
|
} else {
|
||||||
$glyph = this._atlas.getRasterizedGlyph(code, bg, fg, ext, false);
|
$glyph = this._atlas.getRasterizedGlyph(code, bg, fg, ext, false, this._terminal.element);
|
||||||
}
|
}
|
||||||
|
|
||||||
$leftCellPadding = Math.floor((this._dimensions.device.cell.width - this._dimensions.device.char.width) / 2);
|
$leftCellPadding = Math.floor((this._dimensions.device.cell.width - this._dimensions.device.char.width) / 2);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
|
||||||
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||||
import { IThemeService } from 'browser/services/Services';
|
import { IThemeService } from 'browser/services/Services';
|
||||||
import { ReadonlyColorSet } from 'browser/Types';
|
import { ReadonlyColorSet } from 'browser/Types';
|
||||||
@@ -14,6 +13,7 @@ import { Terminal } from '@xterm/xterm';
|
|||||||
import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
|
import { RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
|
||||||
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types';
|
import { IRenderModel, IWebGL2RenderingContext, IWebGLVertexArrayObject } from './Types';
|
||||||
import { createProgram, expandFloat32Array, PROJECTION_MATRIX } from './WebglUtils';
|
import { createProgram, expandFloat32Array, PROJECTION_MATRIX } from './WebglUtils';
|
||||||
|
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||||
|
|
||||||
const enum VertexAttribLocations {
|
const enum VertexAttribLocations {
|
||||||
POSITION = 0,
|
POSITION = 0,
|
||||||
|
|||||||
+21
-11
@@ -4,10 +4,10 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { IColorContrastCache } from 'browser/Types';
|
import { IColorContrastCache } from 'browser/Types';
|
||||||
import { DIM_OPACITY, TEXT_BASELINE } from 'browser/renderer/shared/Constants';
|
import { DIM_OPACITY, TEXT_BASELINE } from './Constants';
|
||||||
import { tryDrawCustomChar } from 'browser/renderer/shared/CustomGlyphs';
|
import { tryDrawCustomChar } from './CustomGlyphs';
|
||||||
import { computeNextVariantOffset, treatGlyphAsBackgroundColor, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
import { computeNextVariantOffset, treatGlyphAsBackgroundColor, isPowerlineGlyph, isRestrictedPowerlineGlyph, throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||||
import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from 'browser/renderer/shared/Types';
|
import { IBoundingBox, ICharAtlasConfig, IRasterizedGlyph, ITextureAtlas } from './Types';
|
||||||
import { NULL_COLOR, channels, color, rgba } from 'common/Color';
|
import { NULL_COLOR, channels, color, rgba } from 'common/Color';
|
||||||
import { FourKeyMap } from 'common/MultiKeyMap';
|
import { FourKeyMap } from 'common/MultiKeyMap';
|
||||||
import { IdleTaskQueue } from 'common/TaskQueue';
|
import { IdleTaskQueue } from 'common/TaskQueue';
|
||||||
@@ -103,6 +103,7 @@ export class TextureAtlas implements ITextureAtlas {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public dispose(): void {
|
public dispose(): void {
|
||||||
|
this._tmpCanvas.remove();
|
||||||
for (const page of this.pages) {
|
for (const page of this.pages) {
|
||||||
page.canvas.remove();
|
page.canvas.remove();
|
||||||
}
|
}
|
||||||
@@ -122,7 +123,7 @@ export class TextureAtlas implements ITextureAtlas {
|
|||||||
for (let i = 33; i < 126; i++) {
|
for (let i = 33; i < 126; i++) {
|
||||||
queue.enqueue(() => {
|
queue.enqueue(() => {
|
||||||
if (!this._cacheMap.get(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT)) {
|
if (!this._cacheMap.get(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT)) {
|
||||||
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT);
|
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT, false, undefined);
|
||||||
this._cacheMap.set(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT, rasterizedGlyph);
|
this._cacheMap.set(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT, rasterizedGlyph);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -242,12 +243,12 @@ export class TextureAtlas implements ITextureAtlas {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public getRasterizedGlyphCombinedChar(chars: string, bg: number, fg: number, ext: number, restrictToCellHeight: boolean): IRasterizedGlyph {
|
public getRasterizedGlyphCombinedChar(chars: string, bg: number, fg: number, ext: number, restrictToCellHeight: boolean, domContainer: HTMLElement | undefined): IRasterizedGlyph {
|
||||||
return this._getFromCacheMap(this._cacheMapCombined, chars, bg, fg, ext, restrictToCellHeight);
|
return this._getFromCacheMap(this._cacheMapCombined, chars, bg, fg, ext, restrictToCellHeight, domContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
public getRasterizedGlyph(code: number, bg: number, fg: number, ext: number, restrictToCellHeight: boolean): IRasterizedGlyph {
|
public getRasterizedGlyph(code: number, bg: number, fg: number, ext: number, restrictToCellHeight: boolean, domContainer: HTMLElement | undefined): IRasterizedGlyph {
|
||||||
return this._getFromCacheMap(this._cacheMap, code, bg, fg, ext, restrictToCellHeight);
|
return this._getFromCacheMap(this._cacheMap, code, bg, fg, ext, restrictToCellHeight, domContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -259,11 +260,12 @@ export class TextureAtlas implements ITextureAtlas {
|
|||||||
bg: number,
|
bg: number,
|
||||||
fg: number,
|
fg: number,
|
||||||
ext: number,
|
ext: number,
|
||||||
restrictToCellHeight: boolean = false
|
restrictToCellHeight: boolean,
|
||||||
|
domContainer: HTMLElement | undefined
|
||||||
): IRasterizedGlyph {
|
): IRasterizedGlyph {
|
||||||
$glyph = cacheMap.get(key, bg, fg, ext);
|
$glyph = cacheMap.get(key, bg, fg, ext);
|
||||||
if (!$glyph) {
|
if (!$glyph) {
|
||||||
$glyph = this._drawToCache(key, bg, fg, ext, restrictToCellHeight);
|
$glyph = this._drawToCache(key, bg, fg, ext, restrictToCellHeight, domContainer);
|
||||||
cacheMap.set(key, bg, fg, ext, $glyph);
|
cacheMap.set(key, bg, fg, ext, $glyph);
|
||||||
}
|
}
|
||||||
return $glyph;
|
return $glyph;
|
||||||
@@ -423,12 +425,20 @@ export class TextureAtlas implements ITextureAtlas {
|
|||||||
return this._config.colors.contrastCache;
|
return this._config.colors.contrastCache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private _drawToCache(codeOrChars: number | string, bg: number, fg: number, ext: number, restrictToCellHeight: boolean = false): IRasterizedGlyph {
|
private _drawToCache(codeOrChars: number | string, bg: number, fg: number, ext: number, restrictToCellHeight: boolean, domContainer: HTMLElement | undefined): IRasterizedGlyph {
|
||||||
const chars = typeof codeOrChars === 'number' ? String.fromCharCode(codeOrChars) : codeOrChars;
|
const chars = typeof codeOrChars === 'number' ? String.fromCharCode(codeOrChars) : codeOrChars;
|
||||||
|
|
||||||
// Uncomment for debugging
|
// Uncomment for debugging
|
||||||
// console.log(`draw to cache "${chars}"`, bg, fg, ext);
|
// console.log(`draw to cache "${chars}"`, bg, fg, ext);
|
||||||
|
|
||||||
|
// Attach the canvas to the DOM in order to inherit font-feature-settings
|
||||||
|
// from the parent elements. This is necessary for ligatures and variants to
|
||||||
|
// work.
|
||||||
|
if (domContainer && this._tmpCanvas.parentElement !== domContainer) {
|
||||||
|
this._tmpCanvas.style.display = 'none';
|
||||||
|
domContainer.append(this._tmpCanvas);
|
||||||
|
}
|
||||||
|
|
||||||
// Allow 1 cell width per character, with a minimum of 2 (CJK), plus some padding. This is used
|
// Allow 1 cell width per character, with a minimum of 2 (CJK), plus some padding. This is used
|
||||||
// to draw the glyph to the canvas as well as to restrict the bounding box search to ensure
|
// to draw the glyph to the canvas as well as to restrict the bounding box search to ensure
|
||||||
// giant ligatures (eg. =====>) don't impact overall performance.
|
// giant ligatures (eg. =====>) don't impact overall performance.
|
||||||
@@ -3,8 +3,11 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import { FontWeight } from '@xterm/xterm';
|
||||||
|
import { IColorSet } from 'browser/Types';
|
||||||
import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
|
import { ISelectionRenderModel } from 'browser/renderer/shared/Types';
|
||||||
import { CursorInactiveStyle, CursorStyle } from 'common/Types';
|
import { CursorInactiveStyle, CursorStyle, type IDisposable } from 'common/Types';
|
||||||
|
import type { Event } from 'vs/base/common/event';
|
||||||
|
|
||||||
export interface IRenderModel {
|
export interface IRenderModel {
|
||||||
cells: Uint32Array;
|
cells: Uint32Array;
|
||||||
@@ -31,3 +34,93 @@ export interface IWebGL2RenderingContext extends WebGLRenderingContext {
|
|||||||
|
|
||||||
export interface IWebGLVertexArrayObject {
|
export interface IWebGLVertexArrayObject {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export interface ICharAtlasConfig {
|
||||||
|
customGlyphs: boolean;
|
||||||
|
devicePixelRatio: number;
|
||||||
|
deviceMaxTextureSize: number;
|
||||||
|
letterSpacing: number;
|
||||||
|
lineHeight: number;
|
||||||
|
fontSize: number;
|
||||||
|
fontFamily: string;
|
||||||
|
fontWeight: FontWeight;
|
||||||
|
fontWeightBold: FontWeight;
|
||||||
|
deviceCellWidth: number;
|
||||||
|
deviceCellHeight: number;
|
||||||
|
deviceCharWidth: number;
|
||||||
|
deviceCharHeight: number;
|
||||||
|
allowTransparency: boolean;
|
||||||
|
drawBoldTextInBrightColors: boolean;
|
||||||
|
minimumContrastRatio: number;
|
||||||
|
colors: IColorSet;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ITextureAtlas extends IDisposable {
|
||||||
|
readonly pages: { canvas: HTMLCanvasElement, version: number }[];
|
||||||
|
|
||||||
|
onAddTextureAtlasCanvas: Event<HTMLCanvasElement>;
|
||||||
|
onRemoveTextureAtlasCanvas: Event<HTMLCanvasElement>;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warm up the texture atlas, adding common glyphs to avoid slowing early frame.
|
||||||
|
*/
|
||||||
|
warmUp(): void;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Call when a frame is being drawn, this will return true if the atlas was cleared to make room
|
||||||
|
* for a new set of glyphs.
|
||||||
|
*/
|
||||||
|
beginFrame(): boolean;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Clear all glyphs from the texture atlas.
|
||||||
|
*/
|
||||||
|
clearTexture(): void;
|
||||||
|
getRasterizedGlyph(code: number, bg: number, fg: number, ext: number, restrictToCellHeight: boolean, domContainer: HTMLElement | undefined): IRasterizedGlyph;
|
||||||
|
getRasterizedGlyphCombinedChar(chars: string, bg: number, fg: number, ext: number, restrictToCellHeight: boolean, domContainer: HTMLElement | undefined): IRasterizedGlyph;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represents a rasterized glyph within a texture atlas. Some numbers are
|
||||||
|
* tracked in CSS pixels as well in order to reduce calculations during the
|
||||||
|
* render loop.
|
||||||
|
*/
|
||||||
|
export interface IRasterizedGlyph {
|
||||||
|
/**
|
||||||
|
* The x and y offset between the glyph's top/left and the top/left of a cell
|
||||||
|
* in pixels.
|
||||||
|
*/
|
||||||
|
offset: IVector;
|
||||||
|
/**
|
||||||
|
* The index of the texture page that the glyph is on.
|
||||||
|
*/
|
||||||
|
texturePage: number;
|
||||||
|
/**
|
||||||
|
* the x and y position of the glyph in the texture in pixels.
|
||||||
|
*/
|
||||||
|
texturePosition: IVector;
|
||||||
|
/**
|
||||||
|
* the x and y position of the glyph in the texture in clip space coordinates.
|
||||||
|
*/
|
||||||
|
texturePositionClipSpace: IVector;
|
||||||
|
/**
|
||||||
|
* The width and height of the glyph in the texture in pixels.
|
||||||
|
*/
|
||||||
|
size: IVector;
|
||||||
|
/**
|
||||||
|
* The width and height of the glyph in the texture in clip space coordinates.
|
||||||
|
*/
|
||||||
|
sizeClipSpace: IVector;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IVector {
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IBoundingBox {
|
||||||
|
top: number;
|
||||||
|
left: number;
|
||||||
|
right: number;
|
||||||
|
bottom: number;
|
||||||
|
}
|
||||||
|
|||||||
@@ -4,12 +4,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ITerminal } from 'browser/Types';
|
import { ITerminal } from 'browser/Types';
|
||||||
import { CellColorResolver } from 'browser/renderer/shared/CellColorResolver';
|
import { CellColorResolver } from './CellColorResolver';
|
||||||
import { acquireTextureAtlas, removeTerminalFromCache } from 'browser/renderer/shared/CharAtlasCache';
|
import { acquireTextureAtlas, removeTerminalFromCache } from './CharAtlasCache';
|
||||||
import { CursorBlinkStateManager } from 'browser/renderer/shared/CursorBlinkStateManager';
|
import { CursorBlinkStateManager } from './CursorBlinkStateManager';
|
||||||
import { observeDevicePixelDimensions } from 'browser/renderer/shared/DevicePixelObserver';
|
import { observeDevicePixelDimensions } from './DevicePixelObserver';
|
||||||
import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
|
import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/shared/Types';
|
||||||
import { IRenderDimensions, IRenderer, IRequestRedrawEvent, ITextureAtlas } from 'browser/renderer/shared/Types';
|
|
||||||
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
import { ICharSizeService, ICharacterJoinerService, ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
||||||
import { CharData, IBufferLine, ICellData } from 'common/Types';
|
import { CharData, IBufferLine, ICellData } from 'common/Types';
|
||||||
import { AttributeData } from 'common/buffer/AttributeData';
|
import { AttributeData } from 'common/buffer/AttributeData';
|
||||||
@@ -20,12 +19,13 @@ import { Terminal } from '@xterm/xterm';
|
|||||||
import { GlyphRenderer } from './GlyphRenderer';
|
import { GlyphRenderer } from './GlyphRenderer';
|
||||||
import { RectangleRenderer } from './RectangleRenderer';
|
import { RectangleRenderer } from './RectangleRenderer';
|
||||||
import { COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_EXT_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL, RenderModel } from './RenderModel';
|
import { COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_EXT_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL, RenderModel } from './RenderModel';
|
||||||
import { IWebGL2RenderingContext } from './Types';
|
import { IWebGL2RenderingContext, type ITextureAtlas } from './Types';
|
||||||
import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
|
import { LinkRenderLayer } from './renderLayer/LinkRenderLayer';
|
||||||
import { IRenderLayer } from './renderLayer/Types';
|
import { IRenderLayer } from './renderLayer/Types';
|
||||||
import { Emitter, Event } from 'vs/base/common/event';
|
import { Emitter, Event } from 'vs/base/common/event';
|
||||||
import { addDisposableListener } from 'vs/base/browser/dom';
|
import { addDisposableListener } from 'vs/base/browser/dom';
|
||||||
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
import { combinedDisposable, Disposable, MutableDisposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
|
import { createRenderDimensions } from 'browser/renderer/shared/RendererUtils';
|
||||||
|
|
||||||
export class WebglRenderer extends Disposable implements IRenderer {
|
export class WebglRenderer extends Disposable implements IRenderer {
|
||||||
private _renderLayers: IRenderLayer[];
|
private _renderLayers: IRenderLayer[];
|
||||||
|
|||||||
@@ -4,16 +4,17 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import { ReadonlyColorSet } from 'browser/Types';
|
import { ReadonlyColorSet } from 'browser/Types';
|
||||||
import { acquireTextureAtlas } from 'browser/renderer/shared/CharAtlasCache';
|
import { acquireTextureAtlas } from '../CharAtlasCache';
|
||||||
import { TEXT_BASELINE } from 'browser/renderer/shared/Constants';
|
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||||
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
|
||||||
import { IRenderDimensions, ITextureAtlas } from 'browser/renderer/shared/Types';
|
|
||||||
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
||||||
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
|
||||||
import { CellData } from 'common/buffer/CellData';
|
import { CellData } from 'common/buffer/CellData';
|
||||||
import { IOptionsService } from 'common/services/Services';
|
import { IOptionsService } from 'common/services/Services';
|
||||||
import { Terminal } from '@xterm/xterm';
|
import { Terminal } from '@xterm/xterm';
|
||||||
import { IRenderLayer } from './Types';
|
import { IRenderLayer } from './Types';
|
||||||
|
import { throwIfFalsy } from 'browser/renderer/shared/RendererUtils';
|
||||||
|
import { TEXT_BASELINE } from '../Constants';
|
||||||
|
import type { ITextureAtlas } from '../Types';
|
||||||
|
|
||||||
export abstract class BaseRenderLayer extends Disposable implements IRenderLayer {
|
export abstract class BaseRenderLayer extends Disposable implements IRenderLayer {
|
||||||
private _canvas: HTMLCanvasElement;
|
private _canvas: HTMLCanvasElement;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { is256Color } from 'browser/renderer/shared/CharAtlasUtils';
|
import { is256Color } from '../CharAtlasUtils';
|
||||||
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
|
import { INVERTED_DEFAULT_COLOR } from 'browser/renderer/shared/Constants';
|
||||||
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
import { IRenderDimensions } from 'browser/renderer/shared/Types';
|
||||||
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
import { ICoreBrowserService, IThemeService } from 'browser/services/Services';
|
||||||
|
|||||||
+1
-2
@@ -115,8 +115,7 @@ function checkAndPublishPackage(packageDir, repoCommit, peerDependencies) {
|
|||||||
stdio: 'inherit'
|
stdio: 'inherit'
|
||||||
});
|
});
|
||||||
if (result.status) {
|
if (result.status) {
|
||||||
error(`Spawn exited with code ${result.status}`);
|
throw new Error(`Spawn exited with code ${result.status}`);
|
||||||
process.exit(result.status);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return { isStableRelease, nextVersion };
|
return { isStableRelease, nextVersion };
|
||||||
|
|||||||
+25
-6
@@ -646,17 +646,25 @@ function initAddons(term: Terminal): void {
|
|||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
function postInitWebgl(): void {
|
||||||
|
setTimeout(() => {
|
||||||
|
setTextureAtlas(addons.webgl.instance.textureAtlas);
|
||||||
|
addons.webgl.instance.onChangeTextureAtlas(e => setTextureAtlas(e));
|
||||||
|
addons.webgl.instance.onAddTextureAtlasCanvas(e => appendTextureAtlas(e));
|
||||||
|
}, 500);
|
||||||
|
}
|
||||||
|
function preDisposeWebgl(): void {
|
||||||
|
if (addons.webgl.instance.textureAtlas) {
|
||||||
|
addons.webgl.instance.textureAtlas.remove();
|
||||||
|
}
|
||||||
|
}
|
||||||
if (checkbox.checked) {
|
if (checkbox.checked) {
|
||||||
// HACK: Manually remove addons that cannot be changes
|
// HACK: Manually remove addons that cannot be changes
|
||||||
addon.instance = new (addon as IDemoAddon<Exclude<AddonType, 'attach'>>).ctor();
|
addon.instance = new (addon as IDemoAddon<Exclude<AddonType, 'attach'>>).ctor();
|
||||||
try {
|
try {
|
||||||
term.loadAddon(addon.instance);
|
term.loadAddon(addon.instance);
|
||||||
if (name === 'webgl') {
|
if (name === 'webgl') {
|
||||||
setTimeout(() => {
|
postInitWebgl();
|
||||||
setTextureAtlas(addons.webgl.instance.textureAtlas);
|
|
||||||
addons.webgl.instance.onChangeTextureAtlas(e => setTextureAtlas(e));
|
|
||||||
addons.webgl.instance.onAddTextureAtlasCanvas(e => appendTextureAtlas(e));
|
|
||||||
}, 0);
|
|
||||||
} else if (name === 'unicode11') {
|
} else if (name === 'unicode11') {
|
||||||
term.unicode.activeVersion = '11';
|
term.unicode.activeVersion = '11';
|
||||||
} else if (name === 'unicodeGraphemes') {
|
} else if (name === 'unicodeGraphemes') {
|
||||||
@@ -672,13 +680,24 @@ function initAddons(term: Terminal): void {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (name === 'webgl') {
|
if (name === 'webgl') {
|
||||||
addons.webgl.instance.textureAtlas.remove();
|
preDisposeWebgl();
|
||||||
} else if (name === 'unicode11' || name === 'unicodeGraphemes') {
|
} else if (name === 'unicode11' || name === 'unicodeGraphemes') {
|
||||||
term.unicode.activeVersion = '6';
|
term.unicode.activeVersion = '6';
|
||||||
}
|
}
|
||||||
addon.instance!.dispose();
|
addon.instance!.dispose();
|
||||||
addon.instance = undefined;
|
addon.instance = undefined;
|
||||||
}
|
}
|
||||||
|
if (name === 'ligatures') {
|
||||||
|
// Recreate webgl when ligatures are toggled so texture atlas picks up any font feature
|
||||||
|
// settings changes
|
||||||
|
if (addons.webgl.instance) {
|
||||||
|
preDisposeWebgl();
|
||||||
|
addons.webgl.instance.dispose();
|
||||||
|
addons.webgl.instance = new addons.webgl.ctor();
|
||||||
|
term.loadAddon(addons.webgl.instance);
|
||||||
|
postInitWebgl();
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
const label = document.createElement('label');
|
const label = document.createElement('label');
|
||||||
label.classList.add('addon');
|
label.classList.add('addon');
|
||||||
|
|||||||
@@ -93,7 +93,8 @@ export class CompositionHelper {
|
|||||||
*/
|
*/
|
||||||
public keydown(ev: KeyboardEvent): boolean {
|
public keydown(ev: KeyboardEvent): boolean {
|
||||||
if (this._isComposing || this._isSendingComposition) {
|
if (this._isComposing || this._isSendingComposition) {
|
||||||
if (ev.keyCode === 229) {
|
if (ev.keyCode === 20 || ev.keyCode === 229) {
|
||||||
|
// 20 is CapsLock, 229 is Enter
|
||||||
// Continue composing if the keyCode is the "composition character"
|
// Continue composing if the keyCode is the "composition character"
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,12 +3,4 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { isFirefox, isLegacyEdge } from 'common/Platform';
|
|
||||||
|
|
||||||
export const INVERTED_DEFAULT_COLOR = 257;
|
export const INVERTED_DEFAULT_COLOR = 257;
|
||||||
|
|
||||||
export const DIM_OPACITY = 0.5;
|
|
||||||
// The text baseline is set conditionally by browser. Using 'ideographic' for Firefox or Legacy Edge
|
|
||||||
// would result in truncated text (Issue 3353). Using 'bottom' for Chrome would result in slightly
|
|
||||||
// unaligned Powerline fonts (PR 3356#issuecomment-850928179).
|
|
||||||
export const TEXT_BASELINE: CanvasTextBaseline = isFirefox || isLegacyEdge ? 'bottom' : 'ideographic';
|
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
This folder contains files that are shared between the renderer addons, but not necessarily bundled into the `xterm` module.
|
This folder contains files that are shared between the renderers.
|
||||||
|
|||||||
@@ -3,31 +3,11 @@
|
|||||||
* @license MIT
|
* @license MIT
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { FontWeight, Terminal } from '@xterm/xterm';
|
import { Terminal } from '@xterm/xterm';
|
||||||
import { IColorSet, ITerminal } from 'browser/Types';
|
import { ITerminal } from 'browser/Types';
|
||||||
import { IDisposable } from 'common/Types';
|
import { IDisposable } from 'common/Types';
|
||||||
import type { Event } from 'vs/base/common/event';
|
import type { Event } from 'vs/base/common/event';
|
||||||
|
|
||||||
export interface ICharAtlasConfig {
|
|
||||||
customGlyphs: boolean;
|
|
||||||
devicePixelRatio: number;
|
|
||||||
deviceMaxTextureSize: number;
|
|
||||||
letterSpacing: number;
|
|
||||||
lineHeight: number;
|
|
||||||
fontSize: number;
|
|
||||||
fontFamily: string;
|
|
||||||
fontWeight: FontWeight;
|
|
||||||
fontWeightBold: FontWeight;
|
|
||||||
deviceCellWidth: number;
|
|
||||||
deviceCellHeight: number;
|
|
||||||
deviceCharWidth: number;
|
|
||||||
deviceCharHeight: number;
|
|
||||||
allowTransparency: boolean;
|
|
||||||
drawBoldTextInBrightColors: boolean;
|
|
||||||
minimumContrastRatio: number;
|
|
||||||
colors: IColorSet;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDimensions {
|
export interface IDimensions {
|
||||||
width: number;
|
width: number;
|
||||||
height: number;
|
height: number;
|
||||||
@@ -87,76 +67,6 @@ export interface IRenderer extends IDisposable {
|
|||||||
clearTextureAtlas?(): void;
|
clearTextureAtlas?(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ITextureAtlas extends IDisposable {
|
|
||||||
readonly pages: { canvas: HTMLCanvasElement, version: number }[];
|
|
||||||
|
|
||||||
onAddTextureAtlasCanvas: Event<HTMLCanvasElement>;
|
|
||||||
onRemoveTextureAtlasCanvas: Event<HTMLCanvasElement>;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Warm up the texture atlas, adding common glyphs to avoid slowing early frame.
|
|
||||||
*/
|
|
||||||
warmUp(): void;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Call when a frame is being drawn, this will return true if the atlas was cleared to make room
|
|
||||||
* for a new set of glyphs.
|
|
||||||
*/
|
|
||||||
beginFrame(): boolean;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Clear all glyphs from the texture atlas.
|
|
||||||
*/
|
|
||||||
clearTexture(): void;
|
|
||||||
getRasterizedGlyph(code: number, bg: number, fg: number, ext: number, restrictToCellHeight: boolean): IRasterizedGlyph;
|
|
||||||
getRasterizedGlyphCombinedChar(chars: string, bg: number, fg: number, ext: number, restrictToCellHeight: boolean): IRasterizedGlyph;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Represents a rasterized glyph within a texture atlas. Some numbers are
|
|
||||||
* tracked in CSS pixels as well in order to reduce calculations during the
|
|
||||||
* render loop.
|
|
||||||
*/
|
|
||||||
export interface IRasterizedGlyph {
|
|
||||||
/**
|
|
||||||
* The x and y offset between the glyph's top/left and the top/left of a cell
|
|
||||||
* in pixels.
|
|
||||||
*/
|
|
||||||
offset: IVector;
|
|
||||||
/**
|
|
||||||
* The index of the texture page that the glyph is on.
|
|
||||||
*/
|
|
||||||
texturePage: number;
|
|
||||||
/**
|
|
||||||
* the x and y position of the glyph in the texture in pixels.
|
|
||||||
*/
|
|
||||||
texturePosition: IVector;
|
|
||||||
/**
|
|
||||||
* the x and y position of the glyph in the texture in clip space coordinates.
|
|
||||||
*/
|
|
||||||
texturePositionClipSpace: IVector;
|
|
||||||
/**
|
|
||||||
* The width and height of the glyph in the texture in pixels.
|
|
||||||
*/
|
|
||||||
size: IVector;
|
|
||||||
/**
|
|
||||||
* The width and height of the glyph in the texture in clip space coordinates.
|
|
||||||
*/
|
|
||||||
sizeClipSpace: IVector;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IVector {
|
|
||||||
x: number;
|
|
||||||
y: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IBoundingBox {
|
|
||||||
top: number;
|
|
||||||
left: number;
|
|
||||||
right: number;
|
|
||||||
bottom: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ISelectionRenderModel {
|
export interface ISelectionRenderModel {
|
||||||
readonly hasSelection: boolean;
|
readonly hasSelection: boolean;
|
||||||
readonly columnSelectMode: boolean;
|
readonly columnSelectMode: boolean;
|
||||||
|
|||||||
@@ -1669,9 +1669,9 @@ cross-env@^7.0.3:
|
|||||||
cross-spawn "^7.0.1"
|
cross-spawn "^7.0.1"
|
||||||
|
|
||||||
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
cross-spawn@^7.0.0, cross-spawn@^7.0.1, cross-spawn@^7.0.2, cross-spawn@^7.0.3:
|
||||||
version "7.0.3"
|
version "7.0.6"
|
||||||
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6"
|
resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f"
|
||||||
integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==
|
integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==
|
||||||
dependencies:
|
dependencies:
|
||||||
path-key "^3.1.0"
|
path-key "^3.1.0"
|
||||||
shebang-command "^2.0.0"
|
shebang-command "^2.0.0"
|
||||||
|
|||||||
Reference in New Issue
Block a user