@lvce-editor/status-bar-worker 3.32.1 → 3.32.2

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.
@@ -263,7 +263,7 @@ const terminate = () => {
263
263
  const {
264
264
  get: get$5,
265
265
  getCommandIds,
266
- getKeys,
266
+ getKeys: getKeys$1,
267
267
  registerCommands,
268
268
  set: set$9,
269
269
  wrapCommand,
@@ -509,6 +509,7 @@ const TextMeasurementWorker = 7011;
509
509
 
510
510
  const SetDom2 = 'Viewlet.setDom2';
511
511
  const SetFocusContext = 'Viewlet.setFocusContext';
512
+ const SetPatches = 'Viewlet.setPatches';
512
513
 
513
514
  const mergeClassNames = (...classNames) => {
514
515
  return classNames.filter(Boolean).join(' ');
@@ -524,6 +525,266 @@ const text = data => {
524
525
 
525
526
  new Set(Object.values(VirtualDomElements));
526
527
 
528
+ const SetText = 1;
529
+ const Replace = 2;
530
+ const SetAttribute = 3;
531
+ const RemoveAttribute = 4;
532
+ const Add = 6;
533
+ const NavigateChild = 7;
534
+ const NavigateParent = 8;
535
+ const RemoveChild = 9;
536
+ const NavigateSibling = 10;
537
+ const SetReferenceNodeUid = 11;
538
+
539
+ const isKey = key => {
540
+ return key !== 'type' && key !== 'childCount';
541
+ };
542
+
543
+ const getKeys = node => {
544
+ const keys = Object.keys(node).filter(isKey);
545
+ return keys;
546
+ };
547
+
548
+ const arrayToTree = nodes => {
549
+ const result = [];
550
+ let i = 0;
551
+ while (i < nodes.length) {
552
+ const node = nodes[i];
553
+ const {
554
+ children,
555
+ nodesConsumed
556
+ } = getChildrenWithCount(nodes, i + 1, node.childCount || 0);
557
+ result.push({
558
+ node,
559
+ children
560
+ });
561
+ i += 1 + nodesConsumed;
562
+ }
563
+ return result;
564
+ };
565
+ const getChildrenWithCount = (nodes, startIndex, childCount) => {
566
+ if (childCount === 0) {
567
+ return {
568
+ children: [],
569
+ nodesConsumed: 0
570
+ };
571
+ }
572
+ const children = [];
573
+ let i = startIndex;
574
+ let remaining = childCount;
575
+ let totalConsumed = 0;
576
+ while (remaining > 0 && i < nodes.length) {
577
+ const node = nodes[i];
578
+ const nodeChildCount = node.childCount || 0;
579
+ const {
580
+ children: nodeChildren,
581
+ nodesConsumed
582
+ } = getChildrenWithCount(nodes, i + 1, nodeChildCount);
583
+ children.push({
584
+ node,
585
+ children: nodeChildren
586
+ });
587
+ const nodeSize = 1 + nodesConsumed;
588
+ i += nodeSize;
589
+ totalConsumed += nodeSize;
590
+ remaining--;
591
+ }
592
+ return {
593
+ children,
594
+ nodesConsumed: totalConsumed
595
+ };
596
+ };
597
+
598
+ const compareNodes = (oldNode, newNode) => {
599
+ // Check if node type changed - return null to signal incompatible nodes
600
+ // (caller should handle this with a Replace operation)
601
+ if (oldNode.type !== newNode.type) {
602
+ return null;
603
+ }
604
+ const patches = [];
605
+ // Handle reference nodes - special handling for uid changes
606
+ if (oldNode.type === Reference && oldNode.uid !== newNode.uid) {
607
+ patches.push({
608
+ type: SetReferenceNodeUid,
609
+ uid: newNode.uid
610
+ });
611
+ }
612
+ // Handle text nodes
613
+ if (oldNode.type === Text && newNode.type === Text) {
614
+ if (oldNode.text !== newNode.text) {
615
+ patches.push({
616
+ type: SetText,
617
+ value: newNode.text
618
+ });
619
+ }
620
+ return patches;
621
+ }
622
+ // Compare attributes
623
+ const oldKeys = getKeys(oldNode).filter(key => oldNode.type !== Reference || key !== 'uid');
624
+ const newKeys = getKeys(newNode).filter(key => newNode.type !== Reference || key !== 'uid');
625
+ // Check for attribute changes
626
+ for (const key of newKeys) {
627
+ if (oldNode[key] !== newNode[key]) {
628
+ patches.push({
629
+ type: SetAttribute,
630
+ key,
631
+ value: newNode[key]
632
+ });
633
+ }
634
+ }
635
+ // Check for removed attributes
636
+ for (const key of oldKeys) {
637
+ if (!Object.hasOwn(newNode, key)) {
638
+ patches.push({
639
+ type: RemoveAttribute,
640
+ key
641
+ });
642
+ }
643
+ }
644
+ return patches;
645
+ };
646
+
647
+ const treeToArray = node => {
648
+ const result = [];
649
+ const stack = [node];
650
+ while (stack.length > 0) {
651
+ const current = stack.pop();
652
+ result.push(current.node);
653
+ for (let i = current.children.length - 1; i >= 0; i--) {
654
+ stack.push(current.children[i]);
655
+ }
656
+ }
657
+ return result;
658
+ };
659
+
660
+ const navigateToChild = (patches, currentChildIndex, index) => {
661
+ if (currentChildIndex === -1) {
662
+ patches.push({
663
+ type: NavigateChild,
664
+ index
665
+ });
666
+ return index;
667
+ }
668
+ if (currentChildIndex !== index) {
669
+ patches.push({
670
+ type: NavigateSibling,
671
+ index
672
+ });
673
+ }
674
+ return index;
675
+ };
676
+ const navigateToParent = (patches, currentChildIndex) => {
677
+ if (currentChildIndex >= 0) {
678
+ patches.push({
679
+ type: NavigateParent
680
+ });
681
+ }
682
+ return -1;
683
+ };
684
+ const addTree = (newNode, patches) => {
685
+ patches.push({
686
+ type: Add,
687
+ nodes: treeToArray(newNode)
688
+ });
689
+ };
690
+ const replaceTree = (newNode, patches) => {
691
+ patches.push({
692
+ type: Replace,
693
+ nodes: treeToArray(newNode)
694
+ });
695
+ };
696
+ const diffExistingChild = (oldNode, newNode, patches, currentChildIndex, index) => {
697
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
698
+ if (nodePatches === null) {
699
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
700
+ replaceTree(newNode, patches);
701
+ return nextChildIndex;
702
+ }
703
+ const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
704
+ if (nodePatches.length === 0 && !hasChildrenToCompare) {
705
+ return currentChildIndex;
706
+ }
707
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
708
+ if (nodePatches.length > 0) {
709
+ patches.push(...nodePatches);
710
+ }
711
+ if (hasChildrenToCompare) {
712
+ diffChildren(oldNode.children, newNode.children, patches);
713
+ }
714
+ return nextChildIndex;
715
+ };
716
+ const diffRootNode = (oldNode, newNode, patches) => {
717
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
718
+ if (nodePatches === null) {
719
+ replaceTree(newNode, patches);
720
+ return;
721
+ }
722
+ if (nodePatches.length > 0) {
723
+ patches.push(...nodePatches);
724
+ }
725
+ if (oldNode.children.length > 0 || newNode.children.length > 0) {
726
+ diffChildren(oldNode.children, newNode.children, patches);
727
+ }
728
+ };
729
+ const diffChildren = (oldChildren, newChildren, patches) => {
730
+ const maxLength = Math.max(oldChildren.length, newChildren.length);
731
+ let currentChildIndex = -1;
732
+ const indicesToRemove = [];
733
+ for (let i = 0; i < maxLength; i++) {
734
+ const oldNode = oldChildren[i];
735
+ const newNode = newChildren[i];
736
+ if (!oldNode && !newNode) {
737
+ continue;
738
+ }
739
+ if (!oldNode) {
740
+ currentChildIndex = navigateToParent(patches, currentChildIndex);
741
+ addTree(newNode, patches);
742
+ continue;
743
+ }
744
+ if (!newNode) {
745
+ indicesToRemove.push(i);
746
+ continue;
747
+ }
748
+ currentChildIndex = diffExistingChild(oldNode, newNode, patches, currentChildIndex, i);
749
+ }
750
+ navigateToParent(patches, currentChildIndex);
751
+ for (let j = indicesToRemove.length - 1; j >= 0; j--) {
752
+ patches.push({
753
+ type: RemoveChild,
754
+ index: indicesToRemove[j]
755
+ });
756
+ }
757
+ };
758
+ const diffTrees = (oldTree, newTree, patches, path) => {
759
+ if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
760
+ diffRootNode(oldTree[0], newTree[0], patches);
761
+ return;
762
+ }
763
+ diffChildren(oldTree, newTree, patches);
764
+ };
765
+
766
+ const removeTrailingNavigationPatches = patches => {
767
+ while (patches.length > 0) {
768
+ const patch = patches.at(-1);
769
+ if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
770
+ break;
771
+ }
772
+ patches.pop();
773
+ }
774
+ return patches;
775
+ };
776
+
777
+ const diffTree = (oldNodes, newNodes) => {
778
+ // Step 1: Convert flat arrays to tree structures
779
+ const oldTree = arrayToTree(oldNodes);
780
+ const newTree = arrayToTree(newNodes);
781
+ // Step 3: Compare the trees
782
+ const patches = [];
783
+ diffTrees(oldTree, newTree, patches, []);
784
+ // Remove trailing navigation patches since they serve no purpose
785
+ return removeTrailingNavigationPatches(patches);
786
+ };
787
+
527
788
  const HandleContextMenu = 2;
528
789
  const HandleClick = 11;
529
790
 
@@ -2190,7 +2451,25 @@ const handleEditorStatusChanged = (state, editorStatus, previous = state) => {
2190
2451
  };
2191
2452
 
2192
2453
  const renderIncremental = (oldState, newState) => {
2193
- return renderItems(oldState, newState);
2454
+ if (oldState.initial) {
2455
+ return renderItems(oldState, newState);
2456
+ }
2457
+ const oldDom = getStatusBarVirtualDom(oldState.visibleStatusBarItemsLeft, oldState.visibleStatusBarItemsRight);
2458
+ const newDom = getStatusBarVirtualDom(newState.visibleStatusBarItemsLeft, newState.visibleStatusBarItemsRight);
2459
+ // Structural and visibility changes can replace or reorder item groups.
2460
+ // Keep their full-render fallback, including the renderer's ambiguous
2461
+ // solitary Add encoding. Only patch a stable tree of the same items.
2462
+ if (oldDom.length !== newDom.length || oldDom.some((node, index) => {
2463
+ const other = newDom[index];
2464
+ return node.type !== other.type || node.childCount !== other.childCount || node.className !== other.className || node.name !== other.name;
2465
+ })) {
2466
+ return renderItems(oldState, newState);
2467
+ }
2468
+ const patches = diffTree(oldDom, newDom);
2469
+ if (patches.length === 0) {
2470
+ return [];
2471
+ }
2472
+ return [SetPatches, newState.uid, patches];
2194
2473
  };
2195
2474
 
2196
2475
  const getRenderer = diffType => {
@@ -2333,11 +2612,17 @@ const render2 = async (uid, _diffResult) => {
2333
2612
  }
2334
2613
  newState = latestState;
2335
2614
  }
2336
- const diffResult = [...new Set([..._diffResult, ...diff(current.oldState, newState)])];
2615
+ const changed = [...new Set([..._diffResult, ...diff(current.oldState, newState)])];
2616
+ // A full replacement already includes every change; do not patch its new tree
2617
+ // using paths calculated against the old tree.
2618
+ const diffResult = changed.includes(RenderItems) ? changed.filter(type => type !== RenderIncremental) : changed;
2337
2619
  const {
2338
2620
  oldState
2339
2621
  } = current;
2340
2622
  const commands = applyRender(oldState, newState, diffResult);
2623
+ // Advance synchronously: subsequent out-of-band updates must diff against
2624
+ // the DOM commands just generated, including updates that revert a value.
2625
+ set$9(uid, newState, newState);
2341
2626
  if (!isConnected()) {
2342
2627
  return commands;
2343
2628
  }
@@ -2371,7 +2656,7 @@ const handleEditorStatusChangedAll = async update => {
2371
2656
  };
2372
2657
  const editorStatus = applyUpdate(update);
2373
2658
  const changedUids = [];
2374
- for (const uid of getKeys()) {
2659
+ for (const uid of getKeys$1()) {
2375
2660
  const {
2376
2661
  newState,
2377
2662
  oldState
@@ -2415,7 +2700,7 @@ const handleEditorStatusVisibilityChangedAll = async visible => {
2415
2700
  }
2416
2701
  setVisible(visible);
2417
2702
  const changedUids = [];
2418
- for (const uid of getKeys()) {
2703
+ for (const uid of getKeys$1()) {
2419
2704
  const {
2420
2705
  newState,
2421
2706
  oldState
@@ -2657,7 +2942,7 @@ const handleItemsChanged = async state => {
2657
2942
  };
2658
2943
 
2659
2944
  const handleExtensionManagementChange = async () => {
2660
- for (const uid of getKeys()) {
2945
+ for (const uid of getKeys$1()) {
2661
2946
  const {
2662
2947
  newState,
2663
2948
  oldState
@@ -2705,7 +2990,7 @@ const set = count => {
2705
2990
 
2706
2991
  const handleNotificationCountChangedAll = async count => {
2707
2992
  set(count);
2708
- for (const uid of getKeys()) {
2993
+ for (const uid of getKeys$1()) {
2709
2994
  const {
2710
2995
  newState,
2711
2996
  oldState
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/status-bar-worker",
3
- "version": "3.32.1",
3
+ "version": "3.32.2",
4
4
  "description": "Status Bar Worker",
5
5
  "repository": {
6
6
  "type": "git",