@xterm/xterm 5.6.0-beta.9 → 5.6.0-beta.91

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +9 -3
  2. package/css/xterm.css +71 -4
  3. package/lib/xterm.js +1 -1
  4. package/lib/xterm.js.map +1 -1
  5. package/lib/xterm.mjs +53 -0
  6. package/lib/xterm.mjs.map +7 -0
  7. package/package.json +43 -33
  8. package/src/browser/AccessibilityManager.ts +53 -25
  9. package/src/browser/{Terminal.ts → CoreBrowserTerminal.ts} +139 -148
  10. package/src/browser/Linkifier.ts +26 -14
  11. package/src/browser/LocalizableStrings.ts +15 -4
  12. package/src/browser/{Types.d.ts → Types.ts} +67 -15
  13. package/src/browser/Viewport.ts +143 -370
  14. package/src/browser/decorations/BufferDecorationRenderer.ts +14 -9
  15. package/src/browser/decorations/OverviewRulerRenderer.ts +40 -44
  16. package/src/browser/input/CompositionHelper.ts +2 -1
  17. package/src/browser/public/Terminal.ts +25 -19
  18. package/src/browser/renderer/dom/DomRenderer.ts +19 -14
  19. package/src/browser/renderer/dom/DomRendererRowFactory.ts +35 -15
  20. package/src/browser/renderer/shared/CharAtlasCache.ts +3 -2
  21. package/src/browser/renderer/shared/CharAtlasUtils.ts +6 -1
  22. package/src/browser/renderer/shared/CustomGlyphs.ts +6 -0
  23. package/src/browser/renderer/shared/DevicePixelObserver.ts +1 -2
  24. package/src/browser/renderer/shared/TextureAtlas.ts +45 -12
  25. package/src/browser/renderer/shared/{Types.d.ts → Types.ts} +7 -6
  26. package/src/browser/services/CharSizeService.ts +6 -6
  27. package/src/browser/services/CoreBrowserService.ts +15 -15
  28. package/src/browser/services/LinkProviderService.ts +2 -2
  29. package/src/browser/services/RenderService.ts +20 -20
  30. package/src/browser/services/SelectionService.ts +8 -8
  31. package/src/browser/services/Services.ts +13 -13
  32. package/src/browser/services/ThemeService.ts +19 -58
  33. package/src/browser/shared/Constants.ts +8 -0
  34. package/src/common/CircularList.ts +5 -5
  35. package/src/common/CoreTerminal.ts +35 -41
  36. package/src/common/InputHandler.ts +63 -51
  37. package/src/common/{Types.d.ts → Types.ts} +13 -17
  38. package/src/common/buffer/Buffer.ts +15 -7
  39. package/src/common/buffer/BufferReflow.ts +9 -6
  40. package/src/common/buffer/BufferSet.ts +5 -5
  41. package/src/common/buffer/Marker.ts +4 -4
  42. package/src/common/buffer/{Types.d.ts → Types.ts} +2 -2
  43. package/src/common/input/WriteBuffer.ts +3 -3
  44. package/src/common/parser/EscapeSequenceParser.ts +4 -4
  45. package/src/common/public/BufferNamespaceApi.ts +3 -3
  46. package/src/common/services/BufferService.ts +7 -7
  47. package/src/common/services/CoreMouseService.ts +5 -3
  48. package/src/common/services/CoreService.ts +8 -6
  49. package/src/common/services/DecorationService.ts +8 -9
  50. package/src/common/services/InstantiationService.ts +1 -1
  51. package/src/common/services/LogService.ts +2 -2
  52. package/src/common/services/OptionsService.ts +7 -6
  53. package/src/common/services/ServiceRegistry.ts +1 -1
  54. package/src/common/services/Services.ts +26 -17
  55. package/src/common/services/UnicodeService.ts +2 -2
  56. package/src/vs/base/browser/browser.ts +141 -0
  57. package/src/vs/base/browser/canIUse.ts +49 -0
  58. package/src/vs/base/browser/dom.ts +2369 -0
  59. package/src/vs/base/browser/fastDomNode.ts +316 -0
  60. package/src/vs/base/browser/globalPointerMoveMonitor.ts +112 -0
  61. package/src/vs/base/browser/iframe.ts +135 -0
  62. package/src/vs/base/browser/keyboardEvent.ts +213 -0
  63. package/src/vs/base/browser/mouseEvent.ts +229 -0
  64. package/src/vs/base/browser/touch.ts +372 -0
  65. package/src/vs/base/browser/ui/scrollbar/abstractScrollbar.ts +303 -0
  66. package/src/vs/base/browser/ui/scrollbar/horizontalScrollbar.ts +114 -0
  67. package/src/vs/base/browser/ui/scrollbar/scrollableElement.ts +720 -0
  68. package/src/vs/base/browser/ui/scrollbar/scrollableElementOptions.ts +165 -0
  69. package/src/vs/base/browser/ui/scrollbar/scrollbarArrow.ts +114 -0
  70. package/src/vs/base/browser/ui/scrollbar/scrollbarState.ts +243 -0
  71. package/src/vs/base/browser/ui/scrollbar/scrollbarVisibilityController.ts +118 -0
  72. package/src/vs/base/browser/ui/scrollbar/verticalScrollbar.ts +116 -0
  73. package/src/vs/base/browser/ui/widget.ts +57 -0
  74. package/src/vs/base/browser/window.ts +14 -0
  75. package/src/vs/base/common/arrays.ts +887 -0
  76. package/src/vs/base/common/arraysFind.ts +202 -0
  77. package/src/vs/base/common/assert.ts +71 -0
  78. package/src/vs/base/common/async.ts +1992 -0
  79. package/src/vs/base/common/cancellation.ts +148 -0
  80. package/src/vs/base/common/charCode.ts +450 -0
  81. package/src/vs/base/common/collections.ts +140 -0
  82. package/src/vs/base/common/decorators.ts +130 -0
  83. package/src/vs/base/common/equals.ts +146 -0
  84. package/src/vs/base/common/errors.ts +303 -0
  85. package/src/vs/base/common/event.ts +1778 -0
  86. package/src/vs/base/common/functional.ts +32 -0
  87. package/src/vs/base/common/hash.ts +316 -0
  88. package/src/vs/base/common/iterator.ts +159 -0
  89. package/src/vs/base/common/keyCodes.ts +526 -0
  90. package/src/vs/base/common/keybindings.ts +284 -0
  91. package/src/vs/base/common/lazy.ts +47 -0
  92. package/src/vs/base/common/lifecycle.ts +801 -0
  93. package/src/vs/base/common/linkedList.ts +142 -0
  94. package/src/vs/base/common/map.ts +202 -0
  95. package/src/vs/base/common/numbers.ts +98 -0
  96. package/src/vs/base/common/observable.ts +76 -0
  97. package/src/vs/base/common/observableInternal/api.ts +31 -0
  98. package/src/vs/base/common/observableInternal/autorun.ts +281 -0
  99. package/src/vs/base/common/observableInternal/base.ts +489 -0
  100. package/src/vs/base/common/observableInternal/debugName.ts +145 -0
  101. package/src/vs/base/common/observableInternal/derived.ts +428 -0
  102. package/src/vs/base/common/observableInternal/lazyObservableValue.ts +146 -0
  103. package/src/vs/base/common/observableInternal/logging.ts +328 -0
  104. package/src/vs/base/common/observableInternal/promise.ts +209 -0
  105. package/src/vs/base/common/observableInternal/utils.ts +610 -0
  106. package/src/vs/base/common/platform.ts +281 -0
  107. package/src/vs/base/common/scrollable.ts +522 -0
  108. package/src/vs/base/common/sequence.ts +34 -0
  109. package/src/vs/base/common/stopwatch.ts +43 -0
  110. package/src/vs/base/common/strings.ts +557 -0
  111. package/src/vs/base/common/symbols.ts +9 -0
  112. package/src/vs/base/common/uint.ts +59 -0
  113. package/src/vs/patches/nls.ts +90 -0
  114. package/src/vs/typings/base-common.d.ts +20 -0
  115. package/src/vs/typings/require.d.ts +42 -0
  116. package/src/vs/typings/thenable.d.ts +12 -0
  117. package/src/vs/typings/vscode-globals-nls.d.ts +36 -0
  118. package/src/vs/typings/vscode-globals-product.d.ts +33 -0
  119. package/typings/xterm.d.ts +66 -15
  120. package/src/browser/Lifecycle.ts +0 -33
  121. package/src/common/EventEmitter.ts +0 -78
  122. package/src/common/Lifecycle.ts +0 -108
  123. /package/src/browser/selection/{Types.d.ts → Types.ts} +0 -0
  124. /package/src/common/parser/{Types.d.ts → Types.ts} +0 -0
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@xterm/xterm",
3
3
  "description": "Full xterm terminal, in your browser",
4
- "version": "5.6.0-beta.9",
4
+ "version": "5.6.0-beta.91",
5
5
  "main": "lib/xterm.js",
6
+ "module": "lib/xterm.mjs",
6
7
  "style": "css/xterm.css",
7
8
  "types": "typings/xterm.d.ts",
8
9
  "repository": "https://github.com/xtermjs/xterm.js",
@@ -23,44 +24,50 @@
23
24
  "xterm"
24
25
  ],
25
26
  "scripts": {
26
- "prepackage": "npm run build",
27
- "package": "webpack",
28
- "package-headless": "webpack --config ./webpack.config.headless.js",
29
- "postpackage-headless": "node ./bin/package_headless.js",
27
+ "setup": "npm run build",
28
+ "presetup": "npm run install-addons",
29
+ "install-addons": "node ./bin/install-addons.js",
30
30
  "start": "node demo/start",
31
- "start-server-only": "node demo/start-server-only",
32
- "build-demo": "webpack --config ./demo/webpack.config.js",
33
- "lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/",
34
- "lint-api": "eslint --no-eslintrc -c .eslintrc.json.typings --max-warnings 0 --no-ignore --ext .d.ts typings/",
31
+ "build": "npm run tsc",
32
+ "watch": "npm run tsc-watch",
33
+ "tsc": "tsc -b ./tsconfig.all.json",
34
+ "tsc-watch": "tsc -b -w ./tsconfig.all.json --preserveWatchOutput",
35
+ "esbuild": "node bin/esbuild_all.mjs",
36
+ "esbuild-watch": "node bin/esbuild_all.mjs --watch",
37
+ "esbuild-package": "node bin/esbuild_all.mjs --prod",
38
+ "esbuild-package-watch": "node bin/esbuild_all.mjs --prod --watch",
39
+ "esbuild-package-headless-only": "node bin/esbuild.mjs --prod --headless",
40
+ "esbuild-demo": "node bin/esbuild.mjs --demo-client",
41
+ "esbuild-demo-watch": "node bin/esbuild.mjs --demo-client --watch",
35
42
  "test": "npm run test-unit",
36
43
  "posttest": "npm run lint",
37
- "test-api": "npm run test-api-chromium",
38
- "test-api-chromium": "node ./bin/test_api.js --browser=chromium --timeout=20000",
39
- "test-api-firefox": "node ./bin/test_api.js --browser=firefox --timeout=20000",
40
- "test-api-webkit": "node ./bin/test_api.js --browser=webkit --timeout=20000",
41
- "test-playwright": "node ./bin/test_playwright.js --workers=75%",
42
- "test-playwright-chromium": "node ./bin/test_playwright.js --workers=75% \"--project=Chrome Stable\"",
43
- "test-playwright-firefox": "node ./bin/test_playwright.js --workers=75% \"--project=Firefox Stable\"",
44
- "test-playwright-webkit": "node ./bin/test_playwright.js --workers=75% \"--project=WebKit\"",
45
- "test-playwright-debug": "node ./bin/test_playwright.js --workers=1 --headed --timeout=30000",
46
- "test-unit": "node ./bin/test.js",
47
- "test-unit-coverage": "node ./bin/test.js --coverage",
44
+ "lint": "eslint -c .eslintrc.json --max-warnings 0 --ext .ts src/ addons/",
45
+ "lint-api": "eslint --no-eslintrc -c .eslintrc.json.typings --max-warnings 0 --no-ignore --ext .d.ts typings/",
46
+ "test-unit": "node ./bin/test_unit.js",
47
+ "test-unit-coverage": "node ./bin/test_unit.js --coverage",
48
48
  "test-unit-dev": "cross-env NODE_PATH='./out' mocha",
49
- "build": "tsc -b ./tsconfig.all.json",
50
- "install-addons": "node ./bin/install-addons.js",
51
- "presetup": "npm run install-addons",
52
- "setup": "npm run build",
53
- "prepublishOnly": "npm run package",
54
- "watch": "tsc -b -w ./tsconfig.all.json --preserveWatchOutput",
49
+ "test-integration": "node ./bin/test_integration.js --workers=75%",
50
+ "test-integration-chromium": "node ./bin/test_integration.js --workers=75% \"--project=ChromeStable\"",
51
+ "test-integration-firefox": "node ./bin/test_integration.js --workers=75% \"--project=FirefoxStable\"",
52
+ "test-integration-webkit": "node ./bin/test_integration.js --workers=75% \"--project=WebKit\"",
53
+ "test-integration-debug": "node ./bin/test_integration.js --workers=1 --headed --timeout=30000",
55
54
  "benchmark": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json",
56
- "benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/test/benchmark/*benchmark.js",
57
- "benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/test/benchmark/*benchmark.js",
55
+ "benchmark-baseline": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --baseline out-test/benchmark/*benchmark.js",
56
+ "benchmark-eval": "NODE_PATH=./out xterm-benchmark -r 5 -c test/benchmark/benchmark.json --eval out-test/benchmark/*benchmark.js",
58
57
  "clean": "rm -rf lib out addons/*/lib addons/*/out",
59
- "vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts"
58
+ "vtfeatures": "node bin/extract_vtfeatures.js src/**/*.ts src/*.ts",
59
+ "prepackage": "npm run build",
60
+ "package": "webpack",
61
+ "postpackage": "npm run esbuild-package",
62
+ "prepackage-headless": "npm run esbuild-package-headless-only",
63
+ "package-headless": "webpack --config ./webpack.config.headless.js",
64
+ "postpackage-headless": "node ./bin/package_headless.js",
65
+ "prepublishOnly": "npm run package"
60
66
  },
61
67
  "devDependencies": {
62
68
  "@lunapaint/png-codec": "^0.2.0",
63
69
  "@playwright/test": "^1.37.1",
70
+ "@stylistic/eslint-plugin": "^2.3.0",
64
71
  "@types/chai": "^4.2.22",
65
72
  "@types/debug": "^4.1.7",
66
73
  "@types/deep-equal": "^1.0.1",
@@ -70,6 +77,7 @@
70
77
  "@types/jsdom": "^16.2.13",
71
78
  "@types/mocha": "^9.0.0",
72
79
  "@types/node": "^18.16.0",
80
+ "@types/trusted-types": "^1.0.6",
73
81
  "@types/utf8": "^3.0.0",
74
82
  "@types/webpack": "^5.28.0",
75
83
  "@types/ws": "^8.2.0",
@@ -78,24 +86,26 @@
78
86
  "chai": "^4.3.4",
79
87
  "cross-env": "^7.0.3",
80
88
  "deep-equal": "^2.0.5",
89
+ "esbuild": "^0.23.0",
81
90
  "eslint": "^8.56.0",
82
91
  "eslint-plugin-jsdoc": "^46.9.1",
83
- "express": "^4.17.1",
92
+ "express": "^4.19.2",
84
93
  "express-ws": "^5.0.2",
85
94
  "glob": "^7.2.0",
86
95
  "jsdom": "^18.0.1",
87
96
  "mocha": "^10.1.0",
88
97
  "mustache": "^4.2.0",
89
- "node-pty": "1.1.0-beta5",
98
+ "node-pty": "1.1.0-beta19",
90
99
  "nyc": "^15.1.0",
91
100
  "source-map-loader": "^3.0.0",
92
101
  "source-map-support": "^0.5.20",
93
102
  "ts-loader": "^9.3.1",
94
- "typescript": "^5.1.6",
103
+ "typescript": "5.5",
95
104
  "utf8": "^3.0.0",
96
105
  "webpack": "^5.61.0",
97
106
  "webpack-cli": "^4.9.1",
98
107
  "ws": "^8.2.3",
99
108
  "xterm-benchmark": "^0.3.1"
100
- }
109
+ },
110
+ "commit": "ef4a3fd933c003df868b70d963d73486973f084b"
101
111
  }
@@ -6,11 +6,11 @@
6
6
  import * as Strings from 'browser/LocalizableStrings';
7
7
  import { ITerminal, IRenderDebouncer } from 'browser/Types';
8
8
  import { TimeBasedDebouncer } from 'browser/TimeBasedDebouncer';
9
- import { Disposable, toDisposable } from 'common/Lifecycle';
9
+ import { Disposable, toDisposable } from 'vs/base/common/lifecycle';
10
10
  import { ICoreBrowserService, IRenderService } from 'browser/services/Services';
11
11
  import { IBuffer } from 'common/buffer/Types';
12
12
  import { IInstantiationService } from 'common/services/Services';
13
- import { addDisposableDomListener } from 'browser/Lifecycle';
13
+ import { addDisposableListener } from 'vs/base/browser/dom';
14
14
 
15
15
  const MAX_ROWS_TO_READ = 20;
16
16
 
@@ -58,10 +58,11 @@ export class AccessibilityManager extends Disposable {
58
58
  @IRenderService private readonly _renderService: IRenderService
59
59
  ) {
60
60
  super();
61
- this._accessibilityContainer = this._coreBrowserService.mainDocument.createElement('div');
61
+ const doc = this._coreBrowserService.mainDocument;
62
+ this._accessibilityContainer = doc.createElement('div');
62
63
  this._accessibilityContainer.classList.add('xterm-accessibility');
63
64
 
64
- this._rowContainer = this._coreBrowserService.mainDocument.createElement('div');
65
+ this._rowContainer = doc.createElement('div');
65
66
  this._rowContainer.setAttribute('role', 'list');
66
67
  this._rowContainer.classList.add('xterm-accessibility-tree');
67
68
  this._rowElements = [];
@@ -75,14 +76,13 @@ export class AccessibilityManager extends Disposable {
75
76
  this._rowElements[0].addEventListener('focus', this._topBoundaryFocusListener);
76
77
  this._rowElements[this._rowElements.length - 1].addEventListener('focus', this._bottomBoundaryFocusListener);
77
78
 
78
- this._refreshRowsDimensions();
79
79
  this._accessibilityContainer.appendChild(this._rowContainer);
80
80
 
81
- this._liveRegion = this._coreBrowserService.mainDocument.createElement('div');
81
+ this._liveRegion = doc.createElement('div');
82
82
  this._liveRegion.classList.add('live-region');
83
83
  this._liveRegion.setAttribute('aria-live', 'assertive');
84
84
  this._accessibilityContainer.appendChild(this._liveRegion);
85
- this._liveRegionDebouncer = this.register(new TimeBasedDebouncer(this._renderRows.bind(this)));
85
+ this._liveRegionDebouncer = this._register(new TimeBasedDebouncer(this._renderRows.bind(this)));
86
86
 
87
87
  if (!this._terminal.element) {
88
88
  throw new Error('Cannot enable accessibility before Terminal.open');
@@ -93,33 +93,34 @@ export class AccessibilityManager extends Disposable {
93
93
  this._rowContainer.classList.add('debug');
94
94
 
95
95
  // Use a `<div class="xterm">` container so that the css will still apply.
96
- this._debugRootContainer = document.createElement('div');
96
+ this._debugRootContainer = doc.createElement('div');
97
97
  this._debugRootContainer.classList.add('xterm');
98
98
 
99
- this._debugRootContainer.appendChild(document.createTextNode('------start a11y------'));
99
+ this._debugRootContainer.appendChild(doc.createTextNode('------start a11y------'));
100
100
  this._debugRootContainer.appendChild(this._accessibilityContainer);
101
- this._debugRootContainer.appendChild(document.createTextNode('------end a11y------'));
101
+ this._debugRootContainer.appendChild(doc.createTextNode('------end a11y------'));
102
102
 
103
103
  this._terminal.element.insertAdjacentElement('afterend', this._debugRootContainer);
104
104
  } else {
105
105
  this._terminal.element.insertAdjacentElement('afterbegin', this._accessibilityContainer);
106
106
  }
107
107
 
108
- this.register(this._terminal.onResize(e => this._handleResize(e.rows)));
109
- this.register(this._terminal.onRender(e => this._refreshRows(e.start, e.end)));
110
- this.register(this._terminal.onScroll(() => this._refreshRows()));
108
+ this._register(this._terminal.onResize(e => this._handleResize(e.rows)));
109
+ this._register(this._terminal.onRender(e => this._refreshRows(e.start, e.end)));
110
+ this._register(this._terminal.onScroll(() => this._refreshRows()));
111
111
  // Line feed is an issue as the prompt won't be read out after a command is run
112
- this.register(this._terminal.onA11yChar(char => this._handleChar(char)));
113
- this.register(this._terminal.onLineFeed(() => this._handleChar('\n')));
114
- this.register(this._terminal.onA11yTab(spaceCount => this._handleTab(spaceCount)));
115
- this.register(this._terminal.onKey(e => this._handleKey(e.key)));
116
- this.register(this._terminal.onBlur(() => this._clearLiveRegion()));
117
- this.register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions()));
118
- this.register(addDisposableDomListener(document, 'selectionchange', () => this._handleSelectionChange()));
119
- this.register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions()));
112
+ this._register(this._terminal.onA11yChar(char => this._handleChar(char)));
113
+ this._register(this._terminal.onLineFeed(() => this._handleChar('\n')));
114
+ this._register(this._terminal.onA11yTab(spaceCount => this._handleTab(spaceCount)));
115
+ this._register(this._terminal.onKey(e => this._handleKey(e.key)));
116
+ this._register(this._terminal.onBlur(() => this._clearLiveRegion()));
117
+ this._register(this._renderService.onDimensionsChange(() => this._refreshRowsDimensions()));
118
+ this._register(addDisposableListener(doc, 'selectionchange', () => this._handleSelectionChange()));
119
+ this._register(this._coreBrowserService.onDprChange(() => this._refreshRowsDimensions()));
120
120
 
121
+ this._refreshRowsDimensions();
121
122
  this._refreshRows();
122
- this.register(toDisposable(() => {
123
+ this._register(toDisposable(() => {
123
124
  if (DEBUG) {
124
125
  this._debugRootContainer!.remove();
125
126
  } else {
@@ -150,7 +151,7 @@ export class AccessibilityManager extends Disposable {
150
151
  if (char === '\n') {
151
152
  this._liveRegionLineCount++;
152
153
  if (this._liveRegionLineCount === MAX_ROWS_TO_READ + 1) {
153
- this._liveRegion.textContent += Strings.tooMuchOutput;
154
+ this._liveRegion.textContent += Strings.tooMuchOutput.get();
154
155
  }
155
156
  }
156
157
  }
@@ -192,6 +193,7 @@ export class AccessibilityManager extends Disposable {
192
193
  }
193
194
  element.setAttribute('aria-posinset', posInSet);
194
195
  element.setAttribute('aria-setsize', setSize);
196
+ this._alignRowWidth(element);
195
197
  }
196
198
  }
197
199
  this._announceCharacters();
@@ -270,7 +272,7 @@ export class AccessibilityManager extends Disposable {
270
272
  return;
271
273
  }
272
274
 
273
- const selection = document.getSelection();
275
+ const selection = this._coreBrowserService.mainDocument.getSelection();
274
276
  if (!selection) {
275
277
  return;
276
278
  }
@@ -389,19 +391,45 @@ export class AccessibilityManager extends Disposable {
389
391
  this._refreshRowDimensions(element);
390
392
  return element;
391
393
  }
394
+
392
395
  private _refreshRowsDimensions(): void {
393
396
  if (!this._renderService.dimensions.css.cell.height) {
394
397
  return;
395
398
  }
396
- this._accessibilityContainer.style.width = `${this._renderService.dimensions.css.canvas.width}px`;
399
+ Object.assign(this._accessibilityContainer.style, {
400
+ width: `${this._renderService.dimensions.css.canvas.width}px`,
401
+ fontSize: `${this._terminal.options.fontSize}px`
402
+ });
397
403
  if (this._rowElements.length !== this._terminal.rows) {
398
404
  this._handleResize(this._terminal.rows);
399
405
  }
400
406
  for (let i = 0; i < this._terminal.rows; i++) {
401
407
  this._refreshRowDimensions(this._rowElements[i]);
408
+ this._alignRowWidth(this._rowElements[i]);
402
409
  }
403
410
  }
411
+
404
412
  private _refreshRowDimensions(element: HTMLElement): void {
405
413
  element.style.height = `${this._renderService.dimensions.css.cell.height}px`;
406
414
  }
415
+
416
+ /**
417
+ * Scale the width of a row so that each of the character is (mostly) aligned
418
+ * with the actual rendering. This will allow the screen reader to draw
419
+ * selection outline at the correct position.
420
+ *
421
+ * On top of using the "monospace" font and correct font size, the scaling
422
+ * here is necessary to handle characters that are not covered by the font
423
+ * (e.g. CJK).
424
+ */
425
+ private _alignRowWidth(element: HTMLElement): void {
426
+ element.style.transform = '';
427
+ const width = element.getBoundingClientRect().width;
428
+ const lastColumn = this._rowColumns.get(element)?.slice(-1)?.[0];
429
+ if (!lastColumn) {
430
+ return;
431
+ }
432
+ const targetWidth = lastColumn * this._renderService.dimensions.css.cell.width;
433
+ element.style.transform = `scaleX(${targetWidth / width})`;
434
+ }
407
435
  }