monaco-editor 0.56.0-dev-20260119 → 0.56.0-dev-20260121

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 (143) hide show
  1. package/dev/vs/basic-languages/monaco.contribution.js +18 -18
  2. package/dev/vs/{cssMode-VP5J4n2d.js → cssMode-B0VkNrib.js} +1 -1
  3. package/dev/vs/editor/editor.main.css +42 -25
  4. package/dev/vs/editor/editor.main.js +1 -1
  5. package/dev/vs/{editor-ML6zs6Go.js → editor-CR18QzPP.js} +633 -162
  6. package/dev/vs/editor.js +1 -1
  7. package/dev/vs/{freemarker2-DOuHb9T9.js → freemarker2-Byr9HmH9.js} +1 -1
  8. package/dev/vs/{handlebars-CEHZxVsE.js → handlebars-BEVXeROF.js} +1 -1
  9. package/dev/vs/{html-CHMe_cBk.js → html-CetHjWIf.js} +1 -1
  10. package/dev/vs/{htmlMode-D7MQf6Yp.js → htmlMode-BNKYUVNo.js} +1 -1
  11. package/dev/vs/{index-KO0Jv4kb.js → index-g_7JbDIY.js} +1 -1
  12. package/dev/vs/index.js +1 -1
  13. package/dev/vs/{javascript-hfXEMgFg.js → javascript-BEgEU725.js} +1 -1
  14. package/dev/vs/{jsonMode-Dp9qexJG.js → jsonMode-CT2UkfFE.js} +1 -1
  15. package/dev/vs/language/css/monaco.contribution.js +1 -1
  16. package/dev/vs/language/html/monaco.contribution.js +1 -1
  17. package/dev/vs/language/json/monaco.contribution.js +1 -1
  18. package/dev/vs/language/typescript/monaco.contribution.js +1 -1
  19. package/dev/vs/{liquid-C5xy2cvN.js → liquid-D-aiCb1P.js} +1 -1
  20. package/dev/vs/{lspLanguageFeatures-D6ykJL1B.js → lspLanguageFeatures-CE9Occyu.js} +1 -1
  21. package/dev/vs/{mdx-DTsW_-Y_.js → mdx-DchJ8pbq.js} +1 -1
  22. package/dev/vs/{monaco.contribution-DuzmV_VZ.js → monaco.contribution-CHqb1dWh.js} +2 -2
  23. package/dev/vs/{monaco.contribution-t7Hz4wVA.js → monaco.contribution-CVBrIlxn.js} +2 -2
  24. package/dev/vs/{monaco.contribution-CcoogmES.js → monaco.contribution-CZxuzvA9.js} +2 -2
  25. package/dev/vs/{monaco.contribution-CQ8dNY-Q.js → monaco.contribution-Cw4OdERZ.js} +2 -2
  26. package/dev/vs/nls/lang/cs.js +1 -1
  27. package/dev/vs/nls/lang/de.js +1 -1
  28. package/dev/vs/nls/lang/es.js +1 -1
  29. package/dev/vs/nls/lang/fr.js +1 -1
  30. package/dev/vs/nls/lang/it.js +1 -1
  31. package/dev/vs/nls/lang/ja.js +1 -1
  32. package/dev/vs/nls/lang/ko.js +1 -1
  33. package/dev/vs/nls/lang/pl.js +1 -1
  34. package/dev/vs/nls/lang/pt-br.js +1 -1
  35. package/dev/vs/nls/lang/ru.js +1 -1
  36. package/dev/vs/nls/lang/tr.js +1 -1
  37. package/dev/vs/nls/lang/zh-cn.js +1 -1
  38. package/dev/vs/nls/lang/zh-tw.js +1 -1
  39. package/dev/vs/{python-1ZtmJ8bh.js → python-BCOSaCC8.js} +1 -1
  40. package/dev/vs/{razor-D7Pdon_S.js → razor-BM2tZCwj.js} +1 -1
  41. package/dev/vs/{toggleHighContrast-Btd2ryZF.js → toggleHighContrast-CLgtrrIB.js} +148 -315
  42. package/dev/vs/{tsMode-Dy3ckMs8.js → tsMode-jpkv3SbL.js} +1 -1
  43. package/dev/vs/{typescript-BBL8N09V.js → typescript-f8pt88eA.js} +1 -1
  44. package/dev/vs/{workers-B9Ao1ciR.js → workers-zrUx_2Gw.js} +1 -1
  45. package/dev/vs/{xml-7BH7GgP4.js → xml-CmSjtiR0.js} +1 -1
  46. package/dev/vs/{yaml-DvwGvgS8.js → yaml-PRriLGdw.js} +1 -1
  47. package/esm/vs/base/browser/markdownRenderer.js +1 -0
  48. package/esm/vs/base/browser/ui/actionbar/actionViewItems.js +4 -1
  49. package/esm/vs/base/browser/ui/actionbar/actionbar.css +8 -5
  50. package/esm/vs/base/browser/ui/contextview/contextview.js +1 -1
  51. package/esm/vs/base/browser/ui/list/list.js +2 -1
  52. package/esm/vs/base/browser/ui/list/listWidget.js +62 -5
  53. package/esm/vs/base/browser/ui/tree/abstractTree.js +4 -1
  54. package/esm/vs/base/browser/ui/tree/asyncDataTree.js +4 -1
  55. package/esm/vs/editor/browser/controller/editContext/clipboardUtils.js +81 -35
  56. package/esm/vs/editor/browser/controller/editContext/editContext.js +11 -0
  57. package/esm/vs/editor/browser/controller/editContext/native/nativeEditContext.js +38 -18
  58. package/esm/vs/editor/browser/controller/editContext/textArea/textAreaEditContext.js +4 -0
  59. package/esm/vs/editor/browser/controller/editContext/textArea/textAreaEditContextInput.js +39 -16
  60. package/esm/vs/editor/browser/dataTransfer.js +1 -1
  61. package/esm/vs/editor/browser/view.js +21 -1
  62. package/esm/vs/editor/browser/widget/codeEditor/codeEditorWidget.js +18 -0
  63. package/esm/vs/editor/common/model/bracketPairsTextModelPart/colorizedBracketPairsDecorationProvider.js +3 -3
  64. package/esm/vs/editor/common/model/textModel.js +7 -5
  65. package/esm/vs/editor/common/model/tokens/tokenizationFontDecorationsProvider.js +21 -17
  66. package/esm/vs/editor/common/viewModel/viewModelDecorations.js +11 -4
  67. package/esm/vs/editor/common/viewModel/viewModelImpl.js +25 -14
  68. package/esm/vs/editor/contrib/clipboard/browser/clipboard.js +3 -3
  69. package/esm/vs/editor/contrib/dropOrPasteInto/browser/copyPasteController.js +28 -64
  70. package/esm/vs/editor/contrib/floatingMenu/browser/floatingMenu.css +27 -20
  71. package/esm/vs/editor/contrib/floatingMenu/browser/floatingMenu.js +37 -9
  72. package/esm/vs/editor/contrib/inlineCompletions/browser/model/inlineCompletionsModel.js +2 -2
  73. package/esm/vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.css +7 -0
  74. package/esm/vs/editor/contrib/inlineCompletions/browser/view/ghostText/ghostTextView.js +22 -3
  75. package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineEdits/components/gutterIndicatorView.js +20 -14
  76. package/esm/vs/editor/contrib/inlineCompletions/browser/view/inlineSuggestionsView.js +1 -0
  77. package/esm/vs/editor/editor.api.d.ts +5 -1
  78. package/esm/vs/nls/lang/cs.js +1 -1
  79. package/esm/vs/nls/lang/de.js +1 -1
  80. package/esm/vs/nls/lang/es.js +1 -1
  81. package/esm/vs/nls/lang/fr.js +1 -1
  82. package/esm/vs/nls/lang/it.js +1 -1
  83. package/esm/vs/nls/lang/ja.js +1 -1
  84. package/esm/vs/nls/lang/ko.js +1 -1
  85. package/esm/vs/nls/lang/pl.js +1 -1
  86. package/esm/vs/nls/lang/pt-br.js +1 -1
  87. package/esm/vs/nls/lang/ru.js +1 -1
  88. package/esm/vs/nls/lang/tr.js +1 -1
  89. package/esm/vs/nls/lang/zh-cn.js +1 -1
  90. package/esm/vs/nls/lang/zh-tw.js +1 -1
  91. package/esm/vs/platform/actionWidget/browser/actionList.js +46 -6
  92. package/esm/vs/platform/actionWidget/browser/actionWidget.js +9 -2
  93. package/esm/vs/platform/actions/common/actions.js +2 -1
  94. package/esm/vs/platform/hover/browser/hoverService.js +1 -0
  95. package/esm/vs/platform/product/common/product.js +16 -1
  96. package/min/vs/basic-languages/monaco.contribution.js +1 -1
  97. package/min/vs/{cssMode-CxJ_Cr_Z.js → cssMode-CheCY05R.js} +1 -1
  98. package/min/vs/editor/editor.main.css +1 -1
  99. package/min/vs/editor/editor.main.js +1 -1
  100. package/min/vs/{editor-CyVlw8K4.js → editor-DxYWA3-X.js} +112 -110
  101. package/min/vs/editor.js +1 -1
  102. package/min/vs/{freemarker2-CJcSu3nc.js → freemarker2-C7J7V1Hp.js} +1 -1
  103. package/min/vs/{handlebars-DPLjS6oj.js → handlebars-DsCar5Ix.js} +1 -1
  104. package/min/vs/{html-DUmbFRY-.js → html-BGLIaUZV.js} +1 -1
  105. package/min/vs/{htmlMode-DfUvYWkE.js → htmlMode-BB6WOoy3.js} +1 -1
  106. package/min/vs/{index-DOycyDud.js → index-BdR0nSqf.js} +1 -1
  107. package/min/vs/index.js +1 -1
  108. package/min/vs/{javascript-CQpB78Gy.js → javascript-CXE3i1eX.js} +1 -1
  109. package/min/vs/{jsonMode-B1E1R3KS.js → jsonMode-rtaE9alu.js} +1 -1
  110. package/min/vs/language/css/monaco.contribution.js +1 -1
  111. package/min/vs/language/html/monaco.contribution.js +1 -1
  112. package/min/vs/language/json/monaco.contribution.js +1 -1
  113. package/min/vs/language/typescript/monaco.contribution.js +1 -1
  114. package/min/vs/{liquid-Bh_nhvai.js → liquid-CEdn0ovR.js} +1 -1
  115. package/min/vs/{lspLanguageFeatures-CAWBopti.js → lspLanguageFeatures-CRAjJmzF.js} +1 -1
  116. package/min/vs/{mdx-CvpAYI3X.js → mdx-DLDMIqnu.js} +1 -1
  117. package/min/vs/{monaco.contribution-QIm8iN-Y.js → monaco.contribution-BrRAk-VA.js} +1 -1
  118. package/min/vs/{monaco.contribution-C3jTRlbI.js → monaco.contribution-C67XgReK.js} +1 -1
  119. package/min/vs/{monaco.contribution-Cmckd8EG.js → monaco.contribution-CYT-Sx3l.js} +1 -1
  120. package/min/vs/{monaco.contribution-6Rc9eWJ0.js → monaco.contribution-DjiQkKLa.js} +1 -1
  121. package/min/vs/nls/lang/cs.js +1 -1
  122. package/min/vs/nls/lang/de.js +1 -1
  123. package/min/vs/nls/lang/es.js +1 -1
  124. package/min/vs/nls/lang/fr.js +1 -1
  125. package/min/vs/nls/lang/it.js +1 -1
  126. package/min/vs/nls/lang/ja.js +1 -1
  127. package/min/vs/nls/lang/ko.js +1 -1
  128. package/min/vs/nls/lang/pl.js +1 -1
  129. package/min/vs/nls/lang/pt-br.js +1 -1
  130. package/min/vs/nls/lang/ru.js +1 -1
  131. package/min/vs/nls/lang/tr.js +1 -1
  132. package/min/vs/nls/lang/zh-cn.js +1 -1
  133. package/min/vs/nls/lang/zh-tw.js +1 -1
  134. package/min/vs/{python-BuY3uazV.js → python-CKbl_I3e.js} +1 -1
  135. package/min/vs/{razor-DQBMGsJX.js → razor--RjiPxbd.js} +1 -1
  136. package/min/vs/{toggleHighContrast-BTse4XBl.js → toggleHighContrast-BKDMxisH.js} +31 -33
  137. package/min/vs/{tsMode-C8sInOMc.js → tsMode-C48d5M22.js} +1 -1
  138. package/min/vs/{typescript-DMigl3F4.js → typescript-e7oUhPyX.js} +1 -1
  139. package/min/vs/{workers-BznOw4bL.js → workers-CtpYUoCo.js} +1 -1
  140. package/min/vs/{xml-C2bHWkWJ.js → xml-tOyfgws7.js} +1 -1
  141. package/min/vs/{yaml-gtjQmyMa.js → yaml-Cmf9NYDf.js} +1 -1
  142. package/monaco.d.ts +5 -1
  143. package/package.json +4 -4
@@ -1,4 +1,4 @@
1
- define("vs/tsMode-Dy3ckMs8", ["exports", "./ts.worker-CArJhH03", "./editor-ML6zs6Go", "./workers-B9Ao1ciR", "./monaco.contribution-t7Hz4wVA"], (function(exports, ts_worker, editor, workers, src_deprecated_language_typescript_monaco_contribution_ts) {
1
+ define("vs/tsMode-jpkv3SbL", ["exports", "./ts.worker-CArJhH03", "./editor-CR18QzPP", "./workers-zrUx_2Gw", "./monaco.contribution-CVBrIlxn"], (function(exports, ts_worker, editor, workers, src_deprecated_language_typescript_monaco_contribution_ts) {
2
2
  "use strict";
3
3
  class WorkerManager {
4
4
  constructor(_modeId, _defaults) {
@@ -1,4 +1,4 @@
1
- define("vs/typescript-BBL8N09V", ["exports", "./editor-ML6zs6Go"], (function(exports, editor) {
1
+ define("vs/typescript-f8pt88eA", ["exports", "./editor-CR18QzPP"], (function(exports, editor) {
2
2
  "use strict";
3
3
  const conf = {
4
4
  wordPattern: /(-?\d*\.\d\w*)|([^\`\~\!\@\#\%\^\&\*\(\)\-\=\+\[\{\]\}\\\|\;\:\'\"\,\.\<\>\/\?\s]+)/g,
@@ -1,4 +1,4 @@
1
- define("vs/workers-B9Ao1ciR", ["exports", "./editor-ML6zs6Go", "./toggleHighContrast-Btd2ryZF"], (function(exports, editor, toggleHighContrast) {
1
+ define("vs/workers-zrUx_2Gw", ["exports", "./editor-CR18QzPP", "./toggleHighContrast-CLgtrrIB"], (function(exports, editor, toggleHighContrast) {
2
2
  "use strict";
3
3
  function createTrustedTypesPolicy(policyName, policyOptions) {
4
4
  const monacoEnvironment = globalThis.MonacoEnvironment;
@@ -1,4 +1,4 @@
1
- define("vs/xml-7BH7GgP4", ["exports", "./editor-ML6zs6Go"], (function(exports, editor) {
1
+ define("vs/xml-CmSjtiR0", ["exports", "./editor-CR18QzPP"], (function(exports, editor) {
2
2
  "use strict";
3
3
  const conf = {
4
4
  comments: {
@@ -1,4 +1,4 @@
1
- define("vs/yaml-DvwGvgS8", ["exports", "./editor-ML6zs6Go"], (function(exports, editor) {
1
+ define("vs/yaml-PRriLGdw", ["exports", "./editor-CR18QzPP"], (function(exports, editor) {
2
2
  "use strict";
3
3
  const conf = {
4
4
  comments: {
@@ -498,6 +498,7 @@ function getDomSanitizerConfig(mdStrConfig, options) {
498
498
  Schemas.vscodeRemote,
499
499
  Schemas.vscodeRemoteResource,
500
500
  Schemas.vscodeNotebookCell,
501
+ Schemas.vscodeChatPrompt,
501
502
  // For links that are handled entirely by the action handler
502
503
  Schemas.internal,
503
504
  ];
@@ -283,7 +283,10 @@ class ActionViewItem extends BaseActionViewItem {
283
283
  if (this.cssClass && this.label) {
284
284
  this.label.classList.remove(...this.cssClass.split(' '));
285
285
  }
286
- if (this.options.icon) {
286
+ if (this.action.id === Separator.ID && this.action.class) {
287
+ this.label?.classList.add(this.action.class);
288
+ }
289
+ else if (this.options.icon) {
287
290
  this.cssClass = this.getClass();
288
291
  if (this.label) {
289
292
  this.label.classList.add('codicon');
@@ -45,7 +45,8 @@
45
45
  height: 16px;
46
46
  }
47
47
 
48
- .monaco-action-bar .action-label {
48
+ .monaco-action-bar .action-label,
49
+ .monaco-action-bar .action-item .keybinding {
49
50
  display: flex;
50
51
  font-size: 11px;
51
52
  padding: 3px;
@@ -75,12 +76,14 @@
75
76
  display: block;
76
77
  }
77
78
 
78
- .monaco-action-bar.vertical .action-label.separator {
79
+ .monaco-action-bar.vertical .action-item .action-label.separator {
79
80
  display: block;
80
- border-bottom: 1px solid var(--vscode-disabledForeground);
81
+ border-bottom: 1px solid var(--vscode-menu-separatorBackground, var(--vscode-disabledForeground));
81
82
  padding-top: 1px;
82
- margin-left: .8em;
83
- margin-right: .8em;
83
+ margin: 4px .8em;
84
+ width: 100%;
85
+ height: 0;
86
+ background-color: transparent;
84
87
  }
85
88
 
86
89
  .monaco-action-bar .action-item .action-label.separator {
@@ -39,7 +39,7 @@ function layout(viewportSize, viewSize, anchor) {
39
39
  if (viewSize <= layoutBeforeAnchorBoundary) {
40
40
  return layoutBeforeAnchorBoundary - viewSize; // happy case, lay it out before the anchor
41
41
  }
42
- if (viewSize <= viewportSize - layoutAfterAnchorBoundary) {
42
+ if (viewSize <= viewportSize - layoutAfterAnchorBoundary && layoutBeforeAnchorBoundary < viewSize / 2) {
43
43
  return layoutAfterAnchorBoundary; // ok case, lay it out after the anchor
44
44
  }
45
45
  return 0; // sad case, lay it over the anchor
@@ -2,10 +2,11 @@
2
2
  * Copyright (c) Microsoft Corporation. All rights reserved.
3
3
  * Licensed under the MIT License. See License.txt in the project root for license information.
4
4
  *--------------------------------------------------------------------------------------------*/
5
+ const NotSelectableGroupId = 'notSelectable';
5
6
  class ListError extends Error {
6
7
  constructor(user, message) {
7
8
  super(`ListError [${user}] ${message}`);
8
9
  }
9
10
  }
10
11
 
11
- export { ListError };
12
+ export { ListError, NotSelectableGroupId };
@@ -17,7 +17,7 @@ import { clamp } from '../../../common/numbers.js';
17
17
  import { isMacintosh } from '../../../common/platform.js';
18
18
  import { isNumber } from '../../../common/types.js';
19
19
  import './list.css';
20
- import { ListError } from './list.js';
20
+ import { ListError, NotSelectableGroupId } from './list.js';
21
21
  import { ListView } from './listView.js';
22
22
  import { StandardMouseEvent } from '../../mouseEvent.js';
23
23
  import '../../../common/observableInternal/index.js';
@@ -319,7 +319,14 @@ class KeyboardController {
319
319
  onCtrlA(e) {
320
320
  e.preventDefault();
321
321
  e.stopPropagation();
322
- this.list.setSelection(range(this.list.length), e.browserEvent);
322
+ let selection = range(this.list.length);
323
+ // Filter by group if identity provider has getGroupId
324
+ const focusedElements = this.list.getFocus();
325
+ const referenceGroupId = focusedElements.length > 0 ? this.list.getElementGroupId(focusedElements[0]) : undefined;
326
+ if (referenceGroupId !== undefined) {
327
+ selection = this.list.filterIndicesByGroup(selection, referenceGroupId);
328
+ }
329
+ this.list.setSelection(selection, e.browserEvent);
323
330
  this.list.setAnchor(undefined);
324
331
  this.view.domNode.focus();
325
332
  }
@@ -614,7 +621,11 @@ class MouseController {
614
621
  this.list.setFocus([focus], e.browserEvent);
615
622
  this.list.setAnchor(focus);
616
623
  if (!isMouseRightClick(e.browserEvent)) {
617
- this.list.setSelection([focus], e.browserEvent);
624
+ // Check if the element is selectable (getGroupId must not return undefined)
625
+ const focusGroupId = this.list.getElementGroupId(focus);
626
+ if (focusGroupId !== NotSelectableGroupId) {
627
+ this.list.setSelection([focus], e.browserEvent);
628
+ }
618
629
  }
619
630
  this._onPointer.fire(e);
620
631
  }
@@ -643,7 +654,14 @@ class MouseController {
643
654
  }
644
655
  const min = Math.min(anchor, focus);
645
656
  const max = Math.max(anchor, focus);
646
- const rangeSelection = range(min, max + 1);
657
+ let rangeSelection = range(min, max + 1);
658
+ const selectedElement = this.list.getSelection()[0];
659
+ if (selectedElement !== undefined) {
660
+ const referenceGroupId = this.list.getElementGroupId(selectedElement);
661
+ if (referenceGroupId !== undefined) {
662
+ rangeSelection = this.list.filterIndicesByGroup(rangeSelection, referenceGroupId);
663
+ }
664
+ }
647
665
  const selection = this.list.getSelection();
648
666
  const contiguousRange = getContiguousRangeContaining(disjunction(selection, [anchor]), anchor);
649
667
  if (contiguousRange.length === 0) {
@@ -658,8 +676,15 @@ class MouseController {
658
676
  const newSelection = selection.filter(i => i !== focus);
659
677
  this.list.setFocus([focus]);
660
678
  this.list.setAnchor(focus);
679
+ const focusGroupId = this.list.getElementGroupId(focus);
680
+ if (focusGroupId === NotSelectableGroupId) {
681
+ return; // Cannot select this element, do nothing
682
+ }
661
683
  if (selection.length === newSelection.length) {
662
- this.list.setSelection([...newSelection, focus], e.browserEvent);
684
+ const itemsToBeSelected = focusGroupId !== undefined ?
685
+ this.list.filterIndicesByGroup([...newSelection, focus], focusGroupId)
686
+ : [...newSelection, focus];
687
+ this.list.setSelection(itemsToBeSelected, e.browserEvent);
663
688
  }
664
689
  else {
665
690
  this.list.setSelection(newSelection, e.browserEvent);
@@ -1257,6 +1282,7 @@ class List {
1257
1282
  throw new ListError(this.user, `Invalid index ${index}`);
1258
1283
  }
1259
1284
  }
1285
+ indexes = indexes.filter(i => this.getElementGroupId(i) !== NotSelectableGroupId);
1260
1286
  this.selection.set(indexes, browserEvent);
1261
1287
  }
1262
1288
  getSelection() {
@@ -1282,6 +1308,37 @@ class List {
1282
1308
  const anchor = this.getAnchor();
1283
1309
  return typeof anchor === 'undefined' ? undefined : this.element(anchor);
1284
1310
  }
1311
+ /**
1312
+ * Gets the group ID for an element at the given index.
1313
+ * Returns undefined if no identity provider, no getGroupId method, or if the group ID is undefined.
1314
+ */
1315
+ getElementGroupId(index) {
1316
+ const identityProvider = this.options.identityProvider;
1317
+ if (!identityProvider?.getGroupId) {
1318
+ return undefined;
1319
+ }
1320
+ const element = this.element(index);
1321
+ return identityProvider.getGroupId(element);
1322
+ }
1323
+ /**
1324
+ * Filters the given indices to only include those with a matching group ID.
1325
+ * If no identity provider or getGroupId method exists, returns the original indices.
1326
+ * If referenceGroupId is undefined, returns an empty array (elements without group IDs are not selectable).
1327
+ */
1328
+ filterIndicesByGroup(indices, referenceGroupId) {
1329
+ const identityProvider = this.options.identityProvider;
1330
+ if (!identityProvider?.getGroupId) {
1331
+ return indices;
1332
+ }
1333
+ if (referenceGroupId === NotSelectableGroupId) {
1334
+ return [];
1335
+ }
1336
+ return indices.filter(index => {
1337
+ const element = this.element(index);
1338
+ const groupId = identityProvider.getGroupId(element);
1339
+ return groupId === referenceGroupId;
1340
+ });
1341
+ }
1285
1342
  setFocus(indexes, browserEvent) {
1286
1343
  for (const index of indexes) {
1287
1344
  if (index < 0 || index >= this.length) {
@@ -131,7 +131,10 @@ function asListOptions(modelProvider, disposableStore, options) {
131
131
  identityProvider: options.identityProvider && {
132
132
  getId(el) {
133
133
  return options.identityProvider.getId(el.element);
134
- }
134
+ },
135
+ getGroupId: options.identityProvider.getGroupId ? (el) => {
136
+ return options.identityProvider.getGroupId(el.element);
137
+ } : undefined
135
138
  },
136
139
  dnd: options.dnd && disposableStore.add(new TreeNodeListDragAndDrop(modelProvider, options.dnd)),
137
140
  multipleSelectionController: options.multipleSelectionController && {
@@ -210,7 +210,10 @@ function asObjectTreeOptions(options) {
210
210
  identityProvider: options.identityProvider && {
211
211
  getId(el) {
212
212
  return options.identityProvider.getId(el.element);
213
- }
213
+ },
214
+ getGroupId: options.identityProvider.getGroupId ? (el) => {
215
+ return options.identityProvider.getGroupId(el.element);
216
+ } : undefined
214
217
  },
215
218
  dnd: options.dnd && new AsyncDataTreeNodeListDragAndDrop(options.dnd),
216
219
  multipleSelectionController: options.multipleSelectionController && {
@@ -1,55 +1,42 @@
1
1
  import { isWindows } from '../../../../base/common/platform.js';
2
2
  import { Mimes } from '../../../../base/common/mime.js';
3
- import { LogLevel } from '../../../../platform/log/common/log.js';
4
3
  import { generateUuid } from '../../../../base/common/uuid.js';
4
+ import { toExternalVSDataTransfer } from '../../dataTransfer.js';
5
5
 
6
- function ensureClipboardGetsEditorSelection(e, context, logService, isFirefox) {
7
- const viewModel = context.viewModel;
8
- const options = context.configuration.options;
9
- let id = undefined;
10
- if (logService.getLevel() === LogLevel.Trace) {
11
- id = generateUuid();
12
- }
13
- const { dataToCopy, storedMetadata } = generateDataToCopyAndStoreInMemory(viewModel, options, id, isFirefox);
14
- // !!!!!
15
- // This is a workaround for what we think is an Electron bug where
16
- // execCommand('copy') does not always work (it does not fire a clipboard event)
17
- // !!!!!
18
- // We signal that we have executed a copy command
19
- CopyOptions.electronBugWorkaroundCopyEventHasFired = true;
20
- e.preventDefault();
21
- if (e.clipboardData) {
22
- ClipboardEventUtils.setTextData(e.clipboardData, dataToCopy.text, dataToCopy.html, storedMetadata);
23
- }
24
- logService.trace('ensureClipboardGetsEditorSelection with id : ', id, ' with text.length: ', dataToCopy.text.length);
6
+ function generateDataToCopyAndStoreInMemory(viewModel, id, isFirefox) {
7
+ const { dataToCopy, metadata } = generateDataToCopy(viewModel);
8
+ storeMetadataInMemory(dataToCopy.text, metadata, isFirefox);
9
+ return { dataToCopy, metadata };
10
+ }
11
+ function storeMetadataInMemory(textToCopy, metadata, isFirefox) {
12
+ InMemoryClipboardMetadataManager.INSTANCE.set(
13
+ // When writing "LINE\r\n" to the clipboard and then pasting,
14
+ // Firefox pastes "LINE\n", so let's work around this quirk
15
+ (isFirefox ? textToCopy.replace(/\r\n/g, '\n') : textToCopy), metadata);
25
16
  }
26
- function generateDataToCopyAndStoreInMemory(viewModel, options, id, isFirefox) {
27
- const emptySelectionClipboard = options.get(45 /* EditorOption.emptySelectionClipboard */);
28
- const copyWithSyntaxHighlighting = options.get(31 /* EditorOption.copyWithSyntaxHighlighting */);
17
+ function generateDataToCopy(viewModel) {
18
+ const emptySelectionClipboard = viewModel.getEditorOption(45 /* EditorOption.emptySelectionClipboard */);
19
+ const copyWithSyntaxHighlighting = viewModel.getEditorOption(31 /* EditorOption.copyWithSyntaxHighlighting */);
29
20
  const selections = viewModel.getCursorStates().map(cursorState => cursorState.modelState.selection);
30
21
  const dataToCopy = getDataToCopy(viewModel, selections, emptySelectionClipboard, copyWithSyntaxHighlighting);
31
- const storedMetadata = {
22
+ const metadata = {
32
23
  version: 1,
33
- id,
24
+ id: generateUuid(),
34
25
  isFromEmptySelection: dataToCopy.isFromEmptySelection,
35
26
  multicursorText: dataToCopy.multicursorText,
36
27
  mode: dataToCopy.mode
37
28
  };
38
- InMemoryClipboardMetadataManager.INSTANCE.set(
39
- // When writing "LINE\r\n" to the clipboard and then pasting,
40
- // Firefox pastes "LINE\n", so let's work around this quirk
41
- (isFirefox ? dataToCopy.text.replace(/\r\n/g, '\n') : dataToCopy.text), storedMetadata);
42
- return { dataToCopy, storedMetadata };
29
+ return { dataToCopy, metadata };
43
30
  }
44
31
  function getDataToCopy(viewModel, modelSelections, emptySelectionClipboard, copyWithSyntaxHighlighting) {
45
- const rawTextToCopy = viewModel.getPlainTextToCopy(modelSelections, emptySelectionClipboard, isWindows);
32
+ const { sourceRanges, sourceText } = viewModel.getPlainTextToCopy(modelSelections, emptySelectionClipboard, isWindows);
46
33
  const newLineCharacter = viewModel.model.getEOL();
47
34
  const isFromEmptySelection = (emptySelectionClipboard && modelSelections.length === 1 && modelSelections[0].isEmpty());
48
- const multicursorText = (Array.isArray(rawTextToCopy) ? rawTextToCopy : null);
49
- const text = (Array.isArray(rawTextToCopy) ? rawTextToCopy.join(newLineCharacter) : rawTextToCopy);
35
+ const multicursorText = (Array.isArray(sourceText) ? sourceText : null);
36
+ const text = (Array.isArray(sourceText) ? sourceText.join(newLineCharacter) : sourceText);
50
37
  let html = undefined;
51
38
  let mode = null;
52
- if (CopyOptions.forceCopyWithSyntaxHighlighting || (copyWithSyntaxHighlighting && text.length < 65536)) {
39
+ if (CopyOptions.forceCopyWithSyntaxHighlighting || (copyWithSyntaxHighlighting && sourceText.length < 65536)) {
53
40
  const richText = viewModel.getRichTextToCopy(modelSelections, emptySelectionClipboard);
54
41
  if (richText) {
55
42
  html = richText.html;
@@ -58,6 +45,7 @@ function getDataToCopy(viewModel, modelSelections, emptySelectionClipboard, copy
58
45
  }
59
46
  const dataToCopy = {
60
47
  isFromEmptySelection,
48
+ sourceRanges,
61
49
  multicursorText,
62
50
  text,
63
51
  html,
@@ -122,5 +110,63 @@ const ClipboardEventUtils = {
122
110
  clipboardData.setData('vscode-editor-data', JSON.stringify(metadata));
123
111
  }
124
112
  };
113
+ /**
114
+ * Creates an IClipboardCopyEvent from a DOM ClipboardEvent.
115
+ */
116
+ function createClipboardCopyEvent(e, isCut, context, logService, isFirefox) {
117
+ const { dataToCopy, metadata } = generateDataToCopy(context.viewModel);
118
+ let handled = false;
119
+ return {
120
+ isCut,
121
+ clipboardData: {
122
+ setData: (type, value) => {
123
+ e.clipboardData?.setData(type, value);
124
+ },
125
+ },
126
+ dataToCopy,
127
+ ensureClipboardGetsEditorData: () => {
128
+ e.preventDefault();
129
+ if (e.clipboardData) {
130
+ ClipboardEventUtils.setTextData(e.clipboardData, dataToCopy.text, dataToCopy.html, metadata);
131
+ }
132
+ storeMetadataInMemory(dataToCopy.text, metadata, isFirefox);
133
+ logService.trace('ensureClipboardGetsEditorSelection with id : ', metadata.id, ' with text.length: ', dataToCopy.text.length);
134
+ },
135
+ setHandled: () => {
136
+ handled = true;
137
+ e.preventDefault();
138
+ e.stopImmediatePropagation();
139
+ },
140
+ get isHandled() { return handled; },
141
+ };
142
+ }
143
+ /**
144
+ * Creates an IClipboardPasteEvent from a DOM ClipboardEvent.
145
+ */
146
+ function createClipboardPasteEvent(e) {
147
+ let handled = false;
148
+ let [text, metadata] = e.clipboardData ? ClipboardEventUtils.getTextData(e.clipboardData) : ['', null];
149
+ metadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);
150
+ return {
151
+ clipboardData: createReadableClipboardData(e.clipboardData),
152
+ metadata,
153
+ text,
154
+ toExternalVSDataTransfer: () => e.clipboardData ? toExternalVSDataTransfer(e.clipboardData) : undefined,
155
+ browserEvent: e,
156
+ setHandled: () => {
157
+ handled = true;
158
+ e.preventDefault();
159
+ e.stopImmediatePropagation();
160
+ },
161
+ get isHandled() { return handled; },
162
+ };
163
+ }
164
+ function createReadableClipboardData(dataTransfer) {
165
+ return {
166
+ types: Array.from(dataTransfer?.types ?? []),
167
+ files: Array.prototype.slice.call(dataTransfer?.files ?? [], 0),
168
+ getData: (type) => dataTransfer?.getData(type) ?? '',
169
+ };
170
+ }
125
171
 
126
- export { ClipboardEventUtils, CopyOptions, InMemoryClipboardMetadataManager, ensureClipboardGetsEditorSelection, generateDataToCopyAndStoreInMemory };
172
+ export { CopyOptions, InMemoryClipboardMetadataManager, createClipboardCopyEvent, createClipboardPasteEvent, createReadableClipboardData, generateDataToCopyAndStoreInMemory };
@@ -1,3 +1,4 @@
1
+ import { Emitter } from '../../../../base/common/event.js';
1
2
  import { ViewPart } from '../../view/viewPart.js';
2
3
 
3
4
  /*---------------------------------------------------------------------------------------------
@@ -5,6 +6,16 @@ import { ViewPart } from '../../view/viewPart.js';
5
6
  * Licensed under the MIT License. See License.txt in the project root for license information.
6
7
  *--------------------------------------------------------------------------------------------*/
7
8
  class AbstractEditContext extends ViewPart {
9
+ constructor() {
10
+ super(...arguments);
11
+ // Clipboard events - emitted before the default clipboard handling
12
+ this._onWillCopy = this._register(new Emitter());
13
+ this.onWillCopy = this._onWillCopy.event;
14
+ this._onWillCut = this._register(new Emitter());
15
+ this.onWillCut = this._onWillCut.event;
16
+ this._onWillPaste = this._register(new Emitter());
17
+ this.onWillPaste = this._onWillPaste.event;
18
+ }
8
19
  }
9
20
 
10
21
  export { AbstractEditContext };
@@ -4,7 +4,7 @@ import { getWindow, addDisposableListener, getActiveElement, getWindowId } from
4
4
  import { FastDomNode } from '../../../../../base/browser/fastDomNode.js';
5
5
  import { StandardKeyboardEvent } from '../../../../../base/browser/keyboardEvent.js';
6
6
  import { IInstantiationService } from '../../../../../platform/instantiation/common/instantiation.js';
7
- import { ensureClipboardGetsEditorSelection, ClipboardEventUtils, InMemoryClipboardMetadataManager } from '../clipboardUtils.js';
7
+ import { CopyOptions, createClipboardCopyEvent, createClipboardPasteEvent } from '../clipboardUtils.js';
8
8
  import { AbstractEditContext } from '../editContext.js';
9
9
  import { FocusTracker, editContextAddDisposableListener } from './nativeEditContextUtils.js';
10
10
  import { ScreenReaderSupport } from './screenReaderSupport.js';
@@ -81,14 +81,30 @@ let NativeEditContext = class NativeEditContext extends AbstractEditContext {
81
81
  this._screenReaderSupport = this._register(instantiationService.createInstance(ScreenReaderSupport, this.domNode, context, this._viewController));
82
82
  this._register(addDisposableListener(this.domNode.domNode, 'copy', (e) => {
83
83
  this.logService.trace('NativeEditContext#copy');
84
- ensureClipboardGetsEditorSelection(e, this._context, this.logService, isFirefox);
84
+ // !!!!!
85
+ // This is a workaround for what we think is an Electron bug where
86
+ // execCommand('copy') does not always work (it does not fire a clipboard event)
87
+ // !!!!!
88
+ // We signal that we have executed a copy command
89
+ CopyOptions.electronBugWorkaroundCopyEventHasFired = true;
90
+ const copyEvent = createClipboardCopyEvent(e, /* isCut */ false, this._context, this.logService, isFirefox);
91
+ this._onWillCopy.fire(copyEvent);
92
+ if (copyEvent.isHandled) {
93
+ return;
94
+ }
95
+ copyEvent.ensureClipboardGetsEditorData();
85
96
  }));
86
97
  this._register(addDisposableListener(this.domNode.domNode, 'cut', (e) => {
87
98
  this.logService.trace('NativeEditContext#cut');
99
+ const cutEvent = createClipboardCopyEvent(e, /* isCut */ true, this._context, this.logService, isFirefox);
100
+ this._onWillCut.fire(cutEvent);
101
+ if (cutEvent.isHandled) {
102
+ return;
103
+ }
88
104
  // Pretend here we touched the text area, as the `cut` event will most likely
89
105
  // result in a `selectionchange` event which we want to ignore
90
106
  this._screenReaderSupport.onWillCut();
91
- ensureClipboardGetsEditorSelection(e, this._context, this.logService, isFirefox);
107
+ cutEvent.ensureClipboardGetsEditorData();
92
108
  this.logService.trace('NativeEditContext#cut (before viewController.cut)');
93
109
  this._viewController.cut();
94
110
  }));
@@ -107,28 +123,32 @@ let NativeEditContext = class NativeEditContext extends AbstractEditContext {
107
123
  }));
108
124
  this._register(addDisposableListener(this.domNode.domNode, 'paste', (e) => {
109
125
  this.logService.trace('NativeEditContext#paste');
126
+ const pasteEvent = createClipboardPasteEvent(e);
127
+ this._onWillPaste.fire(pasteEvent);
128
+ if (pasteEvent.isHandled) {
129
+ e.preventDefault();
130
+ return;
131
+ }
110
132
  e.preventDefault();
111
133
  if (!e.clipboardData) {
112
134
  return;
113
135
  }
114
- let [text, metadata] = ClipboardEventUtils.getTextData(e.clipboardData);
115
- this.logService.trace('NativeEditContext#paste with id : ', metadata?.id, ' with text.length: ', text.length);
116
- if (!text) {
136
+ this.logService.trace('NativeEditContext#paste with id : ', pasteEvent.metadata?.id, ' with text.length: ', pasteEvent.text.length);
137
+ if (!pasteEvent.text) {
117
138
  return;
118
139
  }
119
- metadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);
120
140
  let pasteOnNewLine = false;
121
141
  let multicursorText = null;
122
142
  let mode = null;
123
- if (metadata) {
143
+ if (pasteEvent.metadata) {
124
144
  const options = this._context.configuration.options;
125
145
  const emptySelectionClipboard = options.get(45 /* EditorOption.emptySelectionClipboard */);
126
- pasteOnNewLine = emptySelectionClipboard && !!metadata.isFromEmptySelection;
127
- multicursorText = typeof metadata.multicursorText !== 'undefined' ? metadata.multicursorText : null;
128
- mode = metadata.mode;
146
+ pasteOnNewLine = emptySelectionClipboard && !!pasteEvent.metadata.isFromEmptySelection;
147
+ multicursorText = typeof pasteEvent.metadata.multicursorText !== 'undefined' ? pasteEvent.metadata.multicursorText : null;
148
+ mode = pasteEvent.metadata.mode;
129
149
  }
130
150
  this.logService.trace('NativeEditContext#paste (before viewController.paste)');
131
- this._viewController.paste(text, pasteOnNewLine, multicursorText, mode);
151
+ this._viewController.paste(pasteEvent.text, pasteOnNewLine, multicursorText, mode);
132
152
  }));
133
153
  // Edit context events
134
154
  this._register(editContextAddDisposableListener(this._editContext, 'textformatupdate', (e) => this._handleTextFormatUpdate(e)));
@@ -260,15 +280,15 @@ let NativeEditContext = class NativeEditContext extends AbstractEditContext {
260
280
  onZonesChanged(e) {
261
281
  return true;
262
282
  }
263
- onWillPaste() {
264
- this.logService.trace('NativeEditContext#onWillPaste');
265
- this._onWillPaste();
283
+ handleWillPaste() {
284
+ this.logService.trace('NativeEditContext#handleWillPaste');
285
+ this._prepareScreenReaderForPaste();
266
286
  }
267
- _onWillPaste() {
287
+ _prepareScreenReaderForPaste() {
268
288
  this._screenReaderSupport.onWillPaste();
269
289
  }
270
- onWillCopy() {
271
- this.logService.trace('NativeEditContext#onWillCopy');
290
+ handleWillCopy() {
291
+ this.logService.trace('NativeEditContext#handleWillCopy');
272
292
  this.logService.trace('NativeEditContext#isFocused : ', this.domNode.domNode === getActiveElement());
273
293
  }
274
294
  writeScreenReaderContent() {
@@ -205,6 +205,10 @@ let TextAreaEditContext = class TextAreaEditContext extends AbstractEditContext
205
205
  isFirefox: isFirefox,
206
206
  isSafari: isSafari,
207
207
  }));
208
+ // Relay clipboard events from TextAreaInput
209
+ this._register(this._textAreaInput.onWillCopy(e => this._onWillCopy.fire(e)));
210
+ this._register(this._textAreaInput.onWillCut(e => this._onWillCut.fire(e)));
211
+ this._register(this._textAreaInput.onWillPaste(e => this._onWillPaste.fire(e)));
208
212
  this._register(this._textAreaInput.onKeyDown((e) => {
209
213
  this._viewController.emitKeyDown(e);
210
214
  }));
@@ -10,7 +10,7 @@ import { isHighSurrogate } from '../../../../../base/common/strings.js';
10
10
  import { Selection } from '../../../../common/core/selection.js';
11
11
  import { IAccessibilityService } from '../../../../../platform/accessibility/common/accessibility.js';
12
12
  import { ILogService } from '../../../../../platform/log/common/log.js';
13
- import { InMemoryClipboardMetadataManager, ensureClipboardGetsEditorSelection, ClipboardEventUtils } from '../clipboardUtils.js';
13
+ import { InMemoryClipboardMetadataManager, createClipboardCopyEvent, CopyOptions, createClipboardPasteEvent } from '../clipboardUtils.js';
14
14
  import { TextAreaState } from './textAreaEditContextState.js';
15
15
 
16
16
  /*---------------------------------------------------------------------------------------------
@@ -78,6 +78,12 @@ let TextAreaInput = class TextAreaInput extends Disposable {
78
78
  this.onCut = this._onCut.event;
79
79
  this._onPaste = this._register(new Emitter());
80
80
  this.onPaste = this._onPaste.event;
81
+ this._onWillCopy = this._register(new Emitter());
82
+ this.onWillCopy = this._onWillCopy.event;
83
+ this._onWillCut = this._register(new Emitter());
84
+ this.onWillCut = this._onWillCut.event;
85
+ this._onWillPaste = this._register(new Emitter());
86
+ this.onWillPaste = this._onWillPaste.event;
81
87
  this._onType = this._register(new Emitter());
82
88
  this.onType = this._onType.event;
83
89
  this._onCompositionStart = this._register(new Emitter());
@@ -238,40 +244,57 @@ let TextAreaInput = class TextAreaInput extends Disposable {
238
244
  // --- Clipboard operations
239
245
  this._register(this._textArea.onCut((e) => {
240
246
  this._logService.trace(`TextAreaInput#onCut`, e);
247
+ // Fire onWillCut event to allow interception
248
+ const cutEvent = createClipboardCopyEvent(e, /* isCut */ true, this._host.context, this._logService, this._browser.isFirefox);
249
+ this._onWillCut.fire(cutEvent);
250
+ if (cutEvent.isHandled) {
251
+ // Event was handled externally, skip default processing
252
+ return;
253
+ }
241
254
  // Pretend here we touched the text area, as the `cut` event will most likely
242
255
  // result in a `selectionchange` event which we want to ignore
243
256
  this._textArea.setIgnoreSelectionChangeTime('received cut event');
244
- if (this._host.context) {
245
- ensureClipboardGetsEditorSelection(e, this._host.context, this._logService, this._browser.isFirefox);
246
- }
257
+ cutEvent.ensureClipboardGetsEditorData();
247
258
  this._asyncTriggerCut.schedule();
248
259
  }));
249
260
  this._register(this._textArea.onCopy((e) => {
250
261
  this._logService.trace(`TextAreaInput#onCopy`, e);
251
- if (this._host.context) {
252
- ensureClipboardGetsEditorSelection(e, this._host.context, this._logService, this._browser.isFirefox);
262
+ // !!!!!
263
+ // This is a workaround for what we think is an Electron bug where
264
+ // execCommand('copy') does not always work (it does not fire a clipboard event)
265
+ // !!!!!
266
+ // We signal that we have executed a copy command
267
+ CopyOptions.electronBugWorkaroundCopyEventHasFired = true;
268
+ // Fire onWillCopy event to allow interception
269
+ const copyEvent = createClipboardCopyEvent(e, /* isCut */ false, this._host.context, this._logService, this._browser.isFirefox);
270
+ this._onWillCopy.fire(copyEvent);
271
+ if (copyEvent.isHandled) {
272
+ // Event was handled externally, skip default processing
273
+ return;
253
274
  }
275
+ copyEvent.ensureClipboardGetsEditorData();
254
276
  }));
255
277
  this._register(this._textArea.onPaste((e) => {
256
278
  this._logService.trace(`TextAreaInput#onPaste`, e);
279
+ // Fire onWillPaste event to allow interception
280
+ const pasteEvent = createClipboardPasteEvent(e);
281
+ this._onWillPaste.fire(pasteEvent);
282
+ if (pasteEvent.isHandled) {
283
+ // Event was handled externally, skip default processing
284
+ return;
285
+ }
257
286
  // Pretend here we touched the text area, as the `paste` event will most likely
258
287
  // result in a `selectionchange` event which we want to ignore
259
288
  this._textArea.setIgnoreSelectionChangeTime('received paste event');
260
289
  e.preventDefault();
261
- if (!e.clipboardData) {
262
- return;
263
- }
264
- let [text, metadata] = ClipboardEventUtils.getTextData(e.clipboardData);
265
- this._logService.trace(`TextAreaInput#onPaste with id : `, metadata?.id, ' with text.length: ', text.length);
266
- if (!text) {
290
+ this._logService.trace(`TextAreaInput#onPaste with id : `, pasteEvent.metadata?.id, ' with text.length: ', pasteEvent.text.length);
291
+ if (!pasteEvent.text) {
267
292
  return;
268
293
  }
269
- // try the in-memory store
270
- metadata = metadata || InMemoryClipboardMetadataManager.INSTANCE.get(text);
271
294
  this._logService.trace(`TextAreaInput#onPaste (before onPaste)`);
272
295
  this._onPaste.fire({
273
- text: text,
274
- metadata: metadata
296
+ text: pasteEvent.text,
297
+ metadata: pasteEvent.metadata
275
298
  });
276
299
  }));
277
300
  this._register(this._textArea.onFocus(() => {