Move more handlers into testWindow.ts

This commit is contained in:
Daniel Imms
2025-12-26 04:04:08 -08:00
parent 4fffb96f25
commit 02e9e56eef
2 changed files with 496 additions and 510 deletions
-500
View File
@@ -301,23 +301,13 @@ if (document.location.pathname === '/test') {
document.getElementById('create-new-window').addEventListener('click', createNewWindowButtonHandler);
document.getElementById('serialize').addEventListener('click', serializeButtonHandler);
document.getElementById('htmlserialize').addEventListener('click', htmlSerializeButtonHandler);
document.getElementById('custom-glyph-alignment').addEventListener('click', customGlyphAlignmentHandler);
document.getElementById('custom-glyph-ranges').addEventListener('click', customGlyphRangesHandler);
document.getElementById('load-test').addEventListener('click', loadTest);
document.getElementById('load-test-long-lines').addEventListener('click', loadTestLongLines);
document.getElementById('print-cjk-sgr').addEventListener('click', addCjkRandomSgr);
document.getElementById('powerline-symbol-test').addEventListener('click', powerlineSymbolTest);
document.getElementById('underline-test').addEventListener('click', underlineTest);
document.getElementById('ansi-colors').addEventListener('click', ansiColorsTest);
document.getElementById('osc-hyperlinks').addEventListener('click', addAnsiHyperlink);
document.getElementById('sgr-test').addEventListener('click', sgrTest);
document.getElementById('add-grapheme-clusters').addEventListener('click', addGraphemeClusters);
document.getElementById('add-decoration').addEventListener('click', addDecoration);
document.getElementById('add-overview-ruler').addEventListener('click', addOverviewRuler);
document.getElementById('decoration-stress-test').addEventListener('click', decorationStressTest);
document.getElementById('ligatures-test').addEventListener('click', ligaturesTest);
document.getElementById('weblinks-test').addEventListener('click', testWeblinks);
document.getElementById('bce').addEventListener('click', coloredErase);
initImageAddonExposed();
testEvents();
progressButtons();
@@ -662,190 +652,6 @@ function htmlSerializeButtonHandler(): void {
document.getElementById('htmlserialize-output-result').innerText = 'Copied to clipboard';
}
function customGlyphAlignmentHandler(): void {
term.write('\n\r');
term.write('\n\r');
term.write('Box styles: ┎┰┒┍┯┑╓╥╖╒╤╕ ┏┳┓┌┲┓┌┬┐┏┱┐\n\r');
term.write('┌─┬─┐ ┏━┳━┓ ╔═╦═╗ ┠╂┨┝┿┥╟╫╢╞╪╡ ┡╇┩├╊┫┢╈┪┣╉┤\n\r');
term.write('│ │ │ ┃ ┃ ┃ ║ ║ ║ ┖┸┚┕┷┙╙╨╜╘╧╛ └┴┘└┺┛┗┻┛┗┹┘\n\r');
term.write('├─┼─┤ ┣━╋━┫ ╠═╬═╣ ┏┱┐┌┲┓┌┬┐┌┬┐ ┏┳┓┌┮┓┌┬┐┏┭┐\n\r');
term.write('│ │ │ ┃ ┃ ┃ ║ ║ ║ ┡╃┤├╄┩├╆┪┢╅┤ ┞╀┦├┾┫┟╁┧┣┽┤\n\r');
term.write('└─┴─┘ ┗━┻━┛ ╚═╩═╝ └┴┘└┴┘└┺┛┗┹┘ └┴┘└┶┛┗┻┛┗┵┘\n\r');
term.write('\n\r');
term.write('Other:\n\r');
term.write('╭─╮ ╲ ╱ ╷╻╎╏┆┇┊┋ ╺╾╴ ╌╌╌ ┄┄┄ ┈┈┈\n\r');
term.write('│ │ ╳ ╽╿╎╏┆┇┊┋ ╶╼╸ ╍╍╍ ┅┅┅ ┉┉┉\n\r');
term.write('╰─╯ ╱ ╲ ╹╵╎╏┆┇┊┋\n\r');
term.write('\n\r');
term.write('Box drawing alignment tests:\x1b[31m █\n\r');
term.write(' ▉\n\r');
term.write(' ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳\n\r');
term.write(' ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳\n\r');
term.write(' ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳\n\r');
term.write(' ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳\n\r');
term.write(' ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎\n\r');
term.write(' ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏\n\r');
term.write(' ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█\n\r');
term.write('\x1b[0mBox drawing alignment tests:\x1b[32m █\n\r');
term.write(' ▉\n\r');
term.write(' ╔══╦══╗ ┌──┬──┐ ╭──┬──╮ ╭──┬──╮ ┏━━┳━━┓ ┎┒┏┑ ╷ ╻ ┏┯┓ ┌┰┐ ▊ ╱╲╱╲╳╳╳\n\r');
term.write(' ║┌─╨─┐║ │╔═╧═╗│ │╒═╪═╕│ │╓─╁─╖│ ┃┌─╂─┐┃ ┗╃╄┙ ╶┼╴╺╋╸┠┼┨ ┝╋┥ ▋ ╲╱╲╱╳╳╳\n\r');
term.write(' ║│╲ ╱│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╿ │┃ ┍╅╆┓ ╵ ╹ ┗┷┛ └┸┘ ▌ ╱╲╱╲╳╳╳\n\r');
term.write(' ╠╡ ╳ ╞╣ ├╢ ╟┤ ├┼─┼─┼┤ ├╫─╂─╫┤ ┣┿╾┼╼┿┫ ┕┛┖┚ ┌┄┄┐ ╎ ┏┅┅┓ ┋ ▍ ╲╱╲╱╳╳╳\n\r');
term.write(' ║│╱ ╲│║ │║ ║│ ││ │ ││ │║ ┃ ║│ ┃│ ╽ │┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▎\n\r');
term.write(' ║└─╥─┘║ │╚═╤═╝│ │╘═╪═╛│ │╙─╀─╜│ ┃└─╂─┘┃ ░░▒▒▓▓██ ┊ ┆ ╎ ╏ ┇ ┋ ▏\n\r');
term.write(' ╚══╩══╝ └──┴──┘ ╰──┴──╯ ╰──┴──╯ ┗━━┻━━┛ └╌╌┘ ╎ ┗╍╍┛ ┋ ▁▂▃▄▅▆▇█\n\r');
term.write('\x1b[0mSmooth mosaic terminal graphic characters alignment tests:\x1b[33m\n\r');
term.write(' 🭇🬼 🭈🬽 🭉🬾 🭊🬿 🭋🭀 🭁🭌 🭂🭍 🭃🭎 🭄🭏 🭅🭐 🭆🭑 🭨🭪 🭩 🭯 🭮🭬\n\r');
term.write(' 🭢🭗 🭣🭘 🭤🭙 🭥🭚 🭦🭛 🭒🭝 🭓🭞 🭔🭟 🭕🭠 🭖🭡 🭧🭜 🭫 🭭\n\r');
term.write(' 🭇🬼 🭉🬾 🭋🭀\n\r');
term.write(' 🭊🭁🭌🬿 🭈🭆🭂🭍🭑🬽 🭇🭄🭏🬼 🭃🭎 🭅🭐 🭨🭪\n\r');
term.write(' 🭥🭒🭝🭚 🭣🭧🭓🭞🭜🭘 🭢🭕🭠🭗 🭔🭟 🭖🭡 🭪🭨\n\r');
term.write(' 🭢🭗 🭤🭙 🭦🭛\n\r');
term.write('\x1b[0mCharacter cell diagonals (1FBA0-1FBAE) alignment tests:\x1b[34m\n\r');
term.write(' \u{1FBA3}\u{1FBA7}\u{1FBA2} \u{1FBA3}\u{1FBA8}\u{1FBA0} \u{1FBAD}\u{1FBA2} \u{1FBA3}\u{1FBAC} \u{1FBAE}\n\r');
term.write(' \u{1FBA3}\u{1FBA0} \u{1FBA1}\u{1FBA2} \u{1FBA1}\u{1FBA9}\u{1FBA2} \u{1FBA1}\u{1FBAA} \u{1FBAB}\u{1FBA0}\n\r');
term.write(' \u{1FBA4} \u{1FBA5}\n\r');
term.write(' \u{1FBA1}\u{1FBA2} \u{1FBA3}\u{1FBA0}\n\r');
term.write(' \u{1FBA1}\u{1FBA6}\u{1FBA0}\n\r');
term.write('\x1b[0mCharacter cell diagonals (1FBD0-1FBDF) alignment tests:\x1b[34m\n\r');
term.write(' \u{1FBD6}\u{1FBD4} \u{1FBD0}\u{1FBD1}\u{1FBD2}\u{1FBD3} \u{1FBDA} \u{1FBD9}\u{1FBDB} \u{1FBDE} \u{1FBDD}\u{1FBDF}\n\r');
term.write(' \u{1FBD7}\u{1FBD5} \u{1FBD2}\u{1FBD3}\u{1FBD0}\u{1FBD1} \u{1FBD8} \u{1FBDC}\n\r');
term.write(' \u{1FBD4}\u{1FBD6}\n\r');
term.write(' \u{1FBD5}\u{1FBD7}\n\r');
term.write('');
term.write('\x1b[0mComposite terminal graphics characters:\x1b[35m\n\r');
term.write('\u{1FBB2}\u{1FBB3} \u{1FBB9}\u{1FBBA} \u{1FBC1}\u{1FBC2}\u{1FBC3}\n\r');
term.write('\x1b[0mFill tests:\x1b[36m\n\r');
const fillChars = ['\u{2591}', '\u{2592}', '\u{2593}', '\u{1FB8C}', '\u{1FB8D}', '\u{1FB8E}', '\u{1FB8F}', '\u{1FB90}', '\u{1FB91}', '\u{1FB92}', '\u{1FB94}', '\u{1FB95}', '\u{1FB96}', '\u{1FB97}', '\u{1FB98}', '\u{1FB99}'];
while (fillChars.length > 0) {
const batch = fillChars.splice(0, 10);
for (const fillChar of batch) {
term.write(`${fillChar.codePointAt(0).toString(16).toUpperCase().padEnd(5, ' ')} `);
}
term.write('\n\r');
for (let i = 0; i < 3; i++) {
for (const fillChar of batch) {
term.write(fillChar.repeat(5));
term.write(' ');
}
term.write('\n\r');
}
}
term.write('\x1b[0mPowerline alignment tests:\n\r');
const powerlineLeftChars = ['\u{E0B2}', '\u{E0B3}', '\u{E0B6}', '\u{E0B7}', '\u{E0BA}', '\u{E0BB}', '\u{E0BE}', '\u{E0BF}', '\u{E0C2}', '\u{E0C3}', '\u{E0C5}', '\u{E0C7}', '\u{E0CA}', '\u{E0D4}'];
const powerlineRightChars = ['\u{E0B0}', '\u{E0B1}', '\u{E0B4}', '\u{E0B5}', '\u{E0B8}', '\u{E0B9}', '\u{E0BC}', '\u{E0BD}', '\u{E0C0}', '\u{E0C1}', '\u{E0C4}', '\u{E0C6}', '\u{E0C8}', '\u{E0D2}', '\u{E0CC}', '\u{E0CD}', '\u{E0CE}', '\u{E0CF}', '\u{E0D0}', '\u{E0D1}'];
for (const char of powerlineLeftChars) {
term.write(`\x1b[31m${char}\x1b[0;41m \x1b[0m `);
}
term.write('\n\r');
for (const char of powerlineRightChars) {
term.write(`\x1b[41m \x1b[0;31m${char}\x1b[0m `);
}
term.write('\n\r');
term.write('\x1b[0mGit Branch Symbols alignment tests:\x1b[32m\n\r');
term.write(' \u{F5F7}\u{F5F7} \u{F5EE}\u{F5EF} \u{F5F6}\u{F5F7} \u{F5D6}\u{F5D0}\u{F5D7} \u{F5FC}\u{F5FC}\u{F5FE} \u{F5FD}\u{F609}\u{F5FF}\n\r');
term.write(' \u{F5DA}\u{F5DD} \u{F5F0}\u{F5F4}\u{F5F2} \u{F5FA}\u{F5FB} \u{F5D1} \u{F5D1} \u{F604}\u{F60C}\u{F606} \u{F605}\u{F60D}\u{F607}\n\r');
term.write(' \u{F5DB}\u{F5DE} \u{F5F1}\u{F5F5}\u{F5F3} \u{F5F8}\u{F5F9} \u{F5D8}\u{F5D0}\u{F5D9} \u{F600}\u{F60A}\u{F602} \u{F601}\u{F60B}\u{F603}\n\r');
term.write(' \u{F5DC}\u{F5DF} \u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\u{F5F7}\n\r');
term.write('\u{F5F1}\u{F5E6}\u{F5E7}\u{F5F3} \u{F5D3}\u{F5D0}\u{F5E0}\u{F5E1}\u{F5E2}\u{F5E3}\u{F5E4}\u{F5E5}\u{F5E8}\u{F5E9}\u{F5EC}\u{F5ED}\u{F5D2}\n\r');
term.write('\u{F5F1}\u{F5EA}\u{F5EB}\u{F5F3} \u{F5F9}\u{F5F9}\u{F5F9} \u{F5F9}\u{F5F9}\u{F5F9}\u{F5F9}\n\r');
term.write(' \u{F5F9}\u{F5F9} \n\r');
term.write('\x1b[0m');
term.write('\n\r');
window.scrollTo(0, 0);
}
function customGlyphRangesHandler(): void {
// Box Drawing
// 2500-257F
// https://www.unicode.org/charts/PDF/U2500.pdf
writeUnicodeTable(term, 'Box Drawing', 0x2500, 0x257F, [
['Light and heavy solid lines', 0x2500, 0x2503],
['Light and heavy dashed lines', 0x2504, 0x250B],
['Light and heavy line box components', 0x250C, 0x254B],
['Light and heavy dashed lines', 0x254C, 0x254F],
['Double lines', 0x2550, 0x2551],
['Light and double line box components', 0x2552, 0x256C],
['Character cell arcs', 0x256D, 0x2570],
['Character cell diagonals', 0x2571, 0x2573],
['Light and heavy half lines', 0x2574, 0x257B],
['Mixed light and heavy lines', 0x257C, 0x257F],
]);
// Box Elements
// 2580-259F
// https://www.unicode.org/charts/PDF/U2580.pdf
writeUnicodeTable(term, 'Box Elements', 0x2580, 0x259F, [
['Block elements', 0x2580, 0x2590],
['Shade characters', 0x2591, 0x2593],
['Block elements', 0x2594, 0x2595],
['Terminal graphic characters', 0x2596, 0x259F],
]);
// Braille Patterns
// 2800-28FF
// https://www.unicode.org/charts/PDF/U2800.pdf
writeUnicodeTable(term, 'Braille patterns', 0x2800, 0x28FF, [
['Braille patterns', 0x2800, 0x28FF],
]);
// Powerline Symbols
// Range: E0A0–E0D4
// https://github.com/ryanoasis/nerd-fonts
writeUnicodeTable(term, 'Powerline Symbols', 0xE0A0, 0xE0D4, [
['Powerline symbols', 0xE0A0, 0xE0B3, [0xE0A4, 0xE0A5, 0xE0A6, 0xE0A7, 0xE0A8, 0xE0A9, 0xE0AA, 0xE0AB, 0xE0AC, 0xE0AD, 0xE0AE, 0xE0AF]],
['Powerline extra symbols', 0xE0B4, 0xE0D4, [0xE0C9, 0xE0CB, 0xE0D3]],
]);
// Git Branch Symbols
// F5D0-F60D
// https://github.com/xtermjs/xterm.js/issues/5477
writeUnicodeTable(term, 'Git Branch Symbols', 0xF5D0, 0xF5FB, [
['Straight lines', 0xF5D0, 0xF5D5],
['Curved lines', 0xF5D6, 0xF5D9],
['Branching lines', 0xF5DA, 0xF5ED],
['Nodes', 0xF5EE, 0xF5FB],
['Extended nodes', 0xF5FC, 0xF60D],
]);
// Symbols for Legacy Computing
// Range: 1FB00–1FBFF
// https://www.unicode.org/charts/PDF/U1FB00.pdf
writeUnicodeTable(term, 'Symbols for Legacy Computing', 0x1FB00, 0x1FBFF, [
['Block mosaic terminal graphic characters (Sextants)', 0x1FB00, 0x1FB3B],
['Smooth mosaic terminal graphic characters', 0x1FB3C, 0x1FB6F],
['Block elements', 0x1FB70, 0x1FB80],
['Window title bar', 0x1FB81, 0x1FB81],
['Block elements', 0x1FB82, 0x1FB8B],
['Rectangular shade characters', 0x1FB8C, 0x1FB94, [0x1FB93]],
['Fill characters', 0x1FB95, 0x1FB97],
['Diagonal fill characters', 0x1FB98, 0x1FB99],
['Smooth mosaic terminal graphic characters', 0x1FB9A, 0x1FB9B],
['Triangular shade characters', 0x1FB9C, 0x1FB9F],
['Character cell diagonals', 0x1FBA0, 0x1FBAE],
['Light solid line with stroke', 0x1FBAF, 0x1FBAF],
['Terminal graphic characters', 0x1FBB0, 0x1FBB3],
['Arrows', 0x1FBB4, 0x1FBB8],
['Terminal graphic characters', 0x1FBB9, 0x1FBBC],
['Negative terminal graphic characters', 0x1FBBD, 0x1FBBF],
['Terminal graphic characters', 0x1FBC0, 0x1FBCA],
['Terminal graphic characters', 0x1FBCB, 0x1FBCD],
['Block elements', 0x1FBCE, 0x1FBCF],
['Character cell diagonals', 0x1FBD0, 0x1FBDF],
['Geometrics shapes', 0x1FBE0, 0x1FBEF],
['Segmented digits', 0x1FBF0, 0x1FBF9],
['Terminal graphic character', 0x1FBFA, 0x1FBFA],
]);
}
function loadTest(): void {
const rendererName = addons.webgl.instance ? 'webgl' : 'dom';
const testData = [];
@@ -912,295 +718,6 @@ function loadTestLongLines(): void {
});
}
function powerlineSymbolTest(): void {
function s(char: string): string {
return `${char} \x1b[7m${char}\x1b[0m `;
}
term.write('\n\n\r');
term.writeln('Standard powerline symbols:');
term.writeln(' 0 1 2 3 4 5 6 7 8 9 A B C D E F');
term.writeln(`0xA_ ${s('\ue0a0')}${s('\ue0a1')}${s('\ue0a2')}`);
term.writeln(`0xB_ ${s('\ue0b0')}${s('\ue0b1')}${s('\ue0b2')}${s('\ue0b3')}`);
term.writeln('');
term.writeln(
`\x1b[7m` +
` inverse \ue0b1 \x1b[0;40m\ue0b0` +
` 0 \ue0b1 \x1b[30;41m\ue0b0\x1b[39m` +
` 1 \ue0b1 \x1b[31;42m\ue0b0\x1b[39m` +
` 2 \ue0b1 \x1b[32;43m\ue0b0\x1b[39m` +
` 3 \ue0b1 \x1b[33;44m\ue0b0\x1b[39m` +
` 4 \ue0b1 \x1b[34;45m\ue0b0\x1b[39m` +
` 5 \ue0b1 \x1b[35;46m\ue0b0\x1b[39m` +
` 6 \ue0b1 \x1b[36;47m\ue0b0\x1b[30m` +
` 7 \ue0b1 \x1b[37;49m\ue0b0\x1b[0m`
);
term.writeln('');
term.writeln(
`\x1b[7m` +
` inverse \ue0b3 \x1b[0;7;40m\ue0b2\x1b[27m` +
` 0 \ue0b3 \x1b[7;30;41m\ue0b2\x1b[27;39m` +
` 1 \ue0b3 \x1b[7;31;42m\ue0b2\x1b[27;39m` +
` 2 \ue0b3 \x1b[7;32;43m\ue0b2\x1b[27;39m` +
` 3 \ue0b3 \x1b[7;33;44m\ue0b2\x1b[27;39m` +
` 4 \ue0b3 \x1b[7;34;45m\ue0b2\x1b[27;39m` +
` 5 \ue0b3 \x1b[7;35;46m\ue0b2\x1b[27;39m` +
` 6 \ue0b3 \x1b[7;36;47m\ue0b2\x1b[27;30m` +
` 7 \ue0b3 \x1b[7;37;49m\ue0b2\x1b[0m`
);
term.writeln('');
term.writeln(
`\x1b[7m` +
` inverse \ue0b5 \x1b[0;40m\ue0b4` +
` 0 \ue0b5 \x1b[30;41m\ue0b4\x1b[39m` +
` 1 \ue0b5 \x1b[31;42m\ue0b4\x1b[39m` +
` 2 \ue0b5 \x1b[32;43m\ue0b4\x1b[39m` +
` 3 \ue0b5 \x1b[33;44m\ue0b4\x1b[39m` +
` 4 \ue0b5 \x1b[34;45m\ue0b4\x1b[39m` +
` 5 \ue0b5 \x1b[35;46m\ue0b4\x1b[39m` +
` 6 \ue0b5 \x1b[36;47m\ue0b4\x1b[30m` +
` 7 \ue0b5 \x1b[37;49m\ue0b4\x1b[0m`
);
term.writeln('');
term.writeln(
`\x1b[7m` +
` inverse \ue0b7 \x1b[0;7;40m\ue0b6\x1b[27m` +
` 0 \ue0b7 \x1b[7;30;41m\ue0b6\x1b[27;39m` +
` 1 \ue0b7 \x1b[7;31;42m\ue0b6\x1b[27;39m` +
` 2 \ue0b7 \x1b[7;32;43m\ue0b6\x1b[27;39m` +
` 3 \ue0b7 \x1b[7;33;44m\ue0b6\x1b[27;39m` +
` 4 \ue0b7 \x1b[7;34;45m\ue0b6\x1b[27;39m` +
` 5 \ue0b7 \x1b[7;35;46m\ue0b6\x1b[27;39m` +
` 6 \ue0b7 \x1b[7;36;47m\ue0b6\x1b[27;30m` +
` 7 \ue0b7 \x1b[7;37;49m\ue0b6\x1b[0m`
);
term.writeln('');
term.writeln('Powerline extra symbols:');
term.writeln(' 0 1 2 3 4 5 6 7 8 9 A B C D E F');
term.writeln(`0xA_ ${s('\ue0a3')}`);
term.writeln(`0xB_ ${s('\ue0b4')}${s('\ue0b5')}${s('\ue0b6')}${s('\ue0b7')}${s('\ue0b8')}${s('\ue0b9')}${s('\ue0ba')}${s('\ue0bb')}${s('\ue0bc')}${s('\ue0bd')}${s('\ue0be')}${s('\ue0bf')}`);
term.writeln(`0xC_ ${s('\ue0c0')}${s('\ue0c1')}${s('\ue0c2')}${s('\ue0c3')}${s('\ue0c4')}${s('\ue0c5')}${s('\ue0c6')}${s('\ue0c7')}${s('\ue0c8')}${s('\ue0c9')}${s('\ue0ca')}${s('\ue0cb')}${s('\ue0cc')}${s('\ue0cd')}${s('\ue0be')}${s('\ue0bf')}`);
term.writeln(`0xD_ ${s('\ue0d0')}${s('\ue0d1')}${s('\ue0d2')} ${s('\ue0d4')}`);
term.writeln('');
term.writeln('Sample of nerd fonts icons:');
term.writeln(' nf-linux-apple (\\uF302) \uf302');
term.writeln('nf-mdi-github_face (\\uFbd9) \ufbd9');
}
function underlineTest(): void {
function u(style: number): string {
return `\x1b[4:${style}m`;
}
function c(color: string): string {
return `\x1b[58:${color}m`;
}
term.write('\n\n\r');
term.writeln('Underline styles:');
term.writeln('');
function showSequence(id: number, name: string): string {
let alphabet = '';
for (let i = 97; i < 123; i++) {
alphabet += String.fromCharCode(i);
}
let numbers = '';
for (let i = 0; i < 10; i++) {
numbers += i.toString();
}
return `${u(id)}4:${id}m - ${name}\x1b[4:0m`.padEnd(33, ' ') + `${u(id)}${alphabet} ${numbers} 汉语 한국어 👽\x1b[4:0m`;
}
term.writeln(showSequence(0, 'No underline'));
term.writeln(showSequence(1, 'Straight'));
term.writeln(showSequence(2, 'Double'));
term.writeln(showSequence(3, 'Curly'));
term.writeln(showSequence(4, 'Dotted'));
term.writeln(showSequence(5, 'Dashed'));
term.writeln('');
term.writeln(`Underline colors (256 color mode):`);
term.writeln('');
for (let i = 0; i < 256; i++) {
term.write((i !== 0 ? '\x1b[0m, ' : '') + u(1 + i % 5) + c('5:' + i) + i);
}
term.writeln(`\x1b[0m\n\n\rUnderline colors (true color mode):`);
term.writeln('');
for (let i = 0; i < 80; i++) {
const v = Math.round(i / 79 * 255);
term.write(u(1) + c(`2:0:${v}:${v}:${v}`) + (i < 4 ? 'grey'[i] : ' '));
}
term.write('\n\r');
for (let i = 0; i < 80; i++) {
const v = Math.round(i / 79 * 255);
term.write(u(1) + c(`2:0:${v}:${0}:${0}`) + (i < 3 ? 'red'[i] : ' '));
}
term.write('\n\r');
for (let i = 0; i < 80; i++) {
const v = Math.round(i / 79 * 255);
term.write(u(1) + c(`2:0:${0}:${v}:${0}`) + (i < 5 ? 'green'[i] : ' '));
}
term.write('\n\r');
for (let i = 0; i < 80; i++) {
const v = Math.round(i / 79 * 255);
term.write(u(1) + c(`2:0:${0}:${0}:${v}`) + (i < 4 ? 'blue'[i] : ' '));
}
term.write('\x1b[0m\n\r');
}
function ansiColorsTest(): void {
term.writeln(`\x1b[0m\n\n\rStandard colors: Bright colors:`);
for (let i = 0; i < 16; i++) {
term.write(`\x1b[48;5;${i}m ${i.toString().padEnd(2, ' ').padStart(3, ' ')} \x1b[0m`);
}
term.writeln(`\x1b[0m\n\n\rColors 17-231 from 256 palette:`);
for (let i = 0; i < 6; i++) {
const startId = 16 + i * 36;
const endId = 16 + (i + 1) * 36 - 1;
term.write(`${startId.toString().padStart(3, ' ')}-${endId.toString().padStart(3, ' ')} `);
for (let j = 0; j < 36; j++) {
const id = 16 + i * 36 + j;
term.write(`\x1b[48;5;${id}m${(id % 10).toString().padStart(2, ' ')}\x1b[0m`);
}
term.write(`\r\n`);
}
term.writeln(`\x1b[0m\n\rGreyscale from 256 palette:`);
term.write('232-255 ');
for (let i = 232; i < 256; i++) {
term.write(`\x1b[48;5;${i}m ${(i % 10)} \x1b[0m`);
}
}
function writeTestString(): string {
let alphabet = '';
for (let i = 97; i < 123; i++) {
alphabet += String.fromCharCode(i);
}
let numbers = '';
for (let i = 0; i < 10; i++) {
numbers += i.toString();
}
return `${alphabet} ${numbers} 汉语 한국어 👽`;
}
const testString = writeTestString();
function sgrTest(): void {
term.write('\n\n\r');
term.writeln(`Character Attributes (SGR, Select Graphic Rendition)`);
const entries: { ps: number, name: string }[] = [
{ ps: 0, name: 'Normal' },
{ ps: 1, name: 'Bold' },
{ ps: 2, name: 'Faint/dim' },
{ ps: 3, name: 'Italicized' },
{ ps: 4, name: 'Underlined' },
{ ps: 5, name: 'Blink' },
{ ps: 7, name: 'Inverse' },
{ ps: 8, name: 'Invisible' },
{ ps: 9, name: 'Crossed-out characters' },
{ ps: 21, name: 'Doubly-underlined' },
{ ps: 22, name: 'Normal' },
{ ps: 23, name: 'Not italicized' },
{ ps: 24, name: 'Not underlined' },
{ ps: 25, name: 'Steady (not blink)' },
{ ps: 27, name: 'Positive (not inverse)' },
{ ps: 28, name: 'Visible (not hidden)' },
{ ps: 29, name: 'Not crossed-out' },
{ ps: 30, name: 'Foreground Black' },
{ ps: 31, name: 'Foreground Red' },
{ ps: 32, name: 'Foreground Green' },
{ ps: 33, name: 'Foreground Yellow' },
{ ps: 34, name: 'Foreground Blue' },
{ ps: 35, name: 'Foreground Magenta' },
{ ps: 36, name: 'Foreground Cyan' },
{ ps: 37, name: 'Foreground White' },
{ ps: 39, name: 'Foreground default' },
{ ps: 40, name: 'Background Black' },
{ ps: 41, name: 'Background Red' },
{ ps: 42, name: 'Background Green' },
{ ps: 43, name: 'Background Yellow' },
{ ps: 44, name: 'Background Blue' },
{ ps: 45, name: 'Background Magenta' },
{ ps: 46, name: 'Background Cyan' },
{ ps: 47, name: 'Background White' },
{ ps: 49, name: 'Background default' },
{ ps: 53, name: 'Overlined' },
{ ps: 55, name: 'Not overlined' }
];
const maxNameLength = entries.reduce<number>((p, c) => Math.max(c.name.length, p), 0);
for (const e of entries) {
term.writeln(`\x1b[0m\x1b[${e.ps}m ${e.ps.toString().padEnd(2, ' ')} ${e.name.padEnd(maxNameLength, ' ')} - ${testString}\x1b[0m`);
}
const entriesByPs: Map<number, string> = new Map();
for (const e of entries) {
entriesByPs.set(e.ps, e.name);
}
const comboEntries: { ps: number[] }[] = [
{ ps: [1, 2, 3, 4, 5, 6, 7, 9] },
{ ps: [2, 41] },
{ ps: [4, 53] }
];
term.write('\n\n\r');
term.writeln(`Combinations`);
for (const e of comboEntries) {
const name = e.ps.map(e => entriesByPs.get(e)).join(', ');
term.writeln(`\x1b[0m\x1b[${e.ps.join(';')}m ${name}\n\r${testString}\x1b[0m`);
}
}
function addAnsiHyperlink(): void {
term.write('\n\n\r');
term.writeln(`Regular link with no id:`);
term.writeln('\x1b]8;;https://github.com\x07GitHub\x1b]8;;\x07');
term.writeln('\x1b]8;;https://xtermjs.org\x07https://xtermjs.org\x1b]8;;\x07\x1b[C<- null cell');
term.writeln(`\nAdjacent links:`);
term.writeln('\x1b]8;;https://github.com\x07GitHub\x1b]8;;https://xtermjs.org\x07\x1b[32mxterm.js\x1b[0m\x1b]8;;\x07');
term.writeln(`\nShared ID link (underline should be shared):`);
term.writeln('╔════╗');
term.writeln('║\x1b]8;id=testid;https://github.com\x07GitH\x1b]8;;\x07║');
term.writeln('║\x1b]8;id=testid;https://github.com\x07ub\x1b]8;;\x07 ║');
term.writeln('╚════╝');
term.writeln(`\nWrapped link with no ID (not necessarily meant to share underline):`);
term.writeln('╔════╗');
term.writeln('║ ║');
term.writeln('║ ║');
term.writeln('╚════╝');
term.write('\x1b[3A\x1b[1C\x1b]8;;https://xtermjs.org\x07xter\x1b[B\x1b[4Dm.js\x1b]8;;\x07\x1b[2B\x1b[5D');
}
/**
* Prints the 20977 characters from the CJK Unified Ideographs unicode block with randomized styles.
*/
function addCjkRandomSgr(): void {
term.write('\n\n\r');
for (let i = 0x4E00; i < 0x9FCC; i++) {
term.write(`\x1b[${getRandomSgr()}m${String.fromCharCode(i)}\x1b[0m`);
}
}
const randomSgrAttributes = [
'1', '2', '3', '4', '5', '6', '7', '9',
'21', '22', '23', '24', '25', '26', '27', '28', '29',
'30', '31', '32', '33', '34', '35', '36', '37', '38', '39',
'40', '41', '42', '43', '44', '45', '46', '47', '48', '49'
];
function getRandomSgr(): string {
return randomSgrAttributes[Math.floor(Math.random() * randomSgrAttributes.length)];
}
function addGraphemeClusters(): void {
term.write('\n\n\r');
term.writeln('🤣🤣🤣🤣🤣🤣🤣🤣🤣🤣 [Simple emoji v6: 10 cells, v15: 20 cells]');
term.writeln('\u{1F476}\u{1F3FF}\u{1F476} [baby with emoji modifier fitzpatrick type-6; baby]');
term.writeln('\u{1F469}\u200d\u{1f469}\u200d\u{1f466} [woman+zwj+woman+zwj+boy]');
term.writeln('\u{1F64B}\u{1F64B}\u{200D}\u{2642}\u{FE0F} [person/man raising hand]');
term.writeln('\u{1F3CB}\u{FE0F}=\u{1F3CB}\u{1F3FE}\u{200D}\u{2640}\u{FE0F} [person lifting weights emoji; woman lighting weights, medium dark]');
term.writeln('\u{1F469}\u{1F469}\u{200D}\u{1F393}\u{1F468}\u{1F3FF}\u{200D}\u{1F393} [woman; woman student; man student dark]');
term.writeln('\u{1f1f3}\u{1f1f4}_ [REGIONAL INDICATOR SYMBOL LETTER N and RI O]');
term.writeln('\u{1f1f3}_\u{1f1f4} {RI N; underscore; RI O]');
term.writeln('\u0061\u0301 [letter a with acute accent]');
term.writeln('\u1100\u1161\u11A8=\u1100\u1161= [Korean Jamo]');
term.writeln('\uAC00=\uD685= [Hangul syllables (pre-composed)]');
term.writeln('(\u26b0\ufe0e) [coffin with text_presentation]');
term.writeln('(\u26b0\ufe0f) [coffin with Emoji_presentation]');
term.writeln('<E\u0301\ufe0fg\ufe0fa\ufe0fl\ufe0fi\ufe0f\ufe0ft\ufe0fe\u0301\ufe0f> [Égalité (using separate acute) emoij_presentation]');
}
function addDecoration(): void {
term.options['overviewRuler'] = { width: 14 };
const marker = term.registerMarker(1);
@@ -1322,23 +839,6 @@ stop at final '?': Maybe this one http://example.com/with?arguments=false?
term.write(linkExamples.split('\n').join('\r\n'));
}
function coloredErase(): void {
const sp5 = ' ';
const data = `
Test BG-colored Erase (BCE):
The color block in the following lines should look identical.
For newly created rows at the bottom the last color should be applied
for all cells to the right.
def 41 42 43 44 45 46 47\x1b[47m
\x1b[m${sp5}\x1b[41m${sp5}\x1b[42m${sp5}\x1b[43m${sp5}\x1b[44m${sp5}\x1b[45m${sp5}\x1b[46m${sp5}\x1b[47m${sp5}
\x1b[m\x1b[5X\x1b[41m\x1b[5C\x1b[5X\x1b[42m\x1b[5C\x1b[5X\x1b[43m\x1b[5C\x1b[5X\x1b[44m\x1b[5C\x1b[5X\x1b[45m\x1b[5C\x1b[5X\x1b[46m\x1b[5C\x1b[5X\x1b[47m\x1b[5C\x1b[5X\x1b[m
`;
term.write(data.split('\n').join('\r\n'));
}
function initImageAddonExposed(): void {
const DEFAULT_OPTIONS: IImageAddonOptions = (addons.image.instance as any)._defaultOpts;
const limitStorageElement = document.querySelector<HTMLInputElement>('#image-storagelimit');