@lvce-editor/find-widget-worker 3.18.0 → 3.20.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.
@@ -995,6 +995,7 @@ const Button = 1;
995
995
  const Div = 4;
996
996
  const Text = 12;
997
997
  const TextArea = 62;
998
+ const Reference = 100;
998
999
 
999
1000
  const ClientX = 'event.clientX';
1000
1001
  const ClientY = 'event.clientY';
@@ -1020,6 +1021,7 @@ const FocusSelector = 'Viewlet.focusSelector';
1020
1021
  const SetCss = 'Viewlet.setCss';
1021
1022
  const SetFocusContext = 'Viewlet.setFocusContext';
1022
1023
  const SetValueByName = 'Viewlet.setValueByName';
1024
+ const SetPatches = 'Viewlet.setPatches';
1023
1025
 
1024
1026
  const Empty = 0;
1025
1027
  const FocusFindWidget$1 = 16;
@@ -1488,7 +1490,7 @@ const isEqual$4 = (oldState, newState) => {
1488
1490
  };
1489
1491
 
1490
1492
  const isEqual$3 = (oldState, newState) => {
1491
- return oldState.inputErrorMessage === newState.inputErrorMessage && oldState.matchCase === newState.matchCase && oldState.matchCount === newState.matchCount && oldState.matchIndex === newState.matchIndex && oldState.matchWholeWord === newState.matchWholeWord && oldState.preserveCase === newState.preserveCase && oldState.replaceExpanded === newState.replaceExpanded && oldState.useRegularExpression === newState.useRegularExpression && oldState.version === newState.version;
1493
+ return oldState.inputErrorMessage === newState.inputErrorMessage && oldState.focus === newState.focus && oldState.matchCase === newState.matchCase && oldState.matchCount === newState.matchCount && oldState.matchIndex === newState.matchIndex && oldState.matchWholeWord === newState.matchWholeWord && oldState.preserveCase === newState.preserveCase && oldState.replaceExpanded === newState.replaceExpanded && oldState.useRegularExpression === newState.useRegularExpression && oldState.value === newState.value && oldState.version === newState.version;
1492
1494
  };
1493
1495
 
1494
1496
  const isEqual$2 = (oldState, newState) => {
@@ -1706,9 +1708,13 @@ const buildRegex = (searchString, options) => {
1706
1708
 
1707
1709
  // eslint-disable-next-line @typescript-eslint/prefer-readonly-parameter-types -- Appends matches to the shared output array.
1708
1710
  const collectMatchesForLineInternal = (matches, line, lineIndex, regex) => {
1711
+ regex.lastIndex = 0;
1709
1712
  let lastMatch = regex.exec(line);
1710
1713
  while (lastMatch) {
1711
1714
  matches.push(lineIndex, lastMatch.index, lastMatch[0].length);
1715
+ if (lastMatch[0].length === 0) {
1716
+ regex.lastIndex = lastMatch.index + 1;
1717
+ }
1712
1718
  lastMatch = regex.exec(line);
1713
1719
  }
1714
1720
  };
@@ -1887,7 +1893,7 @@ const FocusPrevious = 'FocusPrevious';
1887
1893
  const MatchCase$2 = 'MatchCase';
1888
1894
  const MatchWholeWord$2 = 'MatchWholeWord';
1889
1895
  const PreserveCase$1 = 'PreserveCase';
1890
- const Replace$2 = 'Replace';
1896
+ const Replace$3 = 'Replace';
1891
1897
  const ReplaceAll$2 = 'ReplaceAll';
1892
1898
  const ReplaceValue = 'replace-value';
1893
1899
  const SearchValue = 'search-value';
@@ -2142,7 +2148,7 @@ const getClickHandler = name => {
2142
2148
  return toggleMatchWholeWord;
2143
2149
  case PreserveCase$1:
2144
2150
  return togglePreserveCase;
2145
- case Replace$2:
2151
+ case Replace$3:
2146
2152
  return replace$1;
2147
2153
  case ReplaceAll$2:
2148
2154
  return replaceAll$1;
@@ -2167,7 +2173,7 @@ const getFindWidgetFocusKey = name => {
2167
2173
  return FocusSearchWholeWord;
2168
2174
  case PreserveCase$1:
2169
2175
  return FocusSearchPreserveCase;
2170
- case Replace$2:
2176
+ case Replace$3:
2171
2177
  return FocusFindWidgetReplaceButton$1;
2172
2178
  case ReplaceAll$2:
2173
2179
  return FocusFindWidgetReplaceAllButton$1;
@@ -2685,6 +2691,343 @@ const renderBounds = (oldState, newState) => {
2685
2691
  return [SetBounds, uid, x, y, width, height];
2686
2692
  };
2687
2693
 
2694
+ const mergeClassNames = (...classNames) => {
2695
+ return classNames.filter(Boolean).join(' ');
2696
+ };
2697
+
2698
+ const text = data => {
2699
+ return {
2700
+ childCount: 0,
2701
+ text: data,
2702
+ type: Text
2703
+ };
2704
+ };
2705
+
2706
+ const SetText = 1;
2707
+ const Replace$2 = 2;
2708
+ const SetAttribute = 3;
2709
+ const RemoveAttribute = 4;
2710
+ const Add = 6;
2711
+ const NavigateChild = 7;
2712
+ const NavigateParent = 8;
2713
+ const RemoveChild = 9;
2714
+ const NavigateSibling = 10;
2715
+ const SetReferenceNodeUid = 11;
2716
+ const MultiNavigation = 18;
2717
+
2718
+ const isKey = key => {
2719
+ return key !== 'type' && key !== 'childCount';
2720
+ };
2721
+
2722
+ const getKeys = node => {
2723
+ const keys = Object.keys(node).filter(isKey);
2724
+ return keys;
2725
+ };
2726
+
2727
+ const arrayToTree = nodes => {
2728
+ const result = [];
2729
+ let i = 0;
2730
+ while (i < nodes.length) {
2731
+ const node = nodes[i];
2732
+ const {
2733
+ children,
2734
+ nodesConsumed
2735
+ } = getChildrenWithCount(nodes, i + 1, node.childCount || 0);
2736
+ result.push({
2737
+ node,
2738
+ children
2739
+ });
2740
+ i += 1 + nodesConsumed;
2741
+ }
2742
+ return result;
2743
+ };
2744
+ const getChildrenWithCount = (nodes, startIndex, childCount) => {
2745
+ if (childCount === 0) {
2746
+ return {
2747
+ children: [],
2748
+ nodesConsumed: 0
2749
+ };
2750
+ }
2751
+ const children = [];
2752
+ let i = startIndex;
2753
+ let remaining = childCount;
2754
+ let totalConsumed = 0;
2755
+ while (remaining > 0 && i < nodes.length) {
2756
+ const node = nodes[i];
2757
+ const nodeChildCount = node.childCount || 0;
2758
+ const {
2759
+ children: nodeChildren,
2760
+ nodesConsumed
2761
+ } = getChildrenWithCount(nodes, i + 1, nodeChildCount);
2762
+ children.push({
2763
+ node,
2764
+ children: nodeChildren
2765
+ });
2766
+ const nodeSize = 1 + nodesConsumed;
2767
+ i += nodeSize;
2768
+ totalConsumed += nodeSize;
2769
+ remaining--;
2770
+ }
2771
+ return {
2772
+ children,
2773
+ nodesConsumed: totalConsumed
2774
+ };
2775
+ };
2776
+
2777
+ const isNavigationPatch = patch => {
2778
+ switch (patch.type) {
2779
+ case NavigateChild:
2780
+ case NavigateParent:
2781
+ case NavigateSibling:
2782
+ return true;
2783
+ default:
2784
+ return false;
2785
+ }
2786
+ };
2787
+ const getNavigationIndex = patch => {
2788
+ switch (patch.type) {
2789
+ case NavigateChild:
2790
+ case NavigateSibling:
2791
+ return patch.index;
2792
+ default:
2793
+ return 0;
2794
+ }
2795
+ };
2796
+ const appendNavigationPatch = (patches, type, index) => {
2797
+ const previousPatch = patches.at(-1);
2798
+ if (!previousPatch) {
2799
+ patches.push(type === NavigateParent ? {
2800
+ type
2801
+ } : {
2802
+ index,
2803
+ type
2804
+ });
2805
+ return;
2806
+ }
2807
+ if (previousPatch.type === MultiNavigation) {
2808
+ previousPatch.navigations.push(type, index);
2809
+ return;
2810
+ }
2811
+ if (isNavigationPatch(previousPatch)) {
2812
+ patches[patches.length - 1] = {
2813
+ navigations: [previousPatch.type, getNavigationIndex(previousPatch), type, index],
2814
+ type: MultiNavigation
2815
+ };
2816
+ return;
2817
+ }
2818
+ patches.push(type === NavigateParent ? {
2819
+ type
2820
+ } : {
2821
+ index,
2822
+ type
2823
+ });
2824
+ };
2825
+
2826
+ const compareNodes = (oldNode, newNode) => {
2827
+ // Check if node type changed - return null to signal incompatible nodes
2828
+ // (caller should handle this with a Replace operation)
2829
+ if (oldNode.type !== newNode.type) {
2830
+ return null;
2831
+ }
2832
+ const patches = [];
2833
+ // Handle reference nodes - special handling for uid changes
2834
+ if (oldNode.type === Reference && oldNode.uid !== newNode.uid) {
2835
+ patches.push({
2836
+ type: SetReferenceNodeUid,
2837
+ uid: newNode.uid
2838
+ });
2839
+ }
2840
+ // Handle text nodes
2841
+ if (oldNode.type === Text && newNode.type === Text) {
2842
+ if (oldNode.text !== newNode.text) {
2843
+ patches.push({
2844
+ type: SetText,
2845
+ value: newNode.text
2846
+ });
2847
+ }
2848
+ return patches;
2849
+ }
2850
+ // Compare attributes
2851
+ const oldKeys = getKeys(oldNode).filter(key => oldNode.type !== Reference || key !== 'uid');
2852
+ const newKeys = getKeys(newNode).filter(key => newNode.type !== Reference || key !== 'uid');
2853
+ // Check for attribute changes
2854
+ for (const key of newKeys) {
2855
+ if (oldNode[key] !== newNode[key]) {
2856
+ patches.push({
2857
+ type: SetAttribute,
2858
+ key,
2859
+ value: newNode[key]
2860
+ });
2861
+ }
2862
+ }
2863
+ // Check for removed attributes
2864
+ for (const key of oldKeys) {
2865
+ if (!Object.hasOwn(newNode, key)) {
2866
+ patches.push({
2867
+ type: RemoveAttribute,
2868
+ key
2869
+ });
2870
+ }
2871
+ }
2872
+ return patches;
2873
+ };
2874
+
2875
+ const treeToArray = node => {
2876
+ const result = [];
2877
+ const stack = [node];
2878
+ while (stack.length > 0) {
2879
+ const current = stack.pop();
2880
+ result.push(current.node);
2881
+ for (let i = current.children.length - 1; i >= 0; i--) {
2882
+ stack.push(current.children[i]);
2883
+ }
2884
+ }
2885
+ return result;
2886
+ };
2887
+
2888
+ const navigateToChild = (patches, currentChildIndex, index) => {
2889
+ if (currentChildIndex === -1) {
2890
+ appendNavigationPatch(patches, NavigateChild, index);
2891
+ return index;
2892
+ }
2893
+ if (currentChildIndex !== index) {
2894
+ appendNavigationPatch(patches, NavigateSibling, index);
2895
+ }
2896
+ return index;
2897
+ };
2898
+ const navigateToParent = (patches, currentChildIndex) => {
2899
+ if (currentChildIndex >= 0) {
2900
+ appendNavigationPatch(patches, NavigateParent, 0);
2901
+ }
2902
+ return -1;
2903
+ };
2904
+ const addTree = (newNode, patches) => {
2905
+ patches.push({
2906
+ type: Add,
2907
+ nodes: treeToArray(newNode)
2908
+ });
2909
+ };
2910
+ const replaceTree = (newNode, patches) => {
2911
+ patches.push({
2912
+ type: Replace$2,
2913
+ nodes: treeToArray(newNode)
2914
+ });
2915
+ };
2916
+ const appendPatch = (patches, patch) => {
2917
+ switch (patch.type) {
2918
+ case MultiNavigation:
2919
+ for (let i = 0; i < patch.navigations.length; i += 2) {
2920
+ appendNavigationPatch(patches, patch.navigations[i], patch.navigations[i + 1]);
2921
+ }
2922
+ return;
2923
+ case NavigateChild:
2924
+ case NavigateSibling:
2925
+ appendNavigationPatch(patches, patch.type, patch.index);
2926
+ return;
2927
+ case NavigateParent:
2928
+ appendNavigationPatch(patches, patch.type, 0);
2929
+ return;
2930
+ default:
2931
+ patches.push(patch);
2932
+ }
2933
+ };
2934
+ const appendPatches = (patches, newPatches) => {
2935
+ for (const patch of newPatches) {
2936
+ appendPatch(patches, patch);
2937
+ }
2938
+ };
2939
+ const diffExistingChild = (oldNode, newNode, patches, currentChildIndex, index) => {
2940
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
2941
+ if (nodePatches === null) {
2942
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
2943
+ replaceTree(newNode, patches);
2944
+ return nextChildIndex;
2945
+ }
2946
+ const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
2947
+ const childPatches = [];
2948
+ if (hasChildrenToCompare) {
2949
+ diffChildren(oldNode.children, newNode.children, childPatches);
2950
+ }
2951
+ if (nodePatches.length === 0 && childPatches.length === 0) {
2952
+ return currentChildIndex;
2953
+ }
2954
+ const nextChildIndex = navigateToChild(patches, currentChildIndex, index);
2955
+ patches.push(...nodePatches);
2956
+ appendPatches(patches, childPatches);
2957
+ return nextChildIndex;
2958
+ };
2959
+ const diffRootNode = (oldNode, newNode, patches) => {
2960
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
2961
+ if (nodePatches === null) {
2962
+ replaceTree(newNode, patches);
2963
+ return;
2964
+ }
2965
+ if (nodePatches.length > 0) {
2966
+ patches.push(...nodePatches);
2967
+ }
2968
+ if (oldNode.children.length > 0 || newNode.children.length > 0) {
2969
+ diffChildren(oldNode.children, newNode.children, patches);
2970
+ }
2971
+ };
2972
+ const diffChildren = (oldChildren, newChildren, patches) => {
2973
+ const maxLength = Math.max(oldChildren.length, newChildren.length);
2974
+ let currentChildIndex = -1;
2975
+ const indicesToRemove = [];
2976
+ for (let i = 0; i < maxLength; i++) {
2977
+ const oldNode = oldChildren[i];
2978
+ const newNode = newChildren[i];
2979
+ if (!oldNode && !newNode) {
2980
+ continue;
2981
+ }
2982
+ if (!oldNode) {
2983
+ currentChildIndex = navigateToParent(patches, currentChildIndex);
2984
+ addTree(newNode, patches);
2985
+ continue;
2986
+ }
2987
+ if (!newNode) {
2988
+ indicesToRemove.push(i);
2989
+ continue;
2990
+ }
2991
+ currentChildIndex = diffExistingChild(oldNode, newNode, patches, currentChildIndex, i);
2992
+ }
2993
+ navigateToParent(patches, currentChildIndex);
2994
+ for (let j = indicesToRemove.length - 1; j >= 0; j--) {
2995
+ patches.push({
2996
+ type: RemoveChild,
2997
+ index: indicesToRemove[j]
2998
+ });
2999
+ }
3000
+ };
3001
+ const diffTrees = (oldTree, newTree, patches, path) => {
3002
+ if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
3003
+ diffRootNode(oldTree[0], newTree[0], patches);
3004
+ return;
3005
+ }
3006
+ diffChildren(oldTree, newTree, patches);
3007
+ };
3008
+
3009
+ const removeTrailingNavigationPatches = patches => {
3010
+ while (patches.length > 0) {
3011
+ const patch = patches.at(-1);
3012
+ if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling && patch.type !== MultiNavigation) {
3013
+ break;
3014
+ }
3015
+ patches.pop();
3016
+ }
3017
+ return patches;
3018
+ };
3019
+
3020
+ const diffTree = (oldNodes, newNodes) => {
3021
+ // Step 1: Convert flat arrays to tree structures
3022
+ const oldTree = arrayToTree(oldNodes);
3023
+ const newTree = arrayToTree(newNodes);
3024
+ // Step 3: Compare the trees
3025
+ const patches = [];
3026
+ diffTrees(oldTree, newTree, patches, []);
3027
+ // Remove trailing navigation patches since they serve no purpose
3028
+ return removeTrailingNavigationPatches(patches);
3029
+ };
3030
+
2688
3031
  const HandleBlur = 1;
2689
3032
  const HandleClickButton = 2;
2690
3033
  const HandleClickClose = 3;
@@ -2832,7 +3175,7 @@ const getFindWidgetButtons = (findButtonsEnabled, replaceButtonsEnabled, matchCa
2832
3175
  disabled: !replaceButtonsEnabled,
2833
3176
  icon: Replace,
2834
3177
  label: replace(),
2835
- name: Replace$2,
3178
+ name: Replace$3,
2836
3179
  onClick: HandleClickButton
2837
3180
  }, {
2838
3181
  disabled: !replaceButtonsEnabled,
@@ -2858,18 +3201,6 @@ const getFindWidgetButtonsEnabled = (matchCount, value) => {
2858
3201
  };
2859
3202
  };
2860
3203
 
2861
- const mergeClassNames = (...classNames) => {
2862
- return classNames.filter(Boolean).join(' ');
2863
- };
2864
-
2865
- const text = data => {
2866
- return {
2867
- childCount: 0,
2868
- text: data,
2869
- type: Text
2870
- };
2871
- };
2872
-
2873
3204
  const FindWidget = 'FindWidget';
2874
3205
  const FindWidgetFind = 'FindWidgetFind';
2875
3206
  const FindWidgetMatchCount = 'FindWidgetMatchCount';
@@ -3103,20 +3434,20 @@ const getMatchCountText = (matchIndex, matchCount) => {
3103
3434
  return matchOf(matchIndex + 1, matchCount);
3104
3435
  };
3105
3436
 
3106
- const renderContent = (oldState, newState) => {
3437
+ const getDom = state => {
3107
3438
  const {
3108
3439
  focus,
3109
3440
  inputErrorMessage,
3110
3441
  matchCase,
3111
3442
  matchCount,
3443
+ matchIndex,
3112
3444
  matchWholeWord,
3113
3445
  preserveCase,
3114
3446
  replaceExpanded,
3115
- uid,
3116
3447
  useRegularExpression,
3117
3448
  value
3118
- } = newState;
3119
- const matchCountText = inputErrorMessage || getMatchCountText(newState.matchIndex, newState.matchCount);
3449
+ } = state;
3450
+ const matchCountText = inputErrorMessage || getMatchCountText(matchIndex, matchCount);
3120
3451
  const {
3121
3452
  findButtonsEnabled,
3122
3453
  replaceButtonsEnabled
@@ -3131,7 +3462,18 @@ const renderContent = (oldState, newState) => {
3131
3462
  const inputFocused = focus === FocusSearchInput;
3132
3463
  const replaceInputFocused = focus === FocusSearchReplaceInput;
3133
3464
  const dom = getFindWidgetVirtualDom(matchCountText, replaceExpanded, findButtons, findFieldButtons, replaceButtons, replaceFieldButtons, matchCount, value, hasError, inputFocused, replaceInputFocused);
3134
- return [SetDom2, uid, dom];
3465
+ return dom;
3466
+ };
3467
+ const renderContent = (oldState, newState) => {
3468
+ const {
3469
+ uid
3470
+ } = newState;
3471
+ const dom = getDom(newState);
3472
+ if (oldState.version === 0) {
3473
+ return [SetDom2, uid, dom];
3474
+ }
3475
+ const oldDom = getDom(oldState);
3476
+ return [SetPatches, uid, diffTree(oldDom, dom)];
3135
3477
  };
3136
3478
 
3137
3479
  const renderCss = (oldState, newState) => {
@@ -3239,7 +3581,7 @@ const getFocusSelector = focusKey => {
3239
3581
  case FocusFindWidgetReplaceAllButton$1:
3240
3582
  return ReplaceAll$2;
3241
3583
  case FocusFindWidgetReplaceButton$1:
3242
- return Replace$2;
3584
+ return Replace$3;
3243
3585
  case FocusSearchInput:
3244
3586
  return SearchValue;
3245
3587
  case FocusSearchMatchCase:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/find-widget-worker",
3
- "version": "3.18.0",
3
+ "version": "3.20.0",
4
4
  "description": "Web Worker for the find widget in Lvce Editor",
5
5
  "repository": {
6
6
  "type": "git",