Compare commits

...
533 Commits
Author SHA1 Message Date
Daniel Imms 24f431b290 Merge pull request #3333 from Tyriar/v4_12
v4.12.0
2021-05-11 07:11:42 -07:00
Daniel Imms 0c47cd4d4d v4.12.0 2021-05-11 07:09:41 -07:00
Daniel Imms 33f0105d29 Merge pull request #3332 from Tyriar/scroll_refresh
Make sure all rows are refreshed on input
2021-05-11 07:02:41 -07:00
Daniel Imms bcbcc71bfc Trigger scroll when ignoring event
This is a less aggressive fix that doesn't regress tests
2021-05-11 06:52:04 -07:00
Daniel Imms da39129bd2 Revert "Make sure all rows are refreshed on input"
This reverts commit 973eb7b350.
2021-05-11 06:48:17 -07:00
Daniel Imms 973eb7b350 Make sure all rows are refreshed on input
Fixes #3323
2021-05-11 05:10:04 -07:00
Daniel Imms 8f9f2550ef Merge pull request #3327 from Tyriar/tasks
Don't start npm start until watch is done
2021-05-10 05:36:54 -07:00
Daniel Imms 673695068e Don't start npm start until watch is done 2021-05-10 05:35:06 -07:00
Daniel Imms 07c123309f Merge pull request #3322 from vladdoster/patch-1
(docs) update README.md
2021-05-07 04:59:19 -07:00
vlad doster 6a63be9107 (docs) update README.md
- correct spelling
- correct grammar
- reduce verbiage
- correct punctuation
2021-05-07 04:38:12 -05:00
Daniel Imms 978b2a9886 Merge pull request #3321 from xtermjs/dependabot/npm_and_yarn/addons/xterm-addon-ligatures/lodash-4.17.21
Bump lodash from 4.17.19 to 4.17.21 in /addons/xterm-addon-ligatures
2021-05-06 14:18:43 -07:00
dependabot[bot] d1ce8a0586 Bump lodash from 4.17.19 to 4.17.21 in /addons/xterm-addon-ligatures
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.19 to 4.17.21.
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.19...4.17.21)

Signed-off-by: dependabot[bot] <support@github.com>
2021-05-06 21:08:45 +00:00
Daniel Imms dc61950311 Merge pull request #3320 from xtermjs/dependabot/npm_and_yarn/lodash-4.17.21
[Security] Bump lodash from 4.17.20 to 4.17.21
2021-05-06 14:07:58 -07:00
dependabot-preview[bot] 0ba0845563 [Security] Bump lodash from 4.17.20 to 4.17.21
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.20 to 4.17.21. **This update includes a security fix.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.20...4.17.21)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-05-06 20:39:34 +00:00
Daniel Imms d70ba1dc23 Merge pull request #3318 from meganrogge/bufferRange
Fix selection range
2021-05-06 05:02:25 -07:00
meganrogge 9403478049 tweak test 2021-05-05 19:49:33 -07:00
meganrogge 20f320327c Tweak range 2021-05-05 19:45:36 -07:00
meganrogge 9a5f85cc24 remove .only 2021-05-05 12:29:55 -07:00
meganrogge be32590ef0 fix #https://github.com/microsoft/vscode/issues/123000 2021-05-05 08:21:26 -07:00
Daniel Imms e5c9b0e27f Merge pull request #3314 from jeanp413/fix-undefined-soundService
Fixes undefined soundService
2021-05-04 10:39:25 -07:00
jeanp413 58527bb2ff Fixes undefined soundService 2021-05-04 11:23:31 -05:00
Daniel Imms 4a7bbe6738 Merge pull request #3313 from Tyriar/scroll_suppress
Ensure all viewport scroll events are handled by buffer
2021-04-28 13:00:38 -07:00
Daniel Imms d616aaa4f8 Ensure all viewport scroll events are handled by buffer
Some scroll events were never making it to the buffer service when using
a trackpad.

See microsoft/vscode#121017
Fixes #3311
2021-04-28 12:51:40 -07:00
Daniel Imms 376b29673b Merge pull request #3296 from Tyriar/asserttimeout
Don't assert on leave events
2021-04-06 14:05:39 -07:00
Daniel Imms 636e59b949 Merge branch 'master' into asserttimeout 2021-04-06 13:15:01 -07:00
Daniel Imms e3615f63e0 Merge pull request #3299 from bmf-ribeiro/feat/enable-windows-integration-tests
Feat/enable windows integration tests
2021-04-06 13:07:01 -07:00
Daniel Imms 0b02a3c774 Merge branch 'master' into asserttimeout 2021-04-06 13:00:42 -07:00
Daniel Imms 87ef131945 Merge branch 'master' into feat/enable-windows-integration-tests 2021-04-06 12:59:16 -07:00
Daniel Imms 6370a936b8 Merge pull request #3298 from bmf-ribeiro/feat/2714-start-server-on-integration-tests
Fix #2714 - Start demo server before running integration tests
2021-04-06 12:58:31 -07:00
Bruno Ribeiro e686527f87 Try to enable windows integration tests 2021-04-06 17:47:12 +01:00
Bruno Ribeiro c312317af0 Merge branch 'master' into feat/2714-start-server-on-integration-tests 2021-04-06 17:34:01 +01:00
Bruno Ribeiro b8af0ecf05 Await for server to be fully started 2021-04-06 17:21:39 +01:00
Bruno Ribeiro ab659fda5f Remove Start Test Server from pipelines as it now starts in the tests 2021-04-06 16:51:17 +01:00
Bruno Ribeiro 27c87319c1 Fix #2714 - Start demo server before running integration tests
- Use port 3001 instead of  300 to not conflict with the demo
2021-04-06 15:48:48 +01:00
Daniel Imms 5d4cea2119 Merge branch 'master' into asserttimeout 2021-04-06 07:07:58 -07:00
Daniel Imms 26cda84eab Merge pull request #3295 from xtermjs/Tyriar-patch-1
Fix whitespace
2021-04-06 06:50:22 -07:00
Daniel Imms c4fc90e3f8 Don't assert on leave events 2021-04-06 06:50:07 -07:00
Daniel Imms 985040e1cc Merge branch 'master' into Tyriar-patch-1 2021-04-06 06:34:52 -07:00
Daniel Imms 95fcf2f354 Merge pull request #3294 from Tyriar/pollfor
Give actionable error when pollFor times out
2021-04-06 06:34:43 -07:00
Daniel Imms 1422d935d0 Fix whitespace 2021-04-06 06:34:20 -07:00
Daniel Imms 5973e8f0dd Remove unused function 2021-04-06 06:28:49 -07:00
Daniel Imms 934467d484 Give actionable error when pollFor times out 2021-04-06 06:27:39 -07:00
Daniel Imms eedc314ca2 Merge pull request #3290 from nikonso/feat/3014-add-onBell-event-listener
Fix #3014  - Add onBell event listener to allow embeders to hook into it
2021-04-06 05:56:43 -07:00
Daniel Imms 2556137b51 Remove only 2021-04-06 05:44:36 -07:00
Daniel Imms 826493161a Api polish 2021-04-06 05:40:56 -07:00
Daniel Imms 19716957e4 Fix api test 2021-04-06 05:40:29 -07:00
Daniel Imms 3d29357d1d Fix test/lint 2021-04-06 05:34:20 -07:00
Daniel Imms 9143cf4904 Merge branch 'master' into feat/3014-add-onBell-event-listener 2021-04-06 05:28:29 -07:00
Daniel Imms c7978f78a2 Merge pull request #3291 from whattheserver/patch-1
Update README.md
2021-04-06 05:25:57 -07:00
WhatTheServer af26e27e23 Update README.md 2021-04-04 00:09:10 -04:00
Bruno Ribeiro 7b7b7a36db Fix #3014
- Add onBell event listener to allow embeders to hook into it
2021-04-03 16:34:00 +01:00
Daniel Imms 8a1d2cf0f4 Whitespace change to force ligatures publish 2021-04-02 14:22:49 -07:00
Daniel Imms 98f2576497 Merge pull request #3286 from Tyriar/webgl_liga
Webgl ligature support
2021-04-02 11:39:45 -07:00
Daniel Imms 00fa7bec42 Null out secondary ligature chars in cache 2021-04-02 11:32:02 -07:00
Daniel Imms b03a25f4c7 Webgl ligature support
Fixes #3094
2021-04-02 11:15:57 -07:00
Daniel Imms cf8a3514bc Merge pull request #3285 from Tyriar/dom_ligatures
Support for ligatures in DOM renderer
2021-04-02 10:45:41 -07:00
Daniel Imms b7320794bb Ligature support for dom renderer
Fixes #3283
2021-04-02 10:34:14 -07:00
Daniel Imms d8113aa533 Default to Fira Code in demo 2021-04-02 10:21:20 -07:00
Daniel Imms 16a70bdeb7 Merge pull request #3264 from LabhanshAgrawal/local_fonts
Enable using ligatures addon outside electron
2021-04-02 09:43:34 -07:00
Daniel Imms 0564ad4653 Add comments to webpack configs 2021-04-02 09:42:10 -07:00
Daniel Imms a57910e2fa Check navigator safely in node 2021-04-02 08:33:00 -07:00
Daniel Imms 4fa58c978b Fix lint 2021-04-02 07:58:59 -07:00
Daniel Imms 54cdbb3035 Merge branch 'master' into local_fonts 2021-04-02 07:57:51 -07:00
Daniel Imms 367eb45586 Merge pull request #3284 from Tyriar/tyriar/charJoinerService
Convert CharacterJoinerRegistry to a service
2021-04-02 07:57:38 -07:00
Daniel Imms 1124f8b513 Improve error when adding char joiner before open 2021-04-02 07:57:24 -07:00
Daniel Imms 233b78d258 Merge pull request #3282 from Tyriar/spacing_eslint
Require spacing of objects outside of test files
2021-04-02 07:52:37 -07:00
Daniel Imms 5f96f33cf0 Fix dangling comma 2021-04-02 07:50:22 -07:00
Daniel Imms b511f1b52a Fix other case of no spacing 2021-04-02 07:46:30 -07:00
Daniel Imms 6b3fd2f31a Merge branch 'master' into spacing_eslint 2021-04-02 07:45:31 -07:00
Daniel Imms 6501ab044c Merge branch 'master' into tyriar/charJoinerService 2021-04-02 07:44:28 -07:00
Daniel Imms 999116c536 Convert CharacterJoinerRegistry to a service
Part of #3094, #3283
2021-04-02 07:43:39 -07:00
Daniel Imms f19d7f0b70 Require spacing of objects outside of test files 2021-04-02 07:08:06 -07:00
Daniel Imms 1e499c7867 Disable ligatures addon by default
Since it needs a user action to trigger the permissions prompt
2021-04-02 06:57:11 -07:00
Daniel Imms b9d3deae56 Merge branch 'master' into local_fonts 2021-04-02 06:42:48 -07:00
Daniel Imms 0421f6ebcf Merge pull request #3279 from Tyriar/tyriar/powerline
Don't pad powerline glyphs and use ideographic text baseline
2021-04-01 17:45:44 -07:00
Daniel Imms a510ffb3c0 Use ideographic baseline for canvas 2021-04-01 17:10:14 -07:00
Daniel Imms 62f5b8291d Use ideographic over middle
This seems to correctly center the glyphs within the cell, making powerline
fonts appear perfectly aligned.

Fixes #3281
2021-04-01 17:05:29 -07:00
Megan Rogge f9945b3439 Merge pull request #3276 from meganrogge/webgl
add onContextLoss to webgl addon
2021-04-01 17:02:57 -07:00
Daniel Imms 62ca4b7e13 Correct restricted glyph padding 2021-04-01 17:00:02 -07:00
Megan Rogge 6f59b56958 Merge branch 'master' into webgl 2021-04-01 16:57:21 -07:00
meganrogge 113086f97a tweak readme, expose API 2021-04-01 16:57:19 -07:00
Daniel Imms b6d3120086 Restrict all sides of powerline glyphs 2021-04-01 16:55:27 -07:00
Daniel Imms 117f990055 Don't pad powerline glyphs
Fixes #3278
2021-04-01 16:39:59 -07:00
Daniel Imms 337c11d580 Merge pull request #3277 from meganrogge/bufferService
Move scroll to BufferService
2021-04-01 16:01:30 -07:00
Daniel Imms ecb485d2f5 Remove _cachedBlankLine 2021-04-01 15:54:47 -07:00
Daniel Imms c5339116b5 Add note to readme on handling context loss 2021-04-01 15:45:10 -07:00
meganrogge b1877b4dc7 onRecoverContext -> onContextLoss 2021-04-01 13:32:35 -07:00
meganrogge 1c087f6bcd cherry picked commits and scrollSource 2021-04-01 13:24:02 -07:00
meganrogge e40f340036 use bufferService methods 2021-04-01 13:18:20 -07:00
meganrogge c096633f91 get tests to pass
Co-authored-by: Daniel Imms <daimms@microsoft.com>
2021-04-01 13:17:53 -07:00
meganrogge b074c2552a use bufferService in terminal to reduce code a bunch 2021-04-01 13:17:48 -07:00
meganrogge e2885f3a38 move stuff to inputHandler and move scroll to bufferService 2021-04-01 13:16:39 -07:00
Megan Rogge 47ac4dd9fe Merge branch 'master' into webgl 2021-04-01 12:18:21 -07:00
meganrogge fa7889cdd0 add onRecovercontext event 2021-04-01 12:17:34 -07:00
Daniel Imms 759379dfb1 Merge pull request #3205 from schrej/fix/scroll-events
emit onScroll events when user is scrolling
2021-04-01 12:11:47 -07:00
Daniel Imms 87ed4f07cd Tidy up syncTextArea 2021-04-01 12:05:24 -07:00
Daniel Imms 07499380d1 Remove RenderService check, it must be passed to ctor 2021-04-01 12:05:21 -07:00
Daniel Imms 3ae61fc1dd Use buffer y for relative cursor pos 2021-04-01 12:05:17 -07:00
Daniel Imms 085a2b545f Remove now unneeded CharSizeService 2021-04-01 12:05:12 -07:00
kena0ki 49cb6f74bc Remove non-null assertion 2021-04-01 12:05:05 -07:00
kena0ki d4a93fe7e4 Use RenderService.dimensions instead of CharSizeService for textarea position 2021-04-01 12:05:00 -07:00
Daniel Imms f4861aa74a Move onScroll next to _onScroll 2021-04-01 08:54:29 -07:00
Daniel Imms 1925f1f442 Improve whitespace 2021-04-01 08:41:29 -07:00
Daniel Imms 6355852d09 Merge remote-tracking branch 'ups/master' into pr/schrej/3205 2021-04-01 08:36:14 -07:00
Daniel Imms e1641c57fc Merge pull request #3169 from kena0ki/issue#3024
Use RenderService.dimensions instead of CharSizeService for textarea position
2021-04-01 08:34:39 -07:00
Daniel Imms 7b920adbe9 Tidy up syncTextArea 2021-04-01 08:26:35 -07:00
Daniel Imms 05516750b5 Remove RenderService check, it must be passed to ctor 2021-04-01 08:23:35 -07:00
Daniel Imms b62a64519f Use buffer y for relative cursor pos 2021-04-01 08:23:18 -07:00
Daniel Imms e9e716964e Remove now unneeded CharSizeService 2021-04-01 08:19:12 -07:00
kena0ki a15f61bb85 Remove non-null assertion 2021-04-01 00:11:30 +09:00
kena0ki de334ea116 Use RenderService.dimensions instead of CharSizeService for textarea position 2021-03-31 23:32:53 +09:00
Daniel Imms dd952ac166 Merge pull request #3230 from marvinthepa/682_url_selector
Use linkifier2 to double click select links
2021-03-30 06:25:26 -07:00
Daniel Imms d2471b4301 Update src/browser/Types.d.ts 2021-03-30 06:19:39 -07:00
Daniel Imms 04092c80e8 Update src/browser/services/SelectionService.ts 2021-03-30 06:19:34 -07:00
Daniel Imms b7e0489a53 Remove offset from link
The link range is absolute, not relative to viewport
2021-03-30 06:18:17 -07:00
Daniel Imms daf1128df7 Merge branch 'master' into 682_url_selector 2021-03-30 05:34:38 -07:00
Daniel Imms 36c436d4e0 Merge pull request #3273 from Tyriar/webgl_stable
Remove experimental note from webgl renderer
2021-03-30 05:33:59 -07:00
Daniel Imms edf783f155 Merge pull request #3270 from xtermjs/dependabot/npm_and_yarn/y18n-4.0.1
[Security] Bump y18n from 4.0.0 to 4.0.1
2021-03-30 05:16:20 -07:00
Daniel Imms dafe7ea3da Remove experimental note from webgl renderer
Fixes #2033
2021-03-30 04:45:41 -07:00
dependabot-preview[bot] cbe056c27e [Security] Bump y18n from 4.0.0 to 4.0.1
Bumps [y18n](https://github.com/yargs/y18n) from 4.0.0 to 4.0.1. **This update includes a security fix.**
- [Release notes](https://github.com/yargs/y18n/releases)
- [Changelog](https://github.com/yargs/y18n/blob/master/CHANGELOG.md)
- [Commits](https://github.com/yargs/y18n/commits)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2021-03-29 18:46:53 +00:00
Daniel Imms e78561b7b6 Merge pull request #3269 from coderaiser/lint-using-putout
Lint using putout part 3
2021-03-29 02:07:47 -07:00
coderaiser de791cfb35 chore: lint using putout 2021-03-28 15:27:03 +03:00
Daniel Imms 6d1a2f3b57 Merge pull request #3267 from jerch/writeSync_fix
writeSync callstack fix
2021-03-26 05:10:35 -07:00
Jörg Breitbart e106cd02cf fix callstack overflow of writeSync 2021-03-26 12:46:39 +01:00
Thomas Zilz 787ef30279 Revert "Noch mehr änderungen"
This reverts commit b666e6a924.
2021-03-25 14:09:47 +01:00
Thomas Zilz 61519cc10c Revert "Test test"
This reverts commit 61213159ee.
2021-03-25 14:09:44 +01:00
Thomas Zilz b666e6a924 Noch mehr änderungen 2021-03-25 13:59:20 +01:00
Thomas Zilz 61213159ee Test test 2021-03-25 13:55:29 +01:00
Labhansh Agrawal 67934ff35f Enable using ligatures addon outside electron 2021-03-24 20:44:14 +05:30
Daniel Imms 8c1833f117 Merge pull request #3258 from dstein64/master
Add gifcast to "Real-world uses" in README.md
2021-03-19 18:10:37 -07:00
Daniel Steinberg c2f4c4dd32 Add gifcast to "Real-world uses" in README.md 2021-03-19 18:40:36 -04:00
Daniel Imms c4ed61e831 Merge pull request #3257 from xtermjs/Tyriar-patch-1
Change warning to one per session not terminal
2021-03-19 06:32:45 -07:00
Daniel Imms 5c5ca4e213 Change warning to one per session not terminal 2021-03-19 06:24:42 -07:00
Daniel Imms 6edfa513f3 Merge pull request #3256 from jerch/silence_writeSync_warning
silence writeSync warning
2021-03-19 06:02:40 -07:00
Jörg Breitbart 5170a12cb1 silence writeSync warning 2021-03-19 01:07:43 +01:00
Daniel Imms 9a90f1f4ab Merge pull request #3251 from Python-37/Fix-bug-of-some-IMEs-cannot-input-in-terminal
Fix bug of some IMEs cannot input in terminal
2021-03-18 08:49:56 -07:00
Daniel Imms 886f285ab7 Remove old setting dimensions 2021-03-18 08:31:13 -07:00
Daniel Imms 00bdd2805a Ensure in js that the textarea is always > 1x1px 2021-03-18 08:14:27 -07:00
Daniel Imms d392bdb5ea Merge branch 'master' into Fix-bug-of-some-IMEs-cannot-input-in-terminal 2021-03-18 07:00:43 -07:00
jerch 145b4874cb Merge pull request #3222 from jerch/async_handlers
async parser handler support
2021-03-17 22:50:14 +01:00
Jörg Breitbart 869c11f1d8 interface for subparser stack saves 2021-03-17 22:39:09 +01:00
Jörg Breitbart 8e7cdd2587 interface for inputhandler parse stack, proper typing of LogService.logLevel 2021-03-17 22:29:01 +01:00
Jörg Breitbart 76fdf9d378 Merge branch 'async_handlers' of github.com:jerch/xterm.js into async_handlers 2021-03-17 22:08:36 +01:00
Jörg Breitbart a7488456d8 Merge branch 'master' into async_handlers 2021-03-17 22:08:19 +01:00
Martin Sander 5185e5f894 Use linkifier2 to double click select links
Also works with right click select.
Fixes #682.
2021-03-16 16:42:38 +01:00
jerch c19cc9b2d6 Merge branch 'master' into async_handlers 2021-03-15 21:53:59 +01:00
Python-37 7968b7ce7e Fix bug of some IMEs cannot input in terminal
Fix bug of QQ pinyin and Rime IME cannot input characters in terminal.
2021-03-10 17:27:58 +08:00
Megan Rogge ee88fca8c0 Merge pull request #3249 from xtermjs/release
v 4.11.0
2021-03-09 10:21:03 -08:00
meganrogge 9b3fbc9b84 v 4.11.0 2021-03-09 10:18:14 -08:00
Jörg Breitbart cdd238d75e do not timeout on faulty async handlers, continue with false to give default handlers chance to run 2021-02-28 13:53:06 +01:00
Jörg Breitbart 48a93c379f log a warning if an async handler takes too long 2021-02-27 22:24:55 +01:00
Jörg Breitbart cc005a274d multiple changes:
- reorder exception throwing to be sync to band position
- document WriteBuffer._innerWrite
- remove any declarations
- remove conditional assigments
- use faster return value branching in all parsers
- remove dead code in benchmark
2021-02-27 20:18:41 +01:00
Jörg Breitbart 26bf1ab840 Merge branch 'master' into async_handlers 2021-02-25 19:07:28 +01:00
Jörg Breitbart b4635eddf3 make reset async aware 2021-02-25 19:04:37 +01:00
Jörg Breitbart 6b57921567 async handler API tests 2021-02-25 17:41:16 +01:00
Jörg Breitbart d500b0f204 inputhandler tests 2021-02-25 17:06:32 +01:00
Jörg Breitbart 9985ae2c38 fix linter warning 2021-02-25 15:44:39 +01:00
Jörg Breitbart bce3269e44 async OSC/DCS registering/dispose tests on parser instance 2021-02-25 15:41:10 +01:00
Daniel Imms 187f072f43 Merge pull request #3244 from nxshell/patch-1
feat: Add nxshell which use xtermjs
2021-02-16 04:42:09 -08:00
nxshell 3ab2376517 feat: Add nxshell which use xtermjs 2021-02-16 19:37:03 +08:00
Jörg Breitbart 26502114d4 minor tweaks, API docs update 2021-02-15 16:24:29 +01:00
Jörg Breitbart 5db479c25d update public API 2021-02-08 03:35:42 +01:00
Jörg Breitbart d0b555687f update parser hooks api and tests 2021-02-08 03:28:49 +01:00
Jörg Breitbart 041e259c11 OSC impl, OscParser tests 2021-02-08 03:03:28 +01:00
Jörg Breitbart d59f4d2f6f async impl for DCS, DcsParser tests 2021-02-08 01:53:59 +01:00
Jörg Breitbart 898a18db21 Merge branch 'master' into async_handlers 2021-02-07 23:14:30 +01:00
Daniel Imms a73fe62b7a Merge pull request #3243 from jeanp413/measure-charsize-on-devicePixelRatioChange
Force char size measurement when devicePixelRatio changes
2021-02-05 11:39:31 -08:00
jeanp413 350f6cfea1 Fixes https://github.com/microsoft/vscode/issues/102194 2021-02-05 11:15:39 -05:00
Daniel Imms 2936f80013 Merge pull request #3233 from marvinthepa/3056_hover_callback_link_providers
Add hover and leave callbacks for linkprovider
2021-02-03 05:35:15 -08:00
Daniel Imms dec9f6d254 Merge branch 'master' into 3056_hover_callback_link_providers 2021-02-03 05:29:08 -08:00
Daniel Imms bd6676d3b6 Move options to addon and avoid recreating options 2021-02-03 05:28:23 -08:00
Daniel Imms d9309d33af Merge pull request #3232 from jeanp413/fix-3221
Fix webgl renderer does not render when writing if a selection exists
2021-02-03 05:17:18 -08:00
Daniel Imms bb9802e754 Merge branch 'master' into fix-3221 2021-02-03 05:10:48 -08:00
ew eec804dd7c Add hover and leave callbacks for linkprovider
Fixes #3056.
2021-02-03 10:25:33 +01:00
jeanp413 ff6d3a0768 Refresh selection on resize as dimensions changed 2021-02-03 01:29:39 -05:00
jeanp413 94d37bbe4c Keep selection on resize and when changing colors 2021-02-03 00:24:53 -05:00
Daniel Imms 36136a4c29 Merge pull request #3241 from mmis1000/fix/serialize-addon-typings
SerializeAddon: fix parameter name in typing
2021-02-02 19:58:01 -08:00
Mmis1000 8b273e6939 SerializeAddon: fix parameter name in typing 2021-02-03 11:01:55 +08:00
Daniel Imms 2340fa1c91 Merge branch 'master' into fix-3221 2021-02-02 11:57:57 -08:00
Daniel Imms 70051da2ab Merge pull request #3101 from mmis1000/feature/xterm-addon-serialize-restore-layout-and-cursor
Feature/xterm addon serialize restore layout and cursor
2021-02-01 09:46:52 -08:00
Daniel Imms 5659bf3283 Merge branch 'master' into feature/xterm-addon-serialize-restore-layout-and-cursor 2021-02-01 09:36:05 -08:00
Daniel Imms 8de8ac10d4 Merge pull request #3240 from Tyriar/debug
Fix Demo Server debug launch config
2021-02-01 09:35:48 -08:00
Daniel Imms 46c93f1b63 Move util function into page.evaluate 2021-02-01 09:34:38 -08:00
Daniel Imms e3a9d0d14f Merge branch 'master' into debug 2021-02-01 09:29:10 -08:00
Daniel Imms 0a4b403f6a Fix Demo Server debug launch config 2021-02-01 09:28:26 -08:00
Daniel Imms b94b4f5353 Merge branch 'master' into feature/xterm-addon-serialize-restore-layout-and-cursor 2021-02-01 09:01:09 -08:00
Daniel Imms d84576e160 Merge pull request #3239 from hantatsang/fix/2642-terminal-open-check-shadow-dom
Terminal.open: support WebComponent when checking DOM Node
2021-02-01 02:37:38 -08:00
hantatsang a0903fbf9b terminal.open: support webcomponent in dom node check 2021-01-31 11:43:59 +11:00
Daniel Imms 4b29b8a9c6 Merge pull request #3237 from Tyriar/r4_10
v4.10.0
2021-01-29 09:25:08 -08:00
Daniel Imms c994c67dd9 v4.10.0 2021-01-29 09:14:31 -08:00
jeanp413 0b09f0bafd Fixes #3221 2021-01-24 23:17:36 -05:00
Mmis1000 54bb0ee189 SerializeAddon: comment the intent of several check 2021-01-25 10:52:48 +08:00
Jörg Breitbart 68b7f88523 async parser tests for CSI and ESC 2021-01-24 17:09:16 +01:00
Jörg Breitbart a9eb1de4b4 Merge branch 'master' into async_handlers 2021-01-24 09:11:51 +01:00
jerch 28bcd88fb0 Merge pull request #3229 from jerch/replace_expect_testing
replace expect testing with assert
2021-01-23 19:07:26 +01:00
jerch bee4b0ff06 Merge branch 'master' into replace_expect_testing 2021-01-23 19:00:39 +01:00
Daniel Imms 559b3c1392 Merge pull request #3228 from nishant-d/master
added Devtron's usages
2021-01-23 09:12:47 -08:00
Jörg Breitbart d3c9f70bec replace expect testing with assert 2021-01-23 17:09:43 +01:00
Jörg Breitbart 4ba7aef441 Merge branch 'master' into async_handlers 2021-01-23 13:06:50 +01:00
Jörg Breitbart 2f07ed9976 simplify stack save in parser 2021-01-23 13:05:57 +01:00
jerch ff74caf50d Merge pull request #3200 from kena0ki/issue3032
Filter U+FEFF (BOM) when decoding input data
2021-01-23 13:03:57 +01:00
Ken Aoki 3d941f2fdf add BOM skip logic 2021-01-23 11:42:16 +00:00
Ken Aoki 93aab95f7b filter U+FEFF (BOM) when decoding input data 2021-01-23 04:39:57 +00:00
Mmis1000 079702282c SerializeAddon: move test util into seperate file 2021-01-23 12:26:30 +08:00
nishant-d db8e449a8a added Devtron's usages 2021-01-23 09:35:43 +05:30
Mmis1000 a2480bae51 Remove dummy buffer cell in favor of just remember the location 2021-01-23 11:57:08 +08:00
mmis1000andDaniel Imms cd501f9dcc Update addons/xterm-addon-serialize/src/MyBufferCell.ts
Co-authored-by: Daniel Imms <tyriar@tyriar.com>
2021-01-23 10:20:03 +08:00
mmis1000andDaniel Imms 354f3e03a2 Fix: inconsistent styles
Co-authored-by: Daniel Imms <tyriar@tyriar.com>
2021-01-23 10:19:03 +08:00
Jörg Breitbart b07ca8bb24 fix timeout issue on macos 2021-01-22 21:34:12 +01:00
Jörg Breitbart 22d777c9f9 make linter happy 2021-01-22 21:24:54 +01:00
Jörg Breitbart adfeffec76 deprecate writeSync 2021-01-22 21:17:34 +01:00
Jörg Breitbart 4a1bdad759 fix tests for async handlers in inputhandler 2021-01-22 19:48:50 +01:00
Daniel Imms 00ef60ebaf Merge branch 'master' into feature/xterm-addon-serialize-restore-layout-and-cursor 2021-01-22 09:13:07 -08:00
Jörg Breitbart 0ad9f70645 Merge branch 'master' into async_handlers 2021-01-22 17:49:31 +01:00
Daniel Imms 4da5d557a5 Merge pull request #3227 from marvinthepa/3225_onSelectionChange_on_clear
Store old selection when firing onSelectionChange
2021-01-22 08:37:36 -08:00
jerch a1dc85ee57 Merge pull request #3223 from jerch/simplify_handler_interface
cleanup parser handler interface
2021-01-22 17:17:48 +01:00
Martin Sander 554b4a8224 Store old selection when firing onSelectionChange 2021-01-22 16:41:57 +01:00
Jörg Breitbart 3f659a15da minor fixes:
- better perf for short DCS without params (8 times faster)
- test perf for class and string based interfaces of OSC and DCS
  separately
- undo wrong commit on parser
2021-01-21 15:58:03 +01:00
Jörg Breitbart dd5b295219 release active handler list on dispose in DcsHandler 2021-01-21 13:08:01 +01:00
Jörg Breitbart 9d0200252b fix possible OSC handler bug skipping the fallback handler 2021-01-21 13:05:57 +01:00
Jörg Breitbart d67faff92a simplify return eval 2021-01-21 11:38:47 +01:00
Jörg Breitbart c50c134e25 simplify parser handler interface:
- remove setHandler
- apply boolean return to ESC|CSI|OSC|DCS handlers
  (rewrite empty return defaulting to true)
- rename addHandler to registerHandler
2021-01-20 23:03:55 +01:00
Jörg Breitbart bc1048062d early version of async support for CSI and ESC handlers 2021-01-20 20:05:14 +01:00
Daniel Imms 74ea558bfc Merge pull request #3219 from marvinthepa/3216_onSelectionChange_on_right_click
fire onSelectionChange on right click select
2021-01-19 10:24:55 -08:00
Martin Sander c6f93701f5 fire onSelectionChange on right click select
fixes #3216.
2021-01-16 10:14:11 +01:00
Daniel Imms 8a4772ca39 Merge pull request #3215 from marvinthepa/3193_onSelectionChange_on_clear
fire onSelectionChange on empty selection
2021-01-15 10:17:21 -08:00
Daniel ImmsandMegan Rogge 66c80d8b78 Simplify checks
Co-authored-by: Megan Rogge <merogge@microsoft.com>
2021-01-15 09:39:34 -08:00
Martin Sander 0cb38cfdcb fire onSelectionChange on empty selection
Fire the onSelectionChange event when a selection is cleared by
single-clicking somewhere inside the terminal area.

fixes #3193.

This also slightly changes the behaviour when re-selecting the same area
in the terminal. Before, this fired onSelectionChange, but it does not
anymore, even when changing the direction of the selection.
2021-01-14 23:08:34 +01:00
Jakob b0605e4cd1 Merge branch 'master' into fix/scroll-events 2021-01-13 11:12:14 +01:00
Jakob Schrettenbrunner 82a9ee62d7 emit onScroll event when user is scrolling 2021-01-12 22:35:47 +00:00
Jakob Schrettenbrunner 8b2b0f6abc add richer ScrollEvent that includes the source 2021-01-12 22:32:20 +00:00
Daniel Imms c669c3fba7 Merge pull request #3194 from kena0ki/issue3191
Prevent input characters using IME from being duplicated
2021-01-11 14:28:02 -08:00
Daniel Imms 8860726c68 Merge branch 'master' into issue3191 2021-01-11 09:51:02 -08:00
Daniel Imms f64724f54f Merge pull request #3187 from chenjigeng/fix/select-all
fix shift+cmd+a will Select all
2021-01-11 09:41:14 -08:00
Daniel Imms fd222b58b5 Merge branch 'master' into fix/select-all 2021-01-11 09:29:35 -08:00
Daniel Imms 83ba481e3d Merge pull request #3125 from kena0ki/issue#2734
Fix search addon not expanding selection to left when appropriate
2021-01-11 09:29:18 -08:00
Daniel Imms 7d5bbc341f Merge branch 'master' into issue#2734 2021-01-11 09:20:47 -08:00
Daniel ImmsandMegan Rogge 519e44d30e Clean up, improve comments
Co-authored-by: Megan Rogge <merogge@microsoft.com>
2021-01-11 09:19:53 -08:00
Daniel Imms 3bb2c158fd Merge pull request #3213 from Tyriar/update_yarn
Update yarn.lock for font-finder
2021-01-11 08:53:20 -08:00
Daniel Imms 5ada5f0c0c Update yarn.lock for font-finder
Previous update was likely done using npm, not yarn
2021-01-11 08:31:56 -08:00
Daniel Imms ea1fcc6a5f Merge pull request #3163 from slawekzachcial/add-osc-4
Add support for OSC 4 ; color ; color spec
2021-01-11 07:54:04 -08:00
Daniel Imms 19c14b076b Remove resolved TODO 2021-01-11 07:40:25 -08:00
Slawek Zachcial 676aabc3ed Merge branch 'master' into add-osc-4 2021-01-09 16:57:18 +01:00
Slawek Zachcial 5c33e4008d Make _parseAnsiColorChange available for tests in TestInputHandler 2021-01-09 14:30:24 +01:00
Daniel Imms 772e446192 Merge pull request #3210 from meganrogge/windows-git-bash
Get demo working for git bash on windows
2021-01-08 11:33:34 -08:00
meganroggeandPretaSOFT 66be7797cf Get demo working for git bash on windows
Co-authored-by: Megan Rogge merogge@microsoft.com
Co-authored-by: Daniel Imms daimms@microsoft.com
2021-01-08 11:02:34 -08:00
Daniel Imms 3261c53c08 Merge pull request #3209 from Nokel81/freeze-default-colours
freeze the default ANSI colours const
2021-01-08 07:10:12 -08:00
Sebastian Malton 5bab94730f freeze the default ANSI colours const 2021-01-08 09:46:12 -05:00
Daniel Imms 801aeb8462 Merge pull request #3207 from CyanSalt/commas
Add Commas to the Real-world uses List
2021-01-05 23:27:50 -08:00
Sun Xiaoran cbe5abcf27 Add Commas to the Real-world uses List 2021-01-06 14:10:10 +08:00
Daniel Imms 72dbd43be6 Merge pull request #3204 from meganrogge/master
set this._buffer to new buffer
2021-01-05 10:20:57 -08:00
Daniel ImmsandPretaSOFT 7145130835 Fix onBufferChange event not working after reset
Co-authored-by: Megan Rogge (megan.rogge@microsoft.com)
2021-01-05 09:32:09 -08:00
meganrogge b34289cc44 use reset 2021-01-05 07:10:27 -08:00
meganrogge fe2b1c0d43 set this._buffer to new buffer 2021-01-04 11:32:11 -08:00
Daniel Imms 4de6f1c255 Merge pull request #3203 from meganrogge/master
cache buffer to fix VS Code issue #111562
2021-01-04 10:35:46 -08:00
meganrogge 8baff9bade cache buffer 2021-01-04 08:31:22 -08:00
jerch f8f7e7e4c1 Merge pull request #3188 from UziTech/update-font-finder
fix: update font-finder to v1.1.0
2021-01-02 19:34:40 +01:00
jerch 7523505af1 Merge branch 'master' into update-font-finder 2021-01-02 19:23:35 +01:00
jerch d94b119e9d Merge pull request #3190 from jrieken/joh/trustedTypes
Avoid innerHTML usages
2021-01-02 19:21:55 +01:00
kena0ki 3cab8511e4 Prevent input characters using IME from being duplicated 2020-12-31 22:55:54 +09:00
Slawek Zachcial 7d3f5375a8 Implement OSC 4 for list of colors 2020-12-09 22:30:23 +01:00
Johannes Rieken b2c4ed638b fix bad none-breaking whitespace 2020-12-09 09:08:14 +00:00
Slawek Zachcial 2804bfa8b7 Make safe references to colorManager in _changeAnsiColor 2020-12-07 23:20:10 +01:00
Johannes Rieken 64ac67026a avoid innerHTML usages 2020-12-02 16:25:19 +00:00
Slawek Zachcial 5a74ce2e59 Add Ansi color change positive test 2020-11-30 22:00:04 +01:00
Slawek Zachcial f4a56389cd Fix quotes 2020-11-29 23:22:31 +01:00
Slawek Zachcial 52b64beefc Make InputHandler parseAnsiColorChange private 2020-11-29 16:30:05 +01:00
Tony Brix ec1234e8d8 fix: update font-finder to v1.1.0 2020-11-27 14:19:05 -06:00
condichen@tencent.com b7695d2fd6 fix shift+cmd+a will Select all 2020-11-28 00:56:45 +08:00
Slawek Zachcial 4c6dc45d20 Merge branch 'master' into add-osc-4 2020-11-24 22:54:26 +01:00
Daniel Imms 5cb048094e Merge pull request #3181 from awmottaz/master
Make alt+click behavior configurable
2020-11-24 09:04:21 -08:00
Daniel Imms e3cccd619b Update typings/xterm.d.ts 2020-11-24 09:03:59 -08:00
Tony Mottaz 88f0b91056 add altClickMovesCursor option to Services type 2020-11-22 10:01:02 -06:00
Tony Mottaz 78ddb9feba Add 'altClickMovesCursor' option to getOption/setOption in Terminal 2020-11-22 10:00:41 -06:00
Tony Mottaz f68ff2a455 Check for alt+click option sooner 2020-11-22 10:00:02 -06:00
Tony Mottaz 04e2bdd6ec Make alt+click behavior configurable 2020-11-20 19:50:03 -06:00
Daniel Imms 84fa6be370 Merge pull request #3175 from dsanders11/patch-1
use Array.includes
2020-11-11 12:50:07 -08:00
David Sanders af2f744186 use Array.includes 2020-11-11 09:43:17 -08:00
Daniel Imms 5f4b719444 Merge pull request #3172 from KKoukiou/a11y-fix
Fix a11y violation because of using role='listitem' without role='list' parent
2020-11-10 08:53:45 -08:00
Katerina Koukiou 9616851e52 Fix a11y violation because of using role='listitem' without role='list' parent 2020-11-10 16:36:59 +01:00
Daniel Imms 4645fda126 Merge pull request #3170 from blois/shadow_root
Incorporate shadowRoot in focus calculation.
2020-11-09 16:17:09 -08:00
Pete Blois 057a8f6f1b Incorporate shadowRoot in focus calculation.
This adds a call to getRootNode to get either the Document or the
ShadowRoot to use when calculating whether the textarea has focus.

getRootNode is guarded for older browser compatibility (IE).
2020-11-09 13:12:03 -08:00
Slawek Zachcial e6917d1933 Clarify color spec description 2020-11-08 22:07:24 +01:00
Slawek Zachcial 6535995753 Update OSC 4 description to match #3036 2020-11-08 22:05:25 +01:00
Slawek Zachcial 77ed5ba7ed Add terminal sequence doc 2020-11-08 10:19:12 +01:00
Slawek Zachcial bc86b7804c Use all and not only 16 Ansi colors in CharAtlas config 2020-11-07 21:36:05 +01:00
Slawek Zachcial d5f4ae53c9 Add IAnsiColorChangeEvent related tests 2020-11-07 21:36:05 +01:00
Slawek Zachcial b898e016f3 Add IAnsiColorChangeEvent type 2020-11-07 21:36:05 +01:00
Slawek Zachcial 712f0ae2a7 Merge branch 'master' into add-osc-4 2020-11-05 22:02:48 +01:00
Daniel Imms c553107d23 Merge pull request #3167 from xtermjs/dependabot/npm_and_yarn/webpack-cli-4.2.0
Bump webpack-cli from 4.1.0 to 4.2.0
2020-11-05 08:35:34 -08:00
Slawek Zachcial b127436cc4 Fix TODO comment 2020-11-05 08:51:01 +01:00
dependabot-preview[bot] b61ac11a76 Bump webpack-cli from 4.1.0 to 4.2.0
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 4.1.0 to 4.2.0.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/webpack-cli@4.1.0...webpack-cli@4.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-05 07:38:01 +00:00
Slawek Zachcial b22d7f1140 Move color parsing from Terminal to InputHandler 2020-11-04 22:19:55 +01:00
Daniel Imms 925aaf18a1 Merge pull request #3165 from xtermjs/dependabot/npm_and_yarn/webpack-5.4.0
Bump webpack from 5.3.2 to 5.4.0
2020-11-04 06:46:09 -08:00
Daniel Imms 797ed47791 Merge pull request #3164 from xtermjs/dependabot/npm_and_yarn/ts-loader-8.0.8
Bump ts-loader from 8.0.7 to 8.0.8
2020-11-04 06:45:49 -08:00
dependabot-preview[bot] 4128a6e2f1 Bump webpack from 5.3.2 to 5.4.0
Bumps [webpack](https://github.com/webpack/webpack) from 5.3.2 to 5.4.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v5.3.2...v5.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-04 07:28:16 +00:00
dependabot-preview[bot] 69f34be4b8 Bump ts-loader from 8.0.7 to 8.0.8
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.7 to 8.0.8.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v8.0.7...v8.0.8)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-04 07:27:51 +00:00
Slawek Zachcial 1c3da7e2e6 Merge branch 'master' into add-osc-4 2020-11-03 18:57:51 +01:00
Slawek Zachcial 5c7644adc0 Add rudimenatary and not fully working support of OSC 4 2020-11-03 18:36:28 +01:00
Daniel Imms f974010aa3 Merge pull request #3162 from xtermjs/dependabot/npm_and_yarn/mocha-8.2.1
Bump mocha from 8.2.0 to 8.2.1
2020-11-03 06:58:51 -08:00
dependabot-preview[bot] d4d18f741f Bump mocha from 8.2.0 to 8.2.1
Bumps [mocha](https://github.com/mochajs/mocha) from 8.2.0 to 8.2.1.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v8.2.0...v8.2.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-11-03 07:36:13 +00:00
Daniel Imms d97b54b9be Merge pull request #3161 from nasrob/update-to-webpack-5
fixes #3154 upgraded webpack to version 5.3.2
2020-11-02 06:09:21 -08:00
Daniel Imms a7b94fbe1a Revert "Reference tsc/webpack in root dir"
This reverts commit fd6bf6d667.
2020-11-02 05:40:18 -08:00
Daniel Imms 2ab9de91fe Format tsconfig.json 2020-11-02 05:37:31 -08:00
Daniel Imms fd6bf6d667 Reference tsc/webpack in root dir 2020-11-02 05:36:23 -08:00
Daniel Imms 38e81f053f Merge pull request #3133 from coderaiser/lint/putout
Using putout linter on xterm codebase part 2
2020-11-02 05:15:07 -08:00
coderaiser c6f1b456f5 feature: tsconfig: es2017 -> es2016.Array.Include 2020-11-01 09:46:31 +02:00
Nasser Boukehil 8484978ef0 fixes #3154 upgraded webpack to version 5.3.2 with types property in ligatures tsconfig 2020-10-31 21:03:01 +01:00
coderaiser c4919b9a6b feature: tsconfig: es2015 -> es2017 2020-10-31 15:13:12 +02:00
Daniel Imms 02e4db4c82 Merge pull request #3136 from kena0ki/termfit
Fix "term.fit is not a function" error when change padding value in the demo
2020-10-30 12:23:17 -07:00
Daniel Imms 5200766617 Merge branch 'master' into feature/xterm-addon-serialize-restore-layout-and-cursor 2020-10-30 09:38:33 -07:00
Daniel Imms 8d9badb588 Merge pull request #3089 from UziTech/rerender-hidden
Render initially hidden terminal when visible
2020-10-30 08:55:29 -07:00
Daniel Imms fc534a1067 Merge pull request #3158 from xtermjs/dependabot/npm_and_yarn/types/jsdom-16.2.5
Bump @types/jsdom from 16.2.4 to 16.2.5
2020-10-29 13:46:58 -07:00
Daniel Imms f68ef19868 Merge pull request #3157 from xtermjs/dependabot/npm_and_yarn/types/webpack-4.41.24
Bump @types/webpack from 4.41.23 to 4.41.24
2020-10-29 13:46:46 -07:00
dependabot-preview[bot] 0a2e40502f Bump @types/jsdom from 16.2.4 to 16.2.5
Bumps [@types/jsdom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsdom) from 16.2.4 to 16.2.5.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jsdom)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-29 20:34:06 +00:00
dependabot-preview[bot] e843a2f61e Bump @types/webpack from 4.41.23 to 4.41.24
Bumps [@types/webpack](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack) from 4.41.23 to 4.41.24.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-29 20:33:16 +00:00
Daniel Imms d95a633f16 Merge pull request #3149 from xtermjs/dependabot/npm_and_yarn/playwright-1.5.2
Bump playwright from 1.5.1 to 1.5.2
2020-10-28 19:16:51 -07:00
Daniel Imms 6f41aad2ef Merge pull request #3153 from xtermjs/dependabot/npm_and_yarn/types/ws-7.2.9
Bump @types/ws from 7.2.8 to 7.2.9
2020-10-28 17:00:10 -07:00
dependabot-preview[bot] e76cbd9c3f Bump @types/ws from 7.2.8 to 7.2.9
Bumps [@types/ws](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws) from 7.2.8 to 7.2.9.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ws)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-28 23:50:58 +00:00
dependabot-preview[bot] 0c8b299996 Bump playwright from 1.5.1 to 1.5.2
Bumps [playwright](https://github.com/Microsoft/playwright) from 1.5.1 to 1.5.2.
- [Release notes](https://github.com/Microsoft/playwright/releases)
- [Commits](https://github.com/Microsoft/playwright/compare/v1.5.1...v1.5.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-28 23:50:40 +00:00
Daniel Imms 86420d2535 Merge pull request #3151 from xtermjs/dependabot/npm_and_yarn/types/ws-7.2.8
Bump @types/ws from 7.2.7 to 7.2.8
2020-10-28 06:22:40 -07:00
Daniel Imms 9e4dcdaf91 Merge pull request #3147 from xtermjs/dependabot/npm_and_yarn/source-map-loader-1.1.2
Bump source-map-loader from 1.1.1 to 1.1.2
2020-10-28 06:14:05 -07:00
Daniel Imms 45e7bf274a Merge pull request #3148 from xtermjs/dependabot/npm_and_yarn/eslint-7.12.1
Bump eslint from 7.12.0 to 7.12.1
2020-10-28 06:13:48 -07:00
Daniel Imms 62cf413d54 Merge pull request #3150 from xtermjs/dependabot/npm_and_yarn/typescript-4.0.5
Bump typescript from 4.0.3 to 4.0.5
2020-10-28 06:12:57 -07:00
dependabot-preview[bot] 3e0a270891 Bump @types/ws from 7.2.7 to 7.2.8
Bumps [@types/ws](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws) from 7.2.7 to 7.2.8.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ws)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-28 13:01:39 +00:00
dependabot-preview[bot] 22d79eef26 Bump typescript from 4.0.3 to 4.0.5
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.0.3 to 4.0.5.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.0.3...v4.0.5)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-28 13:01:11 +00:00
dependabot-preview[bot] 31d806afce Bump eslint from 7.12.0 to 7.12.1
Bumps [eslint](https://github.com/eslint/eslint) from 7.12.0 to 7.12.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.12.0...v7.12.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-28 13:00:07 +00:00
dependabot-preview[bot] 1e9ca83120 Bump source-map-loader from 1.1.1 to 1.1.2
Bumps [source-map-loader](https://github.com/webpack-contrib/source-map-loader) from 1.1.1 to 1.1.2.
- [Release notes](https://github.com/webpack-contrib/source-map-loader/releases)
- [Changelog](https://github.com/webpack-contrib/source-map-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/source-map-loader/compare/v1.1.1...v1.1.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-28 12:59:33 +00:00
Tony Brix 3d9a33bb69 move measure before refreshRows 2020-10-25 10:59:30 -05:00
Tony Brix ea989ed691 Merge branch 'master' into rerender-hidden 2020-10-25 09:58:09 -05:00
jerch ee2c5969fa Merge branch 'master' into feature/xterm-addon-serialize-restore-layout-and-cursor 2020-10-25 15:35:22 +01:00
jerch 8e151ee6ef Merge pull request #3143 from xtermjs/dependabot/npm_and_yarn/ts-loader-8.0.7
Bump ts-loader from 8.0.6 to 8.0.7
2020-10-25 12:00:21 +01:00
jerch dc904b27a2 Merge branch 'master' into dependabot/npm_and_yarn/ts-loader-8.0.7 2020-10-25 11:49:09 +01:00
jerch 4de539a1ff Merge pull request #3142 from xtermjs/dependabot/npm_and_yarn/eslint-7.12.0
Bump eslint from 7.11.0 to 7.12.0
2020-10-25 11:45:02 +01:00
dependabot-preview[bot] 913de3158e Bump ts-loader from 8.0.6 to 8.0.7
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.6 to 8.0.7.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v8.0.6...v8.0.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-25 09:14:57 +00:00
dependabot-preview[bot] 049ca653ed Bump eslint from 7.11.0 to 7.12.0
Bumps [eslint](https://github.com/eslint/eslint) from 7.11.0 to 7.12.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.11.0...v7.12.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-25 08:59:56 +00:00
coderaiser 246d137c2c src: lint using putout 2020-10-25 10:05:41 +02:00
coderaiser 99b1a7a49b bin: lint using putout 2020-10-25 01:13:40 +03:00
jerch 9fa068f574 Merge pull request #3109 from mmis1000/fix/addon-serialize-benchmark
Fix/addon serialize benchmark
2020-10-24 23:43:59 +02:00
jerch eb5f964bcb Merge branch 'master' into feature/xterm-addon-serialize-restore-layout-and-cursor 2020-10-24 14:57:37 +02:00
jerch 91337d7e57 Merge branch 'master' into fix/addon-serialize-benchmark 2020-10-24 14:57:13 +02:00
jerch cb555d5297 Merge branch 'master' into rerender-hidden 2020-10-24 14:02:17 +02:00
jerch 50dd3cb841 Merge pull request #3114 from jerch/fix_3108
marker fixes
2020-10-24 14:01:18 +02:00
jerch b7750cbf91 Merge branch 'master' into fix_3108 2020-10-24 13:44:19 +02:00
jerch dde47269de Merge branch 'master' into rerender-hidden 2020-10-24 13:43:59 +02:00
jerch bc3f2a12c0 Merge pull request #3132 from xtermjs/dependabot/npm_and_yarn/mocha-8.2.0
Bump mocha from 8.1.3 to 8.2.0
2020-10-24 13:42:06 +02:00
jerch bdb112b23c Merge branch 'master' into dependabot/npm_and_yarn/mocha-8.2.0 2020-10-24 13:32:29 +02:00
jerch 214ccd14ac Merge pull request #3139 from xtermjs/dependabot/npm_and_yarn/ts-loader-8.0.6
Bump ts-loader from 8.0.4 to 8.0.6
2020-10-24 13:30:12 +02:00
jerch e5f3820285 Merge branch 'master' into dependabot/npm_and_yarn/ts-loader-8.0.6 2020-10-24 13:21:37 +02:00
jerch f75b4cfa93 Merge pull request #3140 from xtermjs/dependabot/npm_and_yarn/types/webpack-4.41.23
Bump @types/webpack from 4.41.22 to 4.41.23
2020-10-24 13:21:01 +02:00
jerch f5d651dda1 Merge branch 'master' into dependabot/npm_and_yarn/types/webpack-4.41.23 2020-10-24 13:14:21 +02:00
jerch a90254e778 Merge branch 'master' into dependabot/npm_and_yarn/ts-loader-8.0.6 2020-10-24 13:03:05 +02:00
jerch a6bcfcfba4 Merge pull request #3135 from xtermjs/dependabot/npm_and_yarn/webpack-cli-4.1.0
Bump webpack-cli from 3.3.12 to 4.1.0
2020-10-24 13:01:34 +02:00
jerch 78ae1d09f7 Merge branch 'master' into dependabot/npm_and_yarn/webpack-cli-4.1.0 2020-10-24 12:51:21 +02:00
jerch 1132da8563 Merge pull request #3131 from xtermjs/dependabot/npm_and_yarn/types/chai-4.2.14
Bump @types/chai from 4.2.12 to 4.2.14
2020-10-24 12:49:52 +02:00
jerch 199b9ceb6d Merge branch 'master' into dependabot/npm_and_yarn/types/chai-4.2.14 2020-10-24 12:40:02 +02:00
jerch 8e41d22f8d Merge pull request #3128 from xtermjs/dependabot/npm_and_yarn/playwright-1.5.1
Bump playwright from 1.4.2 to 1.5.1
2020-10-24 12:39:17 +02:00
jerch 57bd61697c Merge branch 'master' into dependabot/npm_and_yarn/playwright-1.5.1 2020-10-24 12:32:16 +02:00
jerch 3e8b8dc6ef Merge pull request #3122 from xtermjs/dependabot/npm_and_yarn/eslint-7.11.0
Bump eslint from 7.10.0 to 7.11.0
2020-10-24 12:31:03 +02:00
jerch b4bc830cee Merge branch 'master' into dependabot/npm_and_yarn/eslint-7.11.0 2020-10-24 12:19:02 +02:00
jerch 2e43f615f6 Merge pull request #3121 from xtermjs/dependabot/npm_and_yarn/source-map-loader-1.1.1
Bump source-map-loader from 1.1.0 to 1.1.1
2020-10-24 12:17:46 +02:00
jerch 5f2d1d2b4e Merge branch 'master' into dependabot/npm_and_yarn/source-map-loader-1.1.1 2020-10-24 12:07:11 +02:00
jerch 4ee305fa21 Merge pull request #3119 from xtermjs/dependabot/npm_and_yarn/deep-equal-2.0.4
Bump deep-equal from 2.0.3 to 2.0.4
2020-10-24 12:06:34 +02:00
jerch 4b3e16dbd0 Merge branch 'master' into dependabot/npm_and_yarn/deep-equal-2.0.4 2020-10-24 11:58:13 +02:00
jerch a7c836e42c Merge pull request #3117 from xtermjs/dependabot/npm_and_yarn/types/ws-7.2.7
Bump @types/ws from 7.2.6 to 7.2.7
2020-10-24 11:57:13 +02:00
dependabot-preview[bot] 886c057d0f Bump @types/webpack from 4.41.22 to 4.41.23
Bumps [@types/webpack](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack) from 4.41.22 to 4.41.23.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-21 09:34:39 +00:00
dependabot-preview[bot] 038704786d Bump ts-loader from 8.0.4 to 8.0.6
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.4 to 8.0.6.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/8.0.4...v8.0.6)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-21 09:33:24 +00:00
Ken Aoki c61076830f Replace function call from term.fit() to addons.fit.instance.fit() 2020-10-21 06:44:17 +00:00
dependabot-preview[bot] 02fccfbdc7 Bump webpack-cli from 3.3.12 to 4.1.0
Bumps [webpack-cli](https://github.com/webpack/webpack-cli) from 3.3.12 to 4.1.0.
- [Release notes](https://github.com/webpack/webpack-cli/releases)
- [Changelog](https://github.com/webpack/webpack-cli/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack/webpack-cli/compare/v3.3.12...webpack-cli@4.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-19 15:48:14 +00:00
dependabot-preview[bot] b250cedf81 Bump mocha from 8.1.3 to 8.2.0
Bumps [mocha](https://github.com/mochajs/mocha) from 8.1.3 to 8.2.0.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v8.1.3...v8.2.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-18 01:30:59 +00:00
dependabot-preview[bot] 7243e330fc Bump @types/chai from 4.2.12 to 4.2.14
Bumps [@types/chai](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/chai) from 4.2.12 to 4.2.14.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/chai)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-16 16:46:16 +00:00
dependabot-preview[bot] 17a7fb2a6e Bump playwright from 1.4.2 to 1.5.1
Bumps [playwright](https://github.com/Microsoft/playwright) from 1.4.2 to 1.5.1.
- [Release notes](https://github.com/Microsoft/playwright/releases)
- [Commits](https://github.com/Microsoft/playwright/compare/v1.4.2...v1.5.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-15 09:50:26 +00:00
Ken Aoki d3d8ec3b20 Fix search not expanding selection to left when appropriate (revenge) 2020-10-13 09:55:10 +00:00
Ken Aoki b6074df4bf Revert "Fix search not expanding selection to left when appropriate"
This reverts commit a9d2b8a55c.
2020-10-13 06:44:01 +00:00
dependabot-preview[bot] f3cc9469a7 Bump eslint from 7.10.0 to 7.11.0
Bumps [eslint](https://github.com/eslint/eslint) from 7.10.0 to 7.11.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.10.0...v7.11.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-10 22:07:29 +00:00
Ken Aoki a9d2b8a55c Fix search not expanding selection to left when appropriate 2020-10-10 04:04:52 +00:00
dependabot-preview[bot] 73e235d9f8 Bump source-map-loader from 1.1.0 to 1.1.1
Bumps [source-map-loader](https://github.com/webpack-contrib/source-map-loader) from 1.1.0 to 1.1.1.
- [Release notes](https://github.com/webpack-contrib/source-map-loader/releases)
- [Changelog](https://github.com/webpack-contrib/source-map-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/source-map-loader/compare/v1.1.0...v1.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-09 16:59:40 +00:00
Tony Brix 17ec85e39e Merge branch 'master' into rerender-hidden 2020-10-09 10:23:20 -05:00
dependabot-preview[bot] 723c64e481 Bump deep-equal from 2.0.3 to 2.0.4
Bumps [deep-equal](https://github.com/inspect-js/node-deep-equal) from 2.0.3 to 2.0.4.
- [Release notes](https://github.com/inspect-js/node-deep-equal/releases)
- [Changelog](https://github.com/inspect-js/node-deep-equal/blob/master/CHANGELOG.md)
- [Commits](https://github.com/inspect-js/node-deep-equal/compare/v2.0.3...v2.0.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-10-05 15:57:08 +00:00
Jörg Breitbart faa60be6fb add missing insert and delete events to CircularList.splice 2020-10-03 17:11:49 +02:00
Jörg Breitbart e95f9815d8 Merge branch 'master' into fix_3108 2020-10-03 16:43:04 +02:00
Jörg Breitbart 9b62d8a01a basic marker test cases 2020-10-03 16:32:46 +02:00
dependabot-preview[bot] 1c206c2c27 Bump @types/ws from 7.2.6 to 7.2.7
Bumps [@types/ws](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/ws) from 7.2.6 to 7.2.7.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/ws)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-30 03:51:40 +00:00
Daniel Imms 782797ca11 Merge pull request #3116 from bhrg3se/master
added TRASA in "Real-world uses" list
2020-09-29 10:37:40 -07:00
bhrg3se b34ee5157e added TRASA in "Real-world uses" list 2020-09-29 19:55:58 +05:45
Daniel Imms ae37c43cd4 Merge pull request #3112 from xtermjs/dependabot/npm_and_yarn/playwright-1.4.2
Bump playwright from 1.3.0 to 1.4.2
2020-09-28 09:15:56 -07:00
dependabot-preview[bot] 272b1d2194 Bump playwright from 1.3.0 to 1.4.2
Bumps [playwright](https://github.com/Microsoft/playwright) from 1.3.0 to 1.4.2.
- [Release notes](https://github.com/Microsoft/playwright/releases)
- [Commits](https://github.com/Microsoft/playwright/compare/v1.3.0...v1.4.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-28 16:05:45 +00:00
Daniel Imms 260e2dab16 Merge pull request #3115 from xtermjs/dependabot/npm_and_yarn/eslint-7.10.0
Bump eslint from 7.9.0 to 7.10.0
2020-09-28 09:03:36 -07:00
dependabot-preview[bot] 7c78390e2b Bump eslint from 7.9.0 to 7.10.0
Bumps [eslint](https://github.com/eslint/eslint) from 7.9.0 to 7.10.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.9.0...v7.10.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-28 15:50:17 +00:00
Jörg Breitbart f5a4eed27c add super.dispose, add oDispose to API 2020-09-27 15:59:11 +02:00
Daniel Imms b0768f18ca Merge pull request #3113 from zaataylor/patch-1
Fix spelling error in README
2020-09-26 15:16:40 -07:00
zaataylor 4d1e532069 Fix spelling error in README
I corrected the spelling error for the Internet Explorer 11 browser mentioned in the "Browser Support" section.
2020-09-26 13:11:24 -04:00
Mmis1000 5beb7f52c2 Serialize addon: Change benchmark random source from /dev/random to /dev/urandom 2020-09-23 21:22:40 +08:00
Mmis1000 eaaf9b7af1 Serialize addon: Fix file path in benchmark 2020-09-23 21:21:54 +08:00
Tony Brix 3c9687decf Merge branch 'master' into rerender-hidden 2020-09-21 17:46:06 -05:00
Daniel Imms a5e269a3f9 Merge pull request #3104 from xtermjs/dependabot/npm_and_yarn/ts-loader-8.0.4
Bump ts-loader from 8.0.3 to 8.0.4
2020-09-21 14:52:45 -07:00
Daniel Imms 30d84b1202 Merge pull request #3106 from xtermjs/dependabot/npm_and_yarn/typescript-4.0.3
Bump typescript from 4.0.2 to 4.0.3
2020-09-21 14:51:52 -07:00
Daniel Imms 0aa1079cd0 Merge pull request #3107 from xtermjs/dependabot/npm_and_yarn/webpack-4.44.2
Bump webpack from 4.44.1 to 4.44.2
2020-09-21 14:51:36 -07:00
dependabot-preview[bot] 1091255d2c Bump webpack from 4.44.1 to 4.44.2
Bumps [webpack](https://github.com/webpack/webpack) from 4.44.1 to 4.44.2.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v4.44.1...v4.44.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-21 15:55:09 +00:00
dependabot-preview[bot] 56e63d762b Bump typescript from 4.0.2 to 4.0.3
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 4.0.2 to 4.0.3.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v4.0.2...v4.0.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-21 15:54:34 +00:00
dependabot-preview[bot] f3c8b8f395 Bump ts-loader from 8.0.3 to 8.0.4
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.3 to 8.0.4.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v8.0.3...8.0.4)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-21 15:53:19 +00:00
Mmis1000 47be9a2df4 Fix another error about impossible wrap 2020-09-18 22:02:30 +08:00
Mmis1000 aee1629c25 Reuse the cell object to redice gc 2020-09-18 21:02:56 +08:00
mmis1000 8587eea54c Merge branch 'master' into feature/xterm-addon-serialize-restore-layout-and-cursor 2020-09-18 15:28:33 +08:00
mmis1000 d7ed109f9d Support the isWrapped handling 2020-09-18 15:21:59 +08:00
Mmis1000 84dfe8fccc CLearup comment 2020-09-18 01:20:41 +08:00
Mmis1000 6904dc5009 Handle BCE + line scroll
Using an additional field for store the current background and compare
  against it to generate proper color sequence
2020-09-18 00:36:10 +08:00
Mmis1000 b89227d365 Workaround firefox bug that yield -0 on bit op 2020-09-16 22:47:23 +08:00
mmis1000 6c01630090 Remove the unused options 2020-09-16 15:13:30 +08:00
mmis1000 10282e4cb1 Move the test util to static method 2020-09-16 14:54:15 +08:00
mmis1000 8518b354a7 Fix test that breaks by the option change 2020-09-16 14:45:14 +08:00
mmis1000 00a8b80ef7 Implement cursor adn alt screen.
Fix background serialize
2020-09-16 14:28:08 +08:00
Daniel Imms 1a0a56c1f2 Merge pull request #3100 from Tyriar/fix_build
Fix publish build
2020-09-15 10:49:58 -07:00
Daniel Imms 055267ee9c Fix publish build 2020-09-15 10:49:21 -07:00
Daniel Imms 6e9040e6ba Merge pull request #3099 from Tyriar/role
Move role=document to xterm element
2020-09-15 10:38:14 -07:00
Daniel Imms a32776e2af Move role=document to xterm element
Feedback in microsoft/vscode#98918 said this could improve the UX on
screen readers
2020-09-15 10:33:28 -07:00
Tony Brix 1d6d6eb716 Merge branch 'master' into rerender-hidden 2020-09-15 09:55:22 -05:00
mmis1000 881a4a0dbb Try implement cursor restortion 2020-09-15 17:58:56 +08:00
Daniel Imms 003cf96910 Merge pull request #3096 from xtermjs/dependabot/npm_and_yarn/eslint-7.9.0
Bump eslint from 7.8.1 to 7.9.0
2020-09-14 10:41:58 -07:00
dependabot-preview[bot] 3cb87af315 Bump eslint from 7.8.1 to 7.9.0
Bumps [eslint](https://github.com/eslint/eslint) from 7.8.1 to 7.9.0.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.8.1...v7.9.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-14 16:07:24 +00:00
Mmis1000 edee1a1067 Handle alt screen 2020-09-13 21:33:32 +08:00
Daniel Imms e32d8774eb Merge branch 'master' into rerender-hidden 2020-09-11 05:56:26 -07:00
Daniel Imms 49d5608fa6 Define member bar in ctor 2020-09-11 05:29:24 -07:00
Daniel Imms 56bfdb64d4 Merge pull request #3088 from UziTech/patch-2
fix: fit addon proposing infinite dimensions
2020-09-11 05:25:09 -07:00
Tony Brix 9513c231c9 fix: rerender hidden terminal when visible 2020-09-11 00:42:18 -05:00
Tony Brix dd92161da5 test: test proposing dimensions on hidden terminal 2020-09-10 19:54:31 -05:00
Tony Brix 55571a1ae8 fix: fit addon proposing infinite dimensions 2020-09-10 12:31:27 -05:00
Daniel Imms c112990d8f Merge pull request #3087 from Tyriar/playwright
Update playwright to 1.3.0
2020-09-10 08:09:13 -07:00
Daniel Imms 23dba6aebd Remove commented out calls 2020-09-10 08:01:31 -07:00
Daniel Imms f669b8ed1d Fix 2444 regression test 2020-09-10 07:52:02 -07:00
Daniel Imms 9a22cbe44b Fix selection api test on Windows 2020-09-10 07:45:38 -07:00
Daniel Imms 883ddba934 Improve search test
Was failing on Windows
2020-09-10 07:38:14 -07:00
Daniel Imms 8f7295b8a2 Avoid cache in integration test jobs 2020-09-10 06:54:25 -07:00
Daniel Imms 0ba97f6941 Put customOscHandlerCallStack on window 2020-09-10 06:38:43 -07:00
Daniel Imms d979c077a0 Update playwright to 1.3.0
Fixes #2917
2020-09-10 06:31:59 -07:00
Daniel Imms 4e18a78c02 Merge pull request #3086 from Tyriar/addon_test_projects
Create addon test tsconfig projects
2020-09-09 14:26:19 -07:00
Daniel Imms 1d6e8abcca More other addons api tests into test project 2020-09-09 13:54:43 -07:00
Daniel Imms 82a65be446 Include new out-test path in test-api 2020-09-09 12:58:39 -07:00
Daniel Imms 0778a823d1 Exclude test dirs in npmignore 2020-09-09 12:54:01 -07:00
Daniel Imms eca36458b3 Move webgl addon test code into own tsconfig
Part of #2917
2020-09-09 12:53:33 -07:00
Daniel Imms 3504e2ebd5 Merge pull request #3084 from Tyriar/release490
v4.9.0
2020-09-08 16:36:32 -07:00
Daniel Imms 6c22e3df6b v4.9.0 2020-09-08 09:35:05 -07:00
Daniel Imms 33bf765b80 Merge pull request #3067 from mmis1000/fix/addon-serialize-cjk-handling
Fix cjk handling in SerializeAddon
2020-09-08 06:25:40 -07:00
Daniel Imms d960793f0c Merge pull request #3062 from IllusionMH/numeric-fontWeight-3051
Add number type to fontWeight & fontWeightBold options
2020-09-08 06:21:38 -07:00
Daniel Imms 4975f389ff Use assert over expect 2020-09-08 06:18:37 -07:00
Daniel Imms 4649ad7e7b Merge pull request #3077 from xtermjs/dependabot/npm_and_yarn/typescript-eslint/eslint-plugin-4.0.0
Bump @typescript-eslint/eslint-plugin from 3.10.1 to 4.0.0
2020-09-07 11:32:28 -07:00
dependabot-preview[bot] a425c325b7 Bump @typescript-eslint/eslint-plugin from 3.10.1 to 4.0.0
Bumps [@typescript-eslint/eslint-plugin](https://github.com/typescript-eslint/typescript-eslint/tree/HEAD/packages/eslint-plugin) from 3.10.1 to 4.0.0.
- [Release notes](https://github.com/typescript-eslint/typescript-eslint/releases)
- [Changelog](https://github.com/typescript-eslint/typescript-eslint/blob/master/packages/eslint-plugin/CHANGELOG.md)
- [Commits](https://github.com/typescript-eslint/typescript-eslint/commits/v4.0.0/packages/eslint-plugin)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-07 18:21:07 +00:00
Daniel Imms c77025b18c Merge pull request #3079 from xtermjs/dependabot/npm_and_yarn/eslint-7.8.1
Bump eslint from 7.7.0 to 7.8.1
2020-09-07 11:19:18 -07:00
Daniel Imms c6abc85810 Merge pull request #3081 from Tyriar/3069_multiline_selection
Fix rendering of multi-line selection when only top row is visible
2020-09-07 09:59:11 -07:00
Daniel Imms 710223ab27 Merge pull request #3082 from Tyriar/3080_selection_canvas
Fix last/first line of selection sometimes not drawing
2020-09-07 09:57:58 -07:00
Daniel Imms ca9df42a73 Fix last/first line of selection sometimes not drawing
The last ydisp wasn't being updated on early exits.

Fixes #3080
2020-09-07 09:46:43 -07:00
Daniel Imms 9f033cb1d2 Fix rendering of multi-line selection when only top row is visible
Fixes #3069
2020-09-07 09:40:02 -07:00
dependabot-preview[bot] 9613f36280 Bump eslint from 7.7.0 to 7.8.1
Bumps [eslint](https://github.com/eslint/eslint) from 7.7.0 to 7.8.1.
- [Release notes](https://github.com/eslint/eslint/releases)
- [Changelog](https://github.com/eslint/eslint/blob/master/CHANGELOG.md)
- [Commits](https://github.com/eslint/eslint/compare/v7.7.0...v7.8.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-07 16:04:56 +00:00
Daniel Imms 41673f2c20 Merge pull request #3078 from xtermjs/dependabot/npm_and_yarn/types/webpack-4.41.22
Bump @types/webpack from 4.41.21 to 4.41.22
2020-09-07 09:02:56 -07:00
dependabot-preview[bot] 6c98f82ffe Bump @types/webpack from 4.41.21 to 4.41.22
Bumps [@types/webpack](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/webpack) from 4.41.21 to 4.41.22.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/webpack)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-07 15:51:27 +00:00
Daniel Imms a90ef52bda Merge pull request #3076 from xtermjs/dependabot/npm_and_yarn/types/jsdom-16.2.4
Bump @types/jsdom from 16.2.3 to 16.2.4
2020-09-07 08:49:49 -07:00
dependabot-preview[bot] 86884d2d88 Bump @types/jsdom from 16.2.3 to 16.2.4
Bumps [@types/jsdom](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/jsdom) from 16.2.3 to 16.2.4.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/jsdom)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-09-07 15:32:12 +00:00
Daniel Imms 47c486e1be Merge pull request #3075 from Tyriar/clearTextureAtlas
Expose API to clear texture atlas
2020-09-06 15:16:51 -07:00
Daniel Imms e07b9684bb Expose API to clear texture atlas
Using canvases on Electron (and plain Chromium I believe), when resuming
from sleep the graphics card may release the texture which results in
the terminal display and char atlas being corrupt. This API allows the
consumer to clear the texture atlas right after resuming, atlas warm up
is not done to simplify this process because the fact that atlases are
shared between multiple terminals complicates this.

Related microsoft/vscode#69665
2020-09-06 14:50:09 -07:00
Daniel Imms 10fb48869e Merge pull request #3073 from Tyriar/tyriar/link_dispose
Support ILink.dispose
2020-09-04 22:11:49 -07:00
Daniel Imms 9f3746a3a1 Improve test case 2020-09-04 22:04:59 -07:00
Daniel Imms 50fc84f7d7 Support ILink.dispose
When displaying hovers/overlays using the link provider API currently
it's not possible to know when unused links are no longer cached in
xterm.js which can result in leaked event listeners.
2020-09-04 21:57:51 -07:00
IllusionMH 3e0f0331b3 Add tests for fontWeight normalization 2020-09-05 00:48:12 +03:00
IllusionMH b918f0d34a Use FontWeight as return type 2020-09-04 23:35:38 +03:00
IllusionMH f0e3159ece Add number type to fontWeight & fontWeightBold options 2020-09-04 23:08:34 +03:00
Daniel Imms ecfc7336c5 Merge pull request #3072 from Tyriar/deps2
Upgrade serialize-javascript
2020-09-04 12:53:34 -07:00
Daniel Imms aec8c68bf6 Upgrade serialize-javascript 2020-09-04 12:08:26 -07:00
mmis1000 0fb63561fb Fix cjk handling in SerializeAddon 2020-09-03 13:23:01 +08:00
Daniel Imms 106ea62b4c Merge pull request #3064 from IllusionMH/validate-constructor-options-3063
Validate constructor options
2020-09-02 08:36:04 -07:00
IllusionMH e73bf11849 Log error instead of throwing. Move test to service. 2020-09-01 22:20:37 +03:00
IllusionMH 8d9eda5d0a Add test 2020-09-01 02:37:25 +03:00
IllusionMH cf0b7ce2d0 Validate constructor options 2020-09-01 01:03:49 +03:00
Daniel Imms 60419a7cc6 Merge pull request #3061 from xtermjs/dependabot/npm_and_yarn/mocha-8.1.3
Bump mocha from 8.1.1 to 8.1.3
2020-08-31 12:46:29 -07:00
dependabot-preview[bot] 1b12b2d15d Bump mocha from 8.1.1 to 8.1.3
Bumps [mocha](https://github.com/mochajs/mocha) from 8.1.1 to 8.1.3.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v8.1.1...v8.1.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-31 16:20:40 +00:00
Daniel Imms b5844990c4 Merge pull request #3060 from xtermjs/dependabot/npm_and_yarn/source-map-loader-1.1.0
Bump source-map-loader from 1.0.2 to 1.1.0
2020-08-31 09:18:56 -07:00
dependabot-preview[bot] 2652768310 Bump source-map-loader from 1.0.2 to 1.1.0
Bumps [source-map-loader](https://github.com/webpack-contrib/source-map-loader) from 1.0.2 to 1.1.0.
- [Release notes](https://github.com/webpack-contrib/source-map-loader/releases)
- [Changelog](https://github.com/webpack-contrib/source-map-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/source-map-loader/compare/v1.0.2...v1.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-31 16:12:37 +00:00
Daniel Imms 1f8a6bece4 Merge pull request #3059 from Tyriar/ts4
Upgrade to typescript 4
2020-08-29 09:39:53 -07:00
Daniel Imms 8817ddf020 Remove empty deps 2020-08-28 20:58:06 -07:00
Daniel Imms 5d61956aff Get rid of removed typescript-eslint rules 2020-08-28 20:41:50 -07:00
Daniel Imms 83ece031a7 typescript@4.0 2020-08-28 19:35:26 -07:00
Daniel Imms 566fad4108 Merge pull request #3043 from xtermjs/dependabot/npm_and_yarn/types/mocha-8.0.3
Bump @types/mocha from 8.0.2 to 8.0.3
2020-08-24 12:55:01 -07:00
Daniel Imms a4aa111eaa Merge pull request #3052 from xtermjs/dependabot/npm_and_yarn/ts-loader-8.0.3
Bump ts-loader from 8.0.2 to 8.0.3
2020-08-24 12:54:45 -07:00
dependabot-preview[bot] f6ed184d49 Bump ts-loader from 8.0.2 to 8.0.3
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.2 to 8.0.3.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v8.0.2...v8.0.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-24 15:59:17 +00:00
Daniel Imms c1820501a8 Merge pull request #3046 from Intervue/patch-1
Update README.md to add intervue
2020-08-24 06:40:21 -07:00
dependabot-preview[bot] c7f50c5c28 Bump @types/mocha from 8.0.2 to 8.0.3
Bumps [@types/mocha](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/mocha) from 8.0.2 to 8.0.3.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/mocha)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-24 13:21:31 +00:00
Daniel Imms 371c96e1da Merge pull request #3048 from xtermjs/dependabot/npm_and_yarn/source-map-loader-1.0.2
Bump source-map-loader from 1.0.1 to 1.0.2
2020-08-24 06:19:46 -07:00
dependabot-preview[bot] 11bd8b7eb1 Bump source-map-loader from 1.0.1 to 1.0.2
Bumps [source-map-loader](https://github.com/webpack-contrib/source-map-loader) from 1.0.1 to 1.0.2.
- [Release notes](https://github.com/webpack-contrib/source-map-loader/releases)
- [Changelog](https://github.com/webpack-contrib/source-map-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/webpack-contrib/source-map-loader/compare/v1.0.1...v1.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-21 15:13:37 +00:00
Intervue cb418eb8d1 Update README.md 2020-08-20 18:18:48 +05:30
Daniel Imms f811fb937e Merge pull request #3040 from akshaykmr/patch-1
readme: adds TeleType cli-tool to Real-world uses section
2020-08-13 06:02:05 -07:00
Akshay Kumar 2a6ccb8009 adds TeleType cli-tool to Real-world uses section 2020-08-13 16:49:25 +05:30
Daniel Imms bf49f99810 Merge pull request #3039 from xtermjs/dependabot/npm_and_yarn/types/mocha-8.0.2
Bump @types/mocha from 8.0.1 to 8.0.2
2020-08-12 08:38:04 -07:00
dependabot-preview[bot] e027a5f97b Bump @types/mocha from 8.0.1 to 8.0.2
Bumps [@types/mocha](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/mocha) from 8.0.1 to 8.0.2.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/mocha)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-12 15:08:48 +00:00
Daniel Imms d1ecb571d8 Merge pull request #3033 from xtermjs/dependabot/npm_and_yarn/mocha-8.1.1
Bump mocha from 8.1.0 to 8.1.1
2020-08-10 13:37:03 -07:00
dependabot-preview[bot] 1e3937830f Bump mocha from 8.1.0 to 8.1.1
Bumps [mocha](https://github.com/mochajs/mocha) from 8.1.0 to 8.1.1.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v8.1.0...v8.1.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-10 14:13:23 +00:00
Daniel Imms 38b2fcb460 Merge pull request #3035 from xtermjs/dependabot/npm_and_yarn/jsdom-16.4.0
Bump jsdom from 16.3.0 to 16.4.0
2020-08-10 07:11:37 -07:00
dependabot-preview[bot] c7ed42226f Bump jsdom from 16.3.0 to 16.4.0
Bumps [jsdom](https://github.com/jsdom/jsdom) from 16.3.0 to 16.4.0.
- [Release notes](https://github.com/jsdom/jsdom/releases)
- [Changelog](https://github.com/jsdom/jsdom/blob/master/Changelog.md)
- [Commits](https://github.com/jsdom/jsdom/compare/16.3.0...16.4.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-10 11:49:09 +00:00
Daniel Imms d0dfad4c92 Merge pull request #3031 from xtermjs/dependabot/npm_and_yarn/ts-loader-8.0.2
Bump ts-loader from 8.0.1 to 8.0.2
2020-08-03 06:40:43 -07:00
dependabot-preview[bot] c66123b91f Bump ts-loader from 8.0.1 to 8.0.2
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.1 to 8.0.2.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v8.0.1...v8.0.2)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-08-03 13:31:14 +00:00
Daniel Imms 8d912e891e Merge pull request #3028 from xtermjs/dependabot/npm_and_yarn/types/mocha-8.0.1
Bump @types/mocha from 8.0.0 to 8.0.1
2020-07-31 19:28:13 -07:00
dependabot-preview[bot] 23fd6b8e60 Bump @types/mocha from 8.0.0 to 8.0.1
Bumps [@types/mocha](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/mocha) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/mocha)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-31 22:06:10 +00:00
Daniel Imms 0320e6e22a Merge pull request #3027 from xtermjs/dependabot/npm_and_yarn/mocha-8.1.0
Bump mocha from 8.0.1 to 8.1.0
2020-07-31 15:04:28 -07:00
dependabot-preview[bot] 9e70d8fc84 Bump mocha from 8.0.1 to 8.1.0
Bumps [mocha](https://github.com/mochajs/mocha) from 8.0.1 to 8.1.0.
- [Release notes](https://github.com/mochajs/mocha/releases)
- [Changelog](https://github.com/mochajs/mocha/blob/master/CHANGELOG.md)
- [Commits](https://github.com/mochajs/mocha/compare/v8.0.1...v8.1.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-31 21:26:19 +00:00
Daniel Imms 27e28eccac Merge pull request #3026 from Tyriar/docker
Remove docker from root
2020-07-31 06:31:58 -07:00
Daniel Imms 0cb0313fc9 Remove docker from root
We will keep the devcontainer as that is something we want to continue to
support.

Fixes #3000
2020-07-31 06:23:05 -07:00
Daniel Imms 94a34c3703 Merge pull request #3023 from xtermjs/dependabot/npm_and_yarn/elliptic-6.5.3
[Security] Bump elliptic from 6.5.2 to 6.5.3
2020-07-30 07:03:40 -07:00
dependabot-preview[bot] c04c836f12 [Security] Bump elliptic from 6.5.2 to 6.5.3
Bumps [elliptic](https://github.com/indutny/elliptic) from 6.5.2 to 6.5.3. **This update includes a security fix.**
- [Release notes](https://github.com/indutny/elliptic/releases)
- [Commits](https://github.com/indutny/elliptic/compare/v6.5.2...v6.5.3)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-30 13:52:44 +00:00
Daniel Imms c5a9d2c52d Merge pull request #3024 from xtermjs/dependabot/npm_and_yarn/webpack-4.44.1
Bump webpack from 4.44.0 to 4.44.1
2020-07-30 06:51:23 -07:00
dependabot-preview[bot] c0050672ab Bump webpack from 4.44.0 to 4.44.1
Bumps [webpack](https://github.com/webpack/webpack) from 4.44.0 to 4.44.1.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v4.44.0...v4.44.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-30 11:23:30 +00:00
Daniel Imms 705f94518f Merge pull request #3021 from sergeichestakov/add-replit
Add Repl.it to Real-world uses
2020-07-29 13:46:53 -07:00
Sergei Chestakov a096217526 Merge branch 'master' into add-replit 2020-07-29 13:11:49 -07:00
sergeichestakov 795768667e Add Repl.it to Real-world uses 2020-07-29 13:08:50 -07:00
Daniel Imms 5e9a8c6321 Merge pull request #3020 from Tyriar/vsc98918
Use document role instead of list
2020-07-29 05:34:06 -07:00
Daniel Imms 03df0565bd Use document role instead of list
See microsoft/vscode#98918
2020-07-29 05:29:30 -07:00
Daniel Imms 3ef6856b36 Merge pull request #3018 from xtermjs/dependabot/npm_and_yarn/webpack-4.44.0
Bump webpack from 4.43.0 to 4.44.0
2020-07-27 05:28:20 -07:00
dependabot-preview[bot] 48e9f33263 Bump webpack from 4.43.0 to 4.44.0
Bumps [webpack](https://github.com/webpack/webpack) from 4.43.0 to 4.44.0.
- [Release notes](https://github.com/webpack/webpack/releases)
- [Commits](https://github.com/webpack/webpack/compare/v4.43.0...v4.44.0)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-27 07:54:25 +00:00
Daniel Imms 9559dd47da Merge pull request #3017 from xtermjs/dependabot/npm_and_yarn/types/chai-4.2.12
Bump @types/chai from 4.2.11 to 4.2.12
2020-07-24 05:23:59 -07:00
dependabot-preview[bot] ad7f8c303c Bump @types/chai from 4.2.11 to 4.2.12
Bumps [@types/chai](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/HEAD/types/chai) from 4.2.11 to 4.2.12.
- [Release notes](https://github.com/DefinitelyTyped/DefinitelyTyped/releases)
- [Commits](https://github.com/DefinitelyTyped/DefinitelyTyped/commits/HEAD/types/chai)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-24 07:41:38 +00:00
Daniel Imms edb7a0edda Merge pull request #3015 from xtermjs/dependabot/npm_and_yarn/typescript-3.9.7
Bump typescript from 3.9.6 to 3.9.7
2020-07-17 06:22:42 -07:00
dependabot-preview[bot] aedcbba211 Bump typescript from 3.9.6 to 3.9.7
Bumps [typescript](https://github.com/Microsoft/TypeScript) from 3.9.6 to 3.9.7.
- [Release notes](https://github.com/Microsoft/TypeScript/releases)
- [Commits](https://github.com/Microsoft/TypeScript/compare/v3.9.6...v3.9.7)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-17 07:43:13 +00:00
Daniel Imms ab63b51681 Merge pull request #3013 from xtermjs/dependabot/npm_and_yarn/lodash-4.17.19
[Security] Bump lodash from 4.17.15 to 4.17.19
2020-07-16 05:28:25 -07:00
dependabot-preview[bot] 63f5d0c266 [Security] Bump lodash from 4.17.15 to 4.17.19
Bumps [lodash](https://github.com/lodash/lodash) from 4.17.15 to 4.17.19. **This update includes a security fix.**
- [Release notes](https://github.com/lodash/lodash/releases)
- [Commits](https://github.com/lodash/lodash/compare/4.17.15...4.17.19)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-16 07:46:50 +00:00
Daniel Imms 349ebd3846 Merge pull request #3012 from xtermjs/dependabot/npm_and_yarn/ts-loader-8.0.1
Bump ts-loader from 8.0.0 to 8.0.1
2020-07-15 05:06:55 -07:00
dependabot-preview[bot] ce496bc389 Bump ts-loader from 8.0.0 to 8.0.1
Bumps [ts-loader](https://github.com/TypeStrong/ts-loader) from 8.0.0 to 8.0.1.
- [Release notes](https://github.com/TypeStrong/ts-loader/releases)
- [Changelog](https://github.com/TypeStrong/ts-loader/blob/master/CHANGELOG.md)
- [Commits](https://github.com/TypeStrong/ts-loader/compare/v8.0.0...v8.0.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-07-15 07:36:40 +00:00
Daniel Imms be1af82ee0 Merge pull request #3010 from Tyriar/mocha8
@types/mocha@8
2020-07-13 06:38:03 -07:00
Daniel Imms 11bfb03add @types/mocha@8 2020-07-13 06:21:25 -07:00
Daniel Imms b89d4b102e Merge pull request #3008 from andrew-schlackman/fix-renderer-pause2
fix renderer pause again with handling of undefined
2020-07-13 06:02:48 -07:00
Andrew Schlackman 0abd121653 fix renderer pause again with handling of undefined 2020-07-12 10:07:47 -04:00
Daniel Imms eeb095b095 Merge pull request #3007 from xtermjs/Tyriar-patch-1
v4.8.1
2020-07-10 12:22:21 -07:00
Daniel Imms 266a289520 Update package.json 2020-07-10 12:21:15 -07:00
Daniel Imms 3c1d6b575a Merge pull request #3005 from Tyriar/fix_passive
Indicate non-passive scroll events for viewport
2020-07-10 12:19:12 -07:00
Daniel Imms bd08862074 Merge pull request #3006 from Tyriar/revert
Revert "fix renderer pausing inadvertently in some cases"
2020-07-10 12:18:36 -07:00
Daniel Imms 70e0c0385a Revert "fix renderer pausing inadvertently in some cases"
This reverts commit 5738f4545f.
2020-07-10 12:14:59 -07:00
Daniel Imms 454cf1fb26 Indicate non-passive scroll events for viewport
Fixes #3004
2020-07-10 12:13:26 -07:00
163 changed files with 7815 additions and 5342 deletions
-16
View File
@@ -1,16 +0,0 @@
node_modules/
*.swp
.lock-wscript
lib/
Makefile.gyp
*.Makefile
*.target.gyp.mk
*.node
example/*.log
docs/
npm-debug.log
/.idea/
.env
build/
.vscode/
.git/
+24 -10
View File
@@ -12,14 +12,21 @@
"test/api/tsconfig.json",
"test/benchmark/tsconfig.json",
"addons/xterm-addon-attach/src/tsconfig.json",
"addons/xterm-addon-attach/test/tsconfig.json",
"addons/xterm-addon-fit/src/tsconfig.json",
"addons/xterm-addon-fit/test/tsconfig.json",
"addons/xterm-addon-ligatures/src/tsconfig.json",
"addons/xterm-addon-search/src/tsconfig.json",
"addons/xterm-addon-unicode11/src/tsconfig.json",
"addons/xterm-addon-web-links/src/tsconfig.json",
"addons/xterm-addon-webgl/src/tsconfig.json",
"addons/xterm-addon-search/test/tsconfig.json",
"addons/xterm-addon-serialize/src/tsconfig.json",
"addons/xterm-addon-serialize/test/tsconfig.json",
"addons/xterm-addon-serialize/benchmark/tsconfig.json",
"addons/xterm-addon-ligatures/src/tsconfig.json"
"addons/xterm-addon-unicode11/src/tsconfig.json",
"addons/xterm-addon-unicode11/test/tsconfig.json",
"addons/xterm-addon-web-links/src/tsconfig.json",
"addons/xterm-addon-web-links/test/tsconfig.json",
"addons/xterm-addon-webgl/src/tsconfig.json",
"addons/xterm-addon-webgl/test/tsconfig.json"
],
"sourceType": "module"
},
@@ -40,7 +47,6 @@
"readonly": "generic"
}
],
"@typescript-eslint/class-name-casing": "warn",
"@typescript-eslint/consistent-type-definitions": "warn",
"@typescript-eslint/explicit-function-return-type": [
"warn",
@@ -61,10 +67,6 @@
"warn",
2
],
"@typescript-eslint/interface-name-prefix": [
"warn",
"always"
],
"@typescript-eslint/member-delimiter-style": [
"warn",
{
@@ -149,6 +151,10 @@
"warn",
"never"
],
"object-curly-spacing": [
"warn",
"always"
],
"prefer-const": "warn",
"spaced-comment": [
"warn",
@@ -158,5 +164,13 @@
"exceptions": ["-"]
}
]
}
},
"overrides": [
{
"files": ["**/*.test.ts"],
"rules": {
"object-curly-spacing": "off"
}
}
]
}
+68 -49
View File
@@ -1,51 +1,70 @@
{
"version": "2.0.0",
"presentation": {
"echo": false,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true
},
"tasks": [
{
"type": "npm",
"script": "test",
"group": "test",
"problemMatcher": []
},
{
"type": "npm",
"script": "watch",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"type": "npm",
"script": "start",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"label": "Start demo",
"dependsOn": ["npm: watch", "npm: start"],
"group": {
"kind": "build",
"isDefault": true
},
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
}
]
"version": "2.0.0",
"presentation": {
"echo": false,
"reveal": "always",
"focus": false,
"panel": "dedicated",
"showReuseMessage": true
},
"tasks": [
{
"type": "npm",
"script": "test",
"group": "test",
"problemMatcher": []
},
{
"type": "npm",
"script": "watch",
"group": "build",
"isBackground": true,
"problemMatcher": "$tsc-watch",
"presentation": {
"group": "vscode"
}
},
{
"type": "npm",
"script": "start",
"dependsOn": "npm: watch",
"group": "build",
"isBackground": true,
"problemMatcher": [],
"presentation": {
"group": "vscode"
}
},
{
"label": "Start demo",
"dependsOn": "npm: start",
"group": {
"kind": "build",
"isDefault": true
},
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"fileLocation": [
"relative",
"${workspaceFolder}"
],
"pattern": [
{
"regexp": "^([^\\\\s].*)\\\\((\\\\d+,\\\\d+)\\\\):\\\\s*(.*)$",
"file": 1,
"location": 2,
"message": 3
}
],
"background": {
"beginsPattern": "assets by",
"endsPattern": "webpack \\d+\\.\\d+\\.\\d+ compiled successfully"
}
},
"presentation": {
"group": "vscode"
}
}
]
}
-19
View File
@@ -1,19 +0,0 @@
FROM node:12
MAINTAINER Paris Kasidiaris <paris@sourcelair.com>
# Set the working directory
WORKDIR /usr/src/app
# Set an entrypoint, to automatically install node modules
ENTRYPOINT ["/bin/bash", "-c", "if [[ ! -d node_modules ]]; then npm install; fi; exec \"${@:0}\";"]
CMD ["npm", "run", "start"]
# First, install dependencies to improve layer caching
COPY package.json /usr/src/app/
RUN npm install
# Add the code
COPY . /usr/src/app
# Run the tests and build, to make sure everything is working nicely
RUN npm run build && npm run test
+31 -21
View File
@@ -6,11 +6,11 @@ Xterm.js is a front-end component written in TypeScript that lets applications b
## Features
- **Terminal apps just work**: Xterm.js works with most terminal apps such as `bash`, `vim` and `tmux`, this includes support for curses-based apps and mouse event support.
- **Terminal apps just work**: Xterm.js works with most terminal apps such as `bash`, `vim`, and `tmux`, including support for curses-based apps and mouse events.
- **Performant**: Xterm.js is *really* fast, it even includes a GPU-accelerated renderer.
- **Rich unicode support**: Supports CJK, emojis and IMEs.
- **Rich Unicode support**: Supports CJK, emojis, and IMEs.
- **Self-contained**: Requires zero dependencies to work.
- **Accessible**: Screen reader and minimum contrast ratio support can be turned on
- **Accessible**: Screen reader and minimum contrast ratio support can be turned on.
- **And much more**: Links, theming, addons, well documented API, etc.
## What xterm.js is not
@@ -20,13 +20,13 @@ Xterm.js is a front-end component written in TypeScript that lets applications b
## Getting Started
First you need to install the module, we ship exclusively through [npm](https://www.npmjs.com/) so you need that installed and then add xterm.js as a dependency by running:
First, you need to install the module, we ship exclusively through [npm](https://www.npmjs.com/), so you need that installed and then add xterm.js as a dependency by running:
```
```bash
npm install xterm
```
To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your html page. Then create a `<div id="terminal"></div>` onto which xterm can attach itself. Finally instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.
To start using xterm.js on your browser, add the `xterm.js` and `xterm.css` to the head of your HTML page. Then create a `<div id="terminal"></div>` onto which xterm can attach itself. Finally, instantiate the `Terminal` object and then call the `open` function with the DOM object of the `div`.
```html
<!doctype html>
@@ -58,7 +58,7 @@ import { Terminal } from 'xterm';
⚠️ *This section describes the new addon format introduced in v3.14.0, see [here](https://github.com/xtermjs/xterm.js/blob/3.14.2/README.md#addons) for the instructions on the old format*
Addons are separate modules that extend the `Terminal` by building on the [xterm.js API](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts). To use an addon you first need to install it in your project:
Addons are separate modules that extend the `Terminal` by building on the [xterm.js API](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts). To use an addon, you first need to install it in your project:
```bash
npm i -S xterm-addon-web-links
@@ -76,7 +76,7 @@ const terminal = new Terminal();
terminal.loadAddon(new WebLinksAddon());
```
The xterm.js team maintains the following addons but they can be built by anyone:
The xterm.js team maintains the following addons, but anyone can build them:
- [`xterm-addon-attach`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-attach): Attaches to a server running a process via a websocket
- [`xterm-addon-fit`](https://github.com/xtermjs/xterm.js/tree/master/addons/xterm-addon-fit): Fits the terminal to the containing element
@@ -85,23 +85,23 @@ The xterm.js team maintains the following addons but they can be built by anyone
## Browser Support
Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Specifically the latest versions of *Chrome*, *Edge*, *Firefox* and *Safari*.
Since xterm.js is typically implemented as a developer tool, only modern browsers are supported officially. Specifically the latest versions of *Chrome*, *Edge*, *Firefox*, and *Safari*.
We also partially support *Intenet Explorer 11*, meaning xterm.js should work for the most part, but we reserve the right to not provide workarounds specifically for it unless it's absolutely necessary to get the basic input/output flow working.
We also partially support *Internet Explorer 11*, meaning xterm.js should work for the most part, but we reserve the right to not provide workarounds specifically for it unless it's absolutely necessary to get the basic input/output flow working.
Xterm.js works seamlessly in [Electron](https://electronjs.org/) apps and may even work on earlier versions of the browsers, these are the versions we strive to keep working.
Xterm.js works seamlessly in [Electron](https://electronjs.org/) apps and may even work on earlier versions of the browsers. These are the versions we strive to keep working.
## API
The full API for xterm.js is contained within the [TypeScript declaration file](https://github.com/xtermjs/xterm.js/blob/master/typings/xterm.d.ts), use the branch/tag picker in GitHub (`w`) to navigate to the correct version of the API.
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.
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.
## Real-world uses
Xterm.js is used in several world-class applications to provide great terminal experiences.
- [**SourceLair**](https://www.sourcelair.com/): In-browser IDE that provides its users with fully-featured Linux terminals based on xterm.js.
- [**Microsoft Visual Studio Code**](http://code.visualstudio.com/): Modern, versatile and powerful open source code editor that provides an integrated terminal based on xterm.js.
- [**Microsoft Visual Studio Code**](http://code.visualstudio.com/): Modern, versatile, and powerful open source code editor that provides an integrated terminal based on xterm.js.
- [**ttyd**](https://github.com/tsl0922/ttyd): A command-line tool for sharing terminal over the web, with fully-featured terminal emulation based on xterm.js.
- [**Katacoda**](https://www.katacoda.com/): Katacoda is an Interactive Learning Platform for software developers, covering the latest Cloud Native technologies.
- [**Eclipse Che**](http://www.eclipse.org/che): Developer workspace server, cloud IDE, and Eclipse next-generation IDE.
@@ -113,10 +113,10 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**Next Tech**](https://next.tech "Next Tech"): Online platform for interactive coding and web development courses. Live container-backed terminal uses xterm.js.
- [**RStudio**](https://www.rstudio.com/products/RStudio "RStudio"): RStudio is an integrated development environment (IDE) for R.
- [**Terminal for Atom**](https://github.com/jsmecham/atom-terminal-tab): A simple terminal for the Atom text editor.
- [**Eclipse Orion**](https://orionhub.org): A modern, open source software development environment that runs in the cloud. Code, deploy and run in the cloud.
- [**Eclipse Orion**](https://orionhub.org): A modern, open source software development environment that runs in the cloud. Code, deploy, and run in the cloud.
- [**Gravitational Teleport**](https://github.com/gravitational/teleport): Gravitational Teleport is a modern SSH server for remotely accessing clusters of Linux servers via SSH or HTTPS.
- [**Hexlet**](https://en.hexlet.io): Practical programming courses (JavaScript, PHP, Unix, databases, functional programming). A steady path from the first line of code to the first job.
- [**Selenoid UI**](https://github.com/aerokube/selenoid-ui): Simple UI for the scallable golang implementation of Selenium Hub named Selenoid. We use XTerm for streaming logs over websockets from docker containers.
- [**Selenoid UI**](https://github.com/aerokube/selenoid-ui): Simple UI for the scalable golang implementation of Selenium Hub named Selenoid. We use XTerm for streaming logs over websockets from docker containers.
- [**Portainer**](https://portainer.io): Simple management UI for Docker.
- [**SSHy**](https://github.com/stuicey/SSHy): HTML5 Based SSHv2 Web Client with E2E encryption utilising xterm.js, SJCL & websockets.
- [**JupyterLab**](https://github.com/jupyterlab/jupyterlab): An extensible computational environment for Jupyter, supporting interactive data science and scientific computing across all programming languages.
@@ -165,9 +165,19 @@ Xterm.js is used in several world-class applications to provide great terminal e
- [**DockerStacks**](https://docker-stacks.com/): Local LAMP/LEMP development studio
- [**Codecademy**](https://codecademy.com/): Uses xterm.js in its courses on Bash.
- [**Laravel Ssh Web Client**](https://github.com/roke22/Laravel-ssh-client): Laravel server inventory with ssh web client to connect at server using xterm.js
- [**Repl.it**](https://repl.it): Collaborative browser based IDE with support for 50+ different languages.
- [**TeleType**](https://github.com/akshaykmr/TeleType): cli tool that allows you to share your terminal online conveniently. Show off mad cli-fu, help a colleague, teach, or troubleshoot.
- [**Intervue**](https://www.intervue.io): Pair programming for interviews. Multiple programming languages are supported, with results displayed by xterm.js.
- [**TRASA**](https://trasa.io): Zero trust access to Web, SSH, RDP, and Database services.
- [**Commas**](https://github.com/CyanSalt/commas): Commas is a hackable terminal and command runner.
- [**Devtron**](https://github.com/devtron-labs/devtron): Software Delivery Workflow For Kubernetes.
- [**NxShell**](https://github.com/nxshell/nxshell): An easy to use new terminal for SSH.
- [**gifcast**](https://dstein64.github.io/gifcast/): Converts an asciinema cast to an animated GIF.
- [**WizardWebssh**](https://gitlab.com/mikeramsey/wizardwebssh): A terminal with Pyqt5 Widget for embedding, which can be used as an ssh client to connect to your ssh servers. It is written in Python, based on tornado, paramiko, and xterm.js.
- [**Wizard Assistant**](https://wizardassistant.com/): Wizard Assistant comes with advanced automation tools, preloaded common and special time-saving commands, and a built-in SSH terminal. Now you can remotely administer, troubleshoot, and analyze any system with ease.
[And much more...](https://github.com/xtermjs/xterm.js/network/dependents)
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 in our list. Note: Please add any new contributions to the end of the list only.
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
@@ -177,21 +187,21 @@ All current and past releases are available on this repo's [Releases page](https
### Beta builds
Our CI releases beta builds to npm for every change that goes into master, install the latest beta build with:
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 for verifying bug fixes.
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 setup xterm.js for development.
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 are implicitly allowing your code to be distributed under the MIT license. You are also implicitly verifying that all code is your original work.
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.
Copyright (c) 2017-2019, [The xterm.js authors](https://github.com/xtermjs/xterm.js/graphs/contributors) (MIT License)<br>
Copyright (c) 2014-2017, SourceLair, Private Company ([www.sourcelair.com](https://www.sourcelair.com/home)) (MIT License)<br>
+1 -1
View File
@@ -10,7 +10,7 @@
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"build": "../../node_modules/.bin/tsc -p .",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
+3 -1
View File
@@ -41,7 +41,9 @@ export class AttachAddon implements ITerminalAddon {
}
public dispose(): void {
this._disposables.forEach(d => d.dispose());
for (const d of this._disposables) {
d.dispose();
}
}
private _sendData(data: string): void {
+1 -2
View File
@@ -12,8 +12,7 @@
"removeComments": true,
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
"../../../node_modules/@types/mocha"
]
},
"include": [
@@ -5,9 +5,9 @@
import WebSocket = require('ws');
import { openTerminal, pollFor, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
import { Browser, Page } from 'playwright';
const APP = 'http://127.0.0.1:3000/test';
const APP = 'http://127.0.0.1:3001/test';
let browser: Browser;
let page: Page;
@@ -17,8 +17,8 @@ const height = 600;
describe('AttachAddon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
browser = await browserType.launch({
headless: process.argv.includes('--headless')
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"es2015"
],
"rootDir": ".",
"outDir": "../out-test",
"sourceMap": true,
"removeComments": true,
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../node_modules/@types/node",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
]
}
+8
View File
@@ -0,0 +1,8 @@
{
"files": [],
"include": [],
"references": [
{ "path": "./src" },
{ "path": "./test" }
]
}
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-fit",
"version": "0.4.0",
"version": "0.5.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
@@ -10,7 +10,7 @@
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"build": "../../node_modules/.bin/tsc -p .",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
+4
View File
@@ -59,6 +59,10 @@ export class FitAddon implements ITerminalAddon {
// TODO: Remove reliance on private API
const core = (this._terminal as any)._core;
if (core._renderService.dimensions.actualCellWidth === 0 || core._renderService.dimensions.actualCellHeight === 0) {
return undefined;
}
const parentElementStyle = window.getComputedStyle(this._terminal.element.parentElement);
const parentElementHeight = parseInt(parentElementStyle.getPropertyValue('height'));
const parentElementWidth = Math.max(0, parseInt(parentElementStyle.getPropertyValue('width')));
+1 -2
View File
@@ -12,8 +12,7 @@
"removeComments": true,
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
"../../../node_modules/@types/mocha"
]
},
"include": [
@@ -5,9 +5,9 @@
import { assert } from 'chai';
import { openTerminal, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
import { Browser, Page } from 'playwright';
const APP = 'http://127.0.0.1:3000/test';
const APP = 'http://127.0.0.1:3001/test';
let browser: Browser;
let page: Page;
@@ -17,12 +17,16 @@ const height = 768;
describe('FitAddon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
browser = await browserType.launch({
headless: process.argv.includes('--headless')
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
await page.goto(APP);
});
beforeEach(async function(): Promise<any> {
await page.evaluate(`document.querySelector('#terminal-container').style.display=''`);
await openTerminal(page);
});
@@ -30,6 +34,10 @@ describe('FitAddon', () => {
await browser.close();
});
afterEach(async function(): Promise<any> {
await page.evaluate(`window.term.dispose()`);
});
it('no terminal', async function(): Promise<any> {
await page.evaluate(`window.fit = new FitAddon();`);
assert.equal(await page.evaluate(`window.fit.proposeDimensions()`), undefined);
@@ -37,7 +45,7 @@ describe('FitAddon', () => {
describe('proposeDimensions', () => {
afterEach(async () => {
return unloadFit();
return await unloadFit();
});
it('default', async function(): Promise<any> {
@@ -63,11 +71,20 @@ describe('FitAddon', () => {
rows: 1
});
});
it('hidden', async function(): Promise<any> {
await page.evaluate(`window.term.dispose()`);
await page.evaluate(`document.querySelector('#terminal-container').style.display='none'`);
await page.evaluate(`window.term = new Terminal()`);
await page.evaluate(`window.term.open(document.querySelector('#terminal-container'))`);
await loadFit();
assert.equal(await page.evaluate(`window.fit.proposeDimensions()`), undefined);
});
});
describe('fit', () => {
afterEach(async () => {
return unloadFit();
return await unloadFit();
});
it('default', async function(): Promise<any> {
+23
View File
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"es2015"
],
"rootDir": ".",
"outDir": "../out-test",
"sourceMap": true,
"removeComments": true,
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../node_modules/@types/node",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
]
}
+8
View File
@@ -0,0 +1,8 @@
{
"files": [],
"include": [],
"references": [
{ "path": "./src" },
{ "path": "./test" }
]
}
+1
View File
@@ -51,3 +51,4 @@ This package makes use of the following fonts for testing:
[Fira Code License]: https://github.com/tonsky/FiraCode/blob/master/LICENSE
[Iosevka]: https://github.com/be5invis/Iosevka
[Iosevka License]: https://github.com/be5invis/Iosevka/blob/master/LICENSE.md
+3 -3
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-ligatures",
"version": "0.3.0",
"version": "0.5.0",
"description": "Add support for programming ligatures to xterm.js",
"author": {
"name": "The xterm.js authors",
@@ -31,8 +31,8 @@
],
"license": "MIT",
"dependencies": {
"font-finder": "^1.0.4",
"font-ligatures": "^1.3.3"
"font-finder": "^1.1.0",
"font-ligatures": "^1.4.0"
},
"devDependencies": {
"@types/sinon": "^5.0.1",
+58 -6
View File
@@ -3,12 +3,19 @@
* @license MIT
*/
import * as fontFinder from 'font-finder';
import * as fontLigatures from 'font-ligatures';
import { FontList } from 'font-finder';
import { Font, loadBuffer, loadFile } from 'font-ligatures';
import parse from './parse';
let fontsPromise: Promise<fontFinder.FontList> | undefined = undefined;
interface IFontMetadata {
family: string;
fullName: string;
postscriptName: string;
blob: () => Promise<Blob>;
}
let fontsPromise: Promise<FontList | Record<string, IFontMetadata[]>> | undefined = undefined;
/**
* Loads the font ligature wrapper for the specified font family if it could be
@@ -16,9 +23,50 @@ let fontsPromise: Promise<fontFinder.FontList> | undefined = undefined;
* @param fontFamily The CSS font family definition to resolve
* @param cacheSize The size of the ligature cache to maintain if the font is resolved
*/
export default async function load(fontFamily: string, cacheSize: number): Promise<fontLigatures.Font | undefined> {
export default async function load(fontFamily: string, cacheSize: number): Promise<Font | undefined> {
if (!fontsPromise) {
fontsPromise = fontFinder.list();
// Web environment that supports font access API
if (typeof navigator !== 'undefined' && 'fonts' in navigator) {
try {
const status = await (navigator as any).permissions.request?.({
name: 'local-fonts'
});
if (status && status.state !== 'granted') {
throw new Error('Permission to access local fonts not granted.');
}
} catch (err) {
// A `TypeError` indicates the 'local-fonts'
// permission is not yet implemented, so
// only `throw` if this is _not_ the problem.
if (err.name !== 'TypeError') {
throw err;
}
}
const fonts: Record<string, IFontMetadata[]> = {};
try {
const fontsIterator: AsyncIterableIterator<IFontMetadata> = (navigator as any).fonts.query();
for await (const metadata of fontsIterator) {
if (!fonts.hasOwnProperty(metadata.family)) {
fonts[metadata.family] = [];
}
fonts[metadata.family].push(metadata);
}
fontsPromise = Promise.resolve(fonts);
} catch (err) {
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({});
}
}
const fonts = await fontsPromise;
@@ -31,7 +79,11 @@ export default async function load(fontFamily: string, cacheSize: number): Promi
}
if (fonts.hasOwnProperty(family) && fonts[family].length > 0) {
return await fontLigatures.loadFile(fonts[family][0].path, { cacheSize });
const font = fonts[family][0];
if ('blob' in font) {
return loadBuffer(await (await font.blob()).arrayBuffer(), { cacheSize });
}
return await loadFile(font.path, { cacheSize });
}
}
+3 -3
View File
@@ -68,7 +68,7 @@ function parseString(context: IParseContext, quoteChar: '\'' | '"'): string {
while (context.offset < context.input.length) {
const char = context.input[context.offset++];
if (escaped) {
if (/[0-9a-fA-F]/.test(char)) {
if (/[\dA-Fa-f]/.test(char)) {
// Unicode escape
context.offset--;
str += parseUnicode(context);
@@ -107,7 +107,7 @@ function parseIdentifier(context: IParseContext): string {
while (context.offset < context.input.length) {
const char = context.input[context.offset++];
if (escaped) {
if (/[0-9a-fA-F]/.test(char)) {
if (/[\dA-Fa-f]/.test(char)) {
// Unicode escape
context.offset--;
str += parseUnicode(context);
@@ -156,7 +156,7 @@ function parseUnicode(context: IParseContext): string {
// of the escape and is swallowed.
return unicodeToString(str);
}
if (str.length >= 6 || !/[0-9a-fA-F]/.test(char)) {
if (str.length >= 6 || !/[\dA-Fa-f]/.test(char)) {
// If the next character is not a valid hex digit or we have reached the
// maximum of 6 digits in the escape, terminate the escape.
context.offset--;
+16 -13
View File
@@ -1,16 +1,19 @@
{
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"sourceMap": true,
"outDir": "../out",
"rootDir": ".",
"strict": true,
"noUnusedLocals": true,
"preserveWatchOutput": true
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
"compilerOptions": {
"target": "es2017",
"module": "commonjs",
"sourceMap": true,
"outDir": "../out",
"rootDir": ".",
"strict": true,
"noUnusedLocals": true,
"preserveWatchOutput": true,
"types": [
"../../../node_modules/@types/mocha"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
]
}
@@ -0,0 +1,7 @@
{
"files": [],
"include": [],
"references": [
{ "path": "./src" }
]
}
+13 -2
View File
@@ -30,7 +30,18 @@ module.exports = {
},
mode: 'production',
externals: {
'font-finder':'font-finder',
'font-ligatures':'font-ligatures'
'font-finder': 'font-finder',
'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,
os: false,
path: false
}
}
};
+26 -21
View File
@@ -78,20 +78,28 @@ follow-redirects@1.5.10:
dependencies:
debug "=3.1.0"
font-finder@^1.0.3, font-finder@^1.0.4:
font-finder@^1.0.3:
version "1.0.4"
resolved "https://registry.yarnpkg.com/font-finder/-/font-finder-1.0.4.tgz#2ca944954dd8d0e1b5bdc4c596cc08607761d89b"
dependencies:
get-system-fonts "^2.0.0"
promise-stream-reader "^1.0.1"
font-ligatures@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/font-ligatures/-/font-ligatures-1.3.3.tgz#63fff18dc8adb3a11fe5eec1f4e8d7edfa8075b9"
integrity sha512-NSGpHgVNX81M7AWS1XylK1UZbN3QllfUIDAAuPv6TUcl5O2b781JcKS5L2RopAU0AqlTyX3ZuX/04eaMpbVrHA==
font-finder@^1.1.0:
version "1.1.0"
resolved "https://registry.npmjs.org/font-finder/-/font-finder-1.1.0.tgz#2bff2b2762acba720239c8bec898a96daae90858"
integrity sha512-wpCL2uIbi6GurJbU7ZlQ3nGd61Ho+dSU6U83/xJT5UPFfN35EeCW/rOtS+5k+IuEZu2SYmHzDIPL9eA5tSYRAw==
dependencies:
get-system-fonts "^2.0.0"
promise-stream-reader "^1.0.1"
font-ligatures@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/font-ligatures/-/font-ligatures-1.4.0.tgz#6a7b370d96be1358dddfad67830e82fbfd59e6dc"
integrity sha512-n7DFnnEpJ0NrVoLqZIL4tMGVs+CnFwQc92m80LWyrbgAFO4x234+t2/H9o4eOYA1eh6ta9dZAEEsJAwsBdNezA==
dependencies:
font-finder "^1.0.3"
lru-cache "^4.1.3"
lru-cache "^6.0.0"
opentype.js "^0.8.0"
get-system-fonts@^2.0.0:
@@ -120,9 +128,9 @@ lodash.get@^4.4.2:
resolved "https://registry.yarnpkg.com/lodash.get/-/lodash.get-4.4.2.tgz#2d177f652fa31e939b4438d5341499dfa3825e99"
lodash@^4.17.15:
version "4.17.19"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.19.tgz#e48ddedbe30b3321783c5b4301fbd353bc1e4a4b"
integrity sha512-JNvd8XER9GQX0v2qJgsaN/mzFCNA5BRe/j8JN9d+tWyGLSodKQHKFicdwNYzWwI3wjRnaKPsGj1XkBjx/F96DQ==
version "4.17.21"
resolved "https://registry.yarnpkg.com/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c"
integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==
lolex@^2.7.5:
version "2.7.5"
@@ -136,12 +144,12 @@ lolex@^5.0.1:
dependencies:
"@sinonjs/commons" "^1.7.0"
lru-cache@^4.1.3:
version "4.1.3"
resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-4.1.3.tgz#a1175cf3496dfc8436c156c334b4955992bce69c"
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94"
integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==
dependencies:
pseudomap "^1.0.2"
yallist "^2.1.2"
yallist "^4.0.0"
minimist@^1.2.5:
version "1.2.5"
@@ -190,10 +198,6 @@ promise-stream-reader@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/promise-stream-reader/-/promise-stream-reader-1.0.1.tgz#4e793a79c9d49a73ccd947c6da9c127f12923649"
pseudomap@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/pseudomap/-/pseudomap-1.0.2.tgz#f052a28da70e618917ef0a8ac34c1ae5a68286b3"
sinon@6.3.5:
version "6.3.5"
resolved "https://registry.yarnpkg.com/sinon/-/sinon-6.3.5.tgz#0f6d6a5b4ebaad1f6e8e019395542d1d02c144a0"
@@ -224,9 +228,10 @@ type-detect@4.0.8, type-detect@^4.0.8:
version "4.0.8"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c"
yallist@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/yallist/-/yallist-2.1.2.tgz#1c11f9218f076089a47dd512f93c6699a6a81d52"
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72"
integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==
yauzl@^2.10.0:
version "2.10.0"
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-search",
"version": "0.7.0",
"version": "0.8.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
@@ -10,7 +10,7 @@
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"build": "../../node_modules/.bin/tsc -p .",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
+12 -4
View File
@@ -158,8 +158,15 @@ export class SearchAddon implements ITerminalAddon {
};
if (incremental) {
// Try to expand selection to right first.
result = this._findInLine(term, searchPosition, searchOptions, false);
if (!(result && result.row === startRow && result.col === startCol)) {
const isOldResultHighlighted = result && result.row === startRow && result.col === startCol;
if (!isOldResultHighlighted) {
// If selection was not able to be expanded to the right, then try reverse search
if (currentSelection) {
searchPosition.startRow = currentSelection.endRow;
searchPosition.startCol = currentSelection.endColumn;
}
result = this._findInLine(term, searchPosition, searchOptions, true);
}
} else {
@@ -233,8 +240,8 @@ export class SearchAddon implements ITerminalAddon {
* @param term the substring that starts at searchIndex
*/
private _isWholeWord(searchIndex: number, line: string, term: string): boolean {
return (((searchIndex === 0) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex - 1]) !== -1)) &&
(((searchIndex + term.length) === line.length) || (NON_WORD_CHARACTERS.indexOf(line[searchIndex + term.length]) !== -1)));
return ((searchIndex === 0) || (NON_WORD_CHARACTERS.includes(line[searchIndex - 1]))) &&
(((searchIndex + term.length) === line.length) || (NON_WORD_CHARACTERS.includes(line[searchIndex + term.length])));
}
/**
@@ -245,6 +252,7 @@ export class SearchAddon implements ITerminalAddon {
* @param term The search term.
* @param position The position to start the search.
* @param searchOptions Search options.
* @param isReverseSearch Whether the search should start from the right side of the terminal and search to the left.
* @return The search result if it was found.
*/
protected _findInLine(term: string, searchPosition: ISearchPosition, searchOptions: ISearchOptions = {}, isReverseSearch: boolean = false): ISearchResult | undefined {
@@ -254,7 +262,7 @@ export class SearchAddon implements ITerminalAddon {
// Ignore wrapped lines, only consider on unwrapped line (first row of command string).
const firstLine = terminal.buffer.active.getLine(row);
if (firstLine && firstLine.isWrapped) {
if (firstLine?.isWrapped) {
if (isReverseSearch) {
searchPosition.startCol += terminal.cols;
return;
+1 -2
View File
@@ -12,8 +12,7 @@
"removeComments": true,
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
"../../../node_modules/@types/mocha"
]
},
"include": [
@@ -7,9 +7,9 @@ import { assert } from 'chai';
import { readFile } from 'fs';
import { resolve } from 'path';
import { openTerminal, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
import { Browser, Page } from 'playwright';
const APP = 'http://127.0.0.1:3000/test';
const APP = 'http://127.0.0.1:3001/test';
let browser: Browser;
let page: Page;
@@ -19,8 +19,8 @@ const height = 600;
describe('Search Tests', function(): void {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
browser = await browserType.launch({
headless: process.argv.includes('--headless')
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
@@ -111,8 +111,15 @@ describe('Search Tests', function(): void {
let fixture: string;
before(async () => {
const rawFixture = await new Promise<Buffer>(r => readFile(resolve(__dirname, '../fixtures/issue-2444'), (err, data) => r(data)));
fixture = rawFixture.toString()
.replace(/\n/g, '\\n\\r')
if (process.platform === 'win32') {
fixture = rawFixture.toString()
.replace(/\n/g, '\\n')
.replace(/\r/g, '\\r');
} else {
fixture = rawFixture.toString()
.replace(/\n/g, '\\n\\r');
}
fixture = fixture
.replace(/'/g, '\\\'');
});
it('should find all occurrences using findNext', async () => {
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"es6",
],
"rootDir": ".",
"outDir": "../out-test",
"sourceMap": true,
"removeComments": true,
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../node_modules/@types/node",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
]
}
+8
View File
@@ -0,0 +1,8 @@
{
"files": [],
"include": [],
"references": [
{ "path": "./src" },
{ "path": "./test" }
]
}
@@ -16,12 +16,12 @@ class TestTerminal extends Terminal {
}
}
perfContext('Terminal: sh -c "dd if=/dev/random count=40 bs=1k | hexdump | lolcat -f"', () => {
perfContext('Terminal: sh -c "dd if=/dev/urandom count=40 bs=1k | hexdump | lolcat -f"', () => {
let content = '';
let contentUtf8: Uint8Array;
before(async () => {
const p = spawn('sh', ['-c', 'dd if=/dev/random count=40 bs=1k | hexdump | lolcat -f'], {
const p = spawn('sh', ['-c', 'dd if=/dev/urandom count=40 bs=1k | hexdump | lolcat -f'], {
name: 'xterm-256color',
cols: 80,
rows: 25,
+4 -4
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-serialize",
"version": "0.3.0",
"version": "0.5.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
@@ -9,13 +9,13 @@
"types": "typings/xterm-addon-serialize.d.ts",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"build": "../../node_modules/.bin/tsc -p .",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package",
"benchmark": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json",
"benchmark-baseline": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --baseline out-benchmark/addons/xterm-addon-serialize/benchmark/*benchmark.js",
"benchmark-eval": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --eval out-benchmark/addons/xterm-addon-serialize/benchmark/*benchmark.js"
"benchmark-baseline": "NODE_PATH=../../out:./out:./out-benchmark/ ../../node_modules/.bin/xterm-benchmark -r 5 -c benchmark/benchmark.json --baseline out-benchmark/benchmark/*benchmark.js",
"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"
@@ -21,7 +21,7 @@ abstract class BaseSerializeHandler {
const cell2 = this._buffer.getNullCell();
let oldCell = cell1;
this._beforeSerialize(endRow - startRow);
this._beforeSerialize(endRow - startRow, startRow, endRow);
for (let row = startRow; row < endRow; row++) {
const line = this._buffer.getLine(row);
@@ -36,7 +36,7 @@ abstract class BaseSerializeHandler {
oldCell = c;
}
}
this._rowEnd(row);
this._rowEnd(row, row === endRow - 1);
}
this._afterSerialize();
@@ -45,8 +45,8 @@ abstract class BaseSerializeHandler {
}
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 { }
protected _serializeString(): string { return ''; }
}
@@ -71,27 +71,152 @@ function equalFlags(cell1: IBufferCell, cell2: IBufferCell): boolean {
&& cell1.isDim() === cell2.isDim();
}
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 = '';
this._nullCellCount = 0;
}
protected _nextCell(cell: IBufferCell, oldCell: IBufferCell, row: number, col: number): void {
private _diffStyle(cell: IBufferCell, oldCell: IBufferCell): number[] {
const sgrSeq: number[] = [];
const fgChanged = !equalFg(cell, oldCell);
const bgChanged = !equalBg(cell, oldCell);
@@ -99,7 +224,9 @@ class StringSerializeHandler extends BaseSerializeHandler {
if (fgChanged || bgChanged || flagsChanged) {
if (cell.isAttributeDefault()) {
this._currentRow += '\x1b[0m';
if (!oldCell.isAttributeDefault()) {
sgrSeq.push(0);
}
} else {
if (fgChanged) {
const color = cell.getFgColor();
@@ -131,30 +258,129 @@ class StringSerializeHandler extends BaseSerializeHandler {
}
}
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() === '') {
this._nullCellCount++;
} else if (this._nullCellCount > 0) {
this._currentRow += `\x1b[${this._nullCellCount}C`;
this._nullCellCount = 0;
}
/**
* handles actual content
*/
if (isEmptyCell) {
this._nullCellCount += cell.getWidth();
} 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();
this._currentRow += cell.getChars();
// update cursor
this._lastContentCursorRow = this._lastCursorRow = row;
this._lastContentCursorCol = this._lastCursorCol = col + cell.getWidth();
}
}
protected _serializeString(): string {
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;
}
}
@@ -167,20 +393,33 @@ export class SerializeAddon implements ITerminalAddon {
this._terminal = terminal;
}
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
if (!this._terminal) {
throw new Error('Cannot use addon until it has been loaded');
}
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;
}
public dispose(): void { }
@@ -18,8 +18,7 @@
},
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
"../../../node_modules/@types/mocha"
]
},
"include": [
@@ -5,20 +5,36 @@
import { assert } from 'chai';
import { openTerminal, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
import { Browser, Page } from 'playwright';
const APP = 'http://127.0.0.1:3000/test';
const APP = 'http://127.0.0.1:3001/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
const writeRawSync = (page: any, str: string): Promise<void> => writeSync(page, '\' +' + JSON.stringify(str) + '+ \'');
const testNormalScreenEqual = async (page: any, str: string): Promise<void> => {
await writeRawSync(page, str);
const originalBuffer = await page.evaluate(`inspectBuffer(term.buffer.normal);`);
const result = await page.evaluate(`serializeAddon.serialize();`) as string;
await page.evaluate(`term.reset();`);
await writeRawSync(page, result);
const newBuffer = await page.evaluate(`inspectBuffer(term.buffer.normal);`);
// chai decides -0 and 0 are different number...
// and firefox have a bug that output -0 for unknown reason
assert.equal(JSON.stringify(originalBuffer), JSON.stringify(newBuffer));
};
describe('SerializeAddon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
browser = await browserType.launch({
headless: process.argv.includes('--headless')
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
@@ -27,19 +43,74 @@ describe('SerializeAddon', () => {
await page.evaluate(`
window.serializeAddon = new SerializeAddon();
window.term.loadAddon(window.serializeAddon);
window.inspectBuffer = (buffer) => {
const lines = [];
for (let i = 0; i < buffer.length; i++) {
// Do this intentionally to get content of underlining source
const bufferLine = buffer.getLine(i)._line;
lines.push(JSON.stringify(bufferLine));
}
return {
x: buffer.cursorX,
y: buffer.cursorY,
data: lines
};
}
`);
});
after(async () => await browser.close());
beforeEach(async () => await page.evaluate(`window.term.reset()`));
it('produce different output when we call test util with different text', async function(): Promise<any> {
await writeRawSync(page, '12345');
const buffer1 = await page.evaluate(`inspectBuffer(term.buffer.normal);`);
await page.evaluate(`term.reset();`);
await writeRawSync(page, '67890');
const buffer2 = await page.evaluate(`inspectBuffer(term.buffer.normal);`);
assert.throw(() => {
assert.equal(JSON.stringify(buffer1), JSON.stringify(buffer2));
});
});
it('produce different output when we call test util with different line wrap', async function(): Promise<any> {
await writeRawSync(page, '1234567890\r\n12345');
const buffer3 = await page.evaluate(`inspectBuffer(term.buffer.normal);`);
await page.evaluate(`term.reset();`);
await writeRawSync(page, '1234567890n12345');
const buffer4 = await page.evaluate(`inspectBuffer(term.buffer.normal);`);
assert.throw(() => {
assert.equal(JSON.stringify(buffer3), JSON.stringify(buffer4));
});
});
it('empty content', async function(): Promise<any> {
const rows = 10;
const cols = 10;
assert.equal(await page.evaluate(`serializeAddon.serialize();`), '');
});
it('trim last empty lines', async function(): Promise<any> {
it('unwrap wrapped line', async function(): Promise<any> {
const lines = ['123456789123456789'];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('does not unwrap non-wrapped line', async function(): Promise<any> {
const lines = [
'123456789',
'123456789'
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('preserve last empty lines', async function(): Promise<any> {
const cols = 10;
const lines = [
'',
@@ -55,7 +126,7 @@ describe('SerializeAddon', () => {
''
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.slice(0, 8).join('\r\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('digits content', async function(): Promise<any> {
@@ -67,21 +138,22 @@ describe('SerializeAddon', () => {
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize half rows of content', async function(): Promise<any> {
const rows = 10;
const halfRows = rows >> 1;
it('serialize with half of scrollback', async function(): Promise<any> {
const rows = 20;
const scrollback = rows - 10;
const halfScrollback = scrollback / 2;
const cols = 10;
const lines = newArray<string>((index: number) => digitsString(cols, index), rows);
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize(${halfRows});`), lines.slice(halfRows, 2 * halfRows).join('\r\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize(${halfScrollback});`), lines.slice(halfScrollback, rows).join('\r\n'));
});
it('serialize 0 rows of content', async function(): Promise<any> {
const rows = 10;
it('serialize 0 rows of scrollback', async function(): Promise<any> {
const rows = 20;
const cols = 10;
const lines = newArray<string>((index: number) => digitsString(cols, index), rows);
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize(0);`), '');
assert.equal(await page.evaluate(`serializeAddon.serialize(0);`), lines.slice(rows - 10, rows).join('\r\n'));
});
it('serialize all rows of content with color16', async function(): Promise<any> {
@@ -270,6 +342,145 @@ describe('SerializeAddon', () => {
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), expected.join('\r\n'));
});
it('serialize CJK correctly', async () => {
const lines = [
'中文中文',
'12中文',
'中文12',
// This line is going to be wrapped at last character
// because it has line length of 11 (1+2*5).
// We concat it back without the null cell currently.
// But this may be incorrect.
// see also #3097
'1中文中文中'
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), lines.join('\r\n'));
});
it('serialize CJK Mixed with tab correctly', async () => {
const lines = [
'中文\t12' // CJK mixed with tab
];
const expected = [
'中文\x1b[4C12'
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`serializeAddon.serialize();`), expected.join('\r\n'));
});
it('serialize with alt screen correctly', async () => {
const SMCUP = '\u001b[?1049h';
const CUP = '\u001b[H';
const lines = [
`1${SMCUP}${CUP}2`
];
const expected = [
`1${SMCUP}${CUP}2`
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`window.term.buffer.active.type`), 'alternate');
assert.equal(JSON.stringify(await page.evaluate(`serializeAddon.serialize();`)), JSON.stringify(expected.join('\r\n')));
});
it('serialize without alt screen correctly', async () => {
const SMCUP = '\u001b[?1049h';
const RMCUP = '\u001b[?1049l';
const lines = [
`1${SMCUP}2${RMCUP}`
];
const expected = [
`1`
];
await writeSync(page, lines.join('\\r\\n'));
assert.equal(await page.evaluate(`window.term.buffer.active.type`), 'normal');
assert.equal(JSON.stringify(await page.evaluate(`serializeAddon.serialize();`)), JSON.stringify(expected.join('\r\n')));
});
it('serialize with background', async () => {
const CLEAR_RIGHT = (l: number): string => `\u001b[${l}X`;
const lines = [
`1\u001b[44m${CLEAR_RIGHT(5)}`,
`2${CLEAR_RIGHT(9)}`
];
await testNormalScreenEqual(page, lines.join('\r\n'));
});
it('cause the BCE on scroll', async () => {
const CLEAR_RIGHT = (l: number): string => `\u001b[${l}X`;
const padLines = newArray<string>(
(index: number) => digitsString(10, index),
10
);
const lines = [
...padLines,
`\u001b[44m${CLEAR_RIGHT(5)}1111111111111111`
];
await testNormalScreenEqual(page, lines.join('\r\n'));
});
it('handle invalid wrap before scroll', async () => {
const CLEAR_RIGHT = (l: number): string => `\u001b[${l}X`;
const MOVE_UP = (l: number): string => `\u001b[${l}A`;
const MOVE_DOWN = (l: number): string => `\u001b[${l}B`;
const MOVE_LEFT = (l: number): string => `\u001b[${l}D`;
// A line wrap happened after current line.
// But there is no content.
// so wrap shouldn't even be able to happen.
const segments = [
`123456789012345`,
MOVE_UP(1),
CLEAR_RIGHT(5),
MOVE_DOWN(1),
MOVE_LEFT(5),
CLEAR_RIGHT(5),
MOVE_UP(1),
'1'
];
await testNormalScreenEqual(page, segments.join(''));
});
it('handle invalid wrap after scroll', async () => {
const CLEAR_RIGHT = (l: number): string => `\u001b[${l}X`;
const MOVE_UP = (l: number): string => `\u001b[${l}A`;
const MOVE_DOWN = (l: number): string => `\u001b[${l}B`;
const MOVE_LEFT = (l: number): string => `\u001b[${l}D`;
const padLines = newArray<string>(
(index: number) => digitsString(10, index),
10
);
// A line wrap happened after current line.
// But there is no content.
// so wrap shouldn't even be able to happen.
const lines = [
padLines.join('\r\n'),
'\r\n',
`123456789012345`,
MOVE_UP(1),
CLEAR_RIGHT(5),
MOVE_DOWN(1),
MOVE_LEFT(5),
CLEAR_RIGHT(5),
MOVE_UP(1),
'1'
];
await testNormalScreenEqual(page, lines.join(''));
});
});
function newArray<T>(initial: T | ((index: number) => T), count: number): T[] {
@@ -0,0 +1,34 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"es2015"
],
"rootDir": ".",
"outDir": "../out-test",
"sourceMap": true,
"removeComments": true,
"baseUrl": ".",
"paths": {
"common/*": [
"../../../src/common/*"
]
},
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../node_modules/@types/node",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
],
"references": [
{
"path": "../../../src/common"
}
]
}
@@ -0,0 +1,9 @@
{
"files": [],
"include": [],
"references": [
{ "path": "./src" },
{ "path": "./test" },
{ "path": "./benchmark" }
]
}
@@ -25,10 +25,10 @@ declare module 'xterm-addon-serialize' {
* to restore the state. The cursor will also be positioned to the correct cell.
* When restoring a terminal it is best to do before `Terminal.open` is called
* to avoid wasting CPU cycles rendering incomplete frames.
* @param rows The number of rows to serialize, starting from the bottom of the
* terminal. This defaults to the number of rows in the viewport.
* @param scrollback The number of rows in scrollback buffer to serialize, starting from the bottom of the
* scrollback buffer. This defaults to the all available rows in the scrollback buffer.
*/
public serialize(rows?: number): string;
public serialize(scrollback?: number): string;
/**
* Disposes the addon.
+1 -1
View File
@@ -10,7 +10,7 @@
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"build": "../../node_modules/.bin/tsc -p .",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
@@ -18,8 +18,7 @@
]
},
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
"../../../node_modules/@types/mocha"
]
},
"include": [
@@ -5,9 +5,9 @@
import { assert } from 'chai';
import { openTerminal, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
import { Browser, Page } from 'playwright';
const APP = 'http://127.0.0.1:3000/test';
const APP = 'http://127.0.0.1:3001/test';
let browser: Browser;
let page: Page;
@@ -17,8 +17,8 @@ const height = 600;
describe('Unicode11Addon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
browser = await browserType.launch({
headless: process.argv.includes('--headless')
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
@@ -0,0 +1,35 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es2015",
"lib": [
"dom",
"es2015"
],
"rootDir": ".",
"outDir": "../out-test",
"sourceMap": true,
"removeComments": true,
"strict": true,
"baseUrl": ".",
"paths": {
"common/*": [
"../../../src/common/*"
]
},
"types": [
"../../../node_modules/@types/mocha",
"../../../node_modules/@types/node",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
],
"references": [
{
"path": "../../../src/common"
}
]
}
@@ -0,0 +1,8 @@
{
"files": [],
"include": [],
"references": [
{ "path": "./src" },
{ "path": "./test" }
]
}
+1 -1
View File
@@ -10,7 +10,7 @@
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"build": "../../node_modules/.bin/tsc -p .",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
@@ -3,25 +3,45 @@
* @license MIT
*/
import { ILinkProvider, IBufferCellPosition, ILink, Terminal } from 'xterm';
import { ILinkProvider, ILink, Terminal, IViewportRange } from 'xterm';
interface ILinkProviderOptions {
hover?(event: MouseEvent, text: string, location: IViewportRange): void;
leave?(event: MouseEvent, text: string): void;
}
export class WebLinkProvider implements ILinkProvider {
constructor(
private readonly _terminal: Terminal,
private readonly _regex: RegExp,
private readonly _handler: (event: MouseEvent, uri: string) => void
private readonly _handler: (event: MouseEvent, uri: string) => void,
private readonly _options: ILinkProviderOptions = {}
) {
}
public provideLinks(y: number, callback: (links: ILink[] | undefined) => void): void {
callback(LinkComputer.computeLink(y, this._regex, this._terminal, this._handler));
const links = LinkComputer.computeLink(y, this._regex, this._terminal, this._handler);
callback(this._addCallbacks(links));
}
private _addCallbacks(links: ILink[]): ILink[] {
return links.map(link => {
link.leave = this._options.leave;
link.hover = (event: MouseEvent, uri: string): void => {
if (this._options.hover) {
const { range } = link;
this._options.hover(event, uri, range);
}
};
return link;
});
}
}
export class LinkComputer {
public static computeLink(y: number, regex: RegExp, terminal: Terminal, handler: (event: MouseEvent, uri: string) => void): ILink[] {
public static computeLink(y: number, regex: RegExp, terminal: Terminal, activate: (event: MouseEvent, uri: string) => void): ILink[] {
const rex = new RegExp(regex.source, (regex.flags || '') + 'g');
const [line, startLineIndex] = LinkComputer._translateBufferLineToStringWithWrap(y - 1, false, terminal);
@@ -69,7 +89,7 @@ export class LinkComputer {
}
};
result.push({ range, text, activate: handler });
result.push({ range, text, activate });
}
return result;
@@ -3,7 +3,7 @@
* @license MIT
*/
import { Terminal, ILinkMatcherOptions, ITerminalAddon, IDisposable } from 'xterm';
import { Terminal, ILinkMatcherOptions, ITerminalAddon, IDisposable, IViewportRange } from 'xterm';
import { WebLinkProvider } from './WebLinkProvider';
const protocolClause = '(https?:\\/\\/)';
@@ -36,6 +36,11 @@ function handleLink(event: MouseEvent, uri: string): void {
}
}
interface ILinkProviderOptions {
hover?(event: MouseEvent, text: string, location: IViewportRange): void;
leave?(event: MouseEvent, text: string): void;
}
export class WebLinksAddon implements ITerminalAddon {
private _linkMatcherId: number | undefined;
private _terminal: Terminal | undefined;
@@ -43,20 +48,22 @@ export class WebLinksAddon implements ITerminalAddon {
constructor(
private _handler: (event: MouseEvent, uri: string) => void = handleLink,
private _options: ILinkMatcherOptions = {},
private _options: ILinkMatcherOptions | ILinkProviderOptions = {},
private _useLinkProvider: boolean = false
) {
this._options.matchIndex = 1;
}
public activate(terminal: Terminal): void {
this._terminal = terminal;
if (this._useLinkProvider && 'registerLinkProvider' in this._terminal) {
this._linkProvider = this._terminal.registerLinkProvider(new WebLinkProvider(this._terminal, strictUrlRegex, this._handler));
const options = this._options as ILinkProviderOptions;
this._linkProvider = this._terminal.registerLinkProvider(new WebLinkProvider(this._terminal, strictUrlRegex, this._handler, options));
} else {
// TODO: This should be removed eventually
this._linkMatcherId = (this._terminal as Terminal).registerLinkMatcher(strictUrlRegex, this._handler, this._options);
const options = this._options as ILinkMatcherOptions;
options.matchIndex = 1;
this._linkMatcherId = (this._terminal as Terminal).registerLinkMatcher(strictUrlRegex, this._handler, options);
}
}
@@ -12,8 +12,7 @@
"removeComments": true,
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
"../../../node_modules/@types/mocha"
]
},
"include": [
@@ -5,9 +5,9 @@
import { assert } from 'chai';
import { openTerminal, pollFor, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
import { Browser, Page } from 'playwright';
const APP = 'http://127.0.0.1:3000/test';
const APP = 'http://127.0.0.1:3001/test';
let browser: Browser;
let page: Page;
@@ -17,8 +17,8 @@ const height = 600;
describe('WebLinksAddon', () => {
before(async function(): Promise<any> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
browser = await browserType.launch({
headless: process.argv.includes('--headless')
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
@@ -0,0 +1,23 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"es2015"
],
"rootDir": ".",
"outDir": "../out-test",
"sourceMap": true,
"removeComments": true,
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../node_modules/@types/node",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
]
}
@@ -0,0 +1,8 @@
{
"files": [],
"include": [],
"references": [
{ "path": "./src" },
{ "path": "./test" }
]
}
@@ -4,7 +4,7 @@
*/
import { Terminal, ILinkMatcherOptions, ITerminalAddon } from 'xterm';
import { Terminal, ILinkMatcherOptions, ITerminalAddon, IViewportRange } from 'xterm';
declare module 'xterm-addon-web-links' {
/**
@@ -20,7 +20,7 @@ declare module 'xterm-addon-web-links' {
* link provider (new) may cause issues. Link provider will eventually be
* the default and only option.
*/
constructor(handler?: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions, useLinkProvider?: boolean);
constructor(handler?: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions | ILinkProviderOptions, useLinkProvider?: boolean);
/**
* Activates the addon
@@ -33,4 +33,21 @@ declare module 'xterm-addon-web-links' {
*/
public dispose(): void;
}
/**
* An object containing options for a link provider.
*/
export interface ILinkProviderOptions {
/**
* A callback that fires when the mouse hovers over a link for a period of
* time (defined by {@link ITerminalOptions.linkTooltipHoverDuration}).
*/
hover?(event: MouseEvent, text: string, location: IViewportRange): void;
/**
* A callback that fires when the mouse leaves a link. Note that this can
* happen even when tooltipCallback hasn't fired for the link yet.
*/
leave?(event: MouseEvent, text: string): void;
}
}
+2
View File
@@ -3,3 +3,5 @@
tsconfig.json
.yarnrc
webpack.config.js
out-test/
test/
+16 -3
View File
@@ -1,8 +1,6 @@
## xterm-addon-webgl
An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables a WebGL-based renderer. This addon requires xterm.js v4+.
⚠️ This is an experimental addon that is [missing some features and may be unstable](https://github.com/xtermjs/xterm.js/issues?q=is%3Aopen+is%3Aissue+label%3Aarea%2Faddon%2Fwebgl) ⚠️
An addon for [xterm.js](https://github.com/xtermjs/xterm.js) that enables a WebGL2-based renderer. This addon requires xterm.js v4+.
### Install
@@ -21,3 +19,18 @@ terminal.loadAddon(new WebglAddon());
```
See the full [API](https://github.com/xtermjs/xterm.js/blob/master/addons/xterm-addon-webgl/typings/xterm-addon-webgl.d.ts) for more advanced usage.
### Handling Context Loss
The browser may drop WebGL contexts for various reasons like OOM or after the system has been suspended. There is an API exposed that fires the `webglcontextlost` event fired on the canvas so embedders can handle it however they wish. An easy, but suboptimal way, to handle this is by disposing of WebglAddon when the event fires:
```ts
const terminal = new Terminal();
const addon = new WebglAddon();
addon.onContextLoss(e => {
addon.dispose();
});
terminal.loadAddon(addon);
```
Read more about handling WebGL context losses on the [Khronos wiki](https://www.khronos.org/webgl/wiki/HandlingContextLost).
+2 -2
View File
@@ -1,6 +1,6 @@
{
"name": "xterm-addon-webgl",
"version": "0.8.0",
"version": "0.11.0",
"author": {
"name": "The xterm.js authors",
"url": "https://xtermjs.org/"
@@ -10,7 +10,7 @@
"repository": "https://github.com/xtermjs/xterm.js",
"license": "MIT",
"scripts": {
"build": "../../node_modules/.bin/tsc -p src",
"build": "../../node_modules/.bin/tsc -p .",
"prepackage": "npm run build",
"package": "../../node_modules/.bin/webpack",
"prepublishOnly": "npm run package"
@@ -196,7 +196,7 @@ export class RectangleRenderer {
} else {
// Draw first row
const startCol = model.viewportStartRow === model.viewportCappedStartRow ? model.startCol : 0;
const startRowEndCol = model.viewportCappedStartRow === model.viewportCappedEndRow ? model.endCol : terminal.cols;
const startRowEndCol = model.viewportCappedStartRow === model.viewportEndRow ? model.endCol : terminal.cols;
this._addRectangleFloat(
this._vertices.selection,
0,
@@ -43,7 +43,6 @@ export class RenderModel implements IRenderModel {
public clear(): void {
fill(this.cells, 0, 0);
fill(this.lineLengths, 0, 0);
this.clearSelection();
}
public clearSelection(): void {
+12 -3
View File
@@ -3,14 +3,17 @@
* @license MIT
*/
import { Terminal, ITerminalAddon } from 'xterm';
import { Terminal, ITerminalAddon, IEvent } from 'xterm';
import { WebglRenderer } from './WebglRenderer';
import { IRenderService } from 'browser/services/Services';
import { ICharacterJoinerService, IRenderService } from 'browser/services/Services';
import { IColorSet } from 'browser/Types';
import { EventEmitter } from 'common/EventEmitter';
export class WebglAddon implements ITerminalAddon {
private _terminal?: Terminal;
private _renderer?: WebglRenderer;
private _onContextLoss = new EventEmitter<void>();
public get onContextLoss(): IEvent<void> { return this._onContextLoss.event; }
constructor(
private _preserveDrawingBuffer?: boolean
@@ -22,8 +25,10 @@ export class WebglAddon implements ITerminalAddon {
}
this._terminal = terminal;
const renderService: IRenderService = (<any>terminal)._core._renderService;
const characterJoinerService: ICharacterJoinerService = (<any>terminal)._core._characterJoinerService;
const colors: IColorSet = (<any>terminal)._core._colorManager.colors;
this._renderer = new WebglRenderer(terminal, colors, this._preserveDrawingBuffer);
this._renderer = new WebglRenderer(terminal, colors, characterJoinerService, this._preserveDrawingBuffer);
this._renderer.onContextLoss(() => this._onContextLoss.fire());
renderService.setRenderer(this._renderer);
}
@@ -40,4 +45,8 @@ export class WebglAddon implements ITerminalAddon {
public get textureAtlas(): HTMLCanvasElement | undefined {
return this._renderer?.textureAtlas;
}
public clearTextureAtlas(): void {
this._renderer?.clearCharAtlas();
}
}
+158 -28
View File
@@ -12,13 +12,17 @@ import { RectangleRenderer } from './RectangleRenderer';
import { IWebGL2RenderingContext } from './Types';
import { RenderModel, COMBINED_CHAR_BIT_MASK, RENDER_MODEL_BG_OFFSET, RENDER_MODEL_FG_OFFSET, RENDER_MODEL_INDICIES_PER_CELL } from './RenderModel';
import { Disposable } from 'common/Lifecycle';
import { NULL_CELL_CODE } from 'common/buffer/Constants';
import { Content, NULL_CELL_CHAR, NULL_CELL_CODE } from 'common/buffer/Constants';
import { Terminal, IEvent } from 'xterm';
import { IRenderLayer } from './renderLayer/Types';
import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types';
import { ITerminal, IColorSet } from 'browser/Types';
import { EventEmitter } from 'common/EventEmitter';
import { CellData } from 'common/buffer/CellData';
import { addDisposableDomListener } from 'browser/Lifecycle';
import { ICharacterJoinerService } from 'browser/services/Services';
import { CharData, ICellData } from 'common/Types';
import { AttributeData } from 'common/buffer/AttributeData';
export class WebglRenderer extends Disposable implements IRenderer {
private _renderLayers: IRenderLayer[];
@@ -41,9 +45,13 @@ export class WebglRenderer extends Disposable implements IRenderer {
private _onRequestRedraw = new EventEmitter<IRequestRedrawEvent>();
public get onRequestRedraw(): IEvent<IRequestRedrawEvent> { return this._onRequestRedraw.event; }
private _onContextLoss = new EventEmitter<void>();
public get onContextLoss(): IEvent<void> { return this._onContextLoss.event; }
constructor(
private _terminal: Terminal,
private _colors: IColorSet,
private readonly _characterJoinerService: ICharacterJoinerService,
preserveDrawingBuffer?: boolean
) {
super();
@@ -82,6 +90,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
if (!this._gl) {
throw new Error('WebGL2 not supported ' + this._gl);
}
this.register(addDisposableDomListener(this._canvas, 'webglcontextlost', (e) => { this._onContextLoss.fire(e); }));
this._core.screenElement!.appendChild(this._canvas);
this._rectangleRenderer = new RectangleRenderer(this._terminal, this._colors, this._gl, this.dimensions);
@@ -94,7 +105,9 @@ export class WebglRenderer extends Disposable implements IRenderer {
}
public dispose(): void {
this._renderLayers.forEach(l => l.dispose());
for (const l of this._renderLayers) {
l.dispose();
}
this._core.screenElement!.removeChild(this._canvas);
super.dispose();
}
@@ -106,19 +119,16 @@ export class WebglRenderer extends Disposable implements IRenderer {
public setColors(colors: IColorSet): void {
this._colors = colors;
// Clear layers and force a full render
this._renderLayers.forEach(l => {
for (const l of this._renderLayers) {
l.setColors(this._terminal, this._colors);
l.reset(this._terminal);
});
}
this._rectangleRenderer.setColors();
this._glyphRenderer.setColors();
this._refreshCharAtlas();
this._rectangleRenderer.updateSelection(this._model.selection);
this._glyphRenderer.updateSelection(this._model);
// Force a full refresh
this._model.clear();
}
@@ -137,10 +147,11 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._updateDimensions();
this._model.resize(this._terminal.cols, this._terminal.rows);
this._rectangleRenderer.onResize();
// Resize all render layers
this._renderLayers.forEach(l => l.resize(this._terminal, this.dimensions));
for (const l of this._renderLayers) {
l.resize(this._terminal, this.dimensions);
}
// Resize the canvas
this._canvas.width = this.dimensions.scaledCanvasWidth;
@@ -151,6 +162,13 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Resize the screen
this._core.screenElement!.style.width = `${this.dimensions.canvasWidth}px`;
this._core.screenElement!.style.height = `${this.dimensions.canvasHeight}px`;
this._rectangleRenderer.onResize();
if (this._model.selection.hasSelection) {
// Update selection as dimensions have changed
this._rectangleRenderer.updateSelection(this._model.selection);
}
this._glyphRenderer.setDimensions(this.dimensions);
this._glyphRenderer.onResize();
@@ -165,30 +183,37 @@ export class WebglRenderer extends Disposable implements IRenderer {
}
public onBlur(): void {
this._renderLayers.forEach(l => l.onBlur(this._terminal));
for (const l of this._renderLayers) {
l.onBlur(this._terminal);
}
}
public onFocus(): void {
this._renderLayers.forEach(l => l.onFocus(this._terminal));
for (const l of this._renderLayers) {
l.onFocus(this._terminal);
}
}
public onSelectionChanged(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void {
this._renderLayers.forEach(l => l.onSelectionChanged(this._terminal, start, end, columnSelectMode));
for (const l of this._renderLayers) {
l.onSelectionChanged(this._terminal, start, end, columnSelectMode);
}
this._updateSelectionModel(start, end, columnSelectMode);
this._rectangleRenderer.updateSelection(this._model.selection);
this._glyphRenderer.updateSelection(this._model);
this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1 });
}
public onCursorMove(): void {
this._renderLayers.forEach(l => l.onCursorMove(this._terminal));
for (const l of this._renderLayers) {
l.onCursorMove(this._terminal);
}
}
public onOptionsChanged(): void {
this._renderLayers.forEach(l => l.onOptionsChanged(this._terminal));
for (const l of this._renderLayers) {
l.onOptionsChanged(this._terminal);
}
this._updateDimensions();
this._refreshCharAtlas();
}
@@ -214,8 +239,17 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._glyphRenderer.setAtlas(this._charAtlas);
}
public clearCharAtlas(): void {
this._charAtlas?.clearTexture();
this._model.clear();
this._updateModel(0, this._terminal.rows - 1);
this._onRequestRedraw.fire({ start: 0, end: this._terminal.rows - 1 });
}
public clear(): void {
this._renderLayers.forEach(l => l.reset(this._terminal));
for (const l of this._renderLayers) {
l.reset(this._terminal);
}
}
public registerCharacterJoiner(handler: (text: string) => [number, number][]): number {
@@ -238,11 +272,14 @@ export class WebglRenderer extends Disposable implements IRenderer {
}
// Update render layers
this._renderLayers.forEach(l => l.onGridChanged(this._terminal, start, end));
for (const l of this._renderLayers) {
l.onGridChanged(this._terminal, start, end);
}
// Tell renderer the frame is beginning
if (this._glyphRenderer.beginFrame()) {
this._model.clear();
this._updateSelectionModel(undefined, undefined);
}
// Update model to reflect what's drawn
@@ -255,16 +292,41 @@ export class WebglRenderer extends Disposable implements IRenderer {
private _updateModel(start: number, end: number): void {
const terminal = this._core;
let cell: ICellData = this._workCell;
for (let y = start; y <= end; y++) {
const row = y + terminal.buffer.ydisp;
const line = terminal.buffer.lines.get(row)!;
this._model.lineLengths[y] = 0;
const joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
for (let x = 0; x < terminal.cols; x++) {
line.loadCell(x, this._workCell);
line.loadCell(x, cell);
const chars = this._workCell.getChars();
let code = this._workCell.getCode();
// If true, indicates that the current character(s) to draw were joined.
let isJoined = false;
let lastCharX = x;
// Process any joined character ranges as needed. Because of how the
// ranges are produced, we know that they are valid for the characters
// and attributes of our input.
if (joinedRanges.length > 0 && x === joinedRanges[0][0]) {
isJoined = true;
const range = joinedRanges.shift()!;
// We already know the exact start and end column of the joined range,
// so we get the string and width representing it directly
cell = new JoinedCellData(
cell,
line!.translateToString(true, range[0], range[1]),
range[1] - range[0]
);
// Skip over the cells occupied by this range in the loop
lastCharX = range[1] - 1;
}
const chars = cell.getChars();
let code = cell.getCode();
const i = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
if (code !== NULL_CELL_CODE) {
@@ -273,8 +335,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Nothing has changed, no updates needed
if (this._model.cells[i] === code &&
this._model.cells[i + RENDER_MODEL_BG_OFFSET] === this._workCell.bg &&
this._model.cells[i + RENDER_MODEL_FG_OFFSET] === this._workCell.fg) {
this._model.cells[i + RENDER_MODEL_BG_OFFSET] === cell.bg &&
this._model.cells[i + RENDER_MODEL_FG_OFFSET] === cell.fg) {
continue;
}
@@ -285,21 +347,40 @@ export class WebglRenderer extends Disposable implements IRenderer {
// Cache the results in the model
this._model.cells[i] = code;
this._model.cells[i + RENDER_MODEL_BG_OFFSET] = this._workCell.bg;
this._model.cells[i + RENDER_MODEL_FG_OFFSET] = this._workCell.fg;
this._model.cells[i + RENDER_MODEL_BG_OFFSET] = cell.bg;
this._model.cells[i + RENDER_MODEL_FG_OFFSET] = cell.fg;
this._glyphRenderer.updateCell(x, y, code, this._workCell.bg, this._workCell.fg, chars);
this._glyphRenderer.updateCell(x, y, code, cell.bg, cell.fg, chars);
if (isJoined) {
// Restore work cell
cell = this._workCell;
// Null out non-first cells
for (x++; x < lastCharX; x++) {
const j = ((y * terminal.cols) + x) * RENDER_MODEL_INDICIES_PER_CELL;
this._glyphRenderer.updateCell(x, y, NULL_CELL_CODE, 0, 0, NULL_CELL_CHAR);
this._model.cells[j] = NULL_CELL_CODE;
this._model.cells[j + RENDER_MODEL_BG_OFFSET] = this._workCell.bg;
this._model.cells[j + RENDER_MODEL_FG_OFFSET] = this._workCell.fg;
}
}
}
}
this._rectangleRenderer.updateBackgrounds(this._model);
if (this._model.selection.hasSelection) {
// Model could be updated but the selection is unchanged
this._glyphRenderer.updateSelection(this._model);
}
}
private _updateSelectionModel(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean): void {
private _updateSelectionModel(start: [number, number] | undefined, end: [number, number] | undefined, columnSelectMode: boolean = false): void {
const terminal = this._terminal;
// Selection does not exist
if (!start || !end || (start[0] === end[0] && start[1] === end[1])) {
this._model.clearSelection();
this._rectangleRenderer.updateSelection(this._model.selection);
return;
}
@@ -312,6 +393,7 @@ export class WebglRenderer extends Disposable implements IRenderer {
// No need to draw the selection
if (viewportCappedStartRow >= terminal.rows || viewportCappedEndRow < 0) {
this._model.clearSelection();
this._rectangleRenderer.updateSelection(this._model.selection);
return;
}
@@ -323,6 +405,8 @@ export class WebglRenderer extends Disposable implements IRenderer {
this._model.selection.viewportCappedEndRow = viewportCappedEndRow;
this._model.selection.startCol = start[0];
this._model.selection.endCol = end[0];
this._rectangleRenderer.updateSelection(this._model.selection);
}
/**
@@ -397,3 +481,49 @@ export class WebglRenderer extends Disposable implements IRenderer {
this.dimensions.actualCellWidth = this.dimensions.scaledCellWidth / this._devicePixelRatio;
}
}
// TODO: Share impl with core
export class JoinedCellData extends AttributeData implements ICellData {
private _width: number;
// .content carries no meaning for joined CellData, simply nullify it
// thus we have to overload all other .content accessors
public content: number = 0;
public fg: number;
public bg: number;
public combinedData: string = '';
constructor(firstCell: ICellData, chars: string, width: number) {
super();
this.fg = firstCell.fg;
this.bg = firstCell.bg;
this.combinedData = chars;
this._width = width;
}
public isCombined(): number {
// always mark joined cell data as combined
return Content.IS_COMBINED_MASK;
}
public getWidth(): number {
return this._width;
}
public getChars(): string {
return this.combinedData;
}
public getCode(): number {
// code always gets the highest possible fake codepoint (read as -1)
// this is needed as code is used by caches as identifier
return 0x1FFFFF;
}
public setFromCharData(value: CharData): void {
throw new Error('not implemented');
}
public getAsCharData(): CharData {
return [this.fg, this.getChars(), this.getWidth(), this.getCode()];
}
}
@@ -80,12 +80,12 @@ export class WebglCharAtlas implements IDisposable {
// The canvas needs alpha because we use clearColor to convert the background color to alpha.
// It might also contain some characters with transparent backgrounds if allowTransparency is
// set.
this._cacheCtx = throwIfFalsy(this.cacheCanvas.getContext('2d', {alpha: true}));
this._cacheCtx = throwIfFalsy(this.cacheCanvas.getContext('2d', { alpha: true }));
this._tmpCanvas = document.createElement('canvas');
this._tmpCanvas.width = this._config.scaledCharWidth * 2 + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.width = this._config.scaledCharWidth * 4 + TMP_CANVAS_GLYPH_PADDING * 2;
this._tmpCanvas.height = this._config.scaledCharHeight + 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 }));
}
public dispose(): void {
@@ -101,7 +101,7 @@ export class WebglCharAtlas implements IDisposable {
}
}
protected _doWarmUp(): void {
private _doWarmUp(): void {
// Pre-fill with ASCII 33-126
for (let i = 33; i < 126; i++) {
const rasterizedGlyph = this._drawToCache(i, DEFAULT_COLOR, DEFAULT_COLOR);
@@ -115,17 +115,26 @@ export class WebglCharAtlas implements IDisposable {
public beginFrame(): boolean {
if (this._currentRowY > TEXTURE_CAPACITY) {
this._cacheCtx.clearRect(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
this._cacheMap = {};
this._currentRowHeight = 0;
this._currentRowX = 0;
this._currentRowY = 0;
this._doWarmUp();
this.clearTexture();
this.warmUp();
return true;
}
return false;
}
public clearTexture(): void {
if (this._currentRowX === 0 && this._currentRowY === 0) {
return;
}
this._cacheCtx.clearRect(0, 0, TEXTURE_WIDTH, TEXTURE_HEIGHT);
this._cacheMap = {};
this._cacheMapCombined = {};
this._currentRowHeight = 0;
this._currentRowX = 0;
this._currentRowY = 0;
this._didWarmUp = false;
}
public getRasterizedGlyphCombinedChar(chars: string, bg: number, fg: number): IRasterizedGlyph {
let rasterizedGlyphSet = this._cacheMapCombined[chars];
if (!rasterizedGlyphSet) {
@@ -308,6 +317,13 @@ export class WebglCharAtlas implements IDisposable {
this.hasCanvasChanged = true;
// Allow 1 cell width per character, with a minimum of 2 (CJK), plus some padding. This is used
// to draw the glyph to the canvas as well as to restrict the bounding box search to ensure
// giant ligatures (eg. =====>) don't impact overall performance.
const allowedWidth = this._config.scaledCharWidth * Math.max(chars.length, 2) + TMP_CANVAS_GLYPH_PADDING * 2;
if (this._tmpCanvas.width < allowedWidth) {
this._tmpCanvas.width = allowedWidth;
}
this._tmpCtx.save();
this._workAttributeData.fg = fg;
@@ -349,7 +365,7 @@ export class WebglCharAtlas implements IDisposable {
const fontStyle = italic ? 'italic' : '';
this._tmpCtx.font =
`${fontStyle} ${fontWeight} ${this._config.fontSize * this._config.devicePixelRatio}px ${this._config.fontFamily}`;
this._tmpCtx.textBaseline = 'middle';
this._tmpCtx.textBaseline = 'ideographic';
this._tmpCtx.fillStyle = this._getForegroundCss(bg, bgColorMode, bgColor, fg, fgColorMode, fgColor, inverse, bold);
@@ -358,8 +374,22 @@ export class WebglCharAtlas implements IDisposable {
this._tmpCtx.globalAlpha = DIM_OPACITY;
}
// Check if the char is a powerline glyph, these will be restricted to a single cell glyph, no
// padding on either side that are allowed for other glyphs since they are designed to be pixel
// perfect but may render with "bad" anti-aliasing
let isPowerlineGlyph = false;
if (chars.length === 1) {
const code = chars.charCodeAt(0);
if (code >= 0xE0A0 && code <= 0xE0D6) {
isPowerlineGlyph = true;
}
}
// For powerline glyphs left/top padding is excluded (https://github.com/microsoft/vscode/issues/120129)
const padding = isPowerlineGlyph ? 0 : TMP_CANVAS_GLYPH_PADDING;
// Draw the character
this._tmpCtx.fillText(chars, TMP_CANVAS_GLYPH_PADDING, TMP_CANVAS_GLYPH_PADDING + this._config.scaledCharHeight / 2);
this._tmpCtx.fillText(chars, padding, padding + this._config.scaledCharHeight);
this._tmpCtx.restore();
// clear the background from the character to avoid issues with drawing over the previous
@@ -382,7 +412,7 @@ export class WebglCharAtlas implements IDisposable {
return NULL_RASTERIZED_GLYPH;
}
const rasterizedGlyph = this._findGlyphBoundingBox(imageData, this._workBoundingBox);
const rasterizedGlyph = this._findGlyphBoundingBox(imageData, this._workBoundingBox, allowedWidth, isPowerlineGlyph);
const clippedImageData = this._clipImageData(imageData, this._workBoundingBox);
// Check if there is enough room in the current row and go to next if needed
@@ -415,11 +445,13 @@ export class WebglCharAtlas implements IDisposable {
* @param imageData The image data to read.
* @param boundingBox An IBoundingBox to put the clipped bounding box values.
*/
private _findGlyphBoundingBox(imageData: ImageData, boundingBox: IBoundingBox): IRasterizedGlyph {
private _findGlyphBoundingBox(imageData: ImageData, boundingBox: IBoundingBox, allowedWidth: number, restrictedGlyph: boolean): IRasterizedGlyph {
boundingBox.top = 0;
const height = restrictedGlyph ? this._config.scaledCharHeight : this._tmpCanvas.height;
const width = restrictedGlyph ? this._config.scaledCharWidth : allowedWidth;
let found = false;
for (let y = 0; y < this._tmpCanvas.height; y++) {
for (let x = 0; x < this._tmpCanvas.width; x++) {
for (let y = 0; y < height; y++) {
for (let x = 0; x < width; x++) {
const alphaOffset = y * this._tmpCanvas.width * 4 + x * 4 + 3;
if (imageData.data[alphaOffset] !== 0) {
boundingBox.top = y;
@@ -433,8 +465,8 @@ export class WebglCharAtlas implements IDisposable {
}
boundingBox.left = 0;
found = false;
for (let x = 0; x < this._tmpCanvas.width; x++) {
for (let y = 0; y < this._tmpCanvas.height; y++) {
for (let x = 0; x < width; x++) {
for (let y = 0; y < height; y++) {
const alphaOffset = y * this._tmpCanvas.width * 4 + x * 4 + 3;
if (imageData.data[alphaOffset] !== 0) {
boundingBox.left = x;
@@ -446,10 +478,10 @@ export class WebglCharAtlas implements IDisposable {
break;
}
}
boundingBox.right = this._tmpCanvas.width;
boundingBox.right = width;
found = false;
for (let x = this._tmpCanvas.width - 1; x >= 0; x--) {
for (let y = 0; y < this._tmpCanvas.height; y++) {
for (let x = width - 1; x >= 0; x--) {
for (let y = 0; y < height; y++) {
const alphaOffset = y * this._tmpCanvas.width * 4 + x * 4 + 3;
if (imageData.data[alphaOffset] !== 0) {
boundingBox.right = x;
@@ -461,10 +493,10 @@ export class WebglCharAtlas implements IDisposable {
break;
}
}
boundingBox.bottom = this._tmpCanvas.height;
boundingBox.bottom = height;
found = false;
for (let y = this._tmpCanvas.height - 1; y >= 0; y--) {
for (let x = 0; x < this._tmpCanvas.width; x++) {
for (let y = height - 1; y >= 0; y--) {
for (let x = 0; x < width; x++) {
const alphaOffset = y * this._tmpCanvas.width * 4 + x * 4 + 3;
if (imageData.data[alphaOffset] !== 0) {
boundingBox.bottom = y;
@@ -488,8 +520,8 @@ export class WebglCharAtlas implements IDisposable {
y: (boundingBox.bottom - boundingBox.top + 1) / TEXTURE_HEIGHT
},
offset: {
x: -boundingBox.left + TMP_CANVAS_GLYPH_PADDING,
y: -boundingBox.top + TMP_CANVAS_GLYPH_PADDING
x: -boundingBox.left + (restrictedGlyph ? 0 : TMP_CANVAS_GLYPH_PADDING),
y: -boundingBox.top + (restrictedGlyph ? 0 : TMP_CANVAS_GLYPH_PADDING)
}
};
}
@@ -46,7 +46,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
}
private _initCanvas(): void {
this._ctx = throwIfFalsy(this._canvas.getContext('2d', {alpha: this._alpha}));
this._ctx = throwIfFalsy(this._canvas.getContext('2d', { alpha: this._alpha }));
// Draw the background if this is an opaque layer
if (!this._alpha) {
this._clearAll();
@@ -224,12 +224,12 @@ export abstract class BaseRenderLayer implements IRenderLayer {
*/
protected _fillCharTrueColor(terminal: Terminal, cell: CellData, x: number, y: number): void {
this._ctx.font = this._getFont(terminal, false, false);
this._ctx.textBaseline = 'middle';
this._ctx.textBaseline = 'ideographic';
this._clipRow(terminal, y);
this._ctx.fillText(
cell.getChars(),
x * this._scaledCellWidth + this._scaledCharLeft,
y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight / 2);
y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight);
}
/**
+1 -2
View File
@@ -21,8 +21,7 @@
},
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../out-test/api/TestUtils"
"../../../node_modules/@types/mocha"
]
},
"include": [
@@ -7,23 +7,21 @@ import { ITerminalOptions } from '../../../src/common/Types';
import { ITheme } from 'xterm';
import { assert } from 'chai';
import { openTerminal, pollFor, writeSync, getBrowserType } from '../../../out-test/api/TestUtils';
import { Browser, Page } from 'playwright-core';
import { Browser, Page } from 'playwright';
const APP = 'http://127.0.0.1:3000/test';
const APP = 'http://127.0.0.1:3001/test';
let browser: Browser;
let page: Page;
const width = 800;
const height = 600;
let itWebgl: (expectation: string, callback?: (this: Mocha.ITestCallbackContext, done: MochaDone) => any) => Mocha.ITest | void;
describe('WebGL Renderer Integration Tests', async () => {
const browserType = getBrowserType();
const isHeadless = process.argv.indexOf('--headless') !== -1;
const isHeadless = process.argv.includes('--headless');
// Firefox works only in non-headless mode https://github.com/microsoft/playwright/issues/1032
const areTestsEnabled = browserType.name() === 'chromium' || (browserType.name() === 'firefox' && !isHeadless);
itWebgl = areTestsEnabled ? it : it.skip;
const itWebgl = areTestsEnabled ? it : it.skip;
itWebgl('dispose removes renderer canvases', async function(): Promise<void> {
await setupBrowser();
@@ -894,8 +892,8 @@ async function getCellColor(col: number, row: number): Promise<number[]> {
async function setupBrowser(options: ITerminalOptions = { rendererType: 'dom' }): Promise<void> {
const browserType = getBrowserType();
browser = await browserType.launch({ dumpio: true,
headless: process.argv.indexOf('--headless') !== -1
browser = await browserType.launch({
headless: process.argv.includes('--headless')
});
page = await (await browser.newContext()).newPage();
await page.setViewportSize({ width, height });
@@ -0,0 +1,40 @@
{
"compilerOptions": {
"module": "commonjs",
"target": "es5",
"lib": [
"es6",
],
"rootDir": ".",
"outDir": "../out-test",
"sourceMap": true,
"removeComments": true,
"baseUrl": ".",
"paths": {
"common/*": [
"../../../src/common/*"
],
"browser/*": [
"../../../src/browser/*"
]
},
"strict": true,
"types": [
"../../../node_modules/@types/mocha",
"../../../node_modules/@types/node",
"../../../out-test/api/TestUtils"
]
},
"include": [
"./**/*",
"../../../typings/xterm.d.ts"
],
"references": [
{
"path": "../../../src/common"
},
{
"path": "../../../src/browser"
}
]
}
+8
View File
@@ -0,0 +1,8 @@
{
"files": [],
"include": [],
"references": [
{ "path": "./src" },
{ "path": "./test" }
]
}
+13 -2
View File
@@ -3,7 +3,8 @@
* @license MIT
*/
import { Terminal, IDisposable, ITerminalAddon } from 'xterm';
import { IEvent } from 'node-pty';
import { Terminal, ITerminalAddon } from 'xterm';
declare module 'xterm-addon-webgl' {
/**
@@ -15,7 +16,7 @@ declare module 'xterm-addon-webgl' {
constructor(preserveDrawingBuffer?: boolean);
/**
* Activates the addon
* Activates the addon.
* @param terminal The terminal the addon is being loaded in.
*/
public activate(terminal: Terminal): void;
@@ -24,5 +25,15 @@ declare module 'xterm-addon-webgl' {
* Disposes the addon.
*/
public dispose(): void;
/**
* Clears the terminal's texture atlas and triggers a redraw.
*/
public clearTextureAtlas(): void;
/**
* Fired when the WebglRenderer loses context
*/
public get onContextLoss(): IEvent<void>;
}
}
+16 -18
View File
@@ -98,17 +98,8 @@ jobs:
inputs:
versionSpec: '1.x'
displayName: 'Install Yarn'
- task: CacheBeta@1
inputs:
key: yarn2 | $(Agent.OS) | yarn.lock
path: node_modules
displayName: Cache node modules
- script: yarn --frozen-lockfile
displayName: 'Install dependencies and build'
- script: |
yarn start &
sleep 10
displayName: 'Start test server'
- script: yarn test-api-chromium --headless --forbid-only
displayName: 'Integration tests (Chromium)'
- script: xvfb-run --auto-servernum -- bash -c "yarn test-api-firefox --headless --forbid-only"
@@ -122,17 +113,8 @@ jobs:
inputs:
versionSpec: '10.x'
displayName: 'Install Node.js'
- task: CacheBeta@1
inputs:
key: yarn2 | $(Agent.OS) | yarn.lock
path: node_modules
displayName: Cache node modules
- script: yarn --frozen-lockfile
displayName: 'Install dependencies and build'
- script: |
yarn start &
sleep 10
displayName: 'Start test server'
- script: yarn test-api-chromium --headless --forbid-only
displayName: 'Integration tests (Chromium)'
- script: yarn test-api-firefox --headless --forbid-only
@@ -140,6 +122,21 @@ jobs:
- script: yarn test-api-webkit --headless --forbid-only
displayName: 'Integration tests (Webkit)'
- job: Windows_IntegrationTests
pool:
vmImage: 'vs2017-win2016'
steps:
- task: NodeTool@0
inputs:
versionSpec: '10.x'
displayName: 'Install Node.js'
- script: yarn --frozen-lockfile
displayName: 'Install dependencies and build'
- script: yarn test-api-chromium --headless --forbid-only
displayName: 'Integration tests (Chromium)'
- script: yarn test-api-firefox --headless --forbid-only
displayName: 'Integration tests (Firefox)'
- job: Release
dependsOn:
- Linux
@@ -147,6 +144,7 @@ jobs:
- Windows
- Linux_IntegrationTests
- macOS_IntegrationTests
- Windows_IntegrationTests
condition: and(succeeded(), or(eq(variables['Build.SourceBranch'], 'refs/heads/master'), eq(variables['FORCE_RELEASE'], 'true')))
pool:
vmImage: 'ubuntu-16.04'
-23
View File
@@ -1,23 +0,0 @@
/**
* Copyright (c) 2020 The xterm.js authors. All rights reserved.
* @license MIT
*/
const playwright = require('playwright-core');
const fs = require('fs');
// Default to chromium
let browserType = playwright['chromium'];
const index = process.argv.indexOf('--browser');
if (index !== -1 && process.argv.length > index + 1 && typeof process.argv[index + 1] === 'string') {
const string = process.argv[index + 1];
if (string === 'firefox' || string === 'webkit') {
browserType = playwright[string];
}
}
const exists = fs.existsSync(browserType.executablePath());
if (!exists) {
console.log(`Downloading ${browserType.name()}`);
browserType.downloadBrowserIfNeeded().then(() => process.exit(0));
}
+2 -2
View File
@@ -359,7 +359,7 @@ function empty(ar) {
}
function* parseMultiLineGen(filename, s) {
if (!~s.indexOf('@vt:')) {
if (!s.includes('@vt:')) {
return;
}
const lines = s.split('\n').map(el => el.trim().replace(/[*]/, '').replace(/\s/, ''));
@@ -413,7 +413,7 @@ function parseSingleLine(filename, s) {
const line = s.trim();
const match = line.match(REX_VT_LINE);
if (match !== null) {
if (!~TYPES.indexOf(match[2])) {
if (!TYPES.includes(match[2])) {
throw new Error(`unkown vt-command type "${match[2]}" specified in "${filename}"`);
}
return {
+2 -2
View File
@@ -25,7 +25,7 @@ if (fs.existsSync(addonsPath)) {
// walk all addon folders
fs.readdir(addonsPath, (err, files) => {
files.forEach(folder => {
for (const folder of files) {
const addonPath = path.join(addonsPath, folder);
// install only if there are dependencies listed
@@ -51,6 +51,6 @@ if (fs.existsSync(addonsPath)) {
} else {
console.log('Skipped', folder);
}
});
}
});
}
+5 -5
View File
@@ -11,7 +11,7 @@ const path = require('path');
// Setup auth
fs.writeFileSync(`${process.env['HOME']}/.npmrc`, `//registry.npmjs.org/:_authToken=${process.env['NPM_AUTH_TOKEN']}`);
const isDryRun = process.argv.indexOf('--dry') !== -1;
const isDryRun = process.argv.includes('--dry');
if (isDryRun) {
console.log('Publish dry run');
}
@@ -36,13 +36,13 @@ const addonPackageDirs = [
path.resolve(__dirname, '../addons/xterm-addon-webgl')
];
console.log(`Checking if addons need to be published`);
addonPackageDirs.forEach(p => {
for (const p of addonPackageDirs) {
const addon = path.basename(p);
if (changedFiles.some(e => e.indexOf(addon) !== -1)) {
if (changedFiles.some(e => e.includes(addon))) {
console.log(`Try publish ${addon}`);
checkAndPublishPackage(p);
}
});
}
// Publish website if it's a stable release
if (isStableRelease) {
@@ -54,7 +54,7 @@ function checkAndPublishPackage(packageDir) {
// Determine if this is a stable or beta release
const publishedVersions = getPublishedVersions(packageJson);
const isStableRelease = publishedVersions.indexOf(packageJson.version) === -1;
const isStableRelease = !publishedVersions.includes(packageJson.version);
// Get the next version
let nextVersion = isStableRelease ? packageJson.version : getNextBetaVersion(packageJson);
+27 -15
View File
@@ -12,7 +12,7 @@ const env = { ...process.env };
env.NODE_PATH = path.resolve(__dirname, '../out');
let testFiles = [
'./addons/**/out/*api.js',
'./addons/**/out-test/*api.js',
'./out-test/**/*api.js',
];
@@ -34,19 +34,31 @@ if (process.argv.length > 2) {
env.DEBUG = flagArgs.indexOf('--debug') >= 0 ? 'debug' : '';
env.PORT = 3001;
const run = cp.spawnSync(
npmBinScript('mocha'),
[...testFiles, ...flagArgs],
{
cwd: path.resolve(__dirname, '..'),
env,
stdio: 'inherit'
const server = cp.spawn('node', ['demo/start'], {
cwd: path.resolve(__dirname, '..'),
env,
stdio: 'pipe'
})
server.stdout.on('data', (data) => {
// await for the server to fully start
if (data.indexOf("successfully") !== -1) {
const run = cp.spawnSync(
npmBinScript('mocha'),
[...testFiles, ...flagArgs], {
cwd: path.resolve(__dirname, '..'),
env,
stdio: 'inherit'
}
);
function npmBinScript(script) {
return path.resolve(__dirname, `../node_modules/.bin/` + (process.platform === 'win32' ?
`${script}.cmd` : script));
}
process.exit(run.status);
}
);
function npmBinScript(script) {
return path.resolve(__dirname, `../node_modules/.bin/` + (process.platform === 'win32' ? `${script}.cmd` : script));
}
process.exit(run.status);
});
+5 -5
View File
@@ -88,19 +88,19 @@ function evalButtonCode(code) {
if (code & 64) {
button |= 4
}
let actionS = 'press';
let action = 'press';
let buttonS = reverseButtons[button];
if (button === 3) {
buttonS = '<none>';
actionS = 'release';
action = 'release';
}
if (move) {
actionS = 'move';
action = 'move';
} else if (4 <= button && button <= 7) {
buttonS = 'wheel';
actionS = button === 4 ? 'up' : button === 5 ? 'down' : button === 6 ? 'left' : 'right';
action = button === 4 ? 'up' : button === 5 ? 'down' : button === 6 ? 'left' : 'right';
}
return {button: buttonS, action: actionS, modifier};
return {button: buttonS, action, modifier};
}
// protocols
-1
View File
@@ -36,7 +36,6 @@
*/
.xterm {
font-feature-settings: "liga" 0;
position: relative;
user-select: none;
-ms-user-select: none;
+14 -5
View File
@@ -16,6 +16,7 @@ import { SerializeAddon } from '../addons/xterm-addon-serialize/out/SerializeAdd
import { WebLinksAddon } from '../addons/xterm-addon-web-links/out/WebLinksAddon';
import { WebglAddon } from '../addons/xterm-addon-webgl/out/WebglAddon';
import { Unicode11Addon } from '../addons/xterm-addon-unicode11/out/Unicode11Addon';
import { LigaturesAddon } from '../addons/xterm-addon-ligatures/out/LigaturesAddon';
// Use webpacked version (yarn package)
// import { Terminal } from '../lib/xterm';
@@ -26,6 +27,7 @@ import { Unicode11Addon } from '../addons/xterm-addon-unicode11/out/Unicode11Add
// import { WebLinksAddon } from 'xterm-addon-web-links';
// import { WebglAddon } from 'xterm-addon-webgl';
// import { Unicode11Addon } from 'xterm-addon-unicode11';
// import { LigaturesAddon } from 'xterm-addon-ligatures';
// Pulling in the module's types relies on the <reference> above, it's looks a
// little weird here as we're importing "this" module
@@ -41,6 +43,7 @@ export interface IWindowWithTerminal extends Window {
WebLinksAddon?: typeof WebLinksAddon;
WebglAddon?: typeof WebglAddon;
Unicode11Addon?: typeof Unicode11Addon;
LigaturesAddon?: typeof LigaturesAddon;
}
declare let window: IWindowWithTerminal;
@@ -50,7 +53,7 @@ let socketURL;
let socket;
let pid;
type AddonType = 'attach' | 'fit' | 'search' | 'serialize' | 'unicode11' | 'web-links' | 'webgl';
type AddonType = 'attach' | 'fit' | 'search' | 'serialize' | 'unicode11' | 'web-links' | 'webgl' | 'ligatures';
interface IDemoAddon<T extends AddonType> {
name: T;
@@ -62,8 +65,9 @@ interface IDemoAddon<T extends AddonType> {
T extends 'serialize' ? typeof SerializeAddon :
T extends 'web-links' ? typeof WebLinksAddon :
T extends 'unicode11' ? typeof Unicode11Addon :
T extends 'ligatures' ? typeof LigaturesAddon :
typeof WebglAddon;
instance?:
instance?:
T extends 'attach' ? AttachAddon :
T extends 'fit' ? FitAddon :
T extends 'search' ? SearchAddon :
@@ -71,6 +75,7 @@ interface IDemoAddon<T extends AddonType> {
T extends 'web-links' ? WebLinksAddon :
T extends 'webgl' ? WebglAddon :
T extends 'unicode11' ? typeof Unicode11Addon :
T extends 'ligatures' ? typeof LigaturesAddon :
never;
}
@@ -81,7 +86,8 @@ const addons: { [T in AddonType]: IDemoAddon<T>} = {
serialize: { name: 'serialize', ctor: SerializeAddon, canChange: true },
'web-links': { name: 'web-links', ctor: WebLinksAddon, canChange: true },
webgl: { name: 'webgl', ctor: WebglAddon, canChange: true },
unicode11: { name: 'unicode11', ctor: Unicode11Addon, canChange: true }
unicode11: { name: 'unicode11', ctor: Unicode11Addon, canChange: true },
ligatures: { name: 'ligatures', ctor: LigaturesAddon, canChange: true }
};
const terminalContainer = document.getElementById('terminal-container');
@@ -93,7 +99,7 @@ const paddingElement = <HTMLInputElement>document.getElementById('padding');
function setPadding(): void {
term.element.style.padding = parseInt(paddingElement.value, 10).toString() + 'px';
term.fit();
addons.fit.instance.fit();
}
function getSearchOptions(e: KeyboardEvent): ISearchOptions {
@@ -117,6 +123,7 @@ const disposeRecreateButtonHandler = () => {
addons.search.instance = undefined;
addons.serialize.instance = undefined;
addons.unicode11.instance = undefined;
addons.ligatures.instance = undefined;
addons['web-links'].instance = undefined;
addons.webgl.instance = undefined;
document.getElementById('dispose').innerHTML = 'Recreate Terminal';
@@ -133,6 +140,7 @@ if (document.location.pathname === '/test') {
window.SearchAddon = SearchAddon;
window.SerializeAddon = SerializeAddon;
window.Unicode11Addon = Unicode11Addon;
window.LigaturesAddon = LigaturesAddon;
window.WebLinksAddon = WebLinksAddon;
window.WebglAddon = WebglAddon;
} else {
@@ -149,7 +157,8 @@ function createTerminal(): void {
const isWindows = ['Windows', 'Win16', 'Win32', 'WinCE'].indexOf(navigator.platform) >= 0;
term = new Terminal({
windowsMode: isWindows
windowsMode: isWindows,
fontFamily: 'Fira Code, courier-new, courier, monospace'
} as ITerminalOptions);
// Load addons
+9 -9
View File
@@ -43,15 +43,15 @@ function startServer() {
const env = Object.assign({}, process.env);
env['COLORTERM'] = 'truecolor';
var cols = parseInt(req.query.cols),
rows = parseInt(req.query.rows),
term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
name: 'xterm-256color',
cols: cols || 80,
rows: rows || 24,
cwd: env.PWD,
env: env,
encoding: USE_BINARY ? null : 'utf8'
});
rows = parseInt(req.query.rows),
term = pty.spawn(process.platform === 'win32' ? 'cmd.exe' : 'bash', [], {
name: 'xterm-256color',
cols: cols || 80,
rows: rows || 24,
cwd: process.platform === 'win32' ? undefined : env.PWD,
env: env,
encoding: USE_BINARY ? null : 'utf8'
});
console.log('Created terminal with PID: ' + term.pid);
terminals[term.pid] = term;
+8
View File
@@ -49,6 +49,14 @@ const clientConfig = {
alias: {
common: path.resolve('./out/common'),
browser: path.resolve('./out/browser')
},
fallback: {
// The ligature modules contains fallbacks for node environments, we never want to browserify them
stream: false,
util: false,
os: false,
path: false,
fs: false
}
},
output: {
-17
View File
@@ -1,17 +0,0 @@
version: "3"
services:
web:
image: xtermjs/xterm.js:latest
build: .
volumes:
- ./:/usr/src/app
ports:
- ${XTERMJS_PORT:-3000}:3000
command: ["npm", "start"]
watch:
build: .
volumes:
- ./:/usr/src/app
command: ["npm", "run", "watch"]
+19 -21
View File
@@ -1,7 +1,7 @@
{
"name": "xterm",
"description": "Full xterm terminal, in your browser",
"version": "4.8.0",
"version": "4.12.0",
"main": "lib/xterm.js",
"style": "css/xterm.css",
"types": "typings/xterm.d.ts",
@@ -11,6 +11,7 @@
"prepackage": "npm run build",
"package": "webpack",
"start": "node demo/start",
"start-debug": "node --inspect-brk demo/start",
"lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/",
"test": "npm run test-unit",
"posttest": "npm run lint",
@@ -18,9 +19,6 @@
"test-api-chromium": "node ./bin/test_api.js --browser=chromium --timeout=20000",
"test-api-firefox": "node ./bin/test_api.js --browser=firefox --timeout=20000",
"test-api-webkit": "node ./bin/test_api.js --browser=webkit --timeout=20000",
"pretest-api-chromium": "node ./bin/download_browser.js --browser chromium",
"pretest-api-firefox": "node ./bin/download_browser.js --browser firefox",
"pretest-api-webkit": "node ./bin/download_browser.js --browser webkit",
"test-unit": "node ./bin/test.js",
"test-unit-coverage": "node ./bin/test.js --coverage",
"build": "tsc -b ./tsconfig.all.json",
@@ -36,36 +34,36 @@
"vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
},
"devDependencies": {
"@types/chai": "^4.2.11",
"@types/chai": "^4.2.14",
"@types/debug": "^4.1.5",
"@types/deep-equal": "^1.0.1",
"@types/glob": "^7.1.3",
"@types/jsdom": "^16.2.3",
"@types/mocha": "^7.0.2",
"@types/jsdom": "^16.2.5",
"@types/mocha": "^8.0.3",
"@types/node": "^10.17.17",
"@types/utf8": "^2.1.6",
"@types/webpack": "^4.41.21",
"@types/ws": "^7.2.6",
"@typescript-eslint/eslint-plugin": "^2.34.0",
"@typescript-eslint/parser": "^2.34.0",
"@types/webpack": "^4.41.24",
"@types/ws": "^7.2.9",
"@typescript-eslint/eslint-plugin": "^4.0.0",
"@typescript-eslint/parser": "^3.10.1",
"chai": "^4.2.0",
"deep-equal": "^2.0.3",
"eslint": "^6.8.0",
"deep-equal": "^2.0.4",
"eslint": "^7.12.1",
"express": "^4.17.1",
"express-ws": "^4.0.0",
"glob": "^7.0.5",
"jsdom": "^16.3.0",
"mocha": "^8.0.1",
"jsdom": "^16.4.0",
"mocha": "^8.2.1",
"mustache": "^4.0.1",
"node-pty": "^0.9.0",
"nyc": "^15.1.0",
"playwright-core": "^0.11.1",
"source-map-loader": "^1.0.1",
"ts-loader": "^8.0.0",
"typescript": "3.9",
"playwright": "^1.5.2",
"source-map-loader": "^1.1.2",
"ts-loader": "^8.0.8",
"typescript": "4.0",
"utf8": "^3.0.0",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.12",
"webpack": "^5.4.0",
"webpack-cli": "^4.2.0",
"ws": "^7.3.1",
"xterm-benchmark": "^0.1.3"
}
+2 -2
View File
@@ -56,8 +56,8 @@ export class AccessibilityManager extends Disposable {
this._accessibilityTreeRoot.classList.add('xterm-accessibility');
this._rowContainer = document.createElement('div');
this._rowContainer.classList.add('xterm-accessibility-tree');
this._rowContainer.setAttribute('role', 'list');
this._rowContainer.classList.add('xterm-accessibility-tree');
this._rowElements = [];
for (let i = 0; i < this._terminal.rows; i++) {
this._rowElements[i] = this._createAccessibilityTreeNode();
@@ -263,7 +263,7 @@ export class AccessibilityManager extends Disposable {
const element = this._rowElements[i];
if (element) {
if (lineData.length === 0) {
element.innerHTML = '&nbsp;';
element.innerText = '\u00a0';
} else {
element.textContent = lineData;
}
+2 -2
View File
@@ -89,8 +89,8 @@ export function moveTextAreaUnderMouseCursor(ev: MouseEvent, textarea: HTMLTextA
export function rightClickHandler(ev: MouseEvent, textarea: HTMLTextAreaElement, screenElement: HTMLElement, selectionService: ISelectionService, shouldSelectWord: boolean): void {
moveTextAreaUnderMouseCursor(ev, textarea, screenElement);
if (shouldSelectWord && !selectionService.isClickInSelection(ev)) {
selectionService.selectWordAtCursor(ev);
if (shouldSelectWord) {
selectionService.rightClickSelect(ev);
}
// Get textarea ready to copy from the context menu
+3 -4
View File
@@ -17,9 +17,8 @@ const DEFAULT_SELECTION = {
rgba: 0xFFFFFF4D
};
// An IIFE to generate DEFAULT_ANSI_COLORS. Do not mutate DEFAULT_ANSI_COLORS, instead make a copy
// and mutate that.
export const DEFAULT_ANSI_COLORS = (() => {
// An IIFE to generate DEFAULT_ANSI_COLORS.
export const DEFAULT_ANSI_COLORS = Object.freeze((() => {
const colors = [
// dark:
css.toColor('#2e3436'),
@@ -64,7 +63,7 @@ export const DEFAULT_ANSI_COLORS = (() => {
}
return colors;
})();
})());
/**
* Manages the source of truth for a terminal's colors.
+2 -2
View File
@@ -59,7 +59,7 @@ describe('Linkifier', () => {
bufferService.buffer.lines.push(stringToRow(text));
}
function assertLinkifiesRow(rowText: string, linkMatcherRegex: RegExp, links: {x: number, length: number}[], done: MochaDone): void {
function assertLinkifiesRow(rowText: string, linkMatcherRegex: RegExp, links: {x: number, length: number}[], done: Mocha.Done): void {
addRow(rowText);
linkifier.registerLinkMatcher(linkMatcherRegex, () => {});
linkifier.linkifyRows();
@@ -76,7 +76,7 @@ describe('Linkifier', () => {
}, 0);
}
function assertLinkifiesMultiLineLink(rowText: string, linkMatcherRegex: RegExp, links: {x1: number, y1: number, x2: number, y2: number}[], done: MochaDone): void {
function assertLinkifiesMultiLineLink(rowText: string, linkMatcherRegex: RegExp, links: {x1: number, y1: number, x2: number, y2: number}[], done: Mocha.Done): void {
addRow(rowText);
linkifier.registerLinkMatcher(linkMatcherRegex, () => {});
linkifier.linkifyRows();
+9 -11
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent, ILinkDecorations } from 'browser/Types';
import { ILinkifier2, ILinkProvider, IBufferCellPosition, ILink, ILinkifierEvent, ILinkDecorations, ILinkWithState } from 'browser/Types';
import { IDisposable } from 'common/Types';
import { IMouseService, IRenderService } from './services/Services';
import { IBufferService } from 'common/services/Services';
@@ -11,21 +11,12 @@ import { EventEmitter, IEvent } from 'common/EventEmitter';
import { Disposable, getDisposeArrayDisposable, disposeArray } from 'common/Lifecycle';
import { addDisposableDomListener } from 'browser/Lifecycle';
interface ILinkState {
decorations: ILinkDecorations;
isHovered: boolean;
}
interface ILinkWithState {
link: ILink;
state?: ILinkState;
}
export class Linkifier2 extends Disposable implements ILinkifier2 {
private _element: HTMLElement | undefined;
private _mouseService: IMouseService | undefined;
private _renderService: IRenderService | undefined;
private _linkProviders: ILinkProvider[] = [];
public get currentLink(): ILinkWithState | undefined { return this._currentLink; }
protected _currentLink: ILinkWithState | undefined;
private _lastMouseEvent: MouseEvent | undefined;
private _linkCacheDisposables: IDisposable[] = [];
@@ -125,6 +116,13 @@ export class Linkifier2 extends Disposable implements ILinkifier2 {
private _askForLink(position: IBufferCellPosition, useLineCache: boolean): void {
if (!this._activeProviderReplies || !useLineCache) {
this._activeProviderReplies?.forEach(reply => {
reply?.forEach(linkWithState => {
if (linkWithState.link.dispose) {
linkWithState.link.dispose();
}
});
});
this._activeProviderReplies = new Map();
this._activeLine = position.y;
}
+1 -3
View File
@@ -156,9 +156,7 @@ export class MouseZoneManager extends Disposable implements IMouseZoneManager {
private _onTooltip(e: MouseEvent): void {
this._tooltipTimeout = undefined;
const zone = this._findZoneEventAt(e);
if (zone && zone.tooltipCallback) {
zone.tooltipCallback(e);
}
zone?.tooltipCallback(e);
}
private _onMouseDown(e: MouseEvent): void {
File diff suppressed because it is too large Load Diff
+75 -36
View File
@@ -21,8 +21,8 @@
* http://linux.die.net/man/7/urxvt
*/
import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler, ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2 } from 'browser/Types';
import { IRenderer, CharacterJoinerHandler } from 'browser/renderer/Types';
import { ICompositionHelper, ITerminal, IBrowser, CustomKeyEventHandler, ILinkifier, IMouseZoneManager, LinkMatcherHandler, ILinkMatcherOptions, IViewport, ILinkifier2, CharacterJoinerHandler } from 'browser/Types';
import { IRenderer } from 'browser/renderer/Types';
import { CompositionHelper } from 'browser/input/CompositionHelper';
import { Viewport } from 'browser/Viewport';
import { rightClickHandler, moveTextAreaUnderMouseCursor, handlePasteEvent, copyHandler, paste } from 'browser/Clipboard';
@@ -39,13 +39,13 @@ import { MouseZoneManager } from 'browser/MouseZoneManager';
import { AccessibilityManager } from './AccessibilityManager';
import { ITheme, IMarker, IDisposable, ISelectionPosition, ILinkProvider } from 'xterm';
import { DomRenderer } from 'browser/renderer/dom/DomRenderer';
import { IKeyboardEvent, KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions } from 'common/Types';
import { IKeyboardEvent, KeyboardResultType, CoreMouseEventType, CoreMouseButton, CoreMouseAction, ITerminalOptions, ScrollSource, IAnsiColorChangeEvent } from 'common/Types';
import { evaluateKeyboardEvent } from 'common/input/Keyboard';
import { EventEmitter, IEvent, forwardEvent } from 'common/EventEmitter';
import { DEFAULT_ATTR_DATA } from 'common/buffer/BufferLine';
import { ColorManager } from 'browser/ColorManager';
import { RenderService } from 'browser/services/RenderService';
import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService, ICoreBrowserService } from 'browser/services/Services';
import { ICharSizeService, IRenderService, IMouseService, ISelectionService, ISoundService, ICoreBrowserService, ICharacterJoinerService } from 'browser/services/Services';
import { CharSizeService } from 'browser/services/CharSizeService';
import { IBuffer } from 'common/buffer/Types';
import { MouseService } from 'browser/services/MouseService';
@@ -53,6 +53,8 @@ import { Linkifier2 } from 'browser/Linkifier2';
import { CoreBrowserService } from 'browser/services/CoreBrowserService';
import { CoreTerminal } from 'common/CoreTerminal';
import { ITerminalOptions as IInitializedTerminalOptions } from 'common/services/Services';
import { rgba } from 'browser/Color';
import { CharacterJoinerService } from 'browser/services/CharacterJoinerService';
// Let it work inside Node.js for automated testing purposes.
const document: Document = (typeof window !== 'undefined') ? window.document : null as any;
@@ -81,6 +83,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
private _charSizeService: ICharSizeService | undefined;
private _mouseService: IMouseService | undefined;
private _renderService: IRenderService | undefined;
private _characterJoinerService: ICharacterJoinerService | undefined;
private _selectionService: ISelectionService | undefined;
private _soundService: ISoundService | undefined;
@@ -110,6 +113,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
public get onSelectionChange(): IEvent<void> { return this._onSelectionChange.event; }
private _onTitleChange = new EventEmitter<string>();
public get onTitleChange(): IEvent<string> { return this._onTitleChange.event; }
private _onBell = new EventEmitter<void>();
public get onBell (): IEvent<void> { return this._onBell.event; }
private _onFocus = new EventEmitter<void>();
public get onFocus(): IEvent<void> { return this._onFocus.event; }
@@ -146,8 +151,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.register(this._inputHandler.onRequestBell(() => this.bell()));
this.register(this._inputHandler.onRequestRefreshRows((start, end) => this.refresh(start, end)));
this.register(this._inputHandler.onRequestReset(() => this.reset()));
this.register(this._inputHandler.onRequestScroll((eraseAttr, isWrapped) => this.scroll(eraseAttr, isWrapped || undefined)));
this.register(this._inputHandler.onRequestWindowsOptionsReport(type => this._reportWindowsOptions(type)));
this.register(this._inputHandler.onAnsiColorChange((event) => this._changeAnsiColor(event)));
this.register(forwardEvent(this._inputHandler.onCursorMove, this._onCursorMove));
this.register(forwardEvent(this._inputHandler.onTitleChange, this._onTitleChange));
this.register(forwardEvent(this._inputHandler.onA11yChar, this._onA11yCharEmitter));
@@ -157,6 +162,19 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.register(this._bufferService.onResize(e => this._afterResize(e.cols, e.rows)));
}
private _changeAnsiColor(event: IAnsiColorChangeEvent): void {
if (!this._colorManager) { return; }
for (const ansiColor of event.colors) {
const color = rgba.toColor(ansiColor.red, ansiColor.green, ansiColor.blue);
this._colorManager!.colors.ansi[ansiColor.colorIndex] = color;
}
this._renderService?.setColors(this._colorManager!.colors);
this.viewport?.onThemeChange(this._colorManager!.colors);
}
public dispose(): void {
if (this._isDisposed) {
return;
@@ -282,19 +300,26 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
private _syncTextArea(): void {
if (!this.textarea || !this.buffer.isCursorInViewport || this._compositionHelper!.isComposing) {
if (!this.textarea || !this.buffer.isCursorInViewport || this._compositionHelper!.isComposing || !this._renderService) {
return;
}
const cellHeight = Math.ceil(this._charSizeService!.height * this.optionsService.options.lineHeight);
const cursorTop = this._bufferService.buffer.y * cellHeight;
const cursorLeft = this._bufferService.buffer.x * this._charSizeService!.width;
const cursorY = this.buffer.ybase + this.buffer.y;
const bufferLine = this.buffer.lines.get(cursorY);
if (!bufferLine) {
return;
}
const cursorX = Math.min(this.buffer.x, this.cols - 1);
const cellHeight = this._renderService.dimensions.actualCellHeight;
const width = bufferLine.getWidth(cursorX);
const cellWidth = this._renderService.dimensions.actualCellWidth * width;
const cursorTop = this.buffer.y * this._renderService.dimensions.actualCellHeight;
const cursorLeft = cursorX * this._renderService.dimensions.actualCellWidth;
// Sync the textarea to the exact position of the composition view so the IME knows where the
// text is.
this.textarea.style.left = cursorLeft + 'px';
this.textarea.style.top = cursorTop + 'px';
this.textarea.style.width = this._charSizeService!.width + 'px';
this.textarea.style.width = cellWidth + 'px';
this.textarea.style.height = cellHeight + 'px';
this.textarea.style.lineHeight = cellHeight + 'px';
this.textarea.style.zIndex = '-5';
@@ -371,7 +396,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
throw new Error('Terminal requires a parent element.');
}
if (!document.body.contains(parent)) {
if (!parent.isConnected) {
this._logService.debug('Terminal.open was called on an element that was not attached to the DOM');
}
@@ -383,6 +408,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.element.classList.add('terminal');
this.element.classList.add('xterm');
this.element.setAttribute('tabindex', '0');
this.element.setAttribute('role', 'document');
parent.appendChild(this.element);
// Performance: Use a document fragment to build the terminal
@@ -422,6 +448,20 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._charSizeService = this._instantiationService.createInstance(CharSizeService, this._document, this._helperContainer);
this._instantiationService.setService(ICharSizeService, this._charSizeService);
this._theme = this.options.theme || this._theme;
this._colorManager = new ColorManager(document, this.options.allowTransparency);
this.register(this.optionsService.onOptionChange(e => this._colorManager!.onOptionsChange(e)));
this._colorManager.setTheme(this._theme);
this._characterJoinerService = this._instantiationService.createInstance(CharacterJoinerService);
this._instantiationService.setService(ICharacterJoinerService, this._characterJoinerService);
const renderer = this._createRenderer();
this._renderService = this.register(this._instantiationService.createInstance(RenderService, renderer, this.rows, this.screenElement));
this._instantiationService.setService(IRenderService, this._renderService);
this.register(this._renderService.onRenderedBufferChange(e => this._onRender.fire(e)));
this.onResize(e => this._renderService!.resize(e.cols, e.rows));
this._compositionView = document.createElement('div');
this._compositionView.classList.add('composition-view');
this._compositionHelper = this._instantiationService.createInstance(CompositionHelper, this.textarea, this._compositionView);
@@ -430,24 +470,13 @@ export class Terminal extends CoreTerminal implements ITerminal {
// Performance: Add viewport and helper elements from the fragment
this.element.appendChild(fragment);
this._theme = this.options.theme || this._theme;
this._colorManager = new ColorManager(document, this.options.allowTransparency);
this.register(this.optionsService.onOptionChange(e => this._colorManager!.onOptionsChange(e)));
this._colorManager.setTheme(this._theme);
const renderer = this._createRenderer();
this._renderService = this.register(this._instantiationService.createInstance(RenderService, renderer, this.rows, this.screenElement));
this._instantiationService.setService(IRenderService, this._renderService);
this.register(this._renderService.onRenderedBufferChange(e => this._onRender.fire(e)));
this.onResize(e => this._renderService!.resize(e.cols, e.rows));
this._soundService = this._instantiationService.createInstance(SoundService);
this._instantiationService.setService(ISoundService, this._soundService);
this._mouseService = this._instantiationService.createInstance(MouseService);
this._instantiationService.setService(IMouseService, this._mouseService);
this.viewport = this._instantiationService.createInstance(Viewport,
(amount: number, suppressEvent: boolean) => this.scrollLines(amount, suppressEvent),
(amount: number) => this.scrollLines(amount, true, ScrollSource.VIEWPORT),
this._viewportElement,
this._viewportScrollArea
);
@@ -466,7 +495,9 @@ export class Terminal extends CoreTerminal implements ITerminal {
this._selectionService = this.register(this._instantiationService.createInstance(SelectionService,
this.element,
this.screenElement));
this.screenElement,
this.linkifier2
));
this._instantiationService.setService(ISelectionService, this._selectionService);
this.register(this._selectionService.onRequestScrollLines(e => this.scrollLines(e.amount, e.suppressScrollEvent)));
this.register(this._selectionService.onSelectionChange(() => this._onSelectionChange.fire()));
@@ -479,7 +510,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.textarea!.focus();
this.textarea!.select();
}));
this.register(this.onScroll(() => {
this.register(this._onScroll.event(ev => {
this.viewport!.syncScrollArea();
this._selectionService!.refresh();
}));
@@ -778,7 +809,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
if (!this.viewport!.onWheel(ev)) {
return this.cancel(ev);
}
}, { passive: true }));
}, { passive: false }));
this.register(addDisposableDomListener(el, 'touchstart', (ev: TouchEvent) => {
if (this._coreMouseService.areMouseEventsActive) return;
@@ -791,7 +822,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
if (!this.viewport!.onTouchMove(ev)) {
return this.cancel(ev);
}
}, { passive: true }));
}, { passive: false }));
}
@@ -818,7 +849,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
* Change the cursor style for different selection modes
*/
public updateCursorStyle(ev: KeyboardEvent): void {
if (this._selectionService && this._selectionService.shouldColumnSelect(ev)) {
if (this._selectionService?.shouldColumnSelect(ev)) {
this.element!.classList.add('column-select');
} else {
this.element!.classList.remove('column-select');
@@ -835,8 +866,8 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
}
public scrollLines(disp: number, suppressScrollEvent?: boolean): void {
super.scrollLines(disp, suppressScrollEvent);
public scrollLines(disp: number, suppressScrollEvent?: boolean, source = ScrollSource.TERMINAL): void {
super.scrollLines(disp, suppressScrollEvent, source);
this.refresh(0, this.rows - 1);
}
@@ -888,13 +919,19 @@ export class Terminal extends CoreTerminal implements ITerminal {
}
public registerCharacterJoiner(handler: CharacterJoinerHandler): number {
const joinerId = this._renderService!.registerCharacterJoiner(handler);
if (!this._characterJoinerService) {
throw new Error('Terminal must be opened first');
}
const joinerId = this._characterJoinerService.register(handler);
this.refresh(0, this.rows - 1);
return joinerId;
}
public deregisterCharacterJoiner(joinerId: number): void {
if (this._renderService!.deregisterCharacterJoiner(joinerId)) {
if (!this._characterJoinerService) {
throw new Error('Terminal must be opened first');
}
if (this._characterJoinerService.deregister(joinerId)) {
this.refresh(0, this.rows - 1);
}
}
@@ -983,7 +1020,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
if (!this._compositionHelper!.keydown(event)) {
if (this.buffer.ybase !== this.buffer.ydisp) {
this.scrollToBottom();
this._bufferService.scrollToBottom();
}
return false;
}
@@ -1112,9 +1149,11 @@ export class Terminal extends CoreTerminal implements ITerminal {
*/
public bell(): void {
if (this._soundBell()) {
this._soundService!.playBellSound();
this._soundService?.playBellSound();
}
this._onBell.fire();
// if (this._visualBell()) {
// this.element.classList.add('visual-bell-active');
// clearTimeout(this._visualBellTimer);
@@ -1167,7 +1206,7 @@ export class Terminal extends CoreTerminal implements ITerminal {
this.buffer.lines.push(this.buffer.getBlankLine(DEFAULT_ATTR_DATA));
}
this.refresh(0, this.rows - 1);
this._onScroll.fire(this.buffer.ydisp);
this._onScroll.fire({ position: this.buffer.ydisp, source: ScrollSource.TERMINAL });
}
/**
+3 -3
View File
@@ -32,7 +32,7 @@ if (os.platform() === 'darwin') {
);
}
// filter skipFilenames
const FILES = TESTFILES.filter(value => SKIP_FILES.indexOf(value.split('/').slice(-1)[0]) === -1);
const FILES = TESTFILES.filter(value => !SKIP_FILES.includes(value.split('/').slice(-1)[0]));
describe('Escape Sequence Files', function(): void {
this.timeout(1000);
@@ -74,7 +74,7 @@ describe('Escape Sequence Files', function(): void {
let content = '';
const OSC_CODE = 12345;
await new Promise(resolve => {
customHandler = term.addOscHandler(OSC_CODE, () => {
customHandler = term.registerOscHandler(OSC_CODE, () => {
// grab terminal viewport content
content = terminalToString(term);
resolve();
@@ -104,7 +104,7 @@ describe('Escape Sequence Files', function(): void {
function formatError(input: string, output: string, expected: string): string {
function addLineNumber(start: number, color: string): (s: string) => string {
let counter = start || 0;
return function(s: string): string {
return (s: string): string => {
counter += 1;
return '\x1b[33m' + (' ' + counter).slice(-2) + color + s;
};
+24 -15
View File
@@ -5,9 +5,9 @@
import { IDisposable, IMarker, ISelectionPosition, ILinkProvider } from 'xterm';
import { IEvent, EventEmitter } from 'common/EventEmitter';
import { ICharSizeService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services';
import { IRenderDimensions, IRenderer, CharacterJoinerHandler, IRequestRedrawEvent } from 'browser/renderer/Types';
import { IColorSet, ILinkMatcherOptions, ITerminal, ILinkifier, ILinkifier2, IBrowser, IViewport, IColorManager, ICompositionHelper } from 'browser/Types';
import { ICharacterJoinerService, ICharSizeService, IMouseService, IRenderService, ISelectionService } from 'browser/services/Services';
import { IRenderDimensions, IRenderer, IRequestRedrawEvent } from 'browser/renderer/Types';
import { IColorSet, ILinkMatcherOptions, ITerminal, ILinkifier, ILinkifier2, IBrowser, IViewport, IColorManager, ICompositionHelper, CharacterJoinerHandler } from 'browser/Types';
import { IBuffer, IBufferStringIterator, IBufferSet } from 'common/buffer/Types';
import { IBufferLine, ICellData, IAttributeData, ICircularList, XtermListener, ICharset, ITerminalOptions } from 'common/Types';
import { Buffer } from 'common/buffer/Buffer';
@@ -21,6 +21,9 @@ export class TestTerminal extends Terminal {
public get curAttrData(): IAttributeData { return (this as any)._inputHandler._curAttrData; }
public keyDown(ev: any): boolean | undefined { return this._keyDown(ev); }
public keyPress(ev: any): boolean { return this._keyPress(ev); }
public writeP(data: string | Uint8Array): Promise<void> {
return new Promise(r => this.write(data, r));
}
}
export class MockTerminal implements ITerminal {
@@ -34,6 +37,7 @@ export class MockTerminal implements ITerminal {
public onData!: IEvent<string>;
public onBinary!: IEvent<string>;
public onTitleChange!: IEvent<string>;
public onBell!: IEvent<void>;
public onScroll!: IEvent<number>;
public onKey!: IEvent<{ key: string, domEvent: KeyboardEvent }>;
public onRender!: IEvent<{ start: number, end: number }>;
@@ -75,16 +79,16 @@ export class MockTerminal implements ITerminal {
public attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void {
throw new Error('Method not implemented.');
}
public addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable {
public registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise<boolean>): IDisposable {
throw new Error('Method not implemented.');
}
public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable {
public registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable {
throw new Error('Method not implemented.');
}
public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable {
public registerEscHandler(id: IFunctionIdentifier, handler: () => boolean | Promise<boolean>): IDisposable {
throw new Error('Method not implemented.');
}
public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
public registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
throw new Error('Method not implemented.');
}
public registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => boolean | void, options?: ILinkMatcherOptions): number {
@@ -281,8 +285,6 @@ export class MockRenderer implements IRenderer {
public onDevicePixelRatioChange(): void { }
public clear(): void { }
public renderRows(start: number, end: number): void { }
public registerCharacterJoiner(handler: CharacterJoinerHandler): number { return 0; }
public deregisterCharacterJoiner(): boolean { return true; }
}
export class MockViewport implements IViewport {
@@ -406,13 +408,20 @@ export class MockRenderService implements IRenderService {
public clear(): void {
throw new Error('Method not implemented.');
}
public registerCharacterJoiner(handler: CharacterJoinerHandler): number {
throw new Error('Method not implemented.');
}
public deregisterCharacterJoiner(joinerId: number): boolean {
throw new Error('Method not implemented.');
}
public dispose(): void {
throw new Error('Method not implemented.');
}
}
export class MockCharacterJoinerService implements ICharacterJoinerService {
public serviceBrand: undefined;
public register(handler: (text: string) => [number, number][]): number {
return 0;
}
public deregister(joinerId: number): boolean {
return true;
}
public getJoinedCharacters(row: number): [number, number][] {
return [];
}
}
+23 -4
View File
@@ -47,15 +47,16 @@ export interface IPublicTerminal extends IDisposable {
onRender: IEvent<{ start: number, end: number }>;
onResize: IEvent<{ cols: number, rows: number }>;
onTitleChange: IEvent<string>;
onBell: IEvent<void>;
blur(): void;
focus(): void;
resize(columns: number, rows: number): void;
open(parent: HTMLElement): void;
attachCustomKeyEventHandler(customKeyEventHandler: (event: KeyboardEvent) => boolean): void;
addCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean): IDisposable;
addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean): IDisposable;
addEscHandler(id: IFunctionIdentifier, callback: () => boolean): IDisposable;
addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable;
registerCsiHandler(id: IFunctionIdentifier, callback: (params: IParams) => boolean | Promise<boolean>): IDisposable;
registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: IParams) => boolean | Promise<boolean>): IDisposable;
registerEscHandler(id: IFunctionIdentifier, callback: () => boolean | Promise<boolean>): IDisposable;
registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable;
registerLinkMatcher(regex: RegExp, handler: (event: MouseEvent, uri: string) => void, options?: ILinkMatcherOptions): number;
deregisterLinkMatcher(matcherId: number): void;
registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
@@ -205,9 +206,19 @@ export interface ILinkifier {
deregisterLinkMatcher(matcherId: number): boolean;
}
interface ILinkState {
decorations: ILinkDecorations;
isHovered: boolean;
}
export interface ILinkWithState {
link: ILink;
state?: ILinkState;
}
export interface ILinkifier2 {
onShowLinkUnderline: IEvent<ILinkifierEvent>;
onHideLinkUnderline: IEvent<ILinkifierEvent>;
readonly currentLink: ILinkWithState | undefined;
attachToDom(element: HTMLElement, mouseService: IMouseService, renderService: IRenderService): void;
registerLinkProvider(linkProvider: ILinkProvider): IDisposable;
@@ -275,6 +286,7 @@ interface ILink {
activate(event: MouseEvent, text: string): void;
hover?(event: MouseEvent, text: string): void;
leave?(event: MouseEvent, text: string): void;
dispose?(): void;
}
interface ILinkDecorations {
@@ -291,3 +303,10 @@ interface IBufferCellPosition {
x: number;
y: number;
}
export type CharacterJoinerHandler = (text: string) => [number, number][];
export interface ICharacterJoiner {
id: number;
handler: CharacterJoinerHandler;
}
+4 -2
View File
@@ -33,7 +33,7 @@ export class Viewport extends Disposable implements IViewport {
private _ignoreNextScrollEvent: boolean = false;
constructor(
private readonly _scrollLines: (amount: number, suppressEvent: boolean) => void,
private readonly _scrollLines: (amount: number) => void,
private readonly _viewportElement: HTMLElement,
private readonly _scrollArea: HTMLElement,
@IBufferService private readonly _bufferService: IBufferService,
@@ -151,12 +151,14 @@ export class Viewport extends Disposable implements IViewport {
// Ignore the event if it was flagged to ignore (when the source of the event is from Viewport)
if (this._ignoreNextScrollEvent) {
this._ignoreNextScrollEvent = false;
// Still trigger the scroll so lines get refreshed
this._scrollLines(0);
return;
}
const newRow = Math.round(this._lastScrollTop / this._currentRowHeight);
const diff = newRow - this._bufferService.buffer.ydisp;
this._scrollLines(diff, true);
this._scrollLines(diff);
}
/**
+2 -2
View File
@@ -5,7 +5,7 @@
import { assert } from 'chai';
import { CompositionHelper } from 'browser/input/CompositionHelper';
import { MockCharSizeService } from 'browser/TestUtils.test';
import { MockRenderService } from 'browser/TestUtils.test';
import { MockCoreService, MockBufferService, MockOptionsService } from 'common/TestUtils.test';
describe('CompositionHelper', () => {
@@ -42,7 +42,7 @@ describe('CompositionHelper', () => {
};
handledText = '';
const bufferService = new MockBufferService(10, 5);
compositionHelper = new CompositionHelper(textarea, compositionView, bufferService, new MockOptionsService(), new MockCharSizeService(10, 10), coreService);
compositionHelper = new CompositionHelper(textarea, compositionView, bufferService, new MockOptionsService(), coreService, new MockRenderService());
});
describe('Input', () => {
+25 -9
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { ICharSizeService } from 'browser/services/Services';
import { IRenderService } from 'browser/services/Services';
import { IBufferService, ICoreService, IOptionsService } from 'common/services/Services';
interface IPosition {
@@ -35,17 +35,23 @@ export class CompositionHelper {
*/
private _isSendingComposition: boolean;
/**
* Data already sent due to keydown event.
*/
private _dataAlreadySent: string;
constructor(
private readonly _textarea: HTMLTextAreaElement,
private readonly _compositionView: HTMLElement,
@IBufferService private readonly _bufferService: IBufferService,
@IOptionsService private readonly _optionsService: IOptionsService,
@ICharSizeService private readonly _charSizeService: ICharSizeService,
@ICoreService private readonly _coreService: ICoreService
@ICoreService private readonly _coreService: ICoreService,
@IRenderService private readonly _renderService: IRenderService
) {
this._isComposing = false;
this._isSendingComposition = false;
this._compositionPosition = { start: 0, end: 0 };
this._dataAlreadySent = '';
}
/**
@@ -55,6 +61,7 @@ export class CompositionHelper {
this._isComposing = true;
this._compositionPosition.start = this._textarea.value.length;
this._compositionView.textContent = '';
this._dataAlreadySent = '';
this._compositionView.classList.add('active');
}
@@ -147,6 +154,9 @@ export class CompositionHelper {
if (this._isSendingComposition) {
this._isSendingComposition = false;
let input;
// Add length of data already sent due to keydown event,
// otherwise input characters can be duplicated. (Issue #3191)
currentCompositionPosition.start += this._dataAlreadySent.length;
if (this._isComposing) {
// Use the end position to get the string if a new composition has started.
input = this._textarea.value.substring(currentCompositionPosition.start, currentCompositionPosition.end);
@@ -156,7 +166,9 @@ export class CompositionHelper {
// (eg. 2) after a composition character.
input = this._textarea.value.substring(currentCompositionPosition.start);
}
this._coreService.triggerDataEvent(input, true);
if (input.length > 0) {
this._coreService.triggerDataEvent(input, true);
}
}
}, 0);
}
@@ -176,6 +188,7 @@ export class CompositionHelper {
const newValue = this._textarea.value;
const diff = newValue.replace(oldValue, '');
if (diff.length > 0) {
this._dataAlreadySent = diff;
this._coreService.triggerDataEvent(diff, true);
}
}
@@ -194,9 +207,11 @@ export class CompositionHelper {
}
if (this._bufferService.buffer.isCursorInViewport) {
const cellHeight = Math.ceil(this._charSizeService.height * this._optionsService.options.lineHeight);
const cursorTop = this._bufferService.buffer.y * cellHeight;
const cursorLeft = this._bufferService.buffer.x * this._charSizeService.width;
const cursorX = Math.min(this._bufferService.buffer.x, this._bufferService.cols - 1);
const cellHeight = this._renderService.dimensions.actualCellHeight;
const cursorTop = this._bufferService.buffer.y * this._renderService.dimensions.actualCellHeight;
const cursorLeft = cursorX * this._renderService.dimensions.actualCellWidth;
this._compositionView.style.left = cursorLeft + 'px';
this._compositionView.style.top = cursorTop + 'px';
@@ -209,8 +224,9 @@ export class CompositionHelper {
const compositionViewBounds = this._compositionView.getBoundingClientRect();
this._textarea.style.left = cursorLeft + 'px';
this._textarea.style.top = cursorTop + 'px';
this._textarea.style.width = compositionViewBounds.width + 'px';
this._textarea.style.height = compositionViewBounds.height + 'px';
// Ensure the text area is at least 1x1, otherwise certain IMEs may break
this._textarea.style.width = Math.max(compositionViewBounds.width, 1) + 'px';
this._textarea.style.height = Math.max(compositionViewBounds.height, 1) + 'px';
this._textarea.style.lineHeight = compositionViewBounds.height + 'px';
}
+33 -26
View File
@@ -3,7 +3,7 @@
* @license MIT
*/
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider } from 'xterm';
import { Terminal as ITerminalApi, ITerminalOptions, IMarker, IDisposable, ILinkMatcherOptions, ITheme, ILocalizableStrings, ITerminalAddon, ISelectionPosition, IBuffer as IBufferApi, IBufferNamespace as IBufferNamespaceApi, IBufferLine as IBufferLineApi, IBufferCell as IBufferCellApi, IParser, IFunctionIdentifier, ILinkProvider, IUnicodeHandling, IUnicodeVersionProvider, FontWeight } from 'xterm';
import { ITerminal } from 'browser/Types';
import { IBufferLine, ICellData } from 'common/Types';
import { IBuffer, IBufferSet } from 'common/buffer/Types';
@@ -13,11 +13,13 @@ import * as Strings from '../LocalizableStrings';
import { IEvent, EventEmitter } from 'common/EventEmitter';
import { AddonManager } from './AddonManager';
import { IParams } from 'common/parser/Types';
import { BufferSet } from 'common/buffer/BufferSet';
export class Terminal implements ITerminalApi {
private _core: ITerminal;
private _addonManager: AddonManager;
private _parser: IParser | undefined;
private _buffer: BufferNamespaceApi | undefined;
constructor(options?: ITerminalOptions) {
this._core = new TerminalCore(options);
@@ -36,6 +38,7 @@ export class Terminal implements ITerminalApi {
public get onData(): IEvent<string> { return this._core.onData; }
public get onBinary(): IEvent<string> { return this._core.onBinary; }
public get onTitleChange(): IEvent<string> { return this._core.onTitleChange; }
public get onBell(): IEvent<void> { return this._core.onBell; }
public get onScroll(): IEvent<number> { return this._core.onScroll; }
public get onKey(): IEvent<{ key: string, domEvent: KeyboardEvent }> { return this._core.onKey; }
public get onRender(): IEvent<{ start: number, end: number }> { return this._core.onRender; }
@@ -58,7 +61,10 @@ export class Terminal implements ITerminalApi {
public get cols(): number { return this._core.cols; }
public get buffer(): IBufferNamespaceApi {
this._checkProposedApi();
return new BufferNamespaceApi(this._core.buffers);
if (!this._buffer) {
this._buffer = new BufferNamespaceApi(this._core);
}
return this._buffer;
}
public get markers(): ReadonlyArray<IMarker> {
this._checkProposedApi();
@@ -169,19 +175,20 @@ export class Terminal implements ITerminalApi {
public paste(data: string): void {
this._core.paste(data);
}
public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'fontWeight' | 'fontWeightBold' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string;
public getOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'visualBell'): boolean;
public getOption(key: 'bellSound' | 'bellStyle' | 'cursorStyle' | 'fontFamily' | 'logLevel' | 'rendererType' | 'termName' | 'wordSeparator'): string;
public getOption(key: 'allowTransparency' | 'altClickMovesCursor' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'visualBell'): boolean;
public getOption(key: 'cols' | 'fontSize' | 'letterSpacing' | 'lineHeight' | 'rows' | 'tabStopWidth' | 'scrollback'): number;
public getOption(key: 'fontWeight' | 'fontWeightBold'): FontWeight;
public getOption(key: string): any;
public getOption(key: any): any {
return this._core.optionsService.getOption(key);
}
public setOption(key: 'bellSound' | 'fontFamily' | 'termName' | 'wordSeparator', value: string): void;
public setOption(key: 'fontWeight' | 'fontWeightBold', value: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900'): void;
public setOption(key: 'fontWeight' | 'fontWeightBold', value: 'normal' | 'bold' | '100' | '200' | '300' | '400' | '500' | '600' | '700' | '800' | '900' | number): void;
public setOption(key: 'logLevel', value: 'debug' | 'info' | 'warn' | 'error' | 'off'): void;
public setOption(key: 'bellStyle', value: 'none' | 'visual' | 'sound' | 'both'): void;
public setOption(key: 'cursorStyle', value: 'block' | 'underline' | 'bar'): void;
public setOption(key: 'allowTransparency' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'visualBell', value: boolean): void;
public setOption(key: 'allowTransparency' | 'altClickMovesCursor' | 'cancelEvents' | 'convertEol' | 'cursorBlink' | 'disableStdin' | 'macOptionIsMeta' | 'rightClickSelectsWord' | 'popOnBell' | 'visualBell', value: boolean): void;
public setOption(key: 'fontSize' | 'letterSpacing' | 'lineHeight' | 'tabStopWidth' | 'scrollback', value: number): void;
public setOption(key: 'theme', value: ITheme): void;
public setOption(key: 'cols' | 'rows', value: number): void;
@@ -244,21 +251,21 @@ class BufferNamespaceApi implements IBufferNamespaceApi {
private _onBufferChange = new EventEmitter<IBufferApi>();
public get onBufferChange(): IEvent<IBufferApi> { return this._onBufferChange.event; }
constructor(private _buffers: IBufferSet) {
this._normal = new BufferApiView(this._buffers.normal, 'normal');
this._alternate = new BufferApiView(this._buffers.alt, 'alternate');
this._buffers.onBufferActivate(() => this._onBufferChange.fire(this.active));
constructor(private _core: ITerminal) {
this._normal = new BufferApiView(this._core.buffers.normal, 'normal');
this._alternate = new BufferApiView(this._core.buffers.alt, 'alternate');
this._core.buffers.onBufferActivate(() => this._onBufferChange.fire(this.active));
}
public get active(): IBufferApi {
if (this._buffers.active === this._buffers.normal) { return this.normal; }
if (this._buffers.active === this._buffers.alt) { return this.alternate; }
if (this._core.buffers.active === this._core.buffers.normal) { return this.normal; }
if (this._core.buffers.active === this._core.buffers.alt) { return this.alternate; }
throw new Error('Active buffer is neither normal nor alternate');
}
public get normal(): IBufferApi {
return this._normal.init(this._buffers.normal);
return this._normal.init(this._core.buffers.normal);
}
public get alternate(): IBufferApi {
return this._alternate.init(this._buffers.alt);
return this._alternate.init(this._core.buffers.alt);
}
}
@@ -286,28 +293,28 @@ class BufferLineApiView implements IBufferLineApi {
class ParserApi implements IParser {
constructor(private _core: ITerminal) { }
public registerCsiHandler(id: IFunctionIdentifier, callback: (params: (number | number[])[]) => boolean): IDisposable {
return this._core.addCsiHandler(id, (params: IParams) => callback(params.toArray()));
public registerCsiHandler(id: IFunctionIdentifier, callback: (params: (number | number[])[]) => boolean | Promise<boolean>): IDisposable {
return this._core.registerCsiHandler(id, (params: IParams) => callback(params.toArray()));
}
public addCsiHandler(id: IFunctionIdentifier, callback: (params: (number | number[])[]) => boolean): IDisposable {
public addCsiHandler(id: IFunctionIdentifier, callback: (params: (number | number[])[]) => boolean | Promise<boolean>): IDisposable {
return this.registerCsiHandler(id, callback);
}
public registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: (number | number[])[]) => boolean): IDisposable {
return this._core.addDcsHandler(id, (data: string, params: IParams) => callback(data, params.toArray()));
public registerDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: (number | number[])[]) => boolean | Promise<boolean>): IDisposable {
return this._core.registerDcsHandler(id, (data: string, params: IParams) => callback(data, params.toArray()));
}
public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: (number | number[])[]) => boolean): IDisposable {
public addDcsHandler(id: IFunctionIdentifier, callback: (data: string, param: (number | number[])[]) => boolean | Promise<boolean>): IDisposable {
return this.registerDcsHandler(id, callback);
}
public registerEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable {
return this._core.addEscHandler(id, handler);
public registerEscHandler(id: IFunctionIdentifier, handler: () => boolean | Promise<boolean>): IDisposable {
return this._core.registerEscHandler(id, handler);
}
public addEscHandler(id: IFunctionIdentifier, handler: () => boolean): IDisposable {
public addEscHandler(id: IFunctionIdentifier, handler: () => boolean | Promise<boolean>): IDisposable {
return this.registerEscHandler(id, handler);
}
public registerOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
return this._core.addOscHandler(ident, callback);
public registerOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
return this._core.registerOscHandler(ident, callback);
}
public addOscHandler(ident: number, callback: (data: string) => boolean): IDisposable {
public addOscHandler(ident: number, callback: (data: string) => boolean | Promise<boolean>): IDisposable {
return this.registerOscHandler(ident, callback);
}
}
+5 -5
View File
@@ -66,7 +66,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
}
private _initCanvas(): void {
this._ctx = throwIfFalsy(this._canvas.getContext('2d', {alpha: this._alpha}));
this._ctx = throwIfFalsy(this._canvas.getContext('2d', { alpha: this._alpha }));
// Draw the background if this is an opaque layer
if (!this._alpha) {
this._clearAll();
@@ -242,12 +242,12 @@ export abstract class BaseRenderLayer implements IRenderLayer {
*/
protected _fillCharTrueColor(cell: CellData, x: number, y: number): void {
this._ctx.font = this._getFont(false, false);
this._ctx.textBaseline = 'middle';
this._ctx.textBaseline = 'ideographic';
this._clipRow(y);
this._ctx.fillText(
cell.getChars(),
x * this._scaledCellWidth + this._scaledCharLeft,
y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight / 2);
y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight);
}
/**
@@ -320,7 +320,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
private _drawUncachedChars(cell: ICellData, x: number, y: number, fgOverride?: IColor): void {
this._ctx.save();
this._ctx.font = this._getFont(!!cell.isBold(), !!cell.isItalic());
this._ctx.textBaseline = 'middle';
this._ctx.textBaseline = 'ideographic';
if (cell.isInverse()) {
if (fgOverride) {
@@ -362,7 +362,7 @@ export abstract class BaseRenderLayer implements IRenderLayer {
this._ctx.fillText(
cell.getChars(),
x * this._scaledCellWidth + this._scaledCharLeft,
y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight / 2);
y * this._scaledCellHeight + this._scaledCharTop + this._scaledCharHeight);
this._ctx.restore();
}
+4 -4
View File
@@ -37,10 +37,10 @@ export class CursorRenderLayer extends BaseRenderLayer {
colors: IColorSet,
rendererId: number,
private _onRequestRedraw: IEventEmitter<IRequestRedrawEvent>,
bufferService: IBufferService,
optionsService: IOptionsService,
private readonly _coreService: ICoreService,
private readonly _coreBrowserService: ICoreBrowserService
@IBufferService bufferService: IBufferService,
@IOptionsService optionsService: IOptionsService,
@ICoreService private readonly _coreService: ICoreService,
@ICoreBrowserService private readonly _coreBrowserService: ICoreBrowserService
) {
super(container, 'cursor', zIndex, true, colors, rendererId, bufferService, optionsService);
this._state = {
+2 -2
View File
@@ -20,8 +20,8 @@ export class LinkRenderLayer extends BaseRenderLayer {
rendererId: number,
linkifier: ILinkifier,
linkifier2: ILinkifier2,
bufferService: IBufferService,
optionsService: IOptionsService
@IBufferService bufferService: IBufferService,
@IOptionsService optionsService: IOptionsService
) {
super(container, 'link', zIndex, true, colors, rendererId, bufferService, optionsService);
linkifier.onShowLinkUnderline(e => this._onShowLinkUnderline(e));
+8 -20
View File
@@ -6,13 +6,12 @@
import { TextRenderLayer } from 'browser/renderer/TextRenderLayer';
import { SelectionRenderLayer } from 'browser/renderer/SelectionRenderLayer';
import { CursorRenderLayer } from 'browser/renderer/CursorRenderLayer';
import { IRenderLayer, IRenderer, IRenderDimensions, CharacterJoinerHandler, ICharacterJoinerRegistry, IRequestRedrawEvent } from 'browser/renderer/Types';
import { IRenderLayer, IRenderer, IRenderDimensions, IRequestRedrawEvent } from 'browser/renderer/Types';
import { LinkRenderLayer } from 'browser/renderer/LinkRenderLayer';
import { CharacterJoinerRegistry } from 'browser/renderer/CharacterJoinerRegistry';
import { Disposable } from 'common/Lifecycle';
import { IColorSet, ILinkifier, ILinkifier2 } from 'browser/Types';
import { ICharSizeService, ICoreBrowserService } from 'browser/services/Services';
import { IBufferService, IOptionsService, ICoreService } from 'common/services/Services';
import { IBufferService, IOptionsService, ICoreService, IInstantiationService } from 'common/services/Services';
import { removeTerminalFromCache } from 'browser/renderer/atlas/CharAtlasCache';
import { EventEmitter, IEvent } from 'common/EventEmitter';
@@ -23,7 +22,6 @@ export class Renderer extends Disposable implements IRenderer {
private _renderLayers: IRenderLayer[];
private _devicePixelRatio: number;
private _characterJoinerRegistry: ICharacterJoinerRegistry;
public dimensions: IRenderDimensions;
@@ -35,20 +33,18 @@ export class Renderer extends Disposable implements IRenderer {
private readonly _screenElement: HTMLElement,
linkifier: ILinkifier,
linkifier2: ILinkifier2,
@IInstantiationService instantiationService: IInstantiationService,
@IBufferService private readonly _bufferService: IBufferService,
@ICharSizeService private readonly _charSizeService: ICharSizeService,
@IOptionsService private readonly _optionsService: IOptionsService,
@ICoreService coreService: ICoreService,
@ICoreBrowserService coreBrowserService: ICoreBrowserService
@IOptionsService private readonly _optionsService: IOptionsService
) {
super();
const allowTransparency = this._optionsService.options.allowTransparency;
this._characterJoinerRegistry = new CharacterJoinerRegistry(this._bufferService);
this._renderLayers = [
new TextRenderLayer(this._screenElement, 0, this._colors, this._characterJoinerRegistry, allowTransparency, this._id, this._bufferService, _optionsService),
new SelectionRenderLayer(this._screenElement, 1, this._colors, this._id, this._bufferService, _optionsService),
new LinkRenderLayer(this._screenElement, 2, this._colors, this._id, linkifier, linkifier2, this._bufferService, _optionsService),
new CursorRenderLayer(this._screenElement, 3, this._colors, this._id, this._onRequestRedraw, this._bufferService, _optionsService, coreService, coreBrowserService)
instantiationService.createInstance(TextRenderLayer, this._screenElement, 0, this._colors, allowTransparency, this._id),
instantiationService.createInstance(SelectionRenderLayer, this._screenElement, 1, this._colors, this._id),
instantiationService.createInstance(LinkRenderLayer, this._screenElement, 2, this._colors, this._id, linkifier, linkifier2),
instantiationService.createInstance(CursorRenderLayer, this._screenElement, 3, this._colors, this._id, this._onRequestRedraw)
];
this.dimensions = {
scaledCharWidth: 0,
@@ -210,12 +206,4 @@ export class Renderer extends Disposable implements IRenderer {
this.dimensions.actualCellHeight = this.dimensions.canvasHeight / this._bufferService.rows;
this.dimensions.actualCellWidth = this.dimensions.canvasWidth / this._bufferService.cols;
}
public registerCharacterJoiner(handler: CharacterJoinerHandler): number {
return this._characterJoinerRegistry.registerCharacterJoiner(handler);
}
public deregisterCharacterJoiner(joinerId: number): boolean {
return this._characterJoinerRegistry.deregisterCharacterJoiner(joinerId);
}
}
+4 -3
View File
@@ -23,8 +23,8 @@ export class SelectionRenderLayer extends BaseRenderLayer {
zIndex: number,
colors: IColorSet,
rendererId: number,
bufferService: IBufferService,
optionsService: IOptionsService
@IBufferService bufferService: IBufferService,
@IOptionsService optionsService: IOptionsService
) {
super(container, 'selection', zIndex, true, colors, rendererId, bufferService, optionsService);
this._clearState();
@@ -75,6 +75,7 @@ export class SelectionRenderLayer extends BaseRenderLayer {
// No need to draw the selection
if (viewportCappedStartRow >= this._bufferService.rows || viewportCappedEndRow < 0) {
this._state.ydisp = this._bufferService.buffer.ydisp;
return;
}
@@ -88,7 +89,7 @@ export class SelectionRenderLayer extends BaseRenderLayer {
} else {
// Draw first row
const startCol = viewportStartRow === viewportCappedStartRow ? start[0] : 0;
const startRowEndCol = viewportCappedStartRow === viewportCappedEndRow ? end[0] : this._bufferService.cols;
const startRowEndCol = viewportCappedStartRow === viewportEndRow ? end[0] : this._bufferService.cols;
this._fillCells(startCol, viewportCappedStartRow, startRowEndCol - startCol, 1);
// Draw middle rows
+9 -12
View File
@@ -3,16 +3,17 @@
* @license MIT
*/
import { ICharacterJoinerRegistry, IRenderDimensions } from 'browser/renderer/Types';
import { IRenderDimensions } from 'browser/renderer/Types';
import { CharData, ICellData } from 'common/Types';
import { GridCache } from 'browser/renderer/GridCache';
import { BaseRenderLayer } from 'browser/renderer/BaseRenderLayer';
import { AttributeData } from 'common/buffer/AttributeData';
import { NULL_CELL_CODE, Content } from 'common/buffer/Constants';
import { JoinedCellData } from 'browser/renderer/CharacterJoinerRegistry';
import { IColorSet } from 'browser/Types';
import { CellData } from 'common/buffer/CellData';
import { IOptionsService, IBufferService } from 'common/services/Services';
import { ICharacterJoinerService } from 'browser/services/Services';
import { JoinedCellData } from 'browser/services/CharacterJoinerService';
/**
* This CharData looks like a null character, which will forc a clear and render
@@ -26,22 +27,20 @@ export class TextRenderLayer extends BaseRenderLayer {
private _characterWidth: number = 0;
private _characterFont: string = '';
private _characterOverlapCache: { [key: string]: boolean } = {};
private _characterJoinerRegistry: ICharacterJoinerRegistry;
private _workCell = new CellData();
constructor(
container: HTMLElement,
zIndex: number,
colors: IColorSet,
characterJoinerRegistry: ICharacterJoinerRegistry,
alpha: boolean,
rendererId: number,
bufferService: IBufferService,
optionsService: IOptionsService
@IBufferService bufferService: IBufferService,
@IOptionsService optionsService: IOptionsService,
@ICharacterJoinerService private readonly _characterJoinerService: ICharacterJoinerService
) {
super(container, 'text', zIndex, alpha, colors, rendererId, bufferService, optionsService);
this._state = new GridCache<CharData>();
this._characterJoinerRegistry = characterJoinerRegistry;
}
public resize(dim: IRenderDimensions): void {
@@ -67,7 +66,6 @@ export class TextRenderLayer extends BaseRenderLayer {
private _forEachCell(
firstRow: number,
lastRow: number,
joinerRegistry: ICharacterJoinerRegistry | null,
callback: (
cell: ICellData,
x: number,
@@ -77,7 +75,7 @@ export class TextRenderLayer extends BaseRenderLayer {
for (let y = firstRow; y <= lastRow; y++) {
const row = y + this._bufferService.buffer.ydisp;
const line = this._bufferService.buffer.lines.get(row);
const joinedRanges = joinerRegistry ? joinerRegistry.getJoinedCharacters(row) : [];
const joinedRanges = this._characterJoinerService.getJoinedCharacters(row);
for (let x = 0; x < this._bufferService.cols; x++) {
line!.loadCell(x, this._workCell);
let cell = this._workCell;
@@ -101,7 +99,6 @@ export class TextRenderLayer extends BaseRenderLayer {
// We already know the exact start and end column of the joined range,
// so we get the string and width representing it directly
cell = new JoinedCellData(
this._workCell,
line!.translateToString(true, range[0], range[1]),
@@ -160,7 +157,7 @@ export class TextRenderLayer extends BaseRenderLayer {
ctx.save();
this._forEachCell(firstRow, lastRow, null, (cell, x, y) => {
this._forEachCell(firstRow, lastRow, (cell, x, y) => {
// libvte and xterm both draw the background (but not foreground) of invisible characters,
// so we should too.
let nextFillStyle = null; // null represents default background color
@@ -213,7 +210,7 @@ export class TextRenderLayer extends BaseRenderLayer {
}
private _drawForeground(firstRow: number, lastRow: number): void {
this._forEachCell(firstRow, lastRow, this._characterJoinerRegistry, (cell, x, y) => {
this._forEachCell(firstRow, lastRow, (cell, x, y) => {
if (cell.isInvisible()) {
return;
}

Some files were not shown because too many files have changed in this diff Show More