@lvce-editor/editor-worker 19.29.12 → 19.29.13

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.
@@ -1397,8 +1397,10 @@ const KeyJ = 38;
1397
1397
  const KeyK = 39;
1398
1398
  const KeyL = 40;
1399
1399
  const KeyO = 43;
1400
+ const KeyU = 49;
1400
1401
  const KeyV = 50;
1401
1402
  const KeyX = 52;
1403
+ const KeyY = 53;
1402
1404
  const KeyZ = 54;
1403
1405
  const F2 = 58;
1404
1406
  const F3 = 59;
@@ -4209,15 +4211,24 @@ const scheduleDocumentAndCursorsSelections = async (editor, changes, selectionCh
4209
4211
  // then clear old undostack from indexeddb after 3 days
4210
4212
  // TODO should push to undostack after rendering
4211
4213
  const autoClosingRanges = applyAutoClosingRangesEdit(editor, changes);
4214
+ const change = changes[0];
4215
+ const canCoalesceTyping = changes.length === 1 && change.origin === EditorType && change.deleted[0] === '' && change.inserted[0].length > 0 && change.inserted.length === 1 && change.start.rowIndex === change.end.rowIndex && change.start.columnIndex === change.end.columnIndex;
4216
+ const previous = editor.undoStack.at(-1)?.[0];
4217
+ const shouldCoalesce = editor.canCoalesceTyping && canCoalesceTyping && change.start.rowIndex === previous.start.rowIndex && change.start.columnIndex === previous.start.columnIndex + previous.inserted[0].length;
4218
+ const undoStack = shouldCoalesce ? [...editor.undoStack.slice(0, -1), [{
4219
+ ...previous,
4220
+ inserted: [previous.inserted[0] + change.inserted[0]]
4221
+ }]] : [...editor.undoStack, changes];
4212
4222
  const newEditor = {
4213
4223
  ...partialNewEditor,
4214
4224
  autoClosingRanges,
4225
+ canCoalesceTyping,
4215
4226
  invalidStartIndex,
4216
4227
  lines: newLines,
4217
4228
  modified: true,
4218
4229
  redoStack: [],
4219
4230
  selections: newSelections,
4220
- undoStack: [...editor.undoStack, changes]
4231
+ undoStack
4221
4232
  };
4222
4233
  // Update link decorations after text changes
4223
4234
  const linkDecorations = detectAllLinksAsDecorations(newEditor);
@@ -6406,6 +6417,21 @@ const cursorSet = (editor, rowIndex, columnIndex) => {
6406
6417
  return scheduleSelections(editor, selectionEdits);
6407
6418
  };
6408
6419
 
6420
+ const cursorUndo$1 = editor => {
6421
+ const {
6422
+ cursorUndoStack = []
6423
+ } = editor;
6424
+ if (cursorUndoStack.length === 0) {
6425
+ return editor;
6426
+ }
6427
+ const selections = cursorUndoStack.at(-1);
6428
+ const newEditor = {
6429
+ ...editor,
6430
+ cursorUndoStack: cursorUndoStack.slice(0, -1)
6431
+ };
6432
+ return scheduleSelections(newEditor, selections);
6433
+ };
6434
+
6409
6435
  const moveSelectionWithoutIntlSegmenter = (selections, i, selectionStartRow, selectionStartColumn, selectionEndRow, selectionEndColumn) => {
6410
6436
  if (selectionStartRow === 0) {
6411
6437
  moveRangeToPosition$1(selections, i, 0, 0);
@@ -6887,6 +6913,7 @@ const i18nString = (key, placeholders = emptyObject) => {
6887
6913
  };
6888
6914
 
6889
6915
  const Copy = 'Copy';
6916
+ const CursorUndo = 'Cursor Undo';
6890
6917
  const Cut = 'Cut';
6891
6918
  const DeleteLine = 'Delete Line';
6892
6919
  const EditorCloseColorPicker = 'Editor: Close Color Picker';
@@ -6921,9 +6948,11 @@ const NoDefinitionFoundFor = "No definition found for '{PH1}'";
6921
6948
  const NoTypeDefinitionFound = 'No type definition found';
6922
6949
  const NoTypeDefinitionFoundFor = "No type definition found for '{PH1}'";
6923
6950
  const Paste = 'Paste';
6951
+ const Redo = 'Redo';
6924
6952
  const SourceAction = 'Source Action';
6925
6953
  const ToggleBlockComment = 'Toggle Block Comment';
6926
6954
  const ToggleBreakpoint = 'Toggle Breakpoint';
6955
+ const Undo = 'Undo';
6927
6956
  const Unfold = 'Editor: Unfold';
6928
6957
 
6929
6958
  const goToDefinition$1 = () => {
@@ -6978,6 +7007,15 @@ const copy = () => {
6978
7007
  const paste$1 = () => {
6979
7008
  return i18nString(Paste);
6980
7009
  };
7010
+ const cursorUndo = () => {
7011
+ return i18nString(CursorUndo);
7012
+ };
7013
+ const undo$1 = () => {
7014
+ return i18nString(Undo);
7015
+ };
7016
+ const redo$1 = () => {
7017
+ return i18nString(Redo);
7018
+ };
6981
7019
  const unfold$1 = () => {
6982
7020
  return i18nString(Unfold);
6983
7021
  };
@@ -11721,6 +11759,18 @@ const getKeyBindings = () => {
11721
11759
  command: 'Editor.undo',
11722
11760
  key: CtrlCmd | KeyZ,
11723
11761
  when: FocusEditorText
11762
+ }, {
11763
+ command: 'Editor.cursorUndo',
11764
+ key: CtrlCmd | KeyU,
11765
+ when: FocusEditorText
11766
+ }, {
11767
+ command: 'Editor.redo',
11768
+ key: CtrlCmd | Shift | KeyZ,
11769
+ when: FocusEditorText
11770
+ }, {
11771
+ command: 'Editor.redo',
11772
+ key: CtrlCmd | KeyY,
11773
+ when: FocusEditorText
11724
11774
  }, {
11725
11775
  command: 'Editor.cursorLeft',
11726
11776
  key: LeftArrow,
@@ -11959,6 +12009,15 @@ const getProblems = async () => {
11959
12009
 
11960
12010
  const getQuickPickMenuEntries = () => {
11961
12011
  return [{
12012
+ id: 'Editor.undo',
12013
+ label: undo$1()
12014
+ }, {
12015
+ id: 'Editor.redo',
12016
+ label: redo$1()
12017
+ }, {
12018
+ id: 'Editor.cursorUndo',
12019
+ label: cursorUndo()
12020
+ }, {
11962
12021
  id: 'Editor.fold',
11963
12022
  label: fold()
11964
12023
  }, {
@@ -12401,6 +12460,26 @@ const getErrorMessage = error => {
12401
12460
  }
12402
12461
  return String(error);
12403
12462
  };
12463
+ const getSavedHistory = (savedState, content) => {
12464
+ if (!savedState || typeof savedState !== 'object') {
12465
+ return undefined;
12466
+ }
12467
+ const {
12468
+ lines,
12469
+ redoStack,
12470
+ undoStack
12471
+ } = savedState;
12472
+ if (!Array.isArray(lines) || lines.some(line => typeof line !== 'string') || lines.join('\n') !== content) {
12473
+ return undefined;
12474
+ }
12475
+ if (!Array.isArray(redoStack) || !Array.isArray(undoStack)) {
12476
+ return undefined;
12477
+ }
12478
+ return {
12479
+ redoStack,
12480
+ undoStack
12481
+ };
12482
+ };
12404
12483
  const loadContent = async (state, savedState) => {
12405
12484
  const {
12406
12485
  assetDir,
@@ -12484,6 +12563,7 @@ const loadContent = async (state, savedState) => {
12484
12563
  textInfos: []
12485
12564
  };
12486
12565
  }
12566
+ const savedHistory = existingEditor ? undefined : getSavedHistory(savedState, content);
12487
12567
 
12488
12568
  // TODO avoid creating intermediate editors here
12489
12569
  const newEditor1 = setBounds(newEditor0, x, y, width, height, 9);
@@ -12515,8 +12595,8 @@ const loadContent = async (state, savedState) => {
12515
12595
  completionsOnType,
12516
12596
  initial: false,
12517
12597
  modified: existingEditor?.modified || false,
12518
- redoStack: existingEditor?.redoStack || [],
12519
- undoStack: existingEditor?.undoStack || []
12598
+ redoStack: existingEditor?.redoStack || savedHistory?.redoStack || [],
12599
+ undoStack: existingEditor?.undoStack || savedHistory?.undoStack || []
12520
12600
  };
12521
12601
  return newEditor5;
12522
12602
  };
@@ -13527,10 +13607,14 @@ const renderEventListeners = () => {
13527
13607
 
13528
13608
  const saveState = (state, savedState) => {
13529
13609
  const {
13530
- lines
13610
+ lines,
13611
+ redoStack,
13612
+ undoStack
13531
13613
  } = state;
13532
13614
  return {
13533
- lines
13615
+ lines,
13616
+ redoStack,
13617
+ undoStack
13534
13618
  };
13535
13619
  };
13536
13620
 
@@ -13748,6 +13832,21 @@ const editorDiagnosticEffect = {
13748
13832
  };
13749
13833
 
13750
13834
  const queues = {};
13835
+ const cursorUndoLimit = 100;
13836
+ const selectionsEqual = (left, right) => {
13837
+ if (left === right) {
13838
+ return true;
13839
+ }
13840
+ if (left.length !== right.length) {
13841
+ return false;
13842
+ }
13843
+ for (let i = 0; i < left.length; i++) {
13844
+ if (left[i] !== right[i]) {
13845
+ return false;
13846
+ }
13847
+ }
13848
+ return true;
13849
+ };
13751
13850
  const saveAfterDelay = async (uid, token) => {
13752
13851
  if (!get$8(uid)) {
13753
13852
  consume(uid, token);
@@ -13776,7 +13875,7 @@ const saveAfterDelay = async (uid, token) => {
13776
13875
  // TODO wrap commands globally, not per editor
13777
13876
  // TODO only store editor state in editor worker, not in renderer worker also
13778
13877
 
13779
- const wrapCommand = fn => async (uid, ...args) => {
13878
+ const wrapCommand = (fn, preservesTypingCoalescing = false) => async (uid, ...args) => {
13780
13879
  const initialInstance = get$8(uid);
13781
13880
  const queueKey = initialInstance?.newState.uri || uid;
13782
13881
  const previous = queues[queueKey];
@@ -13791,7 +13890,34 @@ const wrapCommand = fn => async (uid, ...args) => {
13791
13890
  try {
13792
13891
  const oldInstance = get$8(uid);
13793
13892
  const state = oldInstance.newState;
13794
- const newEditor = await fn(state, ...args);
13893
+ const {
13894
+ cursorUndoStack,
13895
+ initial,
13896
+ isSelecting,
13897
+ lines,
13898
+ modified,
13899
+ redoStack,
13900
+ selections,
13901
+ undoStack,
13902
+ uri
13903
+ } = state;
13904
+ const commandResult = await fn(state, ...args);
13905
+ let newEditor = !preservesTypingCoalescing && commandResult.canCoalesceTyping ? {
13906
+ ...commandResult,
13907
+ canCoalesceTyping: false
13908
+ } : commandResult;
13909
+ if (lines !== newEditor.lines && newEditor.cursorUndoStack?.length) {
13910
+ newEditor = {
13911
+ ...newEditor,
13912
+ cursorUndoStack: []
13913
+ };
13914
+ } else if (selections && newEditor.selections && !isSelecting && newEditor.cursorUndoStack === cursorUndoStack && (!selectionsEqual(selections, newEditor.selections) || newEditor.isSelecting)) {
13915
+ const previousCursorUndoStack = cursorUndoStack || [];
13916
+ newEditor = {
13917
+ ...newEditor,
13918
+ cursorUndoStack: [...previousCursorUndoStack.slice(1 - cursorUndoLimit), new Uint32Array(selections)]
13919
+ };
13920
+ }
13795
13921
  if (state === newEditor) {
13796
13922
  return newEditor;
13797
13923
  }
@@ -13805,14 +13931,6 @@ const wrapCommand = fn => async (uid, ...args) => {
13805
13931
  }
13806
13932
  set$8(uid, state, finalEditor);
13807
13933
  }
13808
- const {
13809
- initial,
13810
- lines,
13811
- modified,
13812
- redoStack,
13813
- undoStack,
13814
- uri
13815
- } = state;
13816
13934
  if (!initial && uri === finalEditor.uri && (lines !== finalEditor.lines || modified !== finalEditor.modified || redoStack !== finalEditor.redoStack || undoStack !== finalEditor.undoStack)) {
13817
13935
  for (const key of getKeys$2()) {
13818
13936
  const otherUid = Number(key);
@@ -13891,6 +14009,7 @@ const commandMap = {
13891
14009
  'Editor.cursorPageDown': wrapCommand(cursorPageDown),
13892
14010
  'Editor.cursorRight': wrapCommand(cursorCharacterRight),
13893
14011
  'Editor.cursorSet': wrapCommand(cursorSet),
14012
+ 'Editor.cursorUndo': wrapCommand(cursorUndo$1),
13894
14013
  'Editor.cursorUp': wrapCommand(cursorUp),
13895
14014
  'Editor.cursorWordLeft': wrapCommand(cursorWordLeft),
13896
14015
  'Editor.cursorWordPartLeft': wrapCommand(cursorWordPartLeft),
@@ -14043,8 +14162,8 @@ const commandMap = {
14043
14162
  'Editor.toggleBreakpoint': wrapCommand(toggleBreakpoint),
14044
14163
  'Editor.toggleComment': wrapCommand(toggleComment),
14045
14164
  'Editor.toggleLineComment': wrapCommand(editorToggleLineComment),
14046
- 'Editor.type': wrapCommand(type),
14047
- 'Editor.typeWithAutoClosing': wrapCommand(typeWithAutoClosing),
14165
+ 'Editor.type': wrapCommand(type, true),
14166
+ 'Editor.typeWithAutoClosing': wrapCommand(typeWithAutoClosing, true),
14048
14167
  'Editor.undo': wrapCommand(undo),
14049
14168
  'Editor.unfold': wrapCommand(unfold),
14050
14169
  'Editor.unIndent': wrapCommand(editorUnindent),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/editor-worker",
3
- "version": "19.29.12",
3
+ "version": "19.29.13",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git@github.com:lvce-editor/editor-worker.git"