diff --git a/addons/xterm-addon-attach/package.json b/addons/xterm-addon-attach/package.json index 6782c57c..c6225b46 100644 --- a/addons/xterm-addon-attach/package.json +++ b/addons/xterm-addon-attach/package.json @@ -21,6 +21,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-canvas/package.json b/addons/xterm-addon-canvas/package.json index ba19e674..fdc2d93a 100644 --- a/addons/xterm-addon-canvas/package.json +++ b/addons/xterm-addon-canvas/package.json @@ -22,6 +22,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-fit/package.json b/addons/xterm-addon-fit/package.json index da52d15f..1d2f6dd5 100644 --- a/addons/xterm-addon-fit/package.json +++ b/addons/xterm-addon-fit/package.json @@ -21,6 +21,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-ligatures/package.json b/addons/xterm-addon-ligatures/package.json index 7e5e5e90..525f377c 100644 --- a/addons/xterm-addon-ligatures/package.json +++ b/addons/xterm-addon-ligatures/package.json @@ -42,6 +42,6 @@ "yauzl": "^2.10.0" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-ligatures/src/font.ts b/addons/xterm-addon-ligatures/src/font.ts index 5c5f0a6c..ece22367 100644 --- a/addons/xterm-addon-ligatures/src/font.ts +++ b/addons/xterm-addon-ligatures/src/font.ts @@ -3,8 +3,7 @@ * @license MIT */ -import { FontList } from 'font-finder'; -import { Font, loadBuffer, loadFile } from 'font-ligatures'; +import { Font, loadBuffer } from 'font-ligatures'; import parse from './parse'; @@ -24,7 +23,7 @@ interface IFontAccessNavigator { }; } -let fontsPromise: Promise> | undefined = undefined; +let fontsPromise: Promise> | undefined = undefined; /** * Loads the font ligature wrapper for the specified font family if it could be @@ -81,14 +80,6 @@ export default async function load(fontFamily: string, cacheSize: number): Promi console.error(err.name, err.message); } } - // Node environment or no font access API - else { - try { - fontsPromise = (await import('font-finder')).list(); - } catch (err) { - // No-op - } - } if (!fontsPromise) { fontsPromise = Promise.resolve({}); } @@ -110,7 +101,7 @@ export default async function load(fontFamily: string, cacheSize: number): Promi const buffer = await bytes.arrayBuffer(); return loadBuffer(buffer, { cacheSize }); } - return await loadFile(font.path, { cacheSize }); + return undefined; } } diff --git a/addons/xterm-addon-ligatures/src/index.test.ts b/addons/xterm-addon-ligatures/src/index.test.ts index 0cfe2462..c7bf09ce 100644 --- a/addons/xterm-addon-ligatures/src/index.test.ts +++ b/addons/xterm-addon-ligatures/src/index.test.ts @@ -69,76 +69,6 @@ describe('xterm-addon-ligatures', () => { assert.deepEqual(term.joiner!(input), []); }); - it('returns the correct set of ranges once the font has loaded', done => { - assert.deepEqual(term.joiner!(input), []); - onRefresh.callsFake(() => { - assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); - done(); - }); - }); - - it('handles quoted font names', done => { - term.options.fontFamily = '"Fira Code", monospace'; - assert.deepEqual(term.joiner!(input), []); - onRefresh.callsFake(() => { - assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); - done(); - }); - }); - - it('falls back to later fonts if earlier ones are not present', done => { - term.options.fontFamily = 'notinstalled, Fira Code, monospace'; - assert.deepEqual(term.joiner!(input), []); - onRefresh.callsFake(() => { - assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); - done(); - }); - }); - - it('uses the current font value', done => { - // The first three calls are all synchronous so that we don't allow time for - // any fonts to load while we're switching things around - term.options.fontFamily = 'Fira Code'; - assert.deepEqual(term.joiner!(input), []); - term.options.fontFamily = 'notinstalled'; - assert.deepEqual(term.joiner!(input), []); - term.options.fontFamily = 'Iosevka'; - assert.deepEqual(term.joiner!(input), []); - onRefresh.callsFake(() => { - assert.deepEqual(term.joiner!(input), [[2, 4]]); - - // And switch it back to Fira Code for good measure - term.options.fontFamily = 'Fira Code'; - - // At this point, we haven't loaded the new font, so the result reverts - // back to empty until that happens - assert.deepEqual(term.joiner!(input), []); - - onRefresh.callsFake(() => { - assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); - done(); - }); - }); - }); - - it('allows multiple terminal instances that use different fonts', done => { - const onRefresh2 = sinon.stub(); - const term2 = new MockTerminal(onRefresh2); - term2.options.fontFamily = 'Iosevka'; - ligatureSupport.enableLigatures(term2 as any); - - assert.deepEqual(term.joiner!(input), []); - onRefresh.callsFake(() => { - assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); - assert.deepEqual(term2.joiner!(input), []); - onRefresh2.callsFake(() => { - assert.deepEqual(term2.joiner!(input), [[2, 4]]); - assert.deepEqual(term.joiner!(input), [[2, 4], [7, 10]]); - done(); - }); - }); - }); - it('fails if it finds but cannot load the font', async () => { term.options.fontFamily = 'Nonexistant Font, monospace'; assert.deepEqual(term.joiner!(input), []); diff --git a/addons/xterm-addon-ligatures/src/index.ts b/addons/xterm-addon-ligatures/src/index.ts index 82589e36..82675626 100644 --- a/addons/xterm-addon-ligatures/src/index.ts +++ b/addons/xterm-addon-ligatures/src/index.ts @@ -3,7 +3,7 @@ * @license MIT */ -import { Terminal } from 'xterm'; +import type { Terminal } from 'xterm'; import { Font } from 'font-ligatures'; import load from './font'; diff --git a/addons/xterm-addon-ligatures/webpack.config.js b/addons/xterm-addon-ligatures/webpack.config.js index ea69841e..5aeebe2e 100644 --- a/addons/xterm-addon-ligatures/webpack.config.js +++ b/addons/xterm-addon-ligatures/webpack.config.js @@ -11,7 +11,6 @@ const mainFile = 'xterm-addon-ligatures.js'; module.exports = { entry: `./out/${addonName}.js`, devtool: 'source-map', - target: 'electron-renderer', module: { rules: [ { @@ -30,18 +29,19 @@ module.exports = { }, mode: 'production', externals: { - 'font-finder': 'font-finder', + 'fs': 'fs', + 'path': 'path', 'stream': 'stream', - 'os': 'os', 'util': 'util' }, resolve: { // The ligature modules contains fallbacks for node environments, we never want to browserify them fallback: { - stream: false, - util: false, + fs: false, os: false, - path: false + path: false, + stream: false, + util: false } } }; diff --git a/addons/xterm-addon-search/package.json b/addons/xterm-addon-search/package.json index fb76f07b..8a75c812 100644 --- a/addons/xterm-addon-search/package.json +++ b/addons/xterm-addon-search/package.json @@ -21,6 +21,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-serialize/package.json b/addons/xterm-addon-serialize/package.json index bd7605d9..94562688 100644 --- a/addons/xterm-addon-serialize/package.json +++ b/addons/xterm-addon-serialize/package.json @@ -24,6 +24,6 @@ "benchmark-eval": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --eval out-benchmark/benchmark/*benchmark.js" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-unicode11/package.json b/addons/xterm-addon-unicode11/package.json index c4d1f8e3..275cca4a 100644 --- a/addons/xterm-addon-unicode11/package.json +++ b/addons/xterm-addon-unicode11/package.json @@ -21,6 +21,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-web-links/package.json b/addons/xterm-addon-web-links/package.json index 21a3ef4d..2cfbae6c 100644 --- a/addons/xterm-addon-web-links/package.json +++ b/addons/xterm-addon-web-links/package.json @@ -21,6 +21,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/addons/xterm-addon-webgl/package.json b/addons/xterm-addon-webgl/package.json index fce8e24b..45b04897 100644 --- a/addons/xterm-addon-webgl/package.json +++ b/addons/xterm-addon-webgl/package.json @@ -22,6 +22,6 @@ "prepublishOnly": "npm run package" }, "peerDependencies": { - "xterm": "^4.0.0" + "xterm": "^5.0.0" } } diff --git a/demo/client.ts b/demo/client.ts index c0d3af6d..64c694f5 100644 --- a/demo/client.ts +++ b/demo/client.ts @@ -82,7 +82,7 @@ interface IDemoAddon { never; } -const addons: { [T in AddonType]: IDemoAddon} = { +const addons: { [T in AddonType]: IDemoAddon } = { attach: { name: 'attach', ctor: AttachAddon, canChange: false }, canvas: { name: 'canvas', ctor: CanvasAddon, canChange: true }, fit: { name: 'fit', ctor: FitAddon, canChange: false }, @@ -188,6 +188,7 @@ if (document.location.pathname === '/test') { document.getElementById('load-test').addEventListener('click', loadTest); document.getElementById('powerline-symbol-test').addEventListener('click', powerlineSymbolTest); document.getElementById('underline-test').addEventListener('click', underlineTest); + document.getElementById('ansi-colors').addEventListener('click', ansiColorsTest); document.getElementById('add-decoration').addEventListener('click', addDecoration); document.getElementById('add-overview-ruler').addEventListener('click', addOverviewRuler); } @@ -230,18 +231,23 @@ function createTerminal(): void { const rows = size.rows; const url = '/terminals/' + pid + '/size?cols=' + cols + '&rows=' + rows; - fetch(url, {method: 'POST'}); + fetch(url, { method: 'POST' }); }); protocol = (location.protocol === 'https:') ? 'wss://' : 'ws://'; socketURL = protocol + location.hostname + ((location.port) ? (':' + location.port) : '') + '/terminals/'; term.open(terminalContainer); addons.fit.instance!.fit(); - typedTerm.loadAddon(addons.webgl.instance); - setTimeout(() => { - addTextureAtlas(addons.webgl.instance.textureAtlas); - addons.webgl.instance.onChangeTextureAtlas(e => addTextureAtlas(e)); - }, 0); + try { + typedTerm.loadAddon(addons.webgl.instance); + setTimeout(() => { + addTextureAtlas(addons.webgl.instance.textureAtlas); + addons.webgl.instance.onChangeTextureAtlas(e => addTextureAtlas(e)); + }, 0); + } + catch { + addons.webgl.instance = undefined; + } term.focus(); addDomListener(paddingElement, 'change', setPadding); @@ -270,7 +276,7 @@ function createTerminal(): void { // Set terminal size again to set the specific dimensions on the demo updateTerminalSize(); - fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, {method: 'POST'}).then((res) => { + fetch('/terminals?cols=' + term.cols + '&rows=' + term.rows, { method: 'POST' }).then((res) => { res.text().then((processId) => { pid = processId; socketURL += processId; @@ -315,7 +321,7 @@ function runFakeTerminal(): void { if (ev.keyCode === 13) { term.prompt(); } else if (ev.keyCode === 8) { - // Do not delete the prompt + // Do not delete the prompt if (term._core.buffer.x > 2) { term.write('\b \b'); } @@ -501,13 +507,20 @@ function initAddons(term: TerminalType): void { addDomListener(checkbox, 'change', () => { if (checkbox.checked) { addon.instance = new addon.ctor(); - term.loadAddon(addon.instance); - if (name === 'webgl') { - (addon.instance as WebglAddon).onChangeTextureAtlas(e => addTextureAtlas(e)); - } else if (name === 'unicode11') { - term.unicode.activeVersion = '11'; - } else if (name === 'search') { - addon.instance.onDidChangeResults(e => updateFindResults(e)); + try { + term.loadAddon(addon.instance); + if (name === 'webgl') { + (addon.instance as WebglAddon).onChangeTextureAtlas(e => addTextureAtlas(e)); + } else if (name === 'unicode11') { + term.unicode.activeVersion = '11'; + } else if (name === 'search') { + addon.instance.onDidChangeResults(e => updateFindResults(e)); + } + } + catch { + addon.instance = undefined; + checkbox.checked = false; + checkbox.disabled = true; } } else { if (name === 'webgl') { @@ -789,6 +802,31 @@ function underlineTest() { term.write('\x1b[0m\n\r'); } +function ansiColorsTest() { + 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 addDecoration() { term.options['overviewRulerWidth'] = 15; const marker = term.registerMarker(1); @@ -806,13 +844,13 @@ function addDecoration() { function addOverviewRuler() { term.options['overviewRulerWidth'] = 15; - term.registerDecoration({marker: term.registerMarker(1), overviewRulerOptions: { color: '#ef2929' }}); - term.registerDecoration({marker: term.registerMarker(3), overviewRulerOptions: { color: '#8ae234' }}); - term.registerDecoration({marker: term.registerMarker(5), overviewRulerOptions: { color: '#729fcf' }}); - term.registerDecoration({marker: term.registerMarker(7), overviewRulerOptions: { color: '#ef2929', position: 'left' }}); - term.registerDecoration({marker: term.registerMarker(7), overviewRulerOptions: { color: '#8ae234', position: 'center' }}); - term.registerDecoration({marker: term.registerMarker(7), overviewRulerOptions: { color: '#729fcf', position: 'right' }}); - term.registerDecoration({marker: term.registerMarker(10), overviewRulerOptions: { color: '#8ae234', position: 'center' }}); - term.registerDecoration({marker: term.registerMarker(10), overviewRulerOptions: { color: '#ffffff80', position: 'full' }}); + term.registerDecoration({ marker: term.registerMarker(1), overviewRulerOptions: { color: '#ef2929' } }); + term.registerDecoration({ marker: term.registerMarker(3), overviewRulerOptions: { color: '#8ae234' } }); + term.registerDecoration({ marker: term.registerMarker(5), overviewRulerOptions: { color: '#729fcf' } }); + term.registerDecoration({ marker: term.registerMarker(7), overviewRulerOptions: { color: '#ef2929', position: 'left' } }); + term.registerDecoration({ marker: term.registerMarker(7), overviewRulerOptions: { color: '#8ae234', position: 'center' } }); + term.registerDecoration({ marker: term.registerMarker(7), overviewRulerOptions: { color: '#729fcf', position: 'right' } }); + term.registerDecoration({ marker: term.registerMarker(10), overviewRulerOptions: { color: '#8ae234', position: 'center' } }); + term.registerDecoration({ marker: term.registerMarker(10), overviewRulerOptions: { color: '#ffffff80', position: 'full' } }); } diff --git a/demo/index.html b/demo/index.html index 214dd25f..836084b3 100644 --- a/demo/index.html +++ b/demo/index.html @@ -78,6 +78,7 @@
+
Decorations