diff --git a/addons/addon-serialize/src/SerializeAddon.test.ts b/addons/addon-serialize/src/SerializeAddon.test.ts index ac485e549f..7cb071bffb 100644 --- a/addons/addon-serialize/src/SerializeAddon.test.ts +++ b/addons/addon-serialize/src/SerializeAddon.test.ts @@ -138,6 +138,16 @@ describe('SerializeAddon', () => { assert.equal((output.match(/
terminal<\/span><\/div>/g) || []).length, 1, output); }); + it('basic terminal with html unsafe chars', async () => { + await writeP(terminal, ' π '); + terminal.select(1, 0, 7); + + const output = serializeAddon.serializeAsHTML({ + onlySelection: true + }); + assert.equal((output.match(/
<a>&pi;<\/span><\/div>/g) || []).length, 1, output); + }); + it('cells with bold styling', async () => { await writeP(terminal, ' ' + sgr('1') + 'terminal' + sgr('22') + ' '); diff --git a/addons/addon-serialize/src/SerializeAddon.ts b/addons/addon-serialize/src/SerializeAddon.ts index e654eddbee..cd15cfc373 100644 --- a/addons/addon-serialize/src/SerializeAddon.ts +++ b/addons/addon-serialize/src/SerializeAddon.ts @@ -14,6 +14,14 @@ function constrain(value: number, low: number, high: number): number { return Math.max(low, Math.min(value, high)); } +function escapeHTMLChar(c: string): string { + switch (c) { + case '&': return '&'; + case '<': return '<'; + } + return c; +} + // TODO: Refine this template class later abstract class BaseSerializeHandler { constructor( @@ -669,7 +677,7 @@ export class HTMLSerializeHandler extends BaseSerializeHandler { if (isEmptyCell) { this._currentRow += ' '; } else { - this._currentRow += cell.getChars(); + this._currentRow += escapeHTMLChar(cell.getChars()); } }