@lvce-editor/editor-worker 18.3.0 → 18.4.0

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.
@@ -553,7 +553,7 @@ const execute$1 = (command, ...args) => {
553
553
 
554
554
  const Two$1 = '2.0';
555
555
  const callbacks = Object.create(null);
556
- const get$8 = id => {
556
+ const get$9 = id => {
557
557
  return callbacks[id];
558
558
  };
559
559
  const remove$9 = id => {
@@ -702,7 +702,7 @@ const warn$1 = (...args) => {
702
702
  console.warn(...args);
703
703
  };
704
704
  const resolve = (id, response) => {
705
- const fn = get$8(id);
705
+ const fn = get$9(id);
706
706
  if (!fn) {
707
707
  console.log(response);
708
708
  warn$1(`callback ${id} may already be disposed`);
@@ -886,9 +886,9 @@ const create$h = (id, method, params) => {
886
886
  return message;
887
887
  };
888
888
 
889
- let id$1 = 0;
889
+ let id = 0;
890
890
  const create$g = () => {
891
- return ++id$1;
891
+ return ++id;
892
892
  };
893
893
 
894
894
  const registerPromise = map => {
@@ -1084,6 +1084,9 @@ const create$b = async ({
1084
1084
  return rpc;
1085
1085
  };
1086
1086
 
1087
+ const Text$1 = 12;
1088
+ const Reference = 100;
1089
+
1087
1090
  const Backspace = 1;
1088
1091
  const Tab$1 = 2;
1089
1092
  const Enter = 3;
@@ -1149,9 +1152,13 @@ const OpenerWorker = 4561;
1149
1152
  const RendererWorker$1 = 1;
1150
1153
  const TextMeasurementWorker = 7011;
1151
1154
 
1155
+ const FocusSelector = 'Viewlet.focusSelector';
1156
+ const SetCss$1 = 'Viewlet.setCss';
1152
1157
  const SetFocusContext$1 = 'Viewlet.setFocusContext';
1158
+ const SetPatches = 'Viewlet.setPatches';
1153
1159
 
1154
1160
  const FocusEditorText$1 = 12;
1161
+ const FocusExplorer = 13;
1155
1162
 
1156
1163
  const createMockRpc = ({
1157
1164
  commandMap
@@ -1177,7 +1184,7 @@ const rpcs = Object.create(null);
1177
1184
  const set$f = (id, rpc) => {
1178
1185
  rpcs[id] = rpc;
1179
1186
  };
1180
- const get$7 = id => {
1187
+ const get$8 = id => {
1181
1188
  return rpcs[id];
1182
1189
  };
1183
1190
  const remove$8 = id => {
@@ -1188,18 +1195,18 @@ const remove$8 = id => {
1188
1195
  const create$a = rpcId => {
1189
1196
  return {
1190
1197
  async dispose() {
1191
- const rpc = get$7(rpcId);
1198
+ const rpc = get$8(rpcId);
1192
1199
  await rpc.dispose();
1193
1200
  },
1194
1201
  // @ts-ignore
1195
1202
  invoke(method, ...params) {
1196
- const rpc = get$7(rpcId);
1203
+ const rpc = get$8(rpcId);
1197
1204
  // @ts-ignore
1198
1205
  return rpc.invoke(method, ...params);
1199
1206
  },
1200
1207
  // @ts-ignore
1201
1208
  invokeAndTransfer(method, ...params) {
1202
- const rpc = get$7(rpcId);
1209
+ const rpc = get$8(rpcId);
1203
1210
  // @ts-ignore
1204
1211
  return rpc.invokeAndTransfer(method, ...params);
1205
1212
  },
@@ -1715,12 +1722,12 @@ const createLazyRpc = rpcId => {
1715
1722
  return {
1716
1723
  async invoke(method, ...params) {
1717
1724
  await ensureRpc();
1718
- const rpc = get$7(rpcId);
1725
+ const rpc = get$8(rpcId);
1719
1726
  return rpc.invoke(method, ...params);
1720
1727
  },
1721
1728
  async invokeAndTransfer(method, ...params) {
1722
1729
  await ensureRpc();
1723
- const rpc = get$7(rpcId);
1730
+ const rpc = get$8(rpcId);
1724
1731
  return rpc.invokeAndTransfer(method, ...params);
1725
1732
  },
1726
1733
  setFactory(value) {
@@ -1890,8 +1897,10 @@ const loadContent$3 = async (state, parentUid) => {
1890
1897
  };
1891
1898
 
1892
1899
  const {
1900
+ get: get$7,
1893
1901
  getCommandIds,
1894
1902
  set: set$8,
1903
+ wrapCommand: wrapCommand$1,
1895
1904
  wrapGetter
1896
1905
  } = create$9();
1897
1906
 
@@ -1938,6 +1947,7 @@ const createEditor2 = (id, uri, x, y, width, height, platform, assetDir) => {
1938
1947
  highlightedLine: -1,
1939
1948
  id,
1940
1949
  incrementalEdits: emptyIncrementalEdits,
1950
+ initial: true,
1941
1951
  invalidStartIndex: 0,
1942
1952
  isAutoClosingBracketsEnabled: false,
1943
1953
  isAutoClosingQuotesEnabled: false,
@@ -2045,7 +2055,7 @@ const get$5 = id => {
2045
2055
  number(id);
2046
2056
  return editors[id];
2047
2057
  };
2048
- const getKeys$1 = () => {
2058
+ const getKeys$2 = () => {
2049
2059
  return Object.keys(editors);
2050
2060
  };
2051
2061
  const set$6 = (id, oldEditor, newEditor) => {
@@ -3354,7 +3364,7 @@ const notifyListeners = async (listenerType, method, ...params) => {
3354
3364
  // Notify all listeners in parallel
3355
3365
  const notifications = rpcIds.map(async rpcId => {
3356
3366
  try {
3357
- const rpc = get$7(rpcId);
3367
+ const rpc = get$8(rpcId);
3358
3368
  if (rpc) {
3359
3369
  await rpc.invoke(method, ...params);
3360
3370
  }
@@ -4391,6 +4401,46 @@ const createEditor = async ({
4391
4401
  });
4392
4402
  };
4393
4403
 
4404
+ const isEqual$2 = (oldState, newState) => {
4405
+ return oldState.itemHeight === newState.itemHeight;
4406
+ };
4407
+
4408
+ const isEqual$1 = (oldState, newState) => {
4409
+ return oldState.focused === newState.focused && oldState.focus === newState.focus;
4410
+ };
4411
+
4412
+ const isEqual = (oldState, newState) => {
4413
+ return oldState.lines === newState.lines && oldState.textInfos === newState.textInfos && oldState.differences === newState.differences && oldState.initial === newState.initial;
4414
+ };
4415
+
4416
+ const RenderFocus = 6;
4417
+ const RenderFocusContext = 7;
4418
+ const RenderCss = 11;
4419
+ const RenderIncremental = 12;
4420
+
4421
+ const modules = [isEqual, isEqual$1, isEqual$1, isEqual$2];
4422
+ const numbers = [RenderIncremental, RenderFocus, RenderFocusContext, RenderCss];
4423
+
4424
+ const diff = (oldState, newState) => {
4425
+ const diffResult = [];
4426
+ for (let i = 0; i < modules.length; i++) {
4427
+ const fn = modules[i];
4428
+ if (!fn(oldState, newState)) {
4429
+ diffResult.push(numbers[i]);
4430
+ }
4431
+ }
4432
+ return diffResult;
4433
+ };
4434
+
4435
+ const diff2 = uid => {
4436
+ const {
4437
+ newState,
4438
+ oldState
4439
+ } = get$7(uid);
4440
+ const result = diff(oldState, newState);
4441
+ return result;
4442
+ };
4443
+
4394
4444
  // @ts-ignore
4395
4445
  const getNewSelections$c = selections => {
4396
4446
  const newSelections = [];
@@ -7325,18 +7375,18 @@ const launchFindWidgetWorker = async () => {
7325
7375
  const rpcId = 9002;
7326
7376
  const launch = async () => {
7327
7377
  // TODO race condition
7328
- if (get$7(rpcId)) {
7378
+ if (get$8(rpcId)) {
7329
7379
  return;
7330
7380
  }
7331
7381
  const rpc = await launchFindWidgetWorker();
7332
7382
  set$f(rpcId, rpc);
7333
7383
  };
7334
7384
  const invoke$3 = async (method, ...params) => {
7335
- const rpc = get$7(rpcId);
7385
+ const rpc = get$8(rpcId);
7336
7386
  return await rpc.invoke(method, ...params);
7337
7387
  };
7338
7388
  const dispose = async () => {
7339
- const rpc = get$7(rpcId);
7389
+ const rpc = get$8(rpcId);
7340
7390
  remove$8(rpcId);
7341
7391
  if (rpc) {
7342
7392
  await rpc.dispose();
@@ -10637,8 +10687,8 @@ const getKeyBindings = () => {
10637
10687
  }];
10638
10688
  };
10639
10689
 
10640
- const getKeys = () => {
10641
- return getKeys$1();
10690
+ const getKeys$1 = () => {
10691
+ return getKeys$2();
10642
10692
  };
10643
10693
 
10644
10694
  /**
@@ -10723,7 +10773,7 @@ const getDiagnostics = editor => {
10723
10773
  const getProblems = async () => {
10724
10774
  // TODO maybe combine querying diagnostics for problems view with diagnostics for editor
10725
10775
  // or query the diagnostics for the problems view directtly from the extension host worker
10726
- const keys = getKeys$1();
10776
+ const keys = getKeys$2();
10727
10777
  const editors = keys.map(key => {
10728
10778
  const numericKey = parseInt(key);
10729
10779
  const editor = get$5(numericKey);
@@ -10935,7 +10985,7 @@ const hotReload = async () => {
10935
10985
  isReloading = true;
10936
10986
 
10937
10987
  // TODO use getEditors
10938
- const keys = getKeys$1();
10988
+ const keys = getKeys$2();
10939
10989
  const savedStates = await saveWidgetState(keys);
10940
10990
  await relaunchWorkers();
10941
10991
  const newEditors = await restoreWidgetState(keys, savedStates);
@@ -11075,21 +11125,103 @@ const intialize = async (syntaxHighlightingEnabled, syncIncremental) => {
11075
11125
  await Promise.all([initializeSyntaxHighlighting(syntaxHighlightingEnabled, syncIncremental), initializeExtensionHost(), initializeExtensionManagementWorker(), initializeTextMeasurementWorker(), initializeOpenerWorker()]);
11076
11126
  };
11077
11127
 
11078
- const loadContent = async (state, savedState) => {
11079
- const {
11080
- assetDir,
11081
- diagnosticsEnabled,
11128
+ const kLineHeight = 'editor.lineHeight';
11129
+ const kFontSize = 'editor.fontSize';
11130
+ const kFontFamily = 'editor.fontFamily';
11131
+ const kTabSize = 'editor.tabSize';
11132
+ const kLineNumbers = 'editor.lineNumbers';
11133
+ const kDiagnostics = 'editor.diagnostics';
11134
+ const kQuickSuggestions = 'editor.quickSuggestions';
11135
+ const kAutoClosingQuotes = 'editor.autoClosingQuotes';
11136
+ const kAutoClosingBrackets = 'editor.autoclosingBrackets';
11137
+ const kFontWeight = 'editor.fontWeight';
11138
+ const isAutoClosingBracketsEnabled = async () => {
11139
+ return Boolean(await get$1(kAutoClosingBrackets));
11140
+ };
11141
+ const isAutoClosingQuotesEnabled = async () => {
11142
+ return Boolean(await get$1(kAutoClosingQuotes));
11143
+ };
11144
+ const isQuickSuggestionsEnabled = async () => {
11145
+ return Boolean(await get$1(kQuickSuggestions));
11146
+ };
11147
+ const isAutoClosingTagsEnabled = async () => {
11148
+ return true;
11149
+ };
11150
+ const getRowHeight = async () => {
11151
+ return (await get$1(kLineHeight)) || 20;
11152
+ };
11153
+ const getFontSize = async () => {
11154
+ return (await get$1(kFontSize)) || 15; // TODO find out if it is possible to use all numeric values for settings for efficiency, maybe settings could be an array
11155
+ };
11156
+ const getFontFamily = async () => {
11157
+ return (await get$1(kFontFamily)) || 'Fira Code';
11158
+ };
11159
+ const getLetterSpacing = async () => {
11160
+ {
11161
+ return 0;
11162
+ }
11163
+ };
11164
+ const getTabSize = async () => {
11165
+ return (await get$1(kTabSize)) || 2;
11166
+ };
11167
+ const getLineNumbers = async () => {
11168
+ return (await get$1(kLineNumbers)) ?? false;
11169
+ };
11170
+ const getCompletionTriggerCharacters = async () => {
11171
+ return ['.', '/'];
11172
+ };
11173
+ const diagnosticsEnabled = async () => {
11174
+ return (await get$1(kDiagnostics)) ?? false;
11175
+ };
11176
+ const getFontWeight = async () => {
11177
+ return (await get$1(kFontWeight)) ?? 400;
11178
+ };
11179
+
11180
+ const getEditorPreferences = async () => {
11181
+ const [diagnosticsEnabled$1, fontFamily, fontSize, fontWeight, isAutoClosingBracketsEnabled$1, isAutoClosingQuotesEnabled$1, isAutoClosingTagsEnabled$1, isQuickSuggestionsEnabled$1, lineNumbers, rowHeight, tabSize, letterSpacing, completionTriggerCharacters] = await Promise.all([diagnosticsEnabled(), getFontFamily(), getFontSize(), getFontWeight(), isAutoClosingBracketsEnabled(), isAutoClosingQuotesEnabled(), isAutoClosingTagsEnabled(), isQuickSuggestionsEnabled(), getLineNumbers(), getRowHeight(), getTabSize(), getLetterSpacing(), getCompletionTriggerCharacters()]);
11182
+ return {
11183
+ completionTriggerCharacters,
11184
+ diagnosticsEnabled: diagnosticsEnabled$1,
11082
11185
  fontFamily,
11083
11186
  fontSize,
11084
11187
  fontWeight,
11085
- height,
11188
+ isAutoClosingBracketsEnabled: isAutoClosingBracketsEnabled$1,
11189
+ isAutoClosingQuotesEnabled: isAutoClosingQuotesEnabled$1,
11190
+ isAutoClosingTagsEnabled: isAutoClosingTagsEnabled$1,
11191
+ isQuickSuggestionsEnabled: isQuickSuggestionsEnabled$1,
11086
11192
  letterSpacing,
11193
+ lineNumbers,
11194
+ rowHeight,
11195
+ tabSize
11196
+ };
11197
+ };
11198
+
11199
+ const loadContent = async (state, savedState) => {
11200
+ const {
11201
+ assetDir,
11202
+ height,
11203
+ id,
11087
11204
  platform,
11088
11205
  uri,
11089
11206
  width,
11090
11207
  x,
11091
11208
  y
11092
11209
  } = state;
11210
+ const {
11211
+ completionTriggerCharacters,
11212
+ diagnosticsEnabled,
11213
+ fontFamily,
11214
+ fontSize,
11215
+ fontWeight,
11216
+ isAutoClosingBracketsEnabled,
11217
+ isAutoClosingQuotesEnabled,
11218
+ isAutoClosingTagsEnabled,
11219
+ isQuickSuggestionsEnabled,
11220
+ letterSpacing,
11221
+ lineNumbers,
11222
+ rowHeight,
11223
+ tabSize
11224
+ } = await getEditorPreferences();
11093
11225
  // TODO support overwriting language id by setting it explicitly or via settings
11094
11226
  const charWidth = await measureCharacterWidth(fontWeight, fontSize, fontFamily, letterSpacing);
11095
11227
  const languages = await getLanguages(platform, assetDir);
@@ -11097,7 +11229,20 @@ const loadContent = async (state, savedState) => {
11097
11229
  const newEditor0 = {
11098
11230
  ...state,
11099
11231
  charWidth,
11100
- languageId: computedlanguageId
11232
+ completionTriggerCharacters,
11233
+ diagnosticsEnabled,
11234
+ fontFamily,
11235
+ fontSize,
11236
+ fontWeight,
11237
+ isAutoClosingBracketsEnabled,
11238
+ isAutoClosingQuotesEnabled,
11239
+ isAutoClosingTagsEnabled,
11240
+ isQuickSuggestionsEnabled,
11241
+ languageId: computedlanguageId,
11242
+ letterSpacing,
11243
+ lineNumbers,
11244
+ rowHeight,
11245
+ tabSize
11101
11246
  };
11102
11247
  const content = await readFile(uri);
11103
11248
 
@@ -11128,7 +11273,7 @@ const loadContent = async (state, savedState) => {
11128
11273
  // TODO only sync when needed
11129
11274
  // e.g. it might not always be necessary to send text to extension host worker
11130
11275
  // @ts-ignore
11131
- await invoke$6(TextDocumentSyncFull, uri, id, languageId, content);
11276
+ await invoke$6(TextDocumentSyncFull, uri, id, computedlanguageId, content);
11132
11277
 
11133
11278
  // TODO await promise
11134
11279
  if (diagnosticsEnabled) {
@@ -11138,7 +11283,8 @@ const loadContent = async (state, savedState) => {
11138
11283
  const completionsOnType = Boolean(completionsOnTypeRaw);
11139
11284
  const newEditor5 = {
11140
11285
  ...newEditor4,
11141
- completionsOnType
11286
+ completionsOnType,
11287
+ initial: false
11142
11288
  };
11143
11289
  return newEditor5;
11144
11290
  };
@@ -11209,6 +11355,319 @@ const registerListener = (listenerType, rpcId) => {
11209
11355
  registerListener$1(listenerType, rpcId);
11210
11356
  };
11211
11357
 
11358
+ const getCss = itemHeight => {
11359
+ return `:root {
11360
+ --ActivityBarItemHeight: var(--${itemHeight}px);
11361
+ }
11362
+ `;
11363
+ };
11364
+
11365
+ const renderCss = (oldState, newState) => {
11366
+ const {
11367
+ itemHeight,
11368
+ uid
11369
+ } = newState;
11370
+ const css = getCss(itemHeight);
11371
+ return [SetCss$1, uid, css];
11372
+ };
11373
+
11374
+ const renderFocus$2 = (oldState, newState) => {
11375
+ const selector = '.EditorInput';
11376
+ return [FocusSelector, newState.uid, selector];
11377
+ };
11378
+
11379
+ const renderFocusContext$1 = (oldState, newState) => {
11380
+ return [SetFocusContext$1, newState.uid, FocusExplorer];
11381
+ };
11382
+
11383
+ const SetText = 1;
11384
+ const Replace = 2;
11385
+ const SetAttribute = 3;
11386
+ const RemoveAttribute = 4;
11387
+ const Add = 6;
11388
+ const NavigateChild = 7;
11389
+ const NavigateParent = 8;
11390
+ const RemoveChild = 9;
11391
+ const NavigateSibling = 10;
11392
+ const SetReferenceNodeUid = 11;
11393
+
11394
+ const isKey = key => {
11395
+ return key !== 'type' && key !== 'childCount';
11396
+ };
11397
+
11398
+ const getKeys = node => {
11399
+ const keys = Object.keys(node).filter(isKey);
11400
+ return keys;
11401
+ };
11402
+
11403
+ const arrayToTree = nodes => {
11404
+ const result = [];
11405
+ let i = 0;
11406
+ while (i < nodes.length) {
11407
+ const node = nodes[i];
11408
+ const {
11409
+ children,
11410
+ nodesConsumed
11411
+ } = getChildrenWithCount(nodes, i + 1, node.childCount || 0);
11412
+ result.push({
11413
+ node,
11414
+ children
11415
+ });
11416
+ i += 1 + nodesConsumed;
11417
+ }
11418
+ return result;
11419
+ };
11420
+ const getChildrenWithCount = (nodes, startIndex, childCount) => {
11421
+ if (childCount === 0) {
11422
+ return {
11423
+ children: [],
11424
+ nodesConsumed: 0
11425
+ };
11426
+ }
11427
+ const children = [];
11428
+ let i = startIndex;
11429
+ let remaining = childCount;
11430
+ let totalConsumed = 0;
11431
+ while (remaining > 0 && i < nodes.length) {
11432
+ const node = nodes[i];
11433
+ const nodeChildCount = node.childCount || 0;
11434
+ const {
11435
+ children: nodeChildren,
11436
+ nodesConsumed
11437
+ } = getChildrenWithCount(nodes, i + 1, nodeChildCount);
11438
+ children.push({
11439
+ node,
11440
+ children: nodeChildren
11441
+ });
11442
+ const nodeSize = 1 + nodesConsumed;
11443
+ i += nodeSize;
11444
+ totalConsumed += nodeSize;
11445
+ remaining--;
11446
+ }
11447
+ return {
11448
+ children,
11449
+ nodesConsumed: totalConsumed
11450
+ };
11451
+ };
11452
+
11453
+ const compareNodes = (oldNode, newNode) => {
11454
+ const patches = [];
11455
+ // Check if node type changed - return null to signal incompatible nodes
11456
+ // (caller should handle this with a Replace operation)
11457
+ if (oldNode.type !== newNode.type) {
11458
+ return null;
11459
+ }
11460
+ // Handle reference nodes - special handling for uid changes
11461
+ if (oldNode.type === Reference) {
11462
+ if (oldNode.uid !== newNode.uid) {
11463
+ patches.push({
11464
+ type: SetReferenceNodeUid,
11465
+ uid: newNode.uid
11466
+ });
11467
+ }
11468
+ return patches;
11469
+ }
11470
+ // Handle text nodes
11471
+ if (oldNode.type === Text$1 && newNode.type === Text$1) {
11472
+ if (oldNode.text !== newNode.text) {
11473
+ patches.push({
11474
+ type: SetText,
11475
+ value: newNode.text
11476
+ });
11477
+ }
11478
+ return patches;
11479
+ }
11480
+ // Compare attributes
11481
+ const oldKeys = getKeys(oldNode);
11482
+ const newKeys = getKeys(newNode);
11483
+ // Check for attribute changes
11484
+ for (const key of newKeys) {
11485
+ if (oldNode[key] !== newNode[key]) {
11486
+ patches.push({
11487
+ type: SetAttribute,
11488
+ key,
11489
+ value: newNode[key]
11490
+ });
11491
+ }
11492
+ }
11493
+ // Check for removed attributes
11494
+ for (const key of oldKeys) {
11495
+ if (!(key in newNode)) {
11496
+ patches.push({
11497
+ type: RemoveAttribute,
11498
+ key
11499
+ });
11500
+ }
11501
+ }
11502
+ return patches;
11503
+ };
11504
+
11505
+ const treeToArray = node => {
11506
+ const result = [node.node];
11507
+ for (const child of node.children) {
11508
+ result.push(...treeToArray(child));
11509
+ }
11510
+ return result;
11511
+ };
11512
+
11513
+ const diffChildren = (oldChildren, newChildren, patches) => {
11514
+ const maxLength = Math.max(oldChildren.length, newChildren.length);
11515
+ // Track where we are: -1 means at parent, >= 0 means at child index
11516
+ let currentChildIndex = -1;
11517
+ // Collect indices of children to remove (we'll add these patches at the end in reverse order)
11518
+ const indicesToRemove = [];
11519
+ for (let i = 0; i < maxLength; i++) {
11520
+ const oldNode = oldChildren[i];
11521
+ const newNode = newChildren[i];
11522
+ if (!oldNode && !newNode) {
11523
+ continue;
11524
+ }
11525
+ if (!oldNode) {
11526
+ // Add new node - we should be at the parent
11527
+ if (currentChildIndex >= 0) {
11528
+ // Navigate back to parent
11529
+ patches.push({
11530
+ type: NavigateParent
11531
+ });
11532
+ currentChildIndex = -1;
11533
+ }
11534
+ // Flatten the entire subtree so renderInternal can handle it
11535
+ const flatNodes = treeToArray(newNode);
11536
+ patches.push({
11537
+ type: Add,
11538
+ nodes: flatNodes
11539
+ });
11540
+ } else if (newNode) {
11541
+ // Compare nodes to see if we need any patches
11542
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
11543
+ // If nodePatches is null, the node types are incompatible - need to replace
11544
+ if (nodePatches === null) {
11545
+ // Navigate to this child
11546
+ if (currentChildIndex === -1) {
11547
+ patches.push({
11548
+ type: NavigateChild,
11549
+ index: i
11550
+ });
11551
+ currentChildIndex = i;
11552
+ } else if (currentChildIndex !== i) {
11553
+ patches.push({
11554
+ type: NavigateSibling,
11555
+ index: i
11556
+ });
11557
+ currentChildIndex = i;
11558
+ }
11559
+ // Replace the entire subtree
11560
+ const flatNodes = treeToArray(newNode);
11561
+ patches.push({
11562
+ type: Replace,
11563
+ nodes: flatNodes
11564
+ });
11565
+ // After replace, we're at the new element (same position)
11566
+ continue;
11567
+ }
11568
+ // Check if we need to recurse into children
11569
+ const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
11570
+ // Only navigate to this element if we need to do something
11571
+ if (nodePatches.length > 0 || hasChildrenToCompare) {
11572
+ // Navigate to this child if not already there
11573
+ if (currentChildIndex === -1) {
11574
+ patches.push({
11575
+ type: NavigateChild,
11576
+ index: i
11577
+ });
11578
+ currentChildIndex = i;
11579
+ } else if (currentChildIndex !== i) {
11580
+ patches.push({
11581
+ type: NavigateSibling,
11582
+ index: i
11583
+ });
11584
+ currentChildIndex = i;
11585
+ }
11586
+ // Apply node patches (these apply to the current element, not children)
11587
+ if (nodePatches.length > 0) {
11588
+ patches.push(...nodePatches);
11589
+ }
11590
+ // Compare children recursively
11591
+ if (hasChildrenToCompare) {
11592
+ diffChildren(oldNode.children, newNode.children, patches);
11593
+ }
11594
+ }
11595
+ } else {
11596
+ // Remove old node - collect the index for later removal
11597
+ indicesToRemove.push(i);
11598
+ }
11599
+ }
11600
+ // Navigate back to parent if we ended at a child
11601
+ if (currentChildIndex >= 0) {
11602
+ patches.push({
11603
+ type: NavigateParent
11604
+ });
11605
+ currentChildIndex = -1;
11606
+ }
11607
+ // Add remove patches in reverse order (highest index first)
11608
+ // This ensures indices remain valid as we remove
11609
+ for (let j = indicesToRemove.length - 1; j >= 0; j--) {
11610
+ patches.push({
11611
+ type: RemoveChild,
11612
+ index: indicesToRemove[j]
11613
+ });
11614
+ }
11615
+ };
11616
+ const diffTrees = (oldTree, newTree, patches, path) => {
11617
+ // At the root level (path.length === 0), we're already AT the element
11618
+ // So we compare the root node directly, then compare its children
11619
+ if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
11620
+ const oldNode = oldTree[0];
11621
+ const newNode = newTree[0];
11622
+ // Compare root nodes
11623
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
11624
+ // If nodePatches is null, the root node types are incompatible - need to replace
11625
+ if (nodePatches === null) {
11626
+ const flatNodes = treeToArray(newNode);
11627
+ patches.push({
11628
+ type: Replace,
11629
+ nodes: flatNodes
11630
+ });
11631
+ return;
11632
+ }
11633
+ if (nodePatches.length > 0) {
11634
+ patches.push(...nodePatches);
11635
+ }
11636
+ // Compare children
11637
+ if (oldNode.children.length > 0 || newNode.children.length > 0) {
11638
+ diffChildren(oldNode.children, newNode.children, patches);
11639
+ }
11640
+ } else {
11641
+ // Non-root level or multiple root elements - use the regular comparison
11642
+ diffChildren(oldTree, newTree, patches);
11643
+ }
11644
+ };
11645
+
11646
+ const removeTrailingNavigationPatches = patches => {
11647
+ // Find the last non-navigation patch
11648
+ let lastNonNavigationIndex = -1;
11649
+ for (let i = patches.length - 1; i >= 0; i--) {
11650
+ const patch = patches[i];
11651
+ if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
11652
+ lastNonNavigationIndex = i;
11653
+ break;
11654
+ }
11655
+ }
11656
+ // Return patches up to and including the last non-navigation patch
11657
+ return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
11658
+ };
11659
+
11660
+ const diffTree = (oldNodes, newNodes) => {
11661
+ // Step 1: Convert flat arrays to tree structures
11662
+ const oldTree = arrayToTree(oldNodes);
11663
+ const newTree = arrayToTree(newNodes);
11664
+ // Step 3: Compare the trees
11665
+ const patches = [];
11666
+ diffTrees(oldTree, newTree, patches, []);
11667
+ // Remove trailing navigation patches since they serve no purpose
11668
+ return removeTrailingNavigationPatches(patches);
11669
+ };
11670
+
11212
11671
  const getCursorsVirtualDom = cursors => {
11213
11672
  const dom = [];
11214
11673
  for (const translate of cursors) {
@@ -11324,6 +11783,133 @@ const getSelectionsVirtualDom = selections => {
11324
11783
  return dom;
11325
11784
  };
11326
11785
 
11786
+ const getEditorVirtualDom = ({
11787
+ cursorInfos = [],
11788
+ diagnostics = [],
11789
+ differences,
11790
+ gutterInfos = [],
11791
+ highlightedLine = -1,
11792
+ lineNumbers = true,
11793
+ scrollBarDiagnostics = [],
11794
+ selectionInfos = [],
11795
+ textInfos
11796
+ }) => {
11797
+ const cursorInfosArray = [...cursorInfos];
11798
+ const diagnosticsArray = [...diagnostics];
11799
+ const gutterInfosArray = [...gutterInfos];
11800
+ const scrollBarDiagnosticsArray = [...scrollBarDiagnostics];
11801
+ const rowsDom = getEditorRowsVirtualDom(textInfos, differences, lineNumbers, highlightedLine);
11802
+ const cursorsDom = getCursorsVirtualDom(cursorInfosArray);
11803
+ const selectionsDom = getSelectionsVirtualDom(selectionInfos);
11804
+ const diagnosticsDom = getDiagnosticsVirtualDom(diagnosticsArray);
11805
+ const gutterDom = getEditorGutterVirtualDom(gutterInfosArray);
11806
+ const scrollBarDiagnosticsDom = getDiagnosticsVirtualDom(scrollBarDiagnosticsArray);
11807
+ return [{
11808
+ childCount: 2,
11809
+ className: 'Viewlet Editor',
11810
+ role: 'code',
11811
+ type: Div
11812
+ }, {
11813
+ childCount: gutterInfosArray.length,
11814
+ className: 'Gutter',
11815
+ type: Div
11816
+ }, ...gutterDom, {
11817
+ childCount: 4,
11818
+ className: 'EditorContent',
11819
+ type: Div
11820
+ }, {
11821
+ childCount: 4,
11822
+ className: 'EditorLayers',
11823
+ type: Div
11824
+ }, {
11825
+ childCount: selectionsDom.length,
11826
+ className: 'Selections',
11827
+ type: Div
11828
+ }, ...selectionsDom, {
11829
+ childCount: textInfos.length,
11830
+ className: 'EditorRows',
11831
+ type: Div
11832
+ }, ...rowsDom, {
11833
+ childCount: cursorsDom.length,
11834
+ className: 'LayerCursor',
11835
+ type: Div
11836
+ }, ...cursorsDom, {
11837
+ childCount: diagnosticsDom.length,
11838
+ className: 'LayerDiagnostics',
11839
+ type: Div
11840
+ }, ...diagnosticsDom, {
11841
+ childCount: scrollBarDiagnosticsDom.length,
11842
+ className: 'EditorScrollBarDiagnostics',
11843
+ type: Div
11844
+ }, ...scrollBarDiagnosticsDom, {
11845
+ childCount: 1,
11846
+ className: 'ScrollBar ScrollBarVertical',
11847
+ type: Div
11848
+ }, {
11849
+ childCount: 0,
11850
+ className: 'ScrollBarThumb ScrollBarThumbVertical',
11851
+ type: Div
11852
+ }, {
11853
+ childCount: 1,
11854
+ className: 'ScrollBar ScrollBarHorizontal',
11855
+ type: Div
11856
+ }, {
11857
+ childCount: 0,
11858
+ className: 'ScrollBarThumb ScrollBarThumbHorizontal',
11859
+ type: Div
11860
+ }];
11861
+ };
11862
+
11863
+ const getDom = state => {
11864
+ if (state.initial) {
11865
+ return [];
11866
+ }
11867
+ return getEditorVirtualDom(state);
11868
+ };
11869
+ const renderIncremental = (oldState, newState) => {
11870
+ const oldDom = getDom(oldState);
11871
+ const newDom = getDom(newState);
11872
+ const patches = diffTree(oldDom, newDom);
11873
+ return [SetPatches, newState.uid, patches];
11874
+ };
11875
+
11876
+ const getRenderer = diffType => {
11877
+ switch (diffType) {
11878
+ case RenderCss:
11879
+ return renderCss;
11880
+ case RenderFocus:
11881
+ return renderFocus$2;
11882
+ case RenderFocusContext:
11883
+ return renderFocusContext$1;
11884
+ case RenderIncremental:
11885
+ return renderIncremental;
11886
+ default:
11887
+ throw new Error('unknown renderer');
11888
+ }
11889
+ };
11890
+
11891
+ const applyRender = (oldState, newState, diffResult) => {
11892
+ const commands = [];
11893
+ for (const item of diffResult) {
11894
+ const fn = getRenderer(item);
11895
+ const result = fn(oldState, newState);
11896
+ if (result.length > 0) {
11897
+ commands.push(result);
11898
+ }
11899
+ }
11900
+ return commands;
11901
+ };
11902
+
11903
+ const render2 = (uid, diffResult) => {
11904
+ const {
11905
+ newState,
11906
+ oldState
11907
+ } = get$7(uid);
11908
+ set$8(uid, newState, newState);
11909
+ const commands = applyRender(oldState, newState, diffResult);
11910
+ return commands;
11911
+ };
11912
+
11327
11913
  const addWidget = widget => {
11328
11914
  const module = get$6(widget.id);
11329
11915
  if (!module) {
@@ -11607,7 +12193,7 @@ const unregisterListener = (listenerType, rpcId) => {
11607
12193
  };
11608
12194
 
11609
12195
  const invoke = async (method, ...params) => {
11610
- const worker = get$7(DebugWorker);
12196
+ const worker = get$8(DebugWorker);
11611
12197
  return worker.invoke(method, ...params);
11612
12198
  };
11613
12199
 
@@ -11617,7 +12203,7 @@ const getDebugHighlight = async debugId => {
11617
12203
  };
11618
12204
 
11619
12205
  const getKey = () => {
11620
- const keys = getKeys$1();
12206
+ const keys = getKeys$2();
11621
12207
  return parseInt(keys[0]);
11622
12208
  };
11623
12209
  const updateDebugInfo = async debugId => {
@@ -11715,13 +12301,14 @@ const commandMap = {
11715
12301
  'Editor.deleteWordPartLeft': wrapCommand(deleteWordPartLeft),
11716
12302
  'Editor.deleteWordPartRight': wrapCommand(deleteWordPartRight),
11717
12303
  'Editor.deleteWordRight': wrapCommand(deleteWordRight),
12304
+ 'Editor.diff2': diff2,
11718
12305
  'Editor.executeWidgetCommand': wrapCommand(executeWidgetCommand),
11719
12306
  'Editor.findAllReferences': wrapCommand(findAllReferences$1),
11720
12307
  'Editor.format': wrapCommand(format),
11721
12308
  'Editor.getCommandIds': getCommandIds,
11722
12309
  'Editor.getDiagnostics': getDiagnostics$1,
11723
12310
  'Editor.getKeyBindings': getKeyBindings,
11724
- 'Editor.getKeys': getKeys,
12311
+ 'Editor.getKeys': getKeys$1,
11725
12312
  'Editor.getLanguageId': getLanguageId,
11726
12313
  'Editor.getLines2': getLines2,
11727
12314
  'Editor.getMenuEntries': getMenuEntries,
@@ -11773,7 +12360,7 @@ const commandMap = {
11773
12360
  'Editor.indendLess': wrapCommand(indentLess),
11774
12361
  'Editor.indentMore': wrapCommand(indentMore),
11775
12362
  'Editor.insertLineBreak': wrapCommand(insertLineBreak),
11776
- 'Editor.loadContent': loadContent,
12363
+ 'Editor.loadContent': wrapCommand$1(loadContent),
11777
12364
  'Editor.moveLineDown': wrapCommand(moveLineDown),
11778
12365
  'Editor.moveLineUp': wrapCommand(moveLineUp),
11779
12366
  'Editor.moveRectangleSelection': wrapCommand(moveRectangleSelection),
@@ -11791,6 +12378,7 @@ const commandMap = {
11791
12378
  'Editor.paste': wrapCommand(paste),
11792
12379
  'Editor.pasteText': wrapCommand(pasteText),
11793
12380
  'Editor.render': renderEditor,
12381
+ 'Editor.render2': render2,
11794
12382
  'Editor.renderEventListeners': renderEventListeners,
11795
12383
  'Editor.replaceRange': wrapCommand(replaceRange),
11796
12384
  'Editor.rerender': wrapCommand(rerender),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/editor-worker",
3
- "version": "18.3.0",
3
+ "version": "18.4.0",
4
4
  "repository": {
5
5
  "type": "git",
6
6
  "url": "git@github.com:lvce-editor/editor-worker.git"