New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

xterm-addon-serialize

Package Overview
Dependencies
Maintainers
1
Versions
134
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

xterm-addon-serialize - npm Package Compare versions

Comparing version

to
0.5.0-beta.6

2

lib/xterm-addon-serialize.js

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.SerializeAddon=t():e.SerializeAddon=t()}(window,(function(){return function(e){var t={};function i(n){if(t[n])return t[n].exports;var r=t[n]={i:n,l:!1,exports:{}};return e[n].call(r.exports,r,r.exports,i),r.l=!0,r.exports}return i.m=e,i.c=t,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="",i(i.s=0)}([function(e,t,i){"use strict";var n,r=this&&this.__extends||(n=function(e,t){return(n=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(e,t){e.__proto__=t}||function(e,t){for(var i in t)Object.prototype.hasOwnProperty.call(t,i)&&(e[i]=t[i])})(e,t)},function(e,t){function i(){this.constructor=e}n(e,t),e.prototype=null===t?Object.create(t):(i.prototype=t.prototype,new i)});Object.defineProperty(t,"__esModule",{value:!0}),t.SerializeAddon=void 0;var o=function(e){function t(t){var i=e.call(this,t)||this;return i._rowIndex=0,i._allRows=new Array,i._currentRow="",i._nullCellCount=0,i}return r(t,e),t.prototype._beforeSerialize=function(e){this._allRows=new Array(e)},t.prototype._rowEnd=function(e){this._allRows[this._rowIndex++]=this._currentRow,this._currentRow="",this._nullCellCount=0},t.prototype._nextCell=function(e,t,i,n){var r,o,l=[],s=(o=t,!((r=e).getFgColorMode()===o.getFgColorMode()&&r.getFgColor()===o.getFgColor())),u=!function(e,t){return e.getBgColorMode()===t.getBgColorMode()&&e.getBgColor()===t.getBgColor()}(e,t),a=!function(e,t){return e.isInverse()===t.isInverse()&&e.isBold()===t.isBold()&&e.isUnderline()===t.isUnderline()&&e.isBlink()===t.isBlink()&&e.isInvisible()===t.isInvisible()&&e.isItalic()===t.isItalic()&&e.isDim()===t.isDim()}(e,t);if(s||u||a)if(e.isAttributeDefault())this._currentRow+="";else{if(s){var f=e.getFgColor();e.isFgRGB()?l.push(38,2,f>>>16&255,f>>>8&255,255&f):e.isFgPalette()?f>=16?l.push(38,5,f):l.push(8&f?90+(7&f):30+(7&f)):l.push(39)}if(u){f=e.getBgColor();e.isBgRGB()?l.push(48,2,f>>>16&255,f>>>8&255,255&f):e.isBgPalette()?f>=16?l.push(48,5,f):l.push(8&f?100+(7&f):40+(7&f)):l.push(49)}a&&(e.isInverse()!==t.isInverse()&&l.push(e.isInverse()?7:27),e.isBold()!==t.isBold()&&l.push(e.isBold()?1:22),e.isUnderline()!==t.isUnderline()&&l.push(e.isUnderline()?4:24),e.isBlink()!==t.isBlink()&&l.push(e.isBlink()?5:25),e.isInvisible()!==t.isInvisible()&&l.push(e.isInvisible()?8:28),e.isItalic()!==t.isItalic()&&l.push(e.isItalic()?3:23),e.isDim()!==t.isDim()&&l.push(e.isDim()?2:22))}l.length&&(this._currentRow+="["+l.join(";")+"m"),""===e.getChars()?this._nullCellCount+=e.getWidth():this._nullCellCount>0&&(this._currentRow+="["+this._nullCellCount+"C",this._nullCellCount=0),this._currentRow+=e.getChars()},t.prototype._serializeString=function(){for(var e=this._allRows.length;e>0&&!this._allRows[e-1];e--);return this._allRows.slice(0,e).join("\r\n")},t}(function(){function e(e){this._buffer=e}return e.prototype.serialize=function(e,t){var i=this._buffer.getNullCell(),n=this._buffer.getNullCell(),r=i;this._beforeSerialize(t-e);for(var o=e;o<t;o++){var l=this._buffer.getLine(o);if(l)for(var s=0;s<l.length;s++){var u=l.getCell(s,r===i?n:i);u?(this._nextCell(u,r,o,s),r=u):console.warn("Can't get cell at row="+o+", col="+s)}this._rowEnd(o)}return this._afterSerialize(),this._serializeString()},e.prototype._nextCell=function(e,t,i,n){},e.prototype._rowEnd=function(e){},e.prototype._beforeSerialize=function(e){},e.prototype._afterSerialize=function(){},e.prototype._serializeString=function(){return""},e}()),l=function(){function e(){}return e.prototype.activate=function(e){this._terminal=e},e.prototype.serialize=function(e){if(!this._terminal)throw new Error("Cannot use addon until it has been loaded");var t,i,n,r=this._terminal.buffer.active.length,l=new o(this._terminal.buffer.active);return e=void 0===e?r:(t=e,i=0,n=r,Math.max(i,Math.min(t,n))),l.serialize(r-e,r)},e.prototype.dispose=function(){},e}();t.SerializeAddon=l}])}));
!function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.SerializeAddon=e():t.SerializeAddon=e()}(self,(function(){return(()=>{"use strict";var t={44:function(t,e){var r,i=this&&this.__extends||(r=function(t,e){return(r=Object.setPrototypeOf||{__proto__:[]}instanceof Array&&function(t,e){t.__proto__=e}||function(t,e){for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r])})(t,e)},function(t,e){function i(){this.constructor=t}r(t,e),t.prototype=null===e?Object.create(e):(i.prototype=e.prototype,new i)});function s(t,e){return t.getBgColorMode()===e.getBgColorMode()&&t.getBgColor()===e.getBgColor()}Object.defineProperty(e,"__esModule",{value:!0}),e.SerializeAddon=void 0;var o=function(t){function e(e,r){var i=t.call(this,e)||this;return i._buffer1=e,i._terminal=r,i._rowIndex=0,i._allRows=new Array,i._allRowSeparators=new Array,i._currentRow="",i._nullCellCount=0,i._cursorStyle=i._buffer1.getNullCell(),i._cursorStyleRow=0,i._cursorStyleCol=0,i._backgroundCell=i._buffer1.getNullCell(),i._firstRow=0,i._lastCursorRow=0,i._lastCursorCol=0,i._lastContentCursorRow=0,i._lastContentCursorCol=0,i._thisRowLastChar=i._buffer1.getNullCell(),i._thisRowLastSecondChar=i._buffer1.getNullCell(),i._nextRowFirstChar=i._buffer1.getNullCell(),i}return i(e,t),e.prototype._beforeSerialize=function(t,e,r){this._allRows=new Array(t),this._lastContentCursorRow=e,this._lastCursorRow=e,this._firstRow=e},e.prototype._rowEnd=function(t,e){var r;this._nullCellCount>0&&!s(this._cursorStyle,this._backgroundCell)&&(this._currentRow+="["+this._nullCellCount+"X");var i="";if(!e){t-this._firstRow>=this._terminal.rows&&(null===(r=this._buffer1.getLine(this._cursorStyleRow))||void 0===r||r.getCell(this._cursorStyleCol,this._backgroundCell));var o=this._buffer1.getLine(t),l=this._buffer1.getLine(t+1);if(l.isWrapped){i="";var n=o.getCell(o.length-1,this._thisRowLastChar),u=o.getCell(o.length-2,this._thisRowLastSecondChar),h=l.getCell(0,this._nextRowFirstChar),_=h.getWidth()>1,a=!1;(h.getChars()&&_?this._nullCellCount<=1:this._nullCellCount<=0)&&((n.getChars()||0===n.getWidth())&&s(n,h)&&(a=!0),_&&(u.getChars()||0===u.getWidth())&&s(n,h)&&s(u,h)&&(a=!0)),a||(i="-".repeat(this._nullCellCount+1),i+="",this._nullCellCount>0&&(i+="",i+="["+(o.length-this._nullCellCount)+"C",i+="["+this._nullCellCount+"X",i+="["+(o.length-this._nullCellCount)+"D",i+=""),this._lastContentCursorRow=t+1,this._lastContentCursorCol=0,this._lastCursorRow=t+1,this._lastCursorCol=0)}else i="\r\n",this._lastCursorRow=t+1,this._lastCursorCol=0}this._allRows[this._rowIndex]=this._currentRow,this._allRowSeparators[this._rowIndex++]=i,this._currentRow="",this._nullCellCount=0},e.prototype._diffStyle=function(t,e){var r,i,o=[],l=(i=e,!((r=t).getFgColorMode()===i.getFgColorMode()&&r.getFgColor()===i.getFgColor())),n=!s(t,e),u=!function(t,e){return t.isInverse()===e.isInverse()&&t.isBold()===e.isBold()&&t.isUnderline()===e.isUnderline()&&t.isBlink()===e.isBlink()&&t.isInvisible()===e.isInvisible()&&t.isItalic()===e.isItalic()&&t.isDim()===e.isDim()}(t,e);if(l||n||u)if(t.isAttributeDefault())e.isAttributeDefault()||o.push(0);else{if(l){var h=t.getFgColor();t.isFgRGB()?o.push(38,2,h>>>16&255,h>>>8&255,255&h):t.isFgPalette()?h>=16?o.push(38,5,h):o.push(8&h?90+(7&h):30+(7&h)):o.push(39)}n&&(h=t.getBgColor(),t.isBgRGB()?o.push(48,2,h>>>16&255,h>>>8&255,255&h):t.isBgPalette()?h>=16?o.push(48,5,h):o.push(8&h?100+(7&h):40+(7&h)):o.push(49)),u&&(t.isInverse()!==e.isInverse()&&o.push(t.isInverse()?7:27),t.isBold()!==e.isBold()&&o.push(t.isBold()?1:22),t.isUnderline()!==e.isUnderline()&&o.push(t.isUnderline()?4:24),t.isBlink()!==e.isBlink()&&o.push(t.isBlink()?5:25),t.isInvisible()!==e.isInvisible()&&o.push(t.isInvisible()?8:28),t.isItalic()!==e.isItalic()&&o.push(t.isItalic()?3:23),t.isDim()!==e.isDim()&&o.push(t.isDim()?2:22))}return o},e.prototype._nextCell=function(t,e,r,i){if(0!==t.getWidth()){var o=""===t.getChars(),l=this._diffStyle(t,this._cursorStyle);if(o?!s(this._cursorStyle,t):l.length>0){this._nullCellCount>0&&(s(this._cursorStyle,this._backgroundCell)||(this._currentRow+="["+this._nullCellCount+"X"),this._currentRow+="["+this._nullCellCount+"C",this._nullCellCount=0),this._lastContentCursorRow=this._lastCursorRow=r,this._lastContentCursorCol=this._lastCursorCol=i,this._currentRow+="["+l.join(";")+"m";var n=this._buffer1.getLine(r);void 0!==n&&(n.getCell(i,this._cursorStyle),this._cursorStyleRow=r,this._cursorStyleCol=i)}o?this._nullCellCount+=t.getWidth():(this._nullCellCount>0&&(s(this._cursorStyle,this._backgroundCell)||(this._currentRow+="["+this._nullCellCount+"X"),this._currentRow+="["+this._nullCellCount+"C",this._nullCellCount=0),this._currentRow+=t.getChars(),this._lastContentCursorRow=this._lastCursorRow=r,this._lastContentCursorCol=this._lastCursorCol=i+t.getWidth())}},e.prototype._serializeString=function(){var t=this._allRows.length;this._buffer1.length-this._firstRow<=this._terminal.rows&&(t=this._lastContentCursorRow+1-this._firstRow,this._lastCursorCol=this._lastContentCursorCol,this._lastCursorRow=this._lastContentCursorRow);for(var e="",r=0;r<t;r++)e+=this._allRows[r],r+1<t&&(e+=this._allRowSeparators[r]);var i,s=this._buffer1.baseY+this._buffer1.cursorY,o=this._buffer1.cursorX;return(s!==this._lastCursorRow||o!==this._lastCursorCol)&&((i=s-this._lastCursorRow)>0?e+="["+i+"B":i<0&&(e+="["+-i+"A"),function(t){t>0?e+="["+t+"C":t<0&&(e+="["+-t+"D")}(o-this._lastCursorCol)),e},e}(function(){function t(t){this._buffer=t}return t.prototype.serialize=function(t,e){var r=this._buffer.getNullCell(),i=this._buffer.getNullCell(),s=r;this._beforeSerialize(e-t,t,e);for(var o=t;o<e;o++){var l=this._buffer.getLine(o);if(l)for(var n=0;n<l.length;n++){var u=l.getCell(n,s===r?i:r);u?(this._nextCell(u,s,o,n),s=u):console.warn("Can't get cell at row="+o+", col="+n)}this._rowEnd(o,o===e-1)}return this._afterSerialize(),this._serializeString()},t.prototype._nextCell=function(t,e,r,i){},t.prototype._rowEnd=function(t,e){},t.prototype._beforeSerialize=function(t,e,r){},t.prototype._afterSerialize=function(){},t.prototype._serializeString=function(){return""},t}()),l=function(){function t(){}return t.prototype.activate=function(t){this._terminal=t},t.prototype._getString=function(t,e){var r,i,s=t.length,l=new o(t,this._terminal),n=void 0===e?s:(r=e+this._terminal.rows,0,i=s,Math.max(0,Math.min(r,i)));return l.serialize(s-n,s)},t.prototype.serialize=function(t){if(!this._terminal)throw new Error("Cannot use addon until it has been loaded");return"normal"===this._terminal.buffer.active.type?this._getString(this._terminal.buffer.active,t):this._getString(this._terminal.buffer.normal,t)+"[?1049h"+this._getString(this._terminal.buffer.alternate,void 0)},t.prototype.dispose=function(){},t}();e.SerializeAddon=l}},e={};return function r(i){if(e[i])return e[i].exports;var s=e[i]={exports:{}};return t[i].call(s.exports,s,s.exports,r),s.exports}(44)})()}));
//# sourceMappingURL=xterm-addon-serialize.js.map

@@ -23,3 +23,3 @@ "use strict";

let oldCell = cell1;
this._beforeSerialize(endRow - startRow);
this._beforeSerialize(endRow - startRow, startRow, endRow);
for (let row = startRow; row < endRow; row++) {

@@ -38,3 +38,3 @@ const line = this._buffer.getLine(row);

}
this._rowEnd(row);
this._rowEnd(row, row === endRow - 1);
}

@@ -45,4 +45,4 @@ this._afterSerialize();

_nextCell(cell, oldCell, row, col) { }
_rowEnd(row) { }
_beforeSerialize(rows) { }
_rowEnd(row, isLastRow) { }
_beforeSerialize(rows, startRow, endRow) { }
_afterSerialize() { }

@@ -69,18 +69,126 @@ _serializeString() { return ''; }

class StringSerializeHandler extends BaseSerializeHandler {
constructor(buffer) {
super(buffer);
constructor(_buffer1, _terminal) {
super(_buffer1);
this._buffer1 = _buffer1;
this._terminal = _terminal;
this._rowIndex = 0;
this._allRows = new Array();
this._allRowSeparators = new Array();
this._currentRow = '';
this._nullCellCount = 0;
// we can see a full colored cell and a null cell that only have background the same style
// but the information isn't preserved by null cell itself
// so wee need to record it when required.
this._cursorStyle = this._buffer1.getNullCell();
// where exact the cursor styles comes from
// because we can't copy the cell directly
// so we remember where the content comes from instead
this._cursorStyleRow = 0;
this._cursorStyleCol = 0;
// this is a null cell for reference for checking whether background is empty or not
this._backgroundCell = this._buffer1.getNullCell();
this._firstRow = 0;
this._lastCursorRow = 0;
this._lastCursorCol = 0;
this._lastContentCursorRow = 0;
this._lastContentCursorCol = 0;
this._thisRowLastChar = this._buffer1.getNullCell();
this._thisRowLastSecondChar = this._buffer1.getNullCell();
this._nextRowFirstChar = this._buffer1.getNullCell();
}
_beforeSerialize(rows) {
_beforeSerialize(rows, start, end) {
this._allRows = new Array(rows);
this._lastContentCursorRow = start;
this._lastCursorRow = start;
this._firstRow = start;
}
_rowEnd(row) {
this._allRows[this._rowIndex++] = this._currentRow;
_rowEnd(row, isLastRow) {
var _a;
// if there is colorful empty cell at line end, whe must pad it back, or the the color block will missing
if (this._nullCellCount > 0 && !equalBg(this._cursorStyle, this._backgroundCell)) {
// use clear right to set background.
this._currentRow += `\x1b[${this._nullCellCount}X`;
}
let rowSeparator = '';
// handle row separator
if (!isLastRow) {
// Enable BCE
if (row - this._firstRow >= this._terminal.rows) {
(_a = this._buffer1.getLine(this._cursorStyleRow)) === null || _a === void 0 ? void 0 : _a.getCell(this._cursorStyleCol, this._backgroundCell);
}
// Fetch current line
const currentLine = this._buffer1.getLine(row);
// Fetch next line
const nextLine = this._buffer1.getLine(row + 1);
if (!nextLine.isWrapped) {
// just insert the line break
rowSeparator = '\r\n';
// we sended the enter
this._lastCursorRow = row + 1;
this._lastCursorCol = 0;
}
else {
rowSeparator = '';
const thisRowLastChar = currentLine.getCell(currentLine.length - 1, this._thisRowLastChar);
const thisRowLastSecondChar = currentLine.getCell(currentLine.length - 2, this._thisRowLastSecondChar);
const nextRowFirstChar = nextLine.getCell(0, this._nextRowFirstChar);
const isNextRowFirstCharDoubleWidth = nextRowFirstChar.getWidth() > 1;
// validate whether this line wrap is ever possible
// which mean whether cursor can placed at a overflow position (x === row) naturally
let isValid = false;
if (
// you must output character to cause overflow, control sequence can't do this
nextRowFirstChar.getChars() &&
isNextRowFirstCharDoubleWidth ? this._nullCellCount <= 1 : this._nullCellCount <= 0) {
if (
// the last character can't be null,
// you can't use control sequence to move cursor to (x === row)
(thisRowLastChar.getChars() || thisRowLastChar.getWidth() === 0) &&
// change background of the first wrapped cell also affects BCE
// so we mark it as invalid to simply the process to determine line separator
equalBg(thisRowLastChar, nextRowFirstChar)) {
isValid = true;
}
if (
// the second to last character can't be null if the next line starts with CJK,
// you can't use control sequence to move cursor to (x === row)
isNextRowFirstCharDoubleWidth &&
(thisRowLastSecondChar.getChars() || thisRowLastSecondChar.getWidth() === 0) &&
// change background of the first wrapped cell also affects BCE
// so we mark it as invalid to simply the process to determine line separator
equalBg(thisRowLastChar, nextRowFirstChar) &&
equalBg(thisRowLastSecondChar, nextRowFirstChar)) {
isValid = true;
}
}
if (!isValid) {
// force the wrap with magic
// insert enough character to force the wrap
rowSeparator = '-'.repeat(this._nullCellCount + 1);
// move back and erase next line head
rowSeparator += '\x1b[1D\x1b[1X';
if (this._nullCellCount > 0) {
// do these because we filled the last several null slot, which we shouldn't
rowSeparator += '\x1b[A';
rowSeparator += `\x1b[${currentLine.length - this._nullCellCount}C`;
rowSeparator += `\x1b[${this._nullCellCount}X`;
rowSeparator += `\x1b[${currentLine.length - this._nullCellCount}D`;
rowSeparator += '\x1b[B';
}
// This is content and need the be serialized even it is invisible.
// without this, wrap will be missing from outputs.
this._lastContentCursorRow = row + 1;
this._lastContentCursorCol = 0;
// force commit the cursor position
this._lastCursorRow = row + 1;
this._lastCursorCol = 0;
}
}
}
this._allRows[this._rowIndex] = this._currentRow;
this._allRowSeparators[this._rowIndex++] = rowSeparator;
this._currentRow = '';
this._nullCellCount = 0;
}
_nextCell(cell, oldCell, row, col) {
_diffStyle(cell, oldCell) {
const sgrSeq = [];

@@ -92,3 +200,5 @@ const fgChanged = !equalFg(cell, oldCell);

if (cell.isAttributeDefault()) {
this._currentRow += '\x1b[0m';
if (!oldCell.isAttributeDefault()) {
sgrSeq.push(0);
}
}

@@ -155,24 +265,107 @@ else {

}
if (sgrSeq.length) {
return sgrSeq;
}
_nextCell(cell, oldCell, row, col) {
// a width 0 cell don't need to be count because it is just a placeholder after a CJK character;
const isPlaceHolderCell = cell.getWidth() === 0;
if (isPlaceHolderCell) {
return;
}
// this cell don't have content
const isEmptyCell = cell.getChars() === '';
const sgrSeq = this._diffStyle(cell, this._cursorStyle);
// the empty cell style is only assumed to be changed when background changed, because foreground is always 0.
const styleChanged = isEmptyCell ? !equalBg(this._cursorStyle, cell) : sgrSeq.length > 0;
/**
* handles style change
*/
if (styleChanged) {
// before update the style, we need to fill empty cell back
if (this._nullCellCount > 0) {
// use clear right to set background.
if (!equalBg(this._cursorStyle, this._backgroundCell)) {
this._currentRow += `\x1b[${this._nullCellCount}X`;
}
// use move right to move cursor.
this._currentRow += `\x1b[${this._nullCellCount}C`;
this._nullCellCount = 0;
}
this._lastContentCursorRow = this._lastCursorRow = row;
this._lastContentCursorCol = this._lastCursorCol = col;
this._currentRow += `\x1b[${sgrSeq.join(';')}m`;
// update the last cursor style
const line = this._buffer1.getLine(row);
if (line !== undefined) {
line.getCell(col, this._cursorStyle);
this._cursorStyleRow = row;
this._cursorStyleCol = col;
}
}
// Count number of null cells encountered after the last non-null cell and move the cursor
// if a non-null cell is found (eg. \t or cursor move)
if (cell.getChars() === '') {
/**
* handles actual content
*/
if (isEmptyCell) {
this._nullCellCount += cell.getWidth();
}
else if (this._nullCellCount > 0) {
this._currentRow += `\x1b[${this._nullCellCount}C`;
this._nullCellCount = 0;
else {
if (this._nullCellCount > 0) {
// we can just assume we have same style with previous one here
// because style change is handled by previous stage
// use move right when background is empty, use clear right when there is background.
if (equalBg(this._cursorStyle, this._backgroundCell)) {
this._currentRow += `\x1b[${this._nullCellCount}C`;
}
else {
this._currentRow += `\x1b[${this._nullCellCount}X`;
this._currentRow += `\x1b[${this._nullCellCount}C`;
}
this._nullCellCount = 0;
}
this._currentRow += cell.getChars();
// update cursor
this._lastContentCursorRow = this._lastCursorRow = row;
this._lastContentCursorCol = this._lastCursorCol = col + cell.getWidth();
}
this._currentRow += cell.getChars();
}
_serializeString() {
let rowEnd = this._allRows.length;
for (; rowEnd > 0; rowEnd--) {
if (this._allRows[rowEnd - 1]) {
break;
// the fixup is only required for data without scrollback
// because it will always be placed at last line otherwise
if (this._buffer1.length - this._firstRow <= this._terminal.rows) {
rowEnd = this._lastContentCursorRow + 1 - this._firstRow;
this._lastCursorCol = this._lastContentCursorCol;
this._lastCursorRow = this._lastContentCursorRow;
}
let content = '';
for (let i = 0; i < rowEnd; i++) {
content += this._allRows[i];
if (i + 1 < rowEnd) {
content += this._allRowSeparators[i];
}
}
return this._allRows.slice(0, rowEnd).join('\r\n');
// restore the cursor
const realCursorRow = this._buffer1.baseY + this._buffer1.cursorY;
const realCursorCol = this._buffer1.cursorX;
const cursorMoved = (realCursorRow !== this._lastCursorRow || realCursorCol !== this._lastCursorCol);
const moveRight = (offset) => {
if (offset > 0) {
content += `\u001b[${offset}C`;
}
else if (offset < 0) {
content += `\u001b[${-offset}D`;
}
};
const moveDown = (offset) => {
if (offset > 0) {
content += `\u001b[${offset}B`;
}
else if (offset < 0) {
content += `\u001b[${-offset}A`;
}
};
if (cursorMoved) {
moveDown(realCursorRow - this._lastCursorRow);
moveRight(realCursorCol - this._lastCursorCol);
}
return content;
}

@@ -185,5 +378,10 @@ }

}
serialize(rows) {
// TODO: Add re-position cursor support
// TODO: Add word wrap mode support
_getString(buffer, scrollback) {
const maxRows = buffer.length;
const handler = new StringSerializeHandler(buffer, this._terminal);
const correctRows = (scrollback === undefined) ? maxRows : constrain(scrollback + this._terminal.rows, 0, maxRows);
const result = handler.serialize(maxRows - correctRows, maxRows);
return result;
}
serialize(scrollback) {
// TODO: Add combinedData support

@@ -193,6 +391,11 @@ if (!this._terminal) {

}
const maxRows = this._terminal.buffer.active.length;
const handler = new StringSerializeHandler(this._terminal.buffer.active);
rows = (rows === undefined) ? maxRows : constrain(rows, 0, maxRows);
return handler.serialize(maxRows - rows, maxRows);
if (this._terminal.buffer.active.type === 'normal') {
return this._getString(this._terminal.buffer.active, scrollback);
}
const normalScreenContent = this._getString(this._terminal.buffer.normal, scrollback);
// alt screen don't have scrollback
const alternativeScreenContent = this._getString(this._terminal.buffer.alternate, undefined);
return normalScreenContent
+ '\u001b[?1049h\u001b[H'
+ alternativeScreenContent;
}

@@ -199,0 +402,0 @@ dispose() { }

@@ -28,3 +28,3 @@ "use strict";

var oldCell = cell1;
this._beforeSerialize(endRow - startRow);
this._beforeSerialize(endRow - startRow, startRow, endRow);
for (var row = startRow; row < endRow; row++) {

@@ -43,3 +43,3 @@ var line = this._buffer.getLine(row);

}
this._rowEnd(row);
this._rowEnd(row, row === endRow - 1);
}

@@ -50,4 +50,4 @@ this._afterSerialize();

BaseSerializeHandler.prototype._nextCell = function (cell, oldCell, row, col) { };
BaseSerializeHandler.prototype._rowEnd = function (row) { };
BaseSerializeHandler.prototype._beforeSerialize = function (rows) { };
BaseSerializeHandler.prototype._rowEnd = function (row, isLastRow) { };
BaseSerializeHandler.prototype._beforeSerialize = function (rows, startRow, endRow) { };
BaseSerializeHandler.prototype._afterSerialize = function () { };

@@ -76,19 +76,91 @@ BaseSerializeHandler.prototype._serializeString = function () { return ''; };

__extends(StringSerializeHandler, _super);
function StringSerializeHandler(buffer) {
var _this = _super.call(this, buffer) || this;
function StringSerializeHandler(_buffer1, _terminal) {
var _this = _super.call(this, _buffer1) || this;
_this._buffer1 = _buffer1;
_this._terminal = _terminal;
_this._rowIndex = 0;
_this._allRows = new Array();
_this._allRowSeparators = new Array();
_this._currentRow = '';
_this._nullCellCount = 0;
_this._cursorStyle = _this._buffer1.getNullCell();
_this._cursorStyleRow = 0;
_this._cursorStyleCol = 0;
_this._backgroundCell = _this._buffer1.getNullCell();
_this._firstRow = 0;
_this._lastCursorRow = 0;
_this._lastCursorCol = 0;
_this._lastContentCursorRow = 0;
_this._lastContentCursorCol = 0;
_this._thisRowLastChar = _this._buffer1.getNullCell();
_this._thisRowLastSecondChar = _this._buffer1.getNullCell();
_this._nextRowFirstChar = _this._buffer1.getNullCell();
return _this;
}
StringSerializeHandler.prototype._beforeSerialize = function (rows) {
StringSerializeHandler.prototype._beforeSerialize = function (rows, start, end) {
this._allRows = new Array(rows);
this._lastContentCursorRow = start;
this._lastCursorRow = start;
this._firstRow = start;
};
StringSerializeHandler.prototype._rowEnd = function (row) {
this._allRows[this._rowIndex++] = this._currentRow;
StringSerializeHandler.prototype._rowEnd = function (row, isLastRow) {
var _a;
if (this._nullCellCount > 0 && !equalBg(this._cursorStyle, this._backgroundCell)) {
this._currentRow += "\u001B[" + this._nullCellCount + "X";
}
var rowSeparator = '';
if (!isLastRow) {
if (row - this._firstRow >= this._terminal.rows) {
(_a = this._buffer1.getLine(this._cursorStyleRow)) === null || _a === void 0 ? void 0 : _a.getCell(this._cursorStyleCol, this._backgroundCell);
}
var currentLine = this._buffer1.getLine(row);
var nextLine = this._buffer1.getLine(row + 1);
if (!nextLine.isWrapped) {
rowSeparator = '\r\n';
this._lastCursorRow = row + 1;
this._lastCursorCol = 0;
}
else {
rowSeparator = '';
var thisRowLastChar = currentLine.getCell(currentLine.length - 1, this._thisRowLastChar);
var thisRowLastSecondChar = currentLine.getCell(currentLine.length - 2, this._thisRowLastSecondChar);
var nextRowFirstChar = nextLine.getCell(0, this._nextRowFirstChar);
var isNextRowFirstCharDoubleWidth = nextRowFirstChar.getWidth() > 1;
var isValid = false;
if (nextRowFirstChar.getChars() &&
isNextRowFirstCharDoubleWidth ? this._nullCellCount <= 1 : this._nullCellCount <= 0) {
if ((thisRowLastChar.getChars() || thisRowLastChar.getWidth() === 0) &&
equalBg(thisRowLastChar, nextRowFirstChar)) {
isValid = true;
}
if (isNextRowFirstCharDoubleWidth &&
(thisRowLastSecondChar.getChars() || thisRowLastSecondChar.getWidth() === 0) &&
equalBg(thisRowLastChar, nextRowFirstChar) &&
equalBg(thisRowLastSecondChar, nextRowFirstChar)) {
isValid = true;
}
}
if (!isValid) {
rowSeparator = '-'.repeat(this._nullCellCount + 1);
rowSeparator += '\x1b[1D\x1b[1X';
if (this._nullCellCount > 0) {
rowSeparator += '\x1b[A';
rowSeparator += "\u001B[" + (currentLine.length - this._nullCellCount) + "C";
rowSeparator += "\u001B[" + this._nullCellCount + "X";
rowSeparator += "\u001B[" + (currentLine.length - this._nullCellCount) + "D";
rowSeparator += '\x1b[B';
}
this._lastContentCursorRow = row + 1;
this._lastContentCursorCol = 0;
this._lastCursorRow = row + 1;
this._lastCursorCol = 0;
}
}
}
this._allRows[this._rowIndex] = this._currentRow;
this._allRowSeparators[this._rowIndex++] = rowSeparator;
this._currentRow = '';
this._nullCellCount = 0;
};
StringSerializeHandler.prototype._nextCell = function (cell, oldCell, row, col) {
StringSerializeHandler.prototype._diffStyle = function (cell, oldCell) {
var sgrSeq = [];

@@ -100,3 +172,5 @@ var fgChanged = !equalFg(cell, oldCell);

if (cell.isAttributeDefault()) {
this._currentRow += '\x1b[0m';
if (!oldCell.isAttributeDefault()) {
sgrSeq.push(0);
}
}

@@ -163,22 +237,87 @@ else {

}
if (sgrSeq.length) {
return sgrSeq;
};
StringSerializeHandler.prototype._nextCell = function (cell, oldCell, row, col) {
var isPlaceHolderCell = cell.getWidth() === 0;
if (isPlaceHolderCell) {
return;
}
var isEmptyCell = cell.getChars() === '';
var sgrSeq = this._diffStyle(cell, this._cursorStyle);
var styleChanged = isEmptyCell ? !equalBg(this._cursorStyle, cell) : sgrSeq.length > 0;
if (styleChanged) {
if (this._nullCellCount > 0) {
if (!equalBg(this._cursorStyle, this._backgroundCell)) {
this._currentRow += "\u001B[" + this._nullCellCount + "X";
}
this._currentRow += "\u001B[" + this._nullCellCount + "C";
this._nullCellCount = 0;
}
this._lastContentCursorRow = this._lastCursorRow = row;
this._lastContentCursorCol = this._lastCursorCol = col;
this._currentRow += "\u001B[" + sgrSeq.join(';') + "m";
var line = this._buffer1.getLine(row);
if (line !== undefined) {
line.getCell(col, this._cursorStyle);
this._cursorStyleRow = row;
this._cursorStyleCol = col;
}
}
if (cell.getChars() === '') {
if (isEmptyCell) {
this._nullCellCount += cell.getWidth();
}
else if (this._nullCellCount > 0) {
this._currentRow += "\u001B[" + this._nullCellCount + "C";
this._nullCellCount = 0;
else {
if (this._nullCellCount > 0) {
if (equalBg(this._cursorStyle, this._backgroundCell)) {
this._currentRow += "\u001B[" + this._nullCellCount + "C";
}
else {
this._currentRow += "\u001B[" + this._nullCellCount + "X";
this._currentRow += "\u001B[" + this._nullCellCount + "C";
}
this._nullCellCount = 0;
}
this._currentRow += cell.getChars();
this._lastContentCursorRow = this._lastCursorRow = row;
this._lastContentCursorCol = this._lastCursorCol = col + cell.getWidth();
}
this._currentRow += cell.getChars();
};
StringSerializeHandler.prototype._serializeString = function () {
var rowEnd = this._allRows.length;
for (; rowEnd > 0; rowEnd--) {
if (this._allRows[rowEnd - 1]) {
break;
if (this._buffer1.length - this._firstRow <= this._terminal.rows) {
rowEnd = this._lastContentCursorRow + 1 - this._firstRow;
this._lastCursorCol = this._lastContentCursorCol;
this._lastCursorRow = this._lastContentCursorRow;
}
var content = '';
for (var i = 0; i < rowEnd; i++) {
content += this._allRows[i];
if (i + 1 < rowEnd) {
content += this._allRowSeparators[i];
}
}
return this._allRows.slice(0, rowEnd).join('\r\n');
var realCursorRow = this._buffer1.baseY + this._buffer1.cursorY;
var realCursorCol = this._buffer1.cursorX;
var cursorMoved = (realCursorRow !== this._lastCursorRow || realCursorCol !== this._lastCursorCol);
var moveRight = function (offset) {
if (offset > 0) {
content += "\u001B[" + offset + "C";
}
else if (offset < 0) {
content += "\u001B[" + -offset + "D";
}
};
var moveDown = function (offset) {
if (offset > 0) {
content += "\u001B[" + offset + "B";
}
else if (offset < 0) {
content += "\u001B[" + -offset + "A";
}
};
if (cursorMoved) {
moveDown(realCursorRow - this._lastCursorRow);
moveRight(realCursorCol - this._lastCursorCol);
}
return content;
};

@@ -193,10 +332,21 @@ return StringSerializeHandler;

};
SerializeAddon.prototype.serialize = function (rows) {
SerializeAddon.prototype._getString = function (buffer, scrollback) {
var maxRows = buffer.length;
var handler = new StringSerializeHandler(buffer, this._terminal);
var correctRows = (scrollback === undefined) ? maxRows : constrain(scrollback + this._terminal.rows, 0, maxRows);
var result = handler.serialize(maxRows - correctRows, maxRows);
return result;
};
SerializeAddon.prototype.serialize = function (scrollback) {
if (!this._terminal) {
throw new Error('Cannot use addon until it has been loaded');
}
var maxRows = this._terminal.buffer.active.length;
var handler = new StringSerializeHandler(this._terminal.buffer.active);
rows = (rows === undefined) ? maxRows : constrain(rows, 0, maxRows);
return handler.serialize(maxRows - rows, maxRows);
if (this._terminal.buffer.active.type === 'normal') {
return this._getString(this._terminal.buffer.active, scrollback);
}
var normalScreenContent = this._getString(this._terminal.buffer.normal, scrollback);
var alternativeScreenContent = this._getString(this._terminal.buffer.alternate, undefined);
return normalScreenContent
+ '\u001b[?1049h\u001b[H'
+ alternativeScreenContent;
};

@@ -203,0 +353,0 @@ SerializeAddon.prototype.dispose = function () { };

{
"name": "xterm-addon-serialize",
"version": "0.5.0-beta.5",
"version": "0.5.0-beta.6",
"author": {

@@ -5,0 +5,0 @@ "name": "The xterm.js authors",

@@ -24,3 +24,3 @@ /**

this._beforeSerialize(endRow - startRow);
this._beforeSerialize(endRow - startRow, startRow, endRow);

@@ -40,3 +40,3 @@ for (let row = startRow; row < endRow; row++) {

}
this._rowEnd(row);
this._rowEnd(row, row === endRow - 1);
}

@@ -50,4 +50,4 @@

protected _nextCell(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void { }
protected _rowEnd(row: number): void { }
protected _beforeSerialize(rows: number): void { }
protected _rowEnd(row: number, isLastRow: boolean): void { }
protected _beforeSerialize(rows: number, startRow: number, endRow: number): void { }
protected _afterSerialize(): void { }

@@ -77,18 +77,143 @@ protected _serializeString(): string { return ''; }

class StringSerializeHandler extends BaseSerializeHandler {
private _rowIndex: number = 0;
private _allRows: string[] = new Array<string>();
private _allRowSeparators: string[] = new Array<string>();
private _currentRow: string = '';
private _nullCellCount: number = 0;
constructor(buffer: IBuffer) {
super(buffer);
// we can see a full colored cell and a null cell that only have background the same style
// but the information isn't preserved by null cell itself
// so wee need to record it when required.
private _cursorStyle: IBufferCell = this._buffer1.getNullCell();
// where exact the cursor styles comes from
// because we can't copy the cell directly
// so we remember where the content comes from instead
private _cursorStyleRow: number = 0;
private _cursorStyleCol: number = 0;
// this is a null cell for reference for checking whether background is empty or not
private _backgroundCell: IBufferCell = this._buffer1.getNullCell();
private _firstRow: number = 0;
private _lastCursorRow: number = 0;
private _lastCursorCol: number = 0;
private _lastContentCursorRow: number = 0;
private _lastContentCursorCol: number = 0;
constructor(private _buffer1: IBuffer, private _terminal: Terminal) {
super(_buffer1);
}
protected _beforeSerialize(rows: number): void {
protected _beforeSerialize(rows: number, start: number, end: number): void {
this._allRows = new Array<string>(rows);
this._lastContentCursorRow = start;
this._lastCursorRow = start;
this._firstRow = start;
}
protected _rowEnd(row: number): void {
this._allRows[this._rowIndex++] = this._currentRow;
private _thisRowLastChar: IBufferCell = this._buffer1.getNullCell();
private _thisRowLastSecondChar: IBufferCell = this._buffer1.getNullCell();
private _nextRowFirstChar: IBufferCell = this._buffer1.getNullCell();
protected _rowEnd(row: number, isLastRow: boolean): void {
// if there is colorful empty cell at line end, whe must pad it back, or the the color block will missing
if (this._nullCellCount > 0 && !equalBg(this._cursorStyle, this._backgroundCell)) {
// use clear right to set background.
this._currentRow += `\x1b[${this._nullCellCount}X`;
}
let rowSeparator = '';
// handle row separator
if (!isLastRow) {
// Enable BCE
if (row - this._firstRow >= this._terminal.rows) {
this._buffer1.getLine(this._cursorStyleRow)?.getCell(this._cursorStyleCol, this._backgroundCell);
}
// Fetch current line
const currentLine = this._buffer1.getLine(row)!;
// Fetch next line
const nextLine = this._buffer1.getLine(row + 1)!;
if (!nextLine.isWrapped) {
// just insert the line break
rowSeparator = '\r\n';
// we sended the enter
this._lastCursorRow = row + 1;
this._lastCursorCol = 0;
} else {
rowSeparator = '';
const thisRowLastChar = currentLine.getCell(currentLine.length - 1, this._thisRowLastChar)!;
const thisRowLastSecondChar = currentLine.getCell(currentLine.length - 2, this._thisRowLastSecondChar)!;
const nextRowFirstChar = nextLine.getCell(0, this._nextRowFirstChar)!;
const isNextRowFirstCharDoubleWidth = nextRowFirstChar.getWidth() > 1;
// validate whether this line wrap is ever possible
// which mean whether cursor can placed at a overflow position (x === row) naturally
let isValid = false;
if (
// you must output character to cause overflow, control sequence can't do this
nextRowFirstChar.getChars() &&
isNextRowFirstCharDoubleWidth ? this._nullCellCount <= 1 : this._nullCellCount <= 0
) {
if (
// the last character can't be null,
// you can't use control sequence to move cursor to (x === row)
(thisRowLastChar.getChars() || thisRowLastChar.getWidth() === 0) &&
// change background of the first wrapped cell also affects BCE
// so we mark it as invalid to simply the process to determine line separator
equalBg(thisRowLastChar, nextRowFirstChar)
) {
isValid = true;
}
if (
// the second to last character can't be null if the next line starts with CJK,
// you can't use control sequence to move cursor to (x === row)
isNextRowFirstCharDoubleWidth &&
(thisRowLastSecondChar.getChars() || thisRowLastSecondChar.getWidth() === 0) &&
// change background of the first wrapped cell also affects BCE
// so we mark it as invalid to simply the process to determine line separator
equalBg(thisRowLastChar, nextRowFirstChar) &&
equalBg(thisRowLastSecondChar, nextRowFirstChar)
) {
isValid = true;
}
}
if (!isValid) {
// force the wrap with magic
// insert enough character to force the wrap
rowSeparator = '-'.repeat(this._nullCellCount + 1);
// move back and erase next line head
rowSeparator += '\x1b[1D\x1b[1X';
if (this._nullCellCount > 0) {
// do these because we filled the last several null slot, which we shouldn't
rowSeparator += '\x1b[A';
rowSeparator += `\x1b[${currentLine.length - this._nullCellCount}C`;
rowSeparator += `\x1b[${this._nullCellCount}X`;
rowSeparator += `\x1b[${currentLine.length - this._nullCellCount}D`;
rowSeparator += '\x1b[B';
}
// This is content and need the be serialized even it is invisible.
// without this, wrap will be missing from outputs.
this._lastContentCursorRow = row + 1;
this._lastContentCursorCol = 0;
// force commit the cursor position
this._lastCursorRow = row + 1;
this._lastCursorCol = 0;
}
}
}
this._allRows[this._rowIndex] = this._currentRow;
this._allRowSeparators[this._rowIndex++] = rowSeparator;
this._currentRow = '';

@@ -98,3 +223,3 @@ this._nullCellCount = 0;

protected _nextCell(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void {
private _diffStyle(cell: IBufferCell, oldCell: IBufferCell): number[] {
const sgrSeq: number[] = [];

@@ -107,3 +232,5 @@ const fgChanged = !equalFg(cell, oldCell);

if (cell.isAttributeDefault()) {
this._currentRow += '\x1b[0m';
if (!oldCell.isAttributeDefault()) {
sgrSeq.push(0);
}
} else {

@@ -140,16 +267,75 @@ if (fgChanged) {

if (sgrSeq.length) {
return sgrSeq;
}
protected _nextCell(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void {
// a width 0 cell don't need to be count because it is just a placeholder after a CJK character;
const isPlaceHolderCell = cell.getWidth() === 0;
if (isPlaceHolderCell) {
return;
}
// this cell don't have content
const isEmptyCell = cell.getChars() === '';
const sgrSeq = this._diffStyle(cell, this._cursorStyle);
// the empty cell style is only assumed to be changed when background changed, because foreground is always 0.
const styleChanged = isEmptyCell ? !equalBg(this._cursorStyle, cell) : sgrSeq.length > 0;
/**
* handles style change
*/
if (styleChanged) {
// before update the style, we need to fill empty cell back
if (this._nullCellCount > 0) {
// use clear right to set background.
if (!equalBg(this._cursorStyle, this._backgroundCell)) {
this._currentRow += `\x1b[${this._nullCellCount}X`;
}
// use move right to move cursor.
this._currentRow += `\x1b[${this._nullCellCount}C`;
this._nullCellCount = 0;
}
this._lastContentCursorRow = this._lastCursorRow = row;
this._lastContentCursorCol = this._lastCursorCol = col;
this._currentRow += `\x1b[${sgrSeq.join(';')}m`;
// update the last cursor style
const line = this._buffer1.getLine(row);
if (line !== undefined) {
line.getCell(col, this._cursorStyle);
this._cursorStyleRow = row;
this._cursorStyleCol = col;
}
}
// Count number of null cells encountered after the last non-null cell and move the cursor
// if a non-null cell is found (eg. \t or cursor move)
if (cell.getChars() === '') {
/**
* handles actual content
*/
if (isEmptyCell) {
this._nullCellCount += cell.getWidth();
} else if (this._nullCellCount > 0) {
this._currentRow += `\x1b[${this._nullCellCount}C`;
this._nullCellCount = 0;
} else {
if (this._nullCellCount > 0) {
// we can just assume we have same style with previous one here
// because style change is handled by previous stage
// use move right when background is empty, use clear right when there is background.
if (equalBg(this._cursorStyle, this._backgroundCell)) {
this._currentRow += `\x1b[${this._nullCellCount}C`;
} else {
this._currentRow += `\x1b[${this._nullCellCount}X`;
this._currentRow += `\x1b[${this._nullCellCount}C`;
}
this._nullCellCount = 0;
}
this._currentRow += cell.getChars();
// update cursor
this._lastContentCursorRow = this._lastCursorRow = row;
this._lastContentCursorCol = this._lastCursorCol = col + cell.getWidth();
}
this._currentRow += cell.getChars();
}

@@ -159,8 +345,48 @@

let rowEnd = this._allRows.length;
for (; rowEnd > 0; rowEnd--) {
if (this._allRows[rowEnd - 1]) {
break;
// the fixup is only required for data without scrollback
// because it will always be placed at last line otherwise
if (this._buffer1.length - this._firstRow <= this._terminal.rows) {
rowEnd = this._lastContentCursorRow + 1 - this._firstRow;
this._lastCursorCol = this._lastContentCursorCol;
this._lastCursorRow = this._lastContentCursorRow;
}
let content = '';
for (let i = 0; i < rowEnd; i++) {
content += this._allRows[i];
if (i + 1 < rowEnd) {
content += this._allRowSeparators[i];
}
}
return this._allRows.slice(0, rowEnd).join('\r\n');
// restore the cursor
const realCursorRow = this._buffer1.baseY + this._buffer1.cursorY;
const realCursorCol = this._buffer1.cursorX;
const cursorMoved = (realCursorRow !== this._lastCursorRow || realCursorCol !== this._lastCursorCol);
const moveRight = (offset: number): void => {
if (offset > 0) {
content += `\u001b[${offset}C`;
} else if (offset < 0) {
content += `\u001b[${-offset}D`;
}
};
const moveDown = (offset: number): void => {
if (offset > 0) {
content += `\u001b[${offset}B`;
} else if (offset < 0) {
content += `\u001b[${-offset}A`;
}
};
if (cursorMoved) {
moveDown(realCursorRow - this._lastCursorRow);
moveRight(realCursorCol - this._lastCursorCol);
}
return content;
}

@@ -178,5 +404,13 @@ }

public serialize(rows?: number): string {
// TODO: Add re-position cursor support
// TODO: Add word wrap mode support
private _getString(buffer: IBuffer, scrollback?: number): string {
const maxRows = buffer.length;
const handler = new StringSerializeHandler(buffer, this._terminal!);
const correctRows = (scrollback === undefined) ? maxRows : constrain(scrollback + this!._terminal!.rows, 0, maxRows);
const result = handler.serialize(maxRows - correctRows, maxRows);
return result;
}
public serialize(scrollback?: number): string {
// TODO: Add combinedData support

@@ -187,8 +421,13 @@ if (!this._terminal) {

const maxRows = this._terminal.buffer.active.length;
const handler = new StringSerializeHandler(this._terminal.buffer.active);
if (this._terminal.buffer.active.type === 'normal') {
return this._getString(this._terminal.buffer.active, scrollback);
}
rows = (rows === undefined) ? maxRows : constrain(rows, 0, maxRows);
const normalScreenContent = this._getString(this._terminal.buffer.normal, scrollback);
// alt screen don't have scrollback
const alternativeScreenContent = this._getString(this._terminal.buffer.alternate, undefined);
return handler.serialize(maxRows - rows, maxRows);
return normalScreenContent
+ '\u001b[?1049h\u001b[H'
+ alternativeScreenContent;
}

@@ -195,0 +434,0 @@

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet