@lvce-editor/editor-worker 19.61.0 → 19.61.1

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.
package/README.md CHANGED
@@ -41,7 +41,7 @@ Install dependencies from the repository root:
41
41
  npm ci
42
42
  ```
43
43
 
44
- The root `postinstall` script bootstraps the packages with Lerna.
44
+ Installation does not modify the installed server assets.
45
45
 
46
46
  Start a development build and local test server:
47
47
 
@@ -49,7 +49,7 @@ Start a development build and local test server:
49
49
  npm run dev
50
50
  ```
51
51
 
52
- This starts the editor worker watch build and the Lvce Editor test server with `packages/e2e` as the test path.
52
+ This builds the local package, then starts the watch build and the Lvce Editor test server with `packages/e2e` as the test path. The server uses `--link` to load the generated `.tmp/dist` editor-worker package.
53
53
 
54
54
  ## Common Commands
55
55
 
@@ -61,7 +61,7 @@ Run these commands from the repository root unless noted otherwise.
61
61
  | `npm run build:watch` | Watches `packages/editor-worker/src/editorWorkerMain.ts` and rebuilds the worker with esbuild. |
62
62
  | `npm run build:static` | Exports a static test build into `.tmp/static`. Run `npm run build` first. |
63
63
  | `npm run dev` | Runs the watch build and local test server together. |
64
- | `npm test` | Runs package test scripts through Lerna. |
64
+ | `npm test` | Runs package test scripts through npm workspaces. |
65
65
  | `npm run type-check` | Runs TypeScript project references for all packages. |
66
66
  | `npm run lint` | Runs ESLint, Prettier checks, and Knip. |
67
67
  | `npm run format` | Formats the repository with Prettier. |
@@ -107,7 +107,7 @@ The worker listens for RPC messages, registers widget modules, initializes unhan
107
107
 
108
108
  Unit tests live in `packages/editor-worker/test` and are run by the editor-worker package's Jest setup.
109
109
 
110
- End-to-end tests live in `packages/e2e/src` and use fixture extensions from `packages/e2e/fixtures`. Before running e2e tests locally, install Chromium if needed:
110
+ End-to-end tests live in `packages/e2e/src` and use fixture extensions from `packages/e2e/fixtures`. Run `npm run build` from the repository root before launching either e2e suite: both server launchers link the local `.tmp/dist` package. Install Chromium if needed:
111
111
 
112
112
  ```sh
113
113
  cd packages/e2e
@@ -115,6 +115,8 @@ npx playwright install chromium
115
115
  npm run e2e:headless
116
116
  ```
117
117
 
118
+ The memory benchmark pins its Playwright version in `packages/build` to keep the browser runtime consistent with the memory limit. E2e tests use the browser version required by the test harness.
119
+
118
120
  ## CI and Releases
119
121
 
120
122
  Pull requests and pushes to `main` run on Ubuntu, macOS, and Windows. CI builds the worker, exports the static test build, runs unit tests, type checks, linting, e2e tests, and memory measurement.
@@ -669,6 +669,9 @@ const restoreExistingError = (error, currentStack) => {
669
669
  };
670
670
  const restoreMethodNotFoundError = (error, currentStack) => {
671
671
  const restoredError = new JsonRpcError(error.message);
672
+ Object.assign(restoredError, {
673
+ code: error.code
674
+ });
672
675
  const parentStack = getParentStack(error);
673
676
  setStack(restoredError, `${parentStack}${NewLine$1}${currentStack}`);
674
677
  return restoredError;
@@ -688,9 +691,13 @@ const applyDataProperties = (restoredError, error) => {
688
691
  // @ts-ignore
689
692
  restoredError.codeFrame = error.data.codeFrame;
690
693
  }
691
- if (error.data.code) {
694
+ if (typeof error.data.code === 'string' || typeof error.data.code === 'number') {
692
695
  // @ts-ignore
693
- restoredError.code = error.data.code;
696
+ Object.defineProperty(restoredError, 'code', {
697
+ configurable: true,
698
+ value: error.data.code,
699
+ writable: true
700
+ });
694
701
  }
695
702
  if (error.data.type) {
696
703
  // @ts-ignore
@@ -712,6 +719,13 @@ const applyDirectProperties = (restoredError, error) => {
712
719
  };
713
720
  const restoreMessageError = (error, _currentStack) => {
714
721
  const restoredError = constructError(error.message, error.type, error.name);
722
+ if (typeof error.code === 'string' || typeof error.code === 'number') {
723
+ Object.defineProperty(restoredError, 'code', {
724
+ configurable: true,
725
+ value: error.code,
726
+ writable: true
727
+ });
728
+ }
715
729
  if (error.data) {
716
730
  applyDataProperties(restoredError, error);
717
731
  } else {
@@ -790,7 +804,7 @@ const getErrorProperty = (error, prettyError) => {
790
804
  return {
791
805
  code: Custom,
792
806
  data: {
793
- code: prettyError.code,
807
+ code: prettyError.code ?? error?.code,
794
808
  codeFrame: prettyError.codeFrame,
795
809
  name: prettyError.name,
796
810
  stack: getStack(prettyError),
@@ -827,7 +841,12 @@ const getErrorResponseSimple = (id, error) => {
827
841
  return {
828
842
  error: {
829
843
  code: Custom,
830
- data: error,
844
+ data: error instanceof Error ? {
845
+ ...error,
846
+ code: 'code' in error ? error.code : undefined,
847
+ stack: error.stack,
848
+ type: error.name
849
+ } : error,
831
850
  // @ts-ignore
832
851
  message: error.message
833
852
  },
@@ -1262,7 +1281,7 @@ const CtrlCmd = 1 << 11 >>> 0;
1262
1281
  const Shift = 1 << 10 >>> 0;
1263
1282
  const Alt$1 = 1 << 9 >>> 0;
1264
1283
 
1265
- const Editor$1 = 3;
1284
+ const Editor$2 = 3;
1266
1285
  const SourceControl = 22;
1267
1286
 
1268
1287
  const Separator = 1;
@@ -1277,10 +1296,10 @@ const DragAndDropWorker = 3404;
1277
1296
  const EditorWorker = 99;
1278
1297
  const ErrorWorker = 3308;
1279
1298
  const ExtensionManagementWorker = 9006;
1280
- const IconThemeWorker = 7009;
1281
1299
  const MarkdownWorker = 300;
1282
1300
  const OpenerWorker = 4561;
1283
1301
  const RendererWorker = 1;
1302
+ const TextMeasurementWorker = 7011;
1284
1303
 
1285
1304
  const FocusSelector$1 = 'Viewlet.focusSelector';
1286
1305
  const SetCss$1 = 'Viewlet.setCss';
@@ -1396,7 +1415,7 @@ const openUrl = async (url, platform) => {
1396
1415
  const {
1397
1416
  invoke: invoke$d,
1398
1417
  set: set$b
1399
- } = create$a(IconThemeWorker);
1418
+ } = create$a(TextMeasurementWorker);
1400
1419
 
1401
1420
  const {
1402
1421
  invoke: invoke$c,
@@ -1412,7 +1431,7 @@ const showContextMenu2 = async (uid, menuId, x, y, args) => {
1412
1431
  };
1413
1432
  const sendMessagePortToDragAndDropWorker = async port => {
1414
1433
  const command = 'DragAndDrop.handleMessagePort';
1415
- await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToDragAndDropWorker', port, command);
1434
+ await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToRendererProcess', port, command);
1416
1435
  };
1417
1436
  const sendMessagePortToOpenerWorker = async (port, rpcId) => {
1418
1437
  const command = 'HandleMessagePort.handleMessagePort';
@@ -5198,6 +5217,7 @@ const createEditor2 = (id, uri, x, y, width, height, platform, assetDir, _langua
5198
5217
  primarySelectionIndex: 0,
5199
5218
  problemsHighlightedRow: -1,
5200
5219
  redoStack: [],
5220
+ roundedSelection: false,
5201
5221
  rowHeight: 0,
5202
5222
  savedSelections: [],
5203
5223
  scrollBarHeight: 0,
@@ -5507,6 +5527,7 @@ const createEditor = async ({
5507
5527
  platform,
5508
5528
  primarySelectionIndex: 0,
5509
5529
  redoStack: [],
5530
+ roundedSelection: false,
5510
5531
  rowHeight,
5511
5532
  savedSelections,
5512
5533
  scrollBarHeight: 0,
@@ -5764,6 +5785,26 @@ const dispose$2 = uid => {
5764
5785
  pendingSaves.delete(uid);
5765
5786
  };
5766
5787
 
5788
+ const getOffset = (lines, rowIndex, columnIndex) => {
5789
+ let offset = columnIndex;
5790
+ for (let i = 0; i < rowIndex; i++) {
5791
+ offset += lines[i].length + 1;
5792
+ }
5793
+ return offset;
5794
+ };
5795
+ const getSelectedChars = editor => {
5796
+ const {
5797
+ lines,
5798
+ selections
5799
+ } = editor;
5800
+ let selectedChars = 0;
5801
+ for (let i = 0; i < selections.length; i += 4) {
5802
+ const startOffset = getOffset(lines, selections[i], selections[i + 1]);
5803
+ const endOffset = getOffset(lines, selections[i + 2], selections[i + 3]);
5804
+ selectedChars += Math.abs(endOffset - startOffset);
5805
+ }
5806
+ return selectedChars;
5807
+ };
5767
5808
  const getEditorStatus = editor => {
5768
5809
  const primarySelectionIndex = editor.primarySelectionIndex || 0;
5769
5810
  const rowIndex = editor.selections[primarySelectionIndex + 2] || 0;
@@ -5775,6 +5816,7 @@ const getEditorStatus = editor => {
5775
5816
  insertSpaces: editor.insertSpaces,
5776
5817
  languageId: editor.languageId,
5777
5818
  line: rowIndex + 1,
5819
+ selectedChars: getSelectedChars(editor),
5778
5820
  tabSize: editor.tabSize
5779
5821
  };
5780
5822
  };
@@ -7428,13 +7470,15 @@ const copyLineDown = editor => {
7428
7470
  start: position
7429
7471
  };
7430
7472
  });
7431
- const selectionChanges = new Uint32Array(uniqueRows.length * 4);
7432
- for (let i = 0; i < uniqueRows.length; i++) {
7433
- const rowIndex = uniqueRows[i] + i + 1;
7434
- selectionChanges[i * 4] = rowIndex;
7435
- selectionChanges[i * 4 + 1] = 0;
7436
- selectionChanges[i * 4 + 2] = rowIndex;
7437
- selectionChanges[i * 4 + 3] = 0;
7473
+ const rowOffsets = new Map(uniqueRows.map((row, index) => [row, index + 1]));
7474
+ const selectionChanges = new Uint32Array(selections.length);
7475
+ for (let i = 0; i < selections.length; i += 4) {
7476
+ const rowIndex = selections[i] + rowOffsets.get(selections[i]);
7477
+ const columnIndex = selections[i + 1];
7478
+ selectionChanges[i] = rowIndex;
7479
+ selectionChanges[i + 1] = columnIndex;
7480
+ selectionChanges[i + 2] = rowIndex;
7481
+ selectionChanges[i + 3] = columnIndex;
7438
7482
  }
7439
7483
  return scheduleDocumentAndCursorsSelections(editor, changes, selectionChanges);
7440
7484
  };
@@ -7746,17 +7790,18 @@ const cursorDocumentStart = editor => {
7746
7790
  return scheduleSelections(editor, newSelections);
7747
7791
  };
7748
7792
 
7749
- const moveSelectionDown = (selections, i, selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn) => {
7750
- moveRangeToPosition$1(selections, i, selectionEndRow + 1, selectionEndColumn);
7793
+ const moveSelectionDown = (lastRow, selections, i, selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn) => {
7794
+ moveRangeToPosition$1(selections, i, Math.min(selectionEndRow + 1, lastRow), selectionEndColumn);
7751
7795
  };
7752
- const getNewSelections$9 = selections => {
7753
- return map(selections, moveSelectionDown);
7796
+ const getNewSelections$9 = (selections, lastRow) => {
7797
+ return map(selections, moveSelectionDown.bind(null, lastRow));
7754
7798
  };
7755
7799
  const cursorDown = editor => {
7756
7800
  const {
7801
+ lines,
7757
7802
  selections
7758
7803
  } = editor;
7759
- const newSelections = getNewSelections$9(selections);
7804
+ const newSelections = getNewSelections$9(selections, Math.max(0, lines.length - 1));
7760
7805
  return scheduleSelections(editor, newSelections);
7761
7806
  };
7762
7807
 
@@ -7868,24 +7913,60 @@ const cutLine = async editor => {
7868
7913
  rows.push(startRowIndex);
7869
7914
  }
7870
7915
  }
7871
- const replaceRange$1 = new Uint32Array(rows.length * 4);
7872
- const selectionChanges = new Uint32Array(rows.length * 4);
7916
+ rows.sort((a, b) => a - b);
7917
+ const ranges = [];
7873
7918
  const cutLines = [];
7874
- for (let i = 0; i < rows.length; i++) {
7875
- const startRowIndex = rows[i];
7876
- const line = lines[startRowIndex];
7877
- const offset = i * 4;
7878
- replaceRange$1[offset] = startRowIndex;
7879
- replaceRange$1[offset + 1] = 0;
7880
- replaceRange$1[offset + 2] = startRowIndex;
7881
- replaceRange$1[offset + 3] = line.length;
7882
- selectionChanges[offset] = startRowIndex;
7883
- selectionChanges[offset + 1] = 0;
7884
- selectionChanges[offset + 2] = startRowIndex;
7885
- selectionChanges[offset + 3] = 0;
7919
+ const removedRows = [];
7920
+ for (const row of rows) {
7921
+ const line = lines[row];
7922
+ const range = [row, 0, row, line.length];
7923
+ if (line === '' && lines.length > 1) {
7924
+ if (row < lines.length - 1) {
7925
+ range[2] = row + 1;
7926
+ } else {
7927
+ range[0] = row - 1;
7928
+ range[1] = lines[row - 1].length;
7929
+ }
7930
+ removedRows.push(row);
7931
+ }
7932
+ const previous = ranges.at(-1);
7933
+ if (previous && (range[0] < previous[2] || range[0] === previous[2] && range[1] <= previous[3])) {
7934
+ if (row === lines.length - 1 && line === '' && previous[0] > 0 && lines[previous[0]] === '') {
7935
+ previous[0]--;
7936
+ previous[1] = lines[previous[0]].length;
7937
+ }
7938
+ previous[2] = range[2];
7939
+ previous[3] = range[3];
7940
+ } else {
7941
+ ranges.push(range);
7942
+ }
7886
7943
  cutLines.push(line);
7887
7944
  }
7945
+ const mergedRanges = [];
7946
+ for (const range of ranges) {
7947
+ const previous = mergedRanges.at(-1);
7948
+ if (previous && range[0] === previous[2] && range[1] <= previous[3]) {
7949
+ previous[2] = range[2];
7950
+ previous[3] = range[3];
7951
+ } else {
7952
+ mergedRanges.push(range);
7953
+ }
7954
+ }
7955
+ const replaceRange$1 = new Uint32Array(mergedRanges.flat());
7888
7956
  const changes = replaceRange(editor, replaceRange$1, [''], EditorCut);
7957
+ const deletedRowCount = changes.reduce((count, change) => count + change.end.rowIndex - change.start.rowIndex, 0);
7958
+ const lastRow = lines.length - deletedRowCount - 1;
7959
+ const selectionChanges = new Uint32Array(rows.length * 4);
7960
+ let removedBefore = 0;
7961
+ for (let i = 0; i < rows.length; i++) {
7962
+ const row = rows[i];
7963
+ while (removedBefore < removedRows.length && removedRows[removedBefore] < row) {
7964
+ removedBefore++;
7965
+ }
7966
+ const cursorRow = Math.min(row - removedBefore, lastRow);
7967
+ selectionChanges[i * 4] = cursorRow;
7968
+ selectionChanges[i * 4 + 2] = cursorRow;
7969
+ }
7889
7970
  await writeText(joinLines(cutLines));
7890
7971
  return scheduleDocumentAndCursorsSelections(editor, changes, selectionChanges);
7891
7972
  };
@@ -8791,14 +8872,14 @@ const handleClickAtPosition = async (editor, modifier, rowIndex, columnIndex) =>
8791
8872
  };
8792
8873
  };
8793
8874
 
8794
- const Editor = 3;
8875
+ const Editor$1 = 3;
8795
8876
 
8796
8877
  const handleContextMenu = async (editor, button, x, y) => {
8797
8878
  const {
8798
8879
  uid
8799
8880
  } = editor;
8800
- await showContextMenu2(uid, Editor, x, y, {
8801
- menuId: Editor
8881
+ await showContextMenu2(uid, Editor$1, x, y, {
8882
+ menuId: Editor$1
8802
8883
  });
8803
8884
  return editor;
8804
8885
  };
@@ -10520,10 +10601,7 @@ const getSelections$1 = editorUid => {
10520
10601
  };
10521
10602
  const setSelections$1 = async (editorUid, selections) => {
10522
10603
  const editor = getEditor$1(editorUid);
10523
- const newEditor = {
10524
- ...editor,
10525
- selections
10526
- };
10604
+ const newEditor = setSelections$2(editor, selections);
10527
10605
  await updateEditor(editorUid, editor, newEditor);
10528
10606
  };
10529
10607
 
@@ -12825,14 +12903,16 @@ const handleSashPointerUp = (state, eventX, eventY) => {
12825
12903
  return state;
12826
12904
  };
12827
12905
 
12828
- const CodeGeneratorInput$1 = 'CodeGeneratorInput';
12906
+ const CodeGeneratorInput$1 = 'CodeGeneratorInput InputBox';
12829
12907
  const CodeGeneratorMessage = 'CodeGeneratorMessage';
12830
- const CodeGeneratorWidget = 'CodeGeneratorWidget';
12908
+ const CodeGeneratorWidget = 'Viewlet CodeGeneratorWidget';
12831
12909
  const DiagnosticError = 'DiagnosticError';
12832
12910
  const DiagnosticWarning = 'DiagnosticWarning';
12833
12911
  const CompletionDetailCloseButton = 'CompletionDetailCloseButton';
12834
12912
  const CompletionDetailContent = 'CompletionDetailContent';
12835
12913
  const Diagnostic = 'Diagnostic';
12914
+ const Editor = 'Viewlet Editor';
12915
+ const EditorMessage = 'Viewlet EditorMessage EditorMessageText EditorOverlayMessage';
12836
12916
  const EditorCursor = 'EditorCursor';
12837
12917
  const EditorHoverDiagnosticOnly = 'EditorHoverDiagnosticOnly';
12838
12918
  const EditorLineDecoration = 'EditorLineDecoration';
@@ -12842,14 +12922,14 @@ const EditorSelection = 'EditorSelection';
12842
12922
  const HoverDisplayString = 'HoverDisplayString';
12843
12923
  const HoverDocumentation = 'HoverDocumentation';
12844
12924
  const HoverEditorRow = 'HoverEditorRow';
12845
- const HoverProblem = 'HoverProblem';
12925
+ const HoverProblem = 'HoverDisplayString HoverProblem';
12846
12926
  const HoverProblemDetail = 'HoverProblemDetail';
12847
12927
  const HoverProblemMessage = 'HoverProblemMessage';
12848
12928
  const IconClose = 'IconClose';
12849
- const InputBox = 'InputBox';
12850
12929
  const MaskIcon = 'MaskIcon';
12851
- const SelectionUnfocused = 'SelectionUnfocused';
12852
- const Viewlet = 'Viewlet';
12930
+ const SelectionUnfocused = 'EditorSelection SelectionUnfocused';
12931
+ const TextEditorErrorIcon = 'EditorTextIcon EditorTextIconError MaskIcon MaskIconError';
12932
+ const TextEditorError = 'Viewlet TextEditorError';
12853
12933
 
12854
12934
  const HandleBeforeInput = 1;
12855
12935
  const HandleBlur = 2;
@@ -13220,7 +13300,7 @@ const getHoverVirtualDom = (lineInfos, documentation, diagnostics) => {
13220
13300
  if (diagnostics && diagnostics.length > 0) {
13221
13301
  dom.push({
13222
13302
  childCount: diagnostics.length * 2,
13223
- className: mergeClassNames(HoverDisplayString, HoverProblem),
13303
+ className: HoverProblem,
13224
13304
  type: Div
13225
13305
  });
13226
13306
  for (const diagnostic of diagnostics) {
@@ -13395,7 +13475,7 @@ const executeViewletCommand$1 = async (commandMap, uid, commandId, ...args) => {
13395
13475
  throw new TypeError(`Viewlet command not found: ${commandId}`);
13396
13476
  }
13397
13477
  await fn(uid, ...args);
13398
- await invoke$c('Viewlet.requestRender', uid);
13478
+ await invoke$c('Viewlet.executeViewletCommand', uid, '__renderPending', false);
13399
13479
  };
13400
13480
 
13401
13481
  const executeWidgetCommand = async (editor, name, method, _uid, widgetId, ...params) => {
@@ -14061,7 +14141,7 @@ const getMenuEntries = () => {
14061
14141
  };
14062
14142
 
14063
14143
  const getMenuIds = () => {
14064
- return [Editor$1];
14144
+ return [Editor$2];
14065
14145
  };
14066
14146
 
14067
14147
  const getProblems = async () => {
@@ -14247,23 +14327,14 @@ const kFontSize = 'editor.fontSize';
14247
14327
  const kFontFamily = 'editor.fontFamily';
14248
14328
  const kLetterSpacing = 'editor.letterSpacing';
14249
14329
  const kTabSize = 'editor.tabSize';
14250
- const kInsertSpaces = 'editor.insertSpaces';
14251
14330
  const kLineNumbers = 'editor.lineNumbers';
14252
14331
  const kHighlightActiveLineNumber = 'editor.highlightActiveLineNumber';
14253
- const kFormatOnSave = 'editor.formatOnSave';
14254
- const kDiagnostics = 'editor.diagnostics';
14255
14332
  const kQuickSuggestions = 'editor.quickSuggestions';
14256
14333
  const kAutoClosingQuotes = 'editor.autoClosingQuotes';
14257
14334
  const kAutoClosingBrackets = 'editor.autoClosingBrackets';
14258
14335
  const kFontWeight = 'editor.fontWeight';
14259
- const kHover = 'editor.hover';
14260
14336
  const kMinimapEnabled = 'editor.minimap.enabled';
14261
14337
  const kMergeConflictActions = 'editor.mergeConflictActions';
14262
- const kBreadcrumbsEnabled = 'breadcrumbs.enabled';
14263
- const kDragAndDropEnabled = 'editor.dragAndDrop';
14264
- const getDragAndDropEnabled = async () => {
14265
- return (await get$3(kDragAndDropEnabled)) ?? true;
14266
- };
14267
14338
  const isAutoClosingBracketsEnabled = async () => {
14268
14339
  return Boolean(await get$3(kAutoClosingBrackets));
14269
14340
  };
@@ -14282,9 +14353,6 @@ const getRowHeight = async () => {
14282
14353
  const getFontSize = async () => {
14283
14354
  return (await get$3(kFontSize)) || 15; // TODO find out if it is possible to use all numeric values for settings for efficiency, maybe settings could be an array
14284
14355
  };
14285
- const getHoverEnabled = async () => {
14286
- return (await get$3(kHover)) ?? true;
14287
- };
14288
14356
  const getFontFamily = async () => {
14289
14357
  return (await get$3(kFontFamily)) || 'Fira Code';
14290
14358
  };
@@ -14297,9 +14365,6 @@ const getLetterSpacing = async () => {
14297
14365
  const getTabSize = async () => {
14298
14366
  return (await get$3(kTabSize)) || 2;
14299
14367
  };
14300
- const getInsertSpaces = async () => {
14301
- return (await get$3(kInsertSpaces)) ?? true;
14302
- };
14303
14368
  const getLineNumbers = async () => {
14304
14369
  return (await get$3(kLineNumbers)) ?? false;
14305
14370
  };
@@ -14309,12 +14374,6 @@ const getHighlightActiveLineNumber = async () => {
14309
14374
  const getCompletionTriggerCharacters = async () => {
14310
14375
  return ['.', '/'];
14311
14376
  };
14312
- const getFormatOnSave = async () => {
14313
- return (await get$3(kFormatOnSave)) ?? false;
14314
- };
14315
- const diagnosticsEnabled = async () => {
14316
- return (await get$3(kDiagnostics)) ?? false;
14317
- };
14318
14377
  const getFontWeight = async () => {
14319
14378
  return (await get$3(kFontWeight)) ?? 400;
14320
14379
  };
@@ -14324,25 +14383,22 @@ const getMinimapEnabled = async () => {
14324
14383
  const getMergeConflictActionsEnabled = async () => {
14325
14384
  return (await get$3(kMergeConflictActions)) ?? false;
14326
14385
  };
14327
- const getBreadcrumbsEnabled = async () => {
14328
- return (await get$3(kBreadcrumbsEnabled)) ?? false;
14329
- };
14330
14386
 
14331
14387
  const getEditorPreferences = async () => {
14332
- const [diagnosticsEnabled$1, fontFamily, fontSize, fontWeight, formatOnSave, hoverEnabled, isAutoClosingBracketsEnabled$1, isAutoClosingQuotesEnabled$1, isAutoClosingTagsEnabled$1, isQuickSuggestionsEnabled$1, lineNumbers, highlightActiveLineNumber, rowHeight, tabSize, letterSpacing, completionTriggerCharacters, minimapEnabled, mergeConflictActionsEnabled, breadcrumbsEnabled, insertSpaces, dragAndDropEnabled, combineWhitespaceTokens] = await Promise.all([diagnosticsEnabled(), getFontFamily(), getFontSize(), getFontWeight(), getFormatOnSave(), getHoverEnabled(), isAutoClosingBracketsEnabled(), isAutoClosingQuotesEnabled(), isAutoClosingTagsEnabled(), isQuickSuggestionsEnabled(), getLineNumbers(), getHighlightActiveLineNumber(), getRowHeight(), getTabSize(), getLetterSpacing(), getCompletionTriggerCharacters(), getMinimapEnabled(), getMergeConflictActionsEnabled(), getBreadcrumbsEnabled(), getInsertSpaces(), getDragAndDropEnabled(), get$3('editor.combineWhitespaceTokens')]);
14388
+ const [diagnosticsEnabled, fontFamily, fontSize, fontWeight, formatOnSave, hoverEnabled, isAutoClosingBracketsEnabled$1, isAutoClosingQuotesEnabled$1, isAutoClosingTagsEnabled$1, isQuickSuggestionsEnabled$1, lineNumbers, highlightActiveLineNumber, rowHeight, tabSize, letterSpacing, completionTriggerCharacters, minimapEnabled, mergeConflictActionsEnabled, breadcrumbsEnabled, insertSpaces, dragAndDropEnabled, roundedSelection, combineWhitespaceTokens] = await Promise.all([get$3('editor.diagnostics'), getFontFamily(), getFontSize(), getFontWeight(), get$3('editor.formatOnSave'), get$3('editor.hover'), isAutoClosingBracketsEnabled(), isAutoClosingQuotesEnabled(), isAutoClosingTagsEnabled(), isQuickSuggestionsEnabled(), getLineNumbers(), getHighlightActiveLineNumber(), getRowHeight(), getTabSize(), getLetterSpacing(), getCompletionTriggerCharacters(), getMinimapEnabled(), getMergeConflictActionsEnabled(), get$3('breadcrumbs.enabled'), get$3('editor.insertSpaces'), get$3('editor.dragAndDrop'), get$3('editor.roundedSelection'), get$3('editor.combineWhitespaceTokens')]);
14333
14389
  return {
14334
- breadcrumbsEnabled,
14335
- combineWhitespaceTokens: combineWhitespaceTokens ?? false,
14390
+ breadcrumbsEnabled: breadcrumbsEnabled ?? false,
14391
+ combineWhitespaceTokens: combineWhitespaceTokens ?? true,
14336
14392
  completionTriggerCharacters,
14337
- diagnosticsEnabled: diagnosticsEnabled$1,
14338
- dragAndDropEnabled,
14393
+ diagnosticsEnabled: diagnosticsEnabled ?? false,
14394
+ dragAndDropEnabled: dragAndDropEnabled ?? true,
14339
14395
  fontFamily,
14340
14396
  fontSize,
14341
14397
  fontWeight,
14342
- formatOnSave,
14398
+ formatOnSave: formatOnSave ?? false,
14343
14399
  highlightActiveLineNumber,
14344
- hoverEnabled,
14345
- insertSpaces,
14400
+ hoverEnabled: hoverEnabled ?? true,
14401
+ insertSpaces: insertSpaces ?? true,
14346
14402
  isAutoClosingBracketsEnabled: isAutoClosingBracketsEnabled$1,
14347
14403
  isAutoClosingQuotesEnabled: isAutoClosingQuotesEnabled$1,
14348
14404
  isAutoClosingTagsEnabled: isAutoClosingTagsEnabled$1,
@@ -14351,6 +14407,7 @@ const getEditorPreferences = async () => {
14351
14407
  lineNumbers,
14352
14408
  mergeConflictActionsEnabled,
14353
14409
  minimapEnabled,
14410
+ roundedSelection: roundedSelection === true,
14354
14411
  rowHeight,
14355
14412
  tabSize
14356
14413
  };
@@ -14695,6 +14752,7 @@ const loadContent = async (state, savedState) => {
14695
14752
  lineNumbers,
14696
14753
  mergeConflictActionsEnabled,
14697
14754
  minimapEnabled,
14755
+ roundedSelection,
14698
14756
  rowHeight,
14699
14757
  tabSize
14700
14758
  } = await getEditorPreferences();
@@ -14733,6 +14791,7 @@ const loadContent = async (state, savedState) => {
14733
14791
  loadError: '',
14734
14792
  mergeConflictActionsEnabled,
14735
14793
  minimapEnabled,
14794
+ roundedSelection,
14736
14795
  rowHeight,
14737
14796
  tabSize,
14738
14797
  tokenizerId: newTokenizerId
@@ -14942,6 +15001,10 @@ const getCss = (uid, rowHeight, scrollBarHeight, scrollBarTop, scrollBarWidth, s
14942
15001
  --ScrollBarWidth: ${scrollBarWidth}px;
14943
15002
  --ScrollBarLeft: ${scrollBarLeft}px;
14944
15003
  }
15004
+ ${editorSelector} .SelectionTopLeft { border-top-left-radius: 3px; }
15005
+ ${editorSelector} .SelectionTopRight { border-top-right-radius: 3px; }
15006
+ ${editorSelector} .SelectionBottomRight { border-bottom-right-radius: 3px; }
15007
+ ${editorSelector} .SelectionBottomLeft { border-bottom-left-radius: 3px; }
14945
15008
  ${editorSelector} .EditorLayers {
14946
15009
  height: calc(100% + var(--EditorRowHeight));
14947
15010
  translate: ${translate};
@@ -15096,7 +15159,10 @@ const combineWhitespaceTokens = tokens => {
15096
15159
  const combined = [];
15097
15160
  for (let i = 0; i < tokens.length; i += 2) {
15098
15161
  const tokenText = tokens[i];
15099
- if (combined.length > 0 && /^[ \t]+$/.test(tokenText)) {
15162
+ const tokenClass = tokens[i + 1];
15163
+ const previousClass = combined.at(-1);
15164
+ // Decorations add a class after the syntax class; preserve their exact ranges.
15165
+ if (previousClass && /^[ \t]+$/.test(tokenText) && !tokenClass.includes(' ', 6) && !previousClass.includes(' ', 6)) {
15100
15166
  combined[combined.length - 2] += tokenText;
15101
15167
  } else {
15102
15168
  combined.push(tokenText, tokens[i + 1]);
@@ -15399,9 +15465,61 @@ const getEditorRowsVirtualDom = (textInfos, differences, lineNumbers = true, hig
15399
15465
  }, ...rowsDom];
15400
15466
  };
15401
15467
 
15402
- const getSelectionsVirtualDom = (selections, focused = true) => {
15468
+ const getSelectionCornerClasses = selections => {
15469
+ const edges = [new Map(), new Map()];
15470
+ for (let i = 0; i < selections.length; i += 4) {
15471
+ const [x, y, width, height] = selections.slice(i, i + 4);
15472
+ if (width <= 0 || height <= 0) {
15473
+ continue;
15474
+ }
15475
+ for (let side = 0; side < 2; side++) {
15476
+ const key = y + side * height;
15477
+ const row = edges[side].get(key) || [];
15478
+ row.push([x, x + width]);
15479
+ edges[side].set(key, row);
15480
+ }
15481
+ }
15482
+ // Prefix maxima make overlapping intervals searchable in logarithmic time.
15483
+ for (const rows of edges) {
15484
+ for (const row of rows.values()) {
15485
+ row.sort((a, b) => a[0] - b[0]);
15486
+ for (let i = 1; i < row.length; i++) {
15487
+ row[i][1] = Math.max(row[i][1], row[i - 1][1]);
15488
+ }
15489
+ }
15490
+ }
15491
+ const result = [];
15492
+ for (let i = 0; i < selections.length; i += 4) {
15493
+ const [x, y, width, height] = selections.slice(i, i + 4);
15494
+ let corners = '';
15495
+ if (width > 0 && height > 0) {
15496
+ for (const [vertical, horizontal] of [[0, 0], [0, 1], [1, 1], [1, 0]]) {
15497
+ const row = edges[1 - vertical].get(y + vertical * height) || [];
15498
+ const edge = x + horizontal * width;
15499
+ let low = 0;
15500
+ let high = row.length;
15501
+ while (low < high) {
15502
+ const mid = low + high >>> 1;
15503
+ if (horizontal ? row[mid][0] < edge : row[mid][0] <= edge) {
15504
+ low = mid + 1;
15505
+ } else {
15506
+ high = mid;
15507
+ }
15508
+ }
15509
+ if (!low || (horizontal ? row[low - 1][1] < edge : row[low - 1][1] <= edge)) {
15510
+ corners += ` Selection${vertical ? 'Bottom' : 'Top'}${horizontal ? 'Right' : 'Left'}`;
15511
+ }
15512
+ }
15513
+ }
15514
+ result.push(corners);
15515
+ }
15516
+ return result;
15517
+ };
15518
+
15519
+ const getSelectionsVirtualDom = (selections, focused = true, roundedSelection = false) => {
15520
+ const corners = roundedSelection ? getSelectionCornerClasses(selections.map(value => typeof value === 'number' ? value : Number(value.replace(/px$/, '')))) : [];
15403
15521
  const dom = [];
15404
- const className = focused ? EditorSelection : mergeClassNames(EditorSelection, SelectionUnfocused);
15522
+ const className = focused ? EditorSelection : SelectionUnfocused;
15405
15523
  for (let i = 0; i < selections.length; i += 4) {
15406
15524
  const x = selections[i];
15407
15525
  const y = selections[i + 1];
@@ -15409,7 +15527,7 @@ const getSelectionsVirtualDom = (selections, focused = true) => {
15409
15527
  const height = selections[i + 3];
15410
15528
  dom.push({
15411
15529
  childCount: 0,
15412
- className,
15530
+ className: className + (corners[i / 4] || ''),
15413
15531
  height,
15414
15532
  left: x,
15415
15533
  top: y,
@@ -15420,8 +15538,8 @@ const getSelectionsVirtualDom = (selections, focused = true) => {
15420
15538
  return dom;
15421
15539
  };
15422
15540
 
15423
- const getEditorSelectionsVirtualDom = (selectionInfos, focused = true) => {
15424
- const selectionsDom = getSelectionsVirtualDom(selectionInfos, focused);
15541
+ const getEditorSelectionsVirtualDom = (selectionInfos, focused = true, roundedSelection = false) => {
15542
+ const selectionsDom = getSelectionsVirtualDom(selectionInfos, focused, roundedSelection);
15425
15543
  return [{
15426
15544
  childCount: selectionInfos.length / 4,
15427
15545
  className: 'Selections',
@@ -15434,8 +15552,8 @@ const editorLayersNode = {
15434
15552
  className: 'EditorLayers',
15435
15553
  type: Div
15436
15554
  };
15437
- const getEditorLayersVirtualDom = (selectionInfos, textInfos, differences, lineNumbers = true, highlightedLine = -1, cursorInfos = [], diagnostics = [], visibleLineIndices = [], endOfLineDecorations = [], bracketMatchInfos = [], focused = true, visibleViewLineIndices = [], problemsHighlightedRow = -1) => {
15438
- return [editorLayersNode, ...getEditorSelectionsVirtualDom(selectionInfos, focused), ...getEditorRowsVirtualDom(textInfos, differences, lineNumbers, highlightedLine, visibleLineIndices, endOfLineDecorations, visibleViewLineIndices, problemsHighlightedRow), ...getEditorCursorsVirtualDom(cursorInfos), ...getEditorDiagnosticsVirtualDom(diagnostics, bracketMatchInfos)];
15555
+ const getEditorLayersVirtualDom = (selectionInfos, textInfos, differences, lineNumbers = true, highlightedLine = -1, cursorInfos = [], diagnostics = [], visibleLineIndices = [], endOfLineDecorations = [], bracketMatchInfos = [], focused = true, visibleViewLineIndices = [], problemsHighlightedRow = -1, roundedSelection = false) => {
15556
+ return [editorLayersNode, ...getEditorSelectionsVirtualDom(selectionInfos, focused, roundedSelection), ...getEditorRowsVirtualDom(textInfos, differences, lineNumbers, highlightedLine, visibleLineIndices, endOfLineDecorations, visibleViewLineIndices, problemsHighlightedRow), ...getEditorCursorsVirtualDom(cursorInfos), ...getEditorDiagnosticsVirtualDom(diagnostics, bracketMatchInfos)];
15439
15557
  };
15440
15558
 
15441
15559
  const getEditorScrollBarDiagnosticsVirtualDom = scrollBarDiagnostics => {
@@ -15501,13 +15619,14 @@ const getEditorContentVirtualDom = ({
15501
15619
  highlightedLine = -1,
15502
15620
  lineNumbers = true,
15503
15621
  problemsHighlightedRow = -1,
15622
+ roundedSelection = false,
15504
15623
  scrollBarDiagnostics = [],
15505
15624
  selectionInfos = [],
15506
15625
  textInfos,
15507
15626
  visibleLineIndices = [],
15508
15627
  visibleViewLineIndices = []
15509
15628
  }) => {
15510
- return [editorContentNode, ...getEditorInputVirtualDom(), ...getEditorLayersVirtualDom(selectionInfos, textInfos, differences, lineNumbers, highlightedLine, cursorInfos, diagnostics, visibleLineIndices, endOfLineDecorations, bracketMatchInfos, focused, visibleViewLineIndices, problemsHighlightedRow), ...getEditorScrollBarDiagnosticsVirtualDom(scrollBarDiagnostics), ...getScrollBarVirtualDom()];
15629
+ return [editorContentNode, ...getEditorInputVirtualDom(), ...getEditorLayersVirtualDom(selectionInfos, textInfos, differences, lineNumbers, highlightedLine, cursorInfos, diagnostics, visibleLineIndices, endOfLineDecorations, bracketMatchInfos, focused, visibleViewLineIndices, problemsHighlightedRow, roundedSelection), ...getEditorScrollBarDiagnosticsVirtualDom(scrollBarDiagnostics), ...getScrollBarVirtualDom()];
15511
15630
  };
15512
15631
 
15513
15632
  const getGutterInfoVirtualDom = (gutterInfo, activeLineNumber) => {
@@ -15624,7 +15743,7 @@ const getPrimaryCursorRowIndex = (selections, primarySelectionIndex = 0) => {
15624
15743
 
15625
15744
  const textEditorErrorIconNode = {
15626
15745
  childCount: 0,
15627
- className: mergeClassNames('EditorTextIcon', 'EditorTextIconError', 'MaskIcon', 'MaskIconError'),
15746
+ className: TextEditorErrorIcon,
15628
15747
  type: Div
15629
15748
  };
15630
15749
  const textEditorErrorMessageNode = {
@@ -15670,6 +15789,7 @@ const getEditorVirtualDom = ({
15670
15789
  minLineY = 0,
15671
15790
  primarySelectionIndex = 0,
15672
15791
  problemsHighlightedRow = -1,
15792
+ roundedSelection = false,
15673
15793
  scrollBarDiagnostics = [],
15674
15794
  selectionInfos = [],
15675
15795
  selections = new Uint32Array(),
@@ -15683,7 +15803,7 @@ const getEditorVirtualDom = ({
15683
15803
  if (loadError) {
15684
15804
  return [{
15685
15805
  childCount: 2,
15686
- className: mergeClassNames('Viewlet', 'TextEditorError'),
15806
+ className: TextEditorError,
15687
15807
  'data-uid': uid,
15688
15808
  role: Code,
15689
15809
  type: Div
@@ -15707,7 +15827,7 @@ const getEditorVirtualDom = ({
15707
15827
  }) : [];
15708
15828
  return [{
15709
15829
  childCount: (showGutter ? 2 : 1) + (minimapEnabled ? 1 : 0) + (breadcrumbsEnabled ? 1 : 0),
15710
- className: mergeClassNames('Viewlet', 'Editor'),
15830
+ className: Editor,
15711
15831
  'data-uid': uid,
15712
15832
  onContextMenu: HandleContextMenu,
15713
15833
  role: Code,
@@ -15722,6 +15842,7 @@ const getEditorVirtualDom = ({
15722
15842
  highlightedLine,
15723
15843
  lineNumbers,
15724
15844
  problemsHighlightedRow,
15845
+ roundedSelection,
15725
15846
  scrollBarDiagnostics,
15726
15847
  selectionInfos,
15727
15848
  textInfos: combineWhitespaceTokens$1 ? textInfos.map(combineWhitespaceTokens) : textInfos,
@@ -15941,10 +16062,10 @@ const renderSelections = {
15941
16062
  selectionInfos = []
15942
16063
  } = newState;
15943
16064
  const cursorsDom = getCursorsVirtualDom(cursorInfos);
15944
- const selectionsDom = getSelectionsVirtualDom(selectionInfos, newState.focused);
16065
+ const selectionsDom = getSelectionsVirtualDom(selectionInfos, newState.focused, newState.roundedSelection);
15945
16066
  return [/* method */'setSelections', cursorsDom, selectionsDom];
15946
16067
  },
15947
- isEqual: (oldState, newState) => oldState.cursorInfos === newState.cursorInfos && oldState.selectionInfos === newState.selectionInfos && oldState.focused === newState.focused
16068
+ isEqual: (oldState, newState) => oldState.cursorInfos === newState.cursorInfos && oldState.selectionInfos === newState.selectionInfos && oldState.focused === newState.focused && oldState.roundedSelection === newState.roundedSelection
15948
16069
  };
15949
16070
  const renderCss = {
15950
16071
  apply: renderCss$1,
@@ -16932,7 +17053,7 @@ const CodeGeneratorInput = 'CodeGeneratorInput';
16932
17053
 
16933
17054
  const codeGeneratorNode = {
16934
17055
  childCount: 2,
16935
- className: mergeClassNames(Viewlet, CodeGeneratorWidget),
17056
+ className: CodeGeneratorWidget,
16936
17057
  type: Div
16937
17058
  };
16938
17059
  const codeGeneratorMessageNode = {
@@ -16945,7 +17066,7 @@ const getCodeGeneratorVirtualDom = state => {
16945
17066
  const enterCode$1 = enterCode();
16946
17067
  return [codeGeneratorNode, {
16947
17068
  childCount: 0,
16948
- className: mergeClassNames(CodeGeneratorInput$1, InputBox),
17069
+ className: CodeGeneratorInput$1,
16949
17070
  name: CodeGeneratorInput,
16950
17071
  placeholder: enterCode$1,
16951
17072
  type: Input
@@ -17227,7 +17348,7 @@ const render = widget => {
17227
17348
  } = widget.newState;
17228
17349
  const dom = [{
17229
17350
  childCount: 1,
17230
- className: mergeClassNames('Viewlet', 'EditorMessage', 'EditorMessageText', 'EditorOverlayMessage'),
17351
+ className: EditorMessage,
17231
17352
  style: `left:${x}px;top:${y}px;`,
17232
17353
  type: Div
17233
17354
  }, text(message)];
@@ -5,7 +5,7 @@
5
5
  "heading": "Combine Whitespace Tokens",
6
6
  "id": "editor.combineWhitespaceTokens",
7
7
  "type": "boolean",
8
- "value": false
8
+ "value": true
9
9
  },
10
10
  {
11
11
  "category": "text-editor",
@@ -895,7 +895,7 @@
895
895
  "heading": "Rounded Selection",
896
896
  "id": "editor.roundedSelection",
897
897
  "type": "boolean",
898
- "value": "true"
898
+ "value": "false"
899
899
  },
900
900
  {
901
901
  "category": "text-editor",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/editor-worker",
3
- "version": "19.61.0",
3
+ "version": "19.61.1",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git@github.com:lvce-editor/editor-worker.git"