@lvce-editor/file-search-worker 7.4.0 → 7.5.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.
@@ -458,6 +458,7 @@ const create$8 = (uid, uri, listItemHeight, x, y, width, height, platform, args,
458
458
  };
459
459
 
460
460
  const RenderItems = 1;
461
+ const RenderIncremental = 10;
461
462
  const RenderFocus = 2;
462
463
  const RenderValue = 3;
463
464
  const RenderCursorOffset = 7;
@@ -741,6 +742,7 @@ const Text = 12;
741
742
  const Img = 17;
742
743
 
743
744
  const SetDom2 = 'Viewlet.setDom2';
745
+ const SetPatches = 'Viewlet.setPatches';
744
746
 
745
747
  const FocusQuickPickInput = 20;
746
748
 
@@ -3316,6 +3318,283 @@ const text = data => {
3316
3318
  };
3317
3319
  };
3318
3320
 
3321
+ const SetText = 1;
3322
+ const Replace = 2;
3323
+ const SetAttribute = 3;
3324
+ const RemoveAttribute = 4;
3325
+ const Add = 6;
3326
+ const NavigateChild = 7;
3327
+ const NavigateParent = 8;
3328
+ const RemoveChild = 9;
3329
+ const NavigateSibling = 10;
3330
+
3331
+ const isKey = key => {
3332
+ return key !== 'type' && key !== 'childCount';
3333
+ };
3334
+
3335
+ const getKeys = node => {
3336
+ const keys = Object.keys(node).filter(isKey);
3337
+ return keys;
3338
+ };
3339
+
3340
+ const arrayToTree = nodes => {
3341
+ const result = [];
3342
+ let i = 0;
3343
+ while (i < nodes.length) {
3344
+ const node = nodes[i];
3345
+ const {
3346
+ children,
3347
+ nodesConsumed
3348
+ } = getChildrenWithCount(nodes, i + 1, node.childCount || 0);
3349
+ result.push({
3350
+ node,
3351
+ children
3352
+ });
3353
+ i += 1 + nodesConsumed;
3354
+ }
3355
+ return result;
3356
+ };
3357
+ const getChildrenWithCount = (nodes, startIndex, childCount) => {
3358
+ if (childCount === 0) {
3359
+ return {
3360
+ children: [],
3361
+ nodesConsumed: 0
3362
+ };
3363
+ }
3364
+ const children = [];
3365
+ let i = startIndex;
3366
+ let remaining = childCount;
3367
+ let totalConsumed = 0;
3368
+ while (remaining > 0 && i < nodes.length) {
3369
+ const node = nodes[i];
3370
+ const nodeChildCount = node.childCount || 0;
3371
+ const {
3372
+ children: nodeChildren,
3373
+ nodesConsumed
3374
+ } = getChildrenWithCount(nodes, i + 1, nodeChildCount);
3375
+ children.push({
3376
+ node,
3377
+ children: nodeChildren
3378
+ });
3379
+ const nodeSize = 1 + nodesConsumed;
3380
+ i += nodeSize;
3381
+ totalConsumed += nodeSize;
3382
+ remaining--;
3383
+ }
3384
+ return {
3385
+ children,
3386
+ nodesConsumed: totalConsumed
3387
+ };
3388
+ };
3389
+
3390
+ const compareNodes = (oldNode, newNode) => {
3391
+ const patches = [];
3392
+ // Check if node type changed - return null to signal incompatible nodes
3393
+ // (caller should handle this with a Replace operation)
3394
+ if (oldNode.type !== newNode.type) {
3395
+ return null;
3396
+ }
3397
+ // Handle text nodes
3398
+ if (oldNode.type === Text && newNode.type === Text) {
3399
+ if (oldNode.text !== newNode.text) {
3400
+ patches.push({
3401
+ type: SetText,
3402
+ value: newNode.text
3403
+ });
3404
+ }
3405
+ return patches;
3406
+ }
3407
+ // Compare attributes
3408
+ const oldKeys = getKeys(oldNode);
3409
+ const newKeys = getKeys(newNode);
3410
+ // Check for attribute changes
3411
+ for (const key of newKeys) {
3412
+ if (oldNode[key] !== newNode[key]) {
3413
+ patches.push({
3414
+ type: SetAttribute,
3415
+ key,
3416
+ value: newNode[key]
3417
+ });
3418
+ }
3419
+ }
3420
+ // Check for removed attributes
3421
+ for (const key of oldKeys) {
3422
+ if (!(key in newNode)) {
3423
+ patches.push({
3424
+ type: RemoveAttribute,
3425
+ key
3426
+ });
3427
+ }
3428
+ }
3429
+ return patches;
3430
+ };
3431
+
3432
+ const treeToArray = node => {
3433
+ const result = [node.node];
3434
+ for (const child of node.children) {
3435
+ result.push(...treeToArray(child));
3436
+ }
3437
+ return result;
3438
+ };
3439
+
3440
+ const diffChildren = (oldChildren, newChildren, patches) => {
3441
+ const maxLength = Math.max(oldChildren.length, newChildren.length);
3442
+ // Track where we are: -1 means at parent, >= 0 means at child index
3443
+ let currentChildIndex = -1;
3444
+ // Collect indices of children to remove (we'll add these patches at the end in reverse order)
3445
+ const indicesToRemove = [];
3446
+ for (let i = 0; i < maxLength; i++) {
3447
+ const oldNode = oldChildren[i];
3448
+ const newNode = newChildren[i];
3449
+ if (!oldNode && !newNode) {
3450
+ continue;
3451
+ }
3452
+ if (!oldNode) {
3453
+ // Add new node - we should be at the parent
3454
+ if (currentChildIndex >= 0) {
3455
+ // Navigate back to parent
3456
+ patches.push({
3457
+ type: NavigateParent
3458
+ });
3459
+ currentChildIndex = -1;
3460
+ }
3461
+ // Flatten the entire subtree so renderInternal can handle it
3462
+ const flatNodes = treeToArray(newNode);
3463
+ patches.push({
3464
+ type: Add,
3465
+ nodes: flatNodes
3466
+ });
3467
+ } else if (newNode) {
3468
+ // Compare nodes to see if we need any patches
3469
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
3470
+ // If nodePatches is null, the node types are incompatible - need to replace
3471
+ if (nodePatches === null) {
3472
+ // Navigate to this child
3473
+ if (currentChildIndex === -1) {
3474
+ patches.push({
3475
+ type: NavigateChild,
3476
+ index: i
3477
+ });
3478
+ currentChildIndex = i;
3479
+ } else if (currentChildIndex !== i) {
3480
+ patches.push({
3481
+ type: NavigateSibling,
3482
+ index: i
3483
+ });
3484
+ currentChildIndex = i;
3485
+ }
3486
+ // Replace the entire subtree
3487
+ const flatNodes = treeToArray(newNode);
3488
+ patches.push({
3489
+ type: Replace,
3490
+ nodes: flatNodes
3491
+ });
3492
+ // After replace, we're at the new element (same position)
3493
+ continue;
3494
+ }
3495
+ // Check if we need to recurse into children
3496
+ const hasChildrenToCompare = oldNode.children.length > 0 || newNode.children.length > 0;
3497
+ // Only navigate to this element if we need to do something
3498
+ if (nodePatches.length > 0 || hasChildrenToCompare) {
3499
+ // Navigate to this child if not already there
3500
+ if (currentChildIndex === -1) {
3501
+ patches.push({
3502
+ type: NavigateChild,
3503
+ index: i
3504
+ });
3505
+ currentChildIndex = i;
3506
+ } else if (currentChildIndex !== i) {
3507
+ patches.push({
3508
+ type: NavigateSibling,
3509
+ index: i
3510
+ });
3511
+ currentChildIndex = i;
3512
+ }
3513
+ // Apply node patches (these apply to the current element, not children)
3514
+ if (nodePatches.length > 0) {
3515
+ patches.push(...nodePatches);
3516
+ }
3517
+ // Compare children recursively
3518
+ if (hasChildrenToCompare) {
3519
+ diffChildren(oldNode.children, newNode.children, patches);
3520
+ }
3521
+ }
3522
+ } else {
3523
+ // Remove old node - collect the index for later removal
3524
+ indicesToRemove.push(i);
3525
+ }
3526
+ }
3527
+ // Navigate back to parent if we ended at a child
3528
+ if (currentChildIndex >= 0) {
3529
+ patches.push({
3530
+ type: NavigateParent
3531
+ });
3532
+ currentChildIndex = -1;
3533
+ }
3534
+ // Add remove patches in reverse order (highest index first)
3535
+ // This ensures indices remain valid as we remove
3536
+ for (let j = indicesToRemove.length - 1; j >= 0; j--) {
3537
+ patches.push({
3538
+ type: RemoveChild,
3539
+ index: indicesToRemove[j]
3540
+ });
3541
+ }
3542
+ };
3543
+ const diffTrees = (oldTree, newTree, patches, path) => {
3544
+ // At the root level (path.length === 0), we're already AT the element
3545
+ // So we compare the root node directly, then compare its children
3546
+ if (path.length === 0 && oldTree.length === 1 && newTree.length === 1) {
3547
+ const oldNode = oldTree[0];
3548
+ const newNode = newTree[0];
3549
+ // Compare root nodes
3550
+ const nodePatches = compareNodes(oldNode.node, newNode.node);
3551
+ // If nodePatches is null, the root node types are incompatible - need to replace
3552
+ if (nodePatches === null) {
3553
+ const flatNodes = treeToArray(newNode);
3554
+ patches.push({
3555
+ type: Replace,
3556
+ nodes: flatNodes
3557
+ });
3558
+ return;
3559
+ }
3560
+ if (nodePatches.length > 0) {
3561
+ patches.push(...nodePatches);
3562
+ }
3563
+ // Compare children
3564
+ if (oldNode.children.length > 0 || newNode.children.length > 0) {
3565
+ diffChildren(oldNode.children, newNode.children, patches);
3566
+ }
3567
+ } else {
3568
+ // Non-root level or multiple root elements - use the regular comparison
3569
+ diffChildren(oldTree, newTree, patches);
3570
+ }
3571
+ };
3572
+
3573
+ const removeTrailingNavigationPatches = patches => {
3574
+ // Find the last non-navigation patch
3575
+ let lastNonNavigationIndex = -1;
3576
+ for (let i = patches.length - 1; i >= 0; i--) {
3577
+ const patch = patches[i];
3578
+ if (patch.type !== NavigateChild && patch.type !== NavigateParent && patch.type !== NavigateSibling) {
3579
+ lastNonNavigationIndex = i;
3580
+ break;
3581
+ }
3582
+ }
3583
+ // Return patches up to and including the last non-navigation patch
3584
+ return lastNonNavigationIndex === -1 ? [] : patches.slice(0, lastNonNavigationIndex + 1);
3585
+ };
3586
+
3587
+ const diffTree = (oldNodes, newNodes) => {
3588
+ // Step 1: Convert flat arrays to tree structures
3589
+ const oldTree = arrayToTree(oldNodes);
3590
+ const newTree = arrayToTree(newNodes);
3591
+ // Step 3: Compare the trees
3592
+ const patches = [];
3593
+ diffTrees(oldTree, newTree, patches, []);
3594
+ // Remove trailing navigation patches since they serve no purpose
3595
+ return removeTrailingNavigationPatches(patches);
3596
+ };
3597
+
3319
3598
  const ComboBox = 'combobox';
3320
3599
  const ListBox = 'listbox';
3321
3600
  const None = 'none';
@@ -3546,6 +3825,13 @@ const renderItems = newState => {
3546
3825
  return [SetDom2, dom];
3547
3826
  };
3548
3827
 
3828
+ const renderIncremental = newState => {
3829
+ const oldDom = renderItems(newState)[1];
3830
+ const newDom = renderItems(newState)[1];
3831
+ const patches = diffTree(oldDom, newDom);
3832
+ return [SetPatches, newState.uid, patches];
3833
+ };
3834
+
3549
3835
  const renderValue = newState => {
3550
3836
  return ['Viewlet.setValueByName', QuickPickInput, /* value */newState.value];
3551
3837
  };
@@ -3560,6 +3846,8 @@ const getRenderer = diffType => {
3560
3846
  return renderFocus;
3561
3847
  case RenderFocusedIndex:
3562
3848
  return renderFocusedIndex;
3849
+ case RenderIncremental:
3850
+ return renderIncremental;
3563
3851
  case RenderItems:
3564
3852
  return renderItems;
3565
3853
  case RenderValue:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/file-search-worker",
3
- "version": "7.4.0",
3
+ "version": "7.5.0",
4
4
  "keywords": [
5
5
  "text-search"
6
6
  ],