mirror of
https://github.com/wavetermdev/xterm.js.git
synced 2026-08-05 13:43:48 -07:00
Merge branch 'master' into buffer_optimizations
This commit is contained in:
@@ -99,6 +99,26 @@ The full API for xterm.js is contained within the [TypeScript declaration file](
|
||||
|
||||
Note that some APIs are marked *experimental*, these are added to enable experimentation with new ideas without committing to support it like a normal [semver](https://semver.org/) API. Note that these APIs can change radically between versions, so be sure to read release notes if you plan on using experimental APIs.
|
||||
|
||||
## Releases
|
||||
|
||||
Xterm.js follows a monthly release cycle roughly.
|
||||
|
||||
All current and past releases are available on this repo's [Releases page](https://github.com/sourcelair/xterm.js/releases), you can view the [high-level roadmap on the wiki](https://github.com/xtermjs/xterm.js/wiki/Roadmap) and see what we're working on now by looking through [Milestones](https://github.com/sourcelair/xterm.js/milestones).
|
||||
|
||||
### Beta builds
|
||||
|
||||
Our CI releases beta builds to npm for every change that goes into master. Install the latest beta build with:
|
||||
|
||||
```bash
|
||||
npm install -S xterm@beta
|
||||
```
|
||||
|
||||
These should generally be stable, but some bugs may slip in. We recommend using the beta build primarily to test out new features and to verify bug fixes.
|
||||
|
||||
## Contributing
|
||||
|
||||
You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Contributing) to learn how to contribute and set up xterm.js for development.
|
||||
|
||||
## Real-world uses
|
||||
Xterm.js is used in several world-class applications to provide great terminal experiences.
|
||||
|
||||
@@ -197,26 +217,6 @@ Xterm.js is used in several world-class applications to provide great terminal e
|
||||
|
||||
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.
|
||||
|
||||
## Releases
|
||||
|
||||
Xterm.js follows a monthly release cycle roughly.
|
||||
|
||||
All current and past releases are available on this repo's [Releases page](https://github.com/sourcelair/xterm.js/releases), you can view the [high-level roadmap on the wiki](https://github.com/xtermjs/xterm.js/wiki/Roadmap) and see what we're working on now by looking through [Milestones](https://github.com/sourcelair/xterm.js/milestones).
|
||||
|
||||
### Beta builds
|
||||
|
||||
Our CI releases beta builds to npm for every change that goes into master. Install the latest beta build with:
|
||||
|
||||
```bash
|
||||
npm install -S xterm@beta
|
||||
```
|
||||
|
||||
These should generally be stable, but some bugs may slip in. We recommend using the beta build primarily to test out new features and to verify bug fixes.
|
||||
|
||||
## Contributing
|
||||
|
||||
You can read the [guide on the wiki](https://github.com/xtermjs/xterm.js/wiki/Contributing) to learn how to contribute and set up xterm.js for development.
|
||||
|
||||
## License Agreement
|
||||
|
||||
If you contribute code to this project, you implicitly allow your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-attach",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-canvas",
|
||||
"version": "0.1.0",
|
||||
"version": "0.2.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-fit",
|
||||
"version": "0.5.0",
|
||||
"version": "0.6.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-ligatures",
|
||||
"version": "0.5.3",
|
||||
"version": "0.6.0",
|
||||
"description": "Add support for programming ligatures to xterm.js",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-search",
|
||||
"version": "0.9.0",
|
||||
"version": "0.10.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-serialize",
|
||||
"version": "0.7.0",
|
||||
"version": "0.8.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -78,7 +78,7 @@ describe('xterm-addon-serialize', () => {
|
||||
terminal.loadAddon(serializeAddon);
|
||||
|
||||
selectionService = new TestSelectionService((terminal as any)._core._bufferService);
|
||||
cm = new ColorManager(document, false);
|
||||
cm = new ColorManager();
|
||||
(terminal as any)._core._colorManager = cm;
|
||||
(terminal as any)._core._selectionService = selectionService;
|
||||
});
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-unicode11",
|
||||
"version": "0.3.0",
|
||||
"version": "0.4.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-web-links",
|
||||
"version": "0.6.0",
|
||||
"version": "0.7.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "xterm-addon-webgl",
|
||||
"version": "0.12.0",
|
||||
"version": "0.13.0",
|
||||
"author": {
|
||||
"name": "The xterm.js authors",
|
||||
"url": "https://xtermjs.org/"
|
||||
|
||||
@@ -16,6 +16,7 @@ import { tryDrawCustomChar } from 'browser/renderer/CustomGlyphs';
|
||||
import { excludeFromContrastRatioDemands, isPowerlineGlyph, isRestrictedPowerlineGlyph } from 'browser/renderer/RendererUtils';
|
||||
import { IUnicodeService } from 'common/services/Services';
|
||||
import { FourKeyMap } from 'common/MultiKeyMap';
|
||||
import { IdleTaskQueue } from 'common/TaskQueue';
|
||||
|
||||
// For debugging purposes, it can be useful to set this to a really tiny value,
|
||||
// to verify that LRU eviction works.
|
||||
@@ -110,7 +111,10 @@ export class WebglCharAtlas implements IDisposable {
|
||||
this._tmpCanvas = document.createElement('canvas');
|
||||
this._tmpCanvas.width = this._config.scaledCellWidth * 4 + TMP_CANVAS_GLYPH_PADDING * 2;
|
||||
this._tmpCanvas.height = this._config.scaledCellHeight + TMP_CANVAS_GLYPH_PADDING * 2;
|
||||
this._tmpCtx = throwIfFalsy(this._tmpCanvas.getContext('2d', { alpha: this._config.allowTransparency }));
|
||||
this._tmpCtx = throwIfFalsy(this._tmpCanvas.getContext('2d', {
|
||||
alpha: this._config.allowTransparency,
|
||||
willReadFrequently: true
|
||||
}));
|
||||
}
|
||||
|
||||
public dispose(): void {
|
||||
@@ -127,10 +131,15 @@ export class WebglCharAtlas implements IDisposable {
|
||||
}
|
||||
|
||||
private _doWarmUp(): void {
|
||||
// Pre-fill with ASCII 33-126
|
||||
// Pre-fill with ASCII 33-126, this is not urgent and done in idle callbacks
|
||||
const queue = new IdleTaskQueue();
|
||||
for (let i = 33; i < 126; i++) {
|
||||
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT);
|
||||
this._cacheMap.set(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT, rasterizedGlyph);
|
||||
queue.enqueue(() => {
|
||||
if (!this._cacheMap.get(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT)) {
|
||||
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT);
|
||||
this._cacheMap.set(i, DEFAULT_COLOR, DEFAULT_COLOR, DEFAULT_EXT, rasterizedGlyph);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+2
-7
@@ -98,13 +98,8 @@ function getNextBetaVersion(packageJson) {
|
||||
process.exit(1);
|
||||
}
|
||||
const tag = 'beta';
|
||||
let nextStableVersion;
|
||||
if (packageJson.name === 'xterm') {
|
||||
nextStableVersion = `5.0.0`;
|
||||
} else {
|
||||
const stableVersion = packageJson.version.split('.');
|
||||
nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.0`;
|
||||
}
|
||||
const stableVersion = packageJson.version.split('.');
|
||||
const nextStableVersion = `${stableVersion[0]}.${parseInt(stableVersion[1]) + 1}.0`;
|
||||
const publishedVersions = getPublishedVersions(packageJson, nextStableVersion, tag);
|
||||
if (publishedVersions.length === 0) {
|
||||
return `${nextStableVersion}-${tag}.1`;
|
||||
|
||||
+2
-2
@@ -86,7 +86,7 @@ function startServer() {
|
||||
return (data) => {
|
||||
s += data;
|
||||
if (!sender) {
|
||||
sender = setTimeout(() => {
|
||||
sender = queueMicrotask(() => {
|
||||
socket.send(s);
|
||||
s = '';
|
||||
sender = null;
|
||||
@@ -103,7 +103,7 @@ function startServer() {
|
||||
buffer.push(data);
|
||||
length += data.length;
|
||||
if (!sender) {
|
||||
sender = setTimeout(() => {
|
||||
sender = queueMicrotask(() => {
|
||||
socket.send(Buffer.concat(buffer, length));
|
||||
buffer = [];
|
||||
sender = null;
|
||||
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "xterm",
|
||||
"description": "Full xterm terminal, in your browser",
|
||||
"version": "4.19.0",
|
||||
"version": "5.0.0",
|
||||
"main": "lib/xterm.js",
|
||||
"style": "css/xterm.css",
|
||||
"types": "typings/xterm.d.ts",
|
||||
|
||||
@@ -28,7 +28,7 @@ describe('ColorManager', () => {
|
||||
return {data: [0, 0, 0, 0xFF]};
|
||||
}
|
||||
});
|
||||
cm = new ColorManager(document, false);
|
||||
cm = new ColorManager();
|
||||
});
|
||||
|
||||
describe('constructor', () => {
|
||||
|
||||
+14
-81
@@ -80,22 +80,11 @@ export const DEFAULT_ANSI_COLORS = Object.freeze((() => {
|
||||
*/
|
||||
export class ColorManager implements IColorManager {
|
||||
public colors: IColorSet;
|
||||
private _ctx: CanvasRenderingContext2D;
|
||||
private _litmusColor: CanvasGradient;
|
||||
|
||||
private _contrastCache: IColorContrastCache;
|
||||
private _restoreColors!: IRestoreColorSet;
|
||||
|
||||
constructor(document: Document, public allowTransparency: boolean) {
|
||||
const canvas = document.createElement('canvas');
|
||||
canvas.width = 1;
|
||||
canvas.height = 1;
|
||||
const ctx = canvas.getContext('2d');
|
||||
if (!ctx) {
|
||||
throw new Error('Could not get rendering context');
|
||||
}
|
||||
this._ctx = ctx;
|
||||
this._ctx.globalCompositeOperation = 'copy';
|
||||
this._litmusColor = this._ctx.createLinearGradient(0, 0, 1, 1);
|
||||
constructor() {
|
||||
this._contrastCache = new ColorContrastCache();
|
||||
this.colors = {
|
||||
foreground: DEFAULT_FOREGROUND,
|
||||
@@ -118,9 +107,6 @@ export class ColorManager implements IColorManager {
|
||||
case 'minimumContrastRatio':
|
||||
this._contrastCache.clear();
|
||||
break;
|
||||
case 'allowTransparency':
|
||||
this.allowTransparency = value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,11 +118,11 @@ export class ColorManager implements IColorManager {
|
||||
public setTheme(theme: ITheme = {}): void {
|
||||
this.colors.foreground = this._parseColor(theme.foreground, DEFAULT_FOREGROUND);
|
||||
this.colors.background = this._parseColor(theme.background, DEFAULT_BACKGROUND);
|
||||
this.colors.cursor = this._parseColor(theme.cursor, DEFAULT_CURSOR, true);
|
||||
this.colors.cursorAccent = this._parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT, true);
|
||||
this.colors.selectionBackgroundTransparent = this._parseColor(theme.selectionBackground, DEFAULT_SELECTION, true);
|
||||
this.colors.cursor = this._parseColor(theme.cursor, DEFAULT_CURSOR);
|
||||
this.colors.cursorAccent = this._parseColor(theme.cursorAccent, DEFAULT_CURSOR_ACCENT);
|
||||
this.colors.selectionBackgroundTransparent = this._parseColor(theme.selectionBackground, DEFAULT_SELECTION);
|
||||
this.colors.selectionBackgroundOpaque = color.blend(this.colors.background, this.colors.selectionBackgroundTransparent);
|
||||
this.colors.selectionInactiveBackgroundTransparent = this._parseColor(theme.selectionInactiveBackground, this.colors.selectionBackgroundTransparent, true);
|
||||
this.colors.selectionInactiveBackgroundTransparent = this._parseColor(theme.selectionInactiveBackground, this.colors.selectionBackgroundTransparent);
|
||||
this.colors.selectionInactiveBackgroundOpaque = color.blend(this.colors.background, this.colors.selectionInactiveBackgroundTransparent);
|
||||
const nullColor: IColor = {
|
||||
css: '',
|
||||
@@ -220,69 +206,16 @@ export class ColorManager implements IColorManager {
|
||||
}
|
||||
|
||||
private _parseColor(
|
||||
css: string | undefined,
|
||||
fallback: IColor,
|
||||
allowTransparency: boolean = this.allowTransparency
|
||||
cssString: string | undefined,
|
||||
fallback: IColor
|
||||
): IColor {
|
||||
if (css === undefined) {
|
||||
return fallback;
|
||||
}
|
||||
|
||||
// If parsing the value results in failure, then it must be ignored, and the attribute must
|
||||
// retain its previous value.
|
||||
// -- https://html.spec.whatwg.org/multipage/canvas.html#fill-and-stroke-styles
|
||||
this._ctx.fillStyle = this._litmusColor;
|
||||
this._ctx.fillStyle = css;
|
||||
if (typeof this._ctx.fillStyle !== 'string') {
|
||||
console.warn(`Color: ${css} is invalid using fallback ${fallback.css}`);
|
||||
return fallback;
|
||||
}
|
||||
|
||||
this._ctx.fillRect(0, 0, 1, 1);
|
||||
const data = this._ctx.getImageData(0, 0, 1, 1).data;
|
||||
|
||||
// Check if the printed color was transparent
|
||||
if (data[3] !== 0xFF) {
|
||||
if (!allowTransparency) {
|
||||
// Ideally we'd just ignore the alpha channel, but...
|
||||
//
|
||||
// Browsers may not give back exactly the same RGB values we put in, because most/all
|
||||
// convert the color to a pre-multiplied representation. getImageData converts that back to
|
||||
// a un-premultipled representation, but the precision loss may make the RGB channels unuable
|
||||
// on their own.
|
||||
//
|
||||
// E.g. In Chrome #12345610 turns into #10305010, and in the extreme case, 0xFFFFFF00 turns
|
||||
// into 0x00000000.
|
||||
//
|
||||
// "Note: Due to the lossy nature of converting to and from premultiplied alpha color values,
|
||||
// pixels that have just been set using putImageData() might be returned to an equivalent
|
||||
// getImageData() as different values."
|
||||
// -- https://html.spec.whatwg.org/multipage/canvas.html#pixel-manipulation
|
||||
//
|
||||
// So let's just use the fallback color in this case instead.
|
||||
console.warn(
|
||||
`Color: ${css} is using transparency, but allowTransparency is false. ` +
|
||||
`Using fallback ${fallback.css}.`
|
||||
);
|
||||
return fallback;
|
||||
if (cssString !== undefined) {
|
||||
try {
|
||||
return css.toColor(cssString);
|
||||
} catch {
|
||||
// no-op
|
||||
}
|
||||
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
|
||||
// the color value has alpha less than 1.0, and the string is the color value in the CSS rgba()
|
||||
const [r, g, b, a] = this._ctx.fillStyle.substring(5, this._ctx.fillStyle.length - 1).split(',').map(component => Number(component));
|
||||
const alpha = Math.round(a * 255);
|
||||
const rgba: number = channels.toRgba(r, g, b, alpha);
|
||||
return {
|
||||
rgba,
|
||||
css
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
// https://html.spec.whatwg.org/multipage/canvas.html#serialisation-of-a-color
|
||||
// if it has alpha equal to 1.0, then the string is a lowercase six-digit hex value, prefixed with a "#" character
|
||||
css: this._ctx.fillStyle,
|
||||
rgba: channels.toRgba(data[0], data[1], data[2], data[3])
|
||||
};
|
||||
return fallback;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,7 +502,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
|
||||
this._instantiationService.setService(ICharSizeService, this._charSizeService);
|
||||
|
||||
this._theme = this.options.theme || this._theme;
|
||||
this._colorManager = new ColorManager(document, this.options.allowTransparency);
|
||||
this._colorManager = new ColorManager();
|
||||
this.register(this.optionsService.onOptionChange(e => this._colorManager!.onOptionsChange(e, this.optionsService.rawOptions[e])));
|
||||
this._colorManager.setTheme(this._theme);
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ export const blockElementDefinitions: { [index: string]: IBlockVector[] | undefi
|
||||
'▐': [{ x: 4, y: 0, w: 4, h: 8 }], // RIGHT HALF BLOCK
|
||||
|
||||
// Block elements (0x2594-0x2595)
|
||||
'▔': [{ x: 0, y: 0, w: 9, h: 1 }], // UPPER ONE EIGHTH BLOCK
|
||||
'▔': [{ x: 0, y: 0, w: 8, h: 1 }], // UPPER ONE EIGHTH BLOCK
|
||||
'▕': [{ x: 7, y: 0, w: 1, h: 8 }], // RIGHT ONE EIGHTH BLOCK
|
||||
|
||||
// Terminal graphic characters (0x2596-0x259F)
|
||||
|
||||
@@ -166,7 +166,7 @@ export class DomRendererRowFactory {
|
||||
if (cell.isUnderline()) {
|
||||
charElement.classList.add(`${UNDERLINE_CLASS}-${cell.extended.underlineStyle}`);
|
||||
if (charElement.textContent === ' ') {
|
||||
charElement.innerHTML = ' ';
|
||||
charElement.textContent = '\xa0'; // =
|
||||
}
|
||||
if (!cell.isUnderlineColorDefault()) {
|
||||
if (cell.isUnderlineColorRGB()) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user