@lvce-editor/extension-search-view 7.13.1 → 7.13.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.
@@ -1014,6 +1014,34 @@ const listen$1 = async (module, options) => {
1014
1014
  return ipc;
1015
1015
  };
1016
1016
 
1017
+ const createSharedLazyRpc = factory => {
1018
+ let rpcPromise;
1019
+ const getOrCreate = () => {
1020
+ if (!rpcPromise) {
1021
+ rpcPromise = factory();
1022
+ }
1023
+ return rpcPromise;
1024
+ };
1025
+ return {
1026
+ async dispose() {
1027
+ const rpc = await getOrCreate();
1028
+ await rpc.dispose();
1029
+ },
1030
+ async invoke(method, ...params) {
1031
+ const rpc = await getOrCreate();
1032
+ return rpc.invoke(method, ...params);
1033
+ },
1034
+ async invokeAndTransfer(method, ...params) {
1035
+ const rpc = await getOrCreate();
1036
+ return rpc.invokeAndTransfer(method, ...params);
1037
+ },
1038
+ async send(method, ...params) {
1039
+ const rpc = await getOrCreate();
1040
+ rpc.send(method, ...params);
1041
+ }
1042
+ };
1043
+ };
1044
+
1017
1045
  const create$7 = async ({
1018
1046
  commandMap,
1019
1047
  isMessagePortOpen = true,
@@ -1049,34 +1077,6 @@ const create$6 = async ({
1049
1077
  });
1050
1078
  };
1051
1079
 
1052
- const createSharedLazyRpc = factory => {
1053
- let rpcPromise;
1054
- const getOrCreate = () => {
1055
- if (!rpcPromise) {
1056
- rpcPromise = factory();
1057
- }
1058
- return rpcPromise;
1059
- };
1060
- return {
1061
- async dispose() {
1062
- const rpc = await getOrCreate();
1063
- await rpc.dispose();
1064
- },
1065
- async invoke(method, ...params) {
1066
- const rpc = await getOrCreate();
1067
- return rpc.invoke(method, ...params);
1068
- },
1069
- async invokeAndTransfer(method, ...params) {
1070
- const rpc = await getOrCreate();
1071
- return rpc.invokeAndTransfer(method, ...params);
1072
- },
1073
- async send(method, ...params) {
1074
- const rpc = await getOrCreate();
1075
- rpc.send(method, ...params);
1076
- }
1077
- };
1078
- };
1079
-
1080
1080
  const create$5 = async ({
1081
1081
  commandMap,
1082
1082
  isMessagePortOpen,
@@ -1375,6 +1375,9 @@ const {
1375
1375
  invoke: invoke$1,
1376
1376
  set: set$2
1377
1377
  } = create$3(ExtensionManagementWorker);
1378
+ const disableWorkspace$2 = id => {
1379
+ return invoke$1('Extensions.disableWorkspace', id);
1380
+ };
1378
1381
 
1379
1382
  const {
1380
1383
  invoke,
@@ -1406,7 +1409,11 @@ const sendMessagePortToExtensionManagementWorker = async (port, rpcId) => {
1406
1409
  await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionManagementWorker', port, command, rpcId);
1407
1410
  };
1408
1411
  const openUri$1 = async (uri, focus, options) => {
1409
- await invoke('Main.openUri', uri, focus, options);
1412
+ await invoke('Main.openUri', {
1413
+ ...options,
1414
+ focus,
1415
+ uri
1416
+ });
1410
1417
  };
1411
1418
  const showErrorDialog = async errorInfo => {
1412
1419
  await invoke('ErrorHandling.showErrorDialog', errorInfo);
@@ -1668,8 +1675,9 @@ const None$2 = 0;
1668
1675
  const Input = 1;
1669
1676
  const List$2 = 2;
1670
1677
 
1678
+ const RE_WHITESPACE$1 = /\s/;
1671
1679
  const isWhiteSpace = character => {
1672
- return /\s/.test(character);
1680
+ return RE_WHITESPACE$1.test(character);
1673
1681
  };
1674
1682
  const getCompletionRange = (value, cursorOffset) => {
1675
1683
  const offset = Math.min(Math.max(cursorOffset, 0), value.length);
@@ -2016,6 +2024,7 @@ const Recommended = '@recommended';
2016
2024
  const WorkspaceUnsupported = '@workspaceunsupported';
2017
2025
  const Deprecated = '@deprecated';
2018
2026
 
2027
+ const RE_LEADING_COLON = /^:/;
2019
2028
  const RE_PARAM = /@[\w-]+(?::\w+)?/g;
2020
2029
  const deserializeCategory = value => {
2021
2030
  if (value.startsWith(':"') && value.endsWith('"')) {
@@ -2064,7 +2073,7 @@ const parseValue = value => {
2064
2073
  sort = 'installs';
2065
2074
  } else {
2066
2075
  // Handle cases like @sort:installs or @sortsize (without colon)
2067
- sort = sortValue.replace(/^:/, '');
2076
+ sort = sortValue.replace(RE_LEADING_COLON, '');
2068
2077
  }
2069
2078
  }
2070
2079
  if (match.startsWith(Id)) {
@@ -2294,8 +2303,9 @@ const handleChange = async (state, update) => {
2294
2303
  const User = 1;
2295
2304
  const Script = 2;
2296
2305
 
2306
+ const RE_WHITESPACE = /\s/;
2297
2307
  const getCompletionText = (searchValue, completion, rangeEnd) => {
2298
- const hasTrailingWhitespace = /\s/.test(searchValue[rangeEnd] || '');
2308
+ const hasTrailingWhitespace = RE_WHITESPACE.test(searchValue[rangeEnd] || '');
2299
2309
  return completion.endsWith(':') || hasTrailingWhitespace ? completion : `${completion} `;
2300
2310
  };
2301
2311
  const acceptCompletionWithContext = async (context, label) => {
@@ -2535,14 +2545,55 @@ const diff2 = uid => {
2535
2545
  return diff(uid, modules, numbers);
2536
2546
  };
2537
2547
 
2538
- const disable$1 = async (state, _id) => {
2539
- await invoke$2('ConfirmPrompt.prompt', 'not implemented', undefined);
2540
- return state;
2548
+ const Disabled$1 = 'disabled';
2549
+ const Enabled = 'enabled';
2550
+ const Installing = 'installing';
2551
+ const NotInstalled = 'not-installed';
2552
+ const Uninstalling = 'uninstalling';
2553
+ const statuses = [Disabled$1, Enabled, Installing, NotInstalled, Uninstalling];
2554
+ const isExtensionStatus = status => {
2555
+ return statuses.includes(status);
2541
2556
  };
2542
2557
 
2543
- const disableWorkspace = async (state, _id) => {
2544
- await invoke$2('ConfirmPrompt.prompt', 'not implemented', undefined);
2545
- return state;
2558
+ const updateStatus = (extension, id, status, builtin) => {
2559
+ if (extension.id !== id) {
2560
+ return extension;
2561
+ }
2562
+ return {
2563
+ ...extension,
2564
+ builtin: builtin ?? extension.builtin,
2565
+ disabled: status === Disabled$1,
2566
+ status
2567
+ };
2568
+ };
2569
+ const setExtensionStatus = (state, id, status, builtin) => {
2570
+ if (!isExtensionStatus(status)) {
2571
+ throw new TypeError(`Invalid extension status: ${status}`);
2572
+ }
2573
+ return {
2574
+ ...state,
2575
+ allExtensions: state.allExtensions.map(extension => updateStatus(extension, id, status, builtin)),
2576
+ items: state.items.map(extension => updateStatus(extension, id, status, builtin))
2577
+ };
2578
+ };
2579
+
2580
+ const handleDisable = async (state, id) => {
2581
+ const error = await disableExtension(id);
2582
+ return error ? state : setExtensionStatus(state, id, Disabled$1);
2583
+ };
2584
+
2585
+ const disable$1 = async state => {
2586
+ const item = getFocusedItem(state);
2587
+ return item ? handleDisable(state, item.id) : state;
2588
+ };
2589
+
2590
+ const disableWorkspace = async state => {
2591
+ const item = getFocusedItem(state);
2592
+ if (!item) {
2593
+ return state;
2594
+ }
2595
+ await disableWorkspace$2(item.id);
2596
+ return setExtensionStatus(state, item.id, Disabled$1);
2546
2597
  };
2547
2598
 
2548
2599
  const dispose = uid => {
@@ -2550,14 +2601,23 @@ const dispose = uid => {
2550
2601
  dispose$1(uid);
2551
2602
  };
2552
2603
 
2553
- const enable$1 = async (state, _id) => {
2554
- await invoke$2('ConfirmPrompt.prompt', 'not implemented', undefined);
2555
- return state;
2604
+ const handleEnable = async (state, id) => {
2605
+ const error = await enableExtension(id);
2606
+ return error ? state : setExtensionStatus(state, id, Enabled);
2556
2607
  };
2557
2608
 
2558
- const enableWorkspace = async (state, _id) => {
2559
- await invoke$2('ConfirmPrompt.prompt', 'not implemented', undefined);
2560
- return state;
2609
+ const enable$1 = async state => {
2610
+ const item = getFocusedItem(state);
2611
+ return item ? handleEnable(state, item.id) : state;
2612
+ };
2613
+
2614
+ const enableWorkspace = async state => {
2615
+ const item = getFocusedItem(state);
2616
+ if (!item) {
2617
+ return state;
2618
+ }
2619
+ await invoke$1('Extensions.enableWorkspace', item.id);
2620
+ return setExtensionStatus(state, item.id, Enabled);
2561
2621
  };
2562
2622
 
2563
2623
  const CategorySuggestions = ['@category:"ai"', '@category:"azure"', '@category:"chat"', '@category:"data science"', '@category:"debuggers"', '@category:"education"', '@category:"extension packs"', '@category:"formatters"', '@category:"keymaps"', '@category:"language packs"', '@category:"linters"', '@category:"machine learning"', '@category:"notebooks"', '@category:"other"', '@category:"programming languages"', '@category:"scm providers"', '@category:"snippets"', '@category:"testing"', '@category:"themes"', '@category:"visualization"'];
@@ -2621,8 +2681,9 @@ const handleInputWithContext = async (context, value, inputSource = User, cursor
2621
2681
  });
2622
2682
  };
2623
2683
 
2684
+ const RE_WHITESPACE_SEQUENCE = /\s+/;
2624
2685
  const addFilter = (searchValue, filter) => {
2625
- const values = searchValue.trim().split(/\s+/);
2686
+ const values = searchValue.trim().split(RE_WHITESPACE_SEQUENCE);
2626
2687
  if (values.includes(filter)) {
2627
2688
  return searchValue;
2628
2689
  }
@@ -2899,16 +2960,6 @@ const getKeyBindings = () => {
2899
2960
  }];
2900
2961
  };
2901
2962
 
2902
- const Disabled$1 = 'disabled';
2903
- const Enabled = 'enabled';
2904
- const Installing = 'installing';
2905
- const NotInstalled = 'not-installed';
2906
- const Uninstalling = 'uninstalling';
2907
- const statuses = [Disabled$1, Enabled, Installing, NotInstalled, Uninstalling];
2908
- const isExtensionStatus = status => {
2909
- return statuses.includes(status);
2910
- };
2911
-
2912
2963
  const Separator = 1;
2913
2964
  const None$1 = 0;
2914
2965
  const SubMenu = 4;
@@ -2931,12 +2982,12 @@ const getEnablementFlags = (disabled, status) => {
2931
2982
  const getMenuEntriesList = (builtin, disabled = false, status) => {
2932
2983
  const enablementFlags = getEnablementFlags(disabled, status);
2933
2984
  return [{
2934
- command: 'SearchExtensions.enable',
2985
+ command: 'Extensions.enable',
2935
2986
  flags: enablementFlags.enable,
2936
2987
  id: 'enable',
2937
2988
  label: enable$2()
2938
2989
  }, {
2939
- command: 'SearchExtensions.enableWorkspace',
2990
+ command: 'Extensions.enableWorkspace',
2940
2991
  flags: enablementFlags.enable,
2941
2992
  id: 'enableWorkspace',
2942
2993
  label: enableWorkspace$1()
@@ -2946,12 +2997,12 @@ const getMenuEntriesList = (builtin, disabled = false, status) => {
2946
2997
  id: 'separator1',
2947
2998
  label: ''
2948
2999
  }, {
2949
- command: 'SearchExtensions.disable',
3000
+ command: 'Extensions.disable',
2950
3001
  flags: enablementFlags.disable,
2951
3002
  id: 'disable',
2952
3003
  label: disable$2()
2953
3004
  }, {
2954
- command: 'SearchExtensions.disableWorkspace',
3005
+ command: 'Extensions.disableWorkspace',
2955
3006
  flags: enablementFlags.disable,
2956
3007
  id: 'disableWorkspace',
2957
3008
  label: disableWorkspace$1()
@@ -2961,8 +3012,8 @@ const getMenuEntriesList = (builtin, disabled = false, status) => {
2961
3012
  id: 'separator2',
2962
3013
  label: ''
2963
3014
  }, {
2964
- command: 'SearchExtensions.installAnotherVersion',
2965
- flags: builtin ? Disabled : None$1,
3015
+ command: 'Extensions.installAnotherVersion',
3016
+ flags: Disabled,
2966
3017
  id: 'installAnotherVersion',
2967
3018
  label: installAnotherVersion$1()
2968
3019
  }, {
@@ -3212,14 +3263,11 @@ const compareNodes = (oldNode, newNode) => {
3212
3263
  }
3213
3264
  const patches = [];
3214
3265
  // Handle reference nodes - special handling for uid changes
3215
- if (oldNode.type === Reference) {
3216
- if (oldNode.uid !== newNode.uid) {
3217
- patches.push({
3218
- type: SetReferenceNodeUid,
3219
- uid: newNode.uid
3220
- });
3221
- }
3222
- return patches;
3266
+ if (oldNode.type === Reference && oldNode.uid !== newNode.uid) {
3267
+ patches.push({
3268
+ type: SetReferenceNodeUid,
3269
+ uid: newNode.uid
3270
+ });
3223
3271
  }
3224
3272
  // Handle text nodes
3225
3273
  if (oldNode.type === Text && newNode.type === Text) {
@@ -3232,8 +3280,8 @@ const compareNodes = (oldNode, newNode) => {
3232
3280
  return patches;
3233
3281
  }
3234
3282
  // Compare attributes
3235
- const oldKeys = getKeys(oldNode);
3236
- const newKeys = getKeys(newNode);
3283
+ const oldKeys = getKeys(oldNode).filter(key => oldNode.type !== Reference || key !== 'uid');
3284
+ const newKeys = getKeys(newNode).filter(key => newNode.type !== Reference || key !== 'uid');
3237
3285
  // Check for attribute changes
3238
3286
  for (const key of newKeys) {
3239
3287
  if (oldNode[key] !== newNode[key]) {
@@ -3257,9 +3305,14 @@ const compareNodes = (oldNode, newNode) => {
3257
3305
  };
3258
3306
 
3259
3307
  const treeToArray = node => {
3260
- const result = [node.node];
3261
- for (const child of node.children) {
3262
- result.push(...treeToArray(child));
3308
+ const result = [];
3309
+ const stack = [node];
3310
+ while (stack.length > 0) {
3311
+ const current = stack.pop();
3312
+ result.push(current.node);
3313
+ for (let i = current.children.length - 1; i >= 0; i--) {
3314
+ stack.push(current.children[i]);
3315
+ }
3263
3316
  }
3264
3317
  return result;
3265
3318
  };
@@ -3469,138 +3522,336 @@ const handleContextMenu = async (state, button, eventX, eventY) => {
3469
3522
  headerHeight,
3470
3523
  itemHeight,
3471
3524
  items,
3525
+ minLineY,
3472
3526
  uid,
3473
3527
  x,
3474
3528
  y
3475
3529
  } = state;
3476
- const index = getListIndex(eventX, eventY, x, y, deltaY, itemHeight, headerHeight);
3477
- if (index < 0 || index > items.length) {
3530
+ const visibleIndex = getListIndex(eventX, eventY, x, y, deltaY, itemHeight, headerHeight);
3531
+ const index = visibleIndex + minLineY;
3532
+ if (index < 0 || index >= items.length) {
3478
3533
  return state;
3479
3534
  }
3535
+ const item = items[index];
3480
3536
  await show2(uid, ManageExtension, eventX, eventY, {
3481
- builtin: items[index]?.builtin === true,
3482
- disabled: items[index]?.disabled === true,
3537
+ builtin: item.builtin === true,
3538
+ disabled: item.disabled === true,
3483
3539
  menuId: ManageExtension,
3484
- status: items[index]?.status
3540
+ status: item.status
3485
3541
  });
3486
- return state;
3487
- };
3488
-
3489
- const updateStatus = (extension, id, status, builtin) => {
3490
- if (extension.id !== id) {
3491
- return extension;
3492
- }
3493
- return {
3494
- ...extension,
3495
- builtin: builtin ?? extension.builtin,
3496
- disabled: status === Disabled$1,
3497
- status
3498
- };
3499
- };
3500
- const setExtensionStatus = (state, id, status, builtin) => {
3501
- if (!isExtensionStatus(status)) {
3502
- throw new TypeError(`Invalid extension status: ${status}`);
3503
- }
3504
3542
  return {
3505
3543
  ...state,
3506
- allExtensions: state.allExtensions.map(extension => updateStatus(extension, id, status, builtin)),
3507
- items: state.items.map(extension => updateStatus(extension, id, status, builtin))
3544
+ focusedIndex: index
3508
3545
  };
3509
3546
  };
3510
3547
 
3511
- const handleDisable = async (state, id) => {
3512
- const error = await disableExtension(id);
3513
- return error ? state : setExtensionStatus(state, id, Disabled$1);
3514
- };
3515
-
3516
3548
  const handleDisableWorkspace = (state, id) => {
3517
3549
  return state;
3518
3550
  };
3519
3551
 
3520
- const handleEnable = async (state, id) => {
3521
- const error = await enableExtension(id);
3522
- return error ? state : setExtensionStatus(state, id, Enabled);
3523
- };
3524
-
3525
3552
  const handleEnableWorkspace = (state, id) => {
3526
3553
  return state;
3527
3554
  };
3528
3555
 
3529
- const handleFocus = async state => {
3530
- return {
3531
- ...state,
3532
- focus: List$2
3533
- };
3534
- };
3556
+ const Web = 1;
3557
+ const Electron = 2;
3558
+ const Remote = 3;
3535
3559
 
3536
- const handleHeaderContextMenu = async state => {
3537
- return state;
3560
+ const getAllExtensions$1 = async (assetDir, platform) => {
3561
+ try {
3562
+ return await invoke$1('Extensions.getAllExtensions', assetDir, platform);
3563
+ } catch (error) {
3564
+ if (platform === Web) {
3565
+ return [];
3566
+ }
3567
+ throw error;
3568
+ }
3538
3569
  };
3539
3570
 
3540
- const handleInputFocus = state => {
3541
- return {
3542
- ...state,
3543
- focus: Input
3544
- };
3571
+ const getAllExtensions = (assetDir, platform) => {
3572
+ return getAllExtensions$1(assetDir, platform);
3545
3573
  };
3546
3574
 
3547
- const handleInstall = async (state, id) => {
3548
- await installExtension(id);
3549
- return setExtensionStatus(state, id, Enabled);
3575
+ const getBuiltin = extension => {
3576
+ return extension !== null && typeof extension === 'object' && 'builtin' in extension && extension.builtin === true;
3550
3577
  };
3551
3578
 
3552
- const handleScrollBarCaptureLost = state => {
3553
- return {
3554
- ...state,
3555
- scrollBarActive: false
3556
- };
3579
+ const isString = item => {
3580
+ return typeof item === 'string';
3557
3581
  };
3558
3582
 
3559
- const getNewDeltaPercent = (height, scrollBarHeight, relativeY) => {
3560
- const halfScrollBarHeight = scrollBarHeight / 2;
3561
- if (relativeY <= halfScrollBarHeight) {
3562
- // clicked at top
3563
- return {
3564
- handleOffset: relativeY,
3565
- percent: 0
3566
- };
3583
+ const getCategories = extension => {
3584
+ if (extension === null || typeof extension !== 'object' || !('categories' in extension) || !Array.isArray(extension.categories)) {
3585
+ return [];
3567
3586
  }
3568
- if (relativeY <= height - halfScrollBarHeight) {
3569
- // clicked in middle
3570
- return {
3571
- handleOffset: halfScrollBarHeight,
3572
- percent: (relativeY - halfScrollBarHeight) / (height - scrollBarHeight)
3573
- };
3587
+ return extension.categories.filter(isString);
3588
+ };
3589
+
3590
+ const getDescription = extension => {
3591
+ if (extension === null || typeof extension !== 'object' || !('description' in extension) || typeof extension.description !== 'string' || !extension.description) {
3592
+ return 'n/a';
3574
3593
  }
3575
- // clicked at bottom
3576
- return {
3577
- handleOffset: scrollBarHeight - height + relativeY,
3578
- percent: 1
3579
- };
3594
+ return extension.description;
3580
3595
  };
3581
3596
 
3582
- const clamp = (num, min, max) => {
3583
- number(num);
3584
- number(min);
3585
- number(max);
3586
- return Math.min(Math.max(num, min), max);
3597
+ const getDisabled = extension => {
3598
+ return extension !== null && typeof extension === 'object' && 'disabled' in extension && extension.disabled === true;
3587
3599
  };
3588
3600
 
3589
- const setDeltaY = (state, value) => {
3590
- object(state);
3591
- number(value);
3592
- const {
3593
- deltaY,
3594
- finalDeltaY,
3595
- headerHeight,
3596
- height,
3597
- itemHeight,
3598
- items,
3599
- minimumSliderSize
3600
- } = state;
3601
- const listHeight = height - headerHeight;
3602
- const newDeltaY = clamp(value, 0, finalDeltaY);
3603
- if (deltaY === newDeltaY) {
3601
+ const getDownloadCountValue = extension => {
3602
+ if (extension === null || typeof extension !== 'object') {
3603
+ return undefined;
3604
+ }
3605
+ const marketplace = 'marketplace' in extension && extension.marketplace !== null && typeof extension.marketplace === 'object' ? extension.marketplace : {};
3606
+ const packageJson = 'packageJSON' in extension && extension.packageJSON !== null && typeof extension.packageJSON === 'object' ? extension.packageJSON : {};
3607
+ return ('downloadCount' in extension ? extension.downloadCount : undefined) ?? ('downloads' in extension ? extension.downloads : undefined) ?? ('downloadCount' in marketplace ? marketplace.downloadCount : undefined) ?? ('downloads' in marketplace ? marketplace.downloads : undefined) ?? ('downloadCount' in packageJson ? packageJson.downloadCount : undefined) ?? ('downloads' in packageJson ? packageJson.downloads : undefined);
3608
+ };
3609
+ const getDownloadCount = extension => {
3610
+ const downloadCount = getDownloadCountValue(extension);
3611
+ if (typeof downloadCount !== 'number') {
3612
+ return 'n/a';
3613
+ }
3614
+ return downloadCount.toLocaleString();
3615
+ };
3616
+
3617
+ const getRemoteUrl = (extension, platform, assetDir) => {
3618
+ if (extension === null || typeof extension !== 'object') {
3619
+ return '';
3620
+ }
3621
+ const builtin = 'builtin' in extension && extension.builtin === true;
3622
+ const icon = 'icon' in extension && typeof extension.icon === 'string' ? extension.icon : '';
3623
+ const id = 'id' in extension && typeof extension.id === 'string' ? extension.id : '';
3624
+ const path = 'path' in extension && typeof extension.path === 'string' ? extension.path : '';
3625
+ if (platform === Remote || platform === Electron) {
3626
+ if (builtin) {
3627
+ return `${assetDir}/extensions/${id}/${icon}`;
3628
+ }
3629
+ return `/remote/${path}/${icon}`; // TODO support windows paths
3630
+ }
3631
+ if (platform === Web) {
3632
+ return `${path}/${icon}`;
3633
+ }
3634
+ return '';
3635
+ };
3636
+
3637
+ const getExtensionDefaultIcon = assetDir => {
3638
+ return `${assetDir}/icons/extensionDefaultIcon.png`;
3639
+ };
3640
+ const getExtensionLanguageBasicsIcon = assetDir => {
3641
+ return `${assetDir}/icons/language-icon.svg`;
3642
+ };
3643
+ const getExtensionThemeIcon = assetDir => {
3644
+ return `${assetDir}/icons/theme-icon.png`;
3645
+ };
3646
+
3647
+ const isLanguageBasicsExtension = extension => {
3648
+ return 'name' in extension && typeof extension.name === 'string' && extension.name.startsWith('Language Basics');
3649
+ };
3650
+ const isThemeExtension = extension => {
3651
+ return 'name' in extension && typeof extension.name === 'string' && extension.name.endsWith(' Theme');
3652
+ };
3653
+ const getExtensionIcon = (extension, platform, assetDir) => {
3654
+ if (extension === null || typeof extension !== 'object') {
3655
+ return getExtensionDefaultIcon(assetDir);
3656
+ }
3657
+ const hasIcon = 'icon' in extension && typeof extension.icon === 'string' && extension.icon;
3658
+ const hasPath = 'path' in extension && typeof extension.path === 'string' && extension.path;
3659
+ if (!hasPath || !hasIcon) {
3660
+ if (isLanguageBasicsExtension(extension)) {
3661
+ return getExtensionLanguageBasicsIcon(assetDir);
3662
+ }
3663
+ if (isThemeExtension(extension)) {
3664
+ return getExtensionThemeIcon(assetDir);
3665
+ }
3666
+ return getExtensionDefaultIcon(assetDir);
3667
+ }
3668
+ return getRemoteUrl(extension, platform, assetDir);
3669
+ };
3670
+
3671
+ const getIcon = (extension, platform, assetDir) => {
3672
+ return getExtensionIcon(extension, platform, assetDir);
3673
+ };
3674
+
3675
+ const getId = extension => {
3676
+ if (extension === null || typeof extension !== 'object' || !('id' in extension) || typeof extension.id !== 'string' || !extension.id) {
3677
+ return 'n/a';
3678
+ }
3679
+ return extension.id;
3680
+ };
3681
+
3682
+ const getName = extension => {
3683
+ if (extension === null || typeof extension !== 'object') {
3684
+ return 'n/a';
3685
+ }
3686
+ if ('name' in extension && typeof extension.name === 'string' && extension.name) {
3687
+ return extension.name;
3688
+ }
3689
+ if ('id' in extension && typeof extension.id === 'string' && extension.id) {
3690
+ return extension.id;
3691
+ }
3692
+ return 'n/a';
3693
+ };
3694
+
3695
+ const RE_PUBLISHER = /^[a-z\d-]+/;
3696
+ const getPublisher = extension => {
3697
+ if (extension === null || typeof extension !== 'object' || !('id' in extension) || typeof extension.id !== 'string') {
3698
+ return 'n/a';
3699
+ }
3700
+ const match = extension.id.match(RE_PUBLISHER);
3701
+ if (!match) {
3702
+ return 'n/a';
3703
+ }
3704
+ return match[0];
3705
+ };
3706
+
3707
+ const getRatingValue = extension => {
3708
+ if (extension === null || typeof extension !== 'object') {
3709
+ return undefined;
3710
+ }
3711
+ const marketplace = 'marketplace' in extension && extension.marketplace !== null && typeof extension.marketplace === 'object' ? extension.marketplace : {};
3712
+ const packageJson = 'packageJSON' in extension && extension.packageJSON !== null && typeof extension.packageJSON === 'object' ? extension.packageJSON : {};
3713
+ return ('rating' in extension ? extension.rating : undefined) ?? ('averageRating' in extension ? extension.averageRating : undefined) ?? ('rating' in marketplace ? marketplace.rating : undefined) ?? ('averageRating' in marketplace ? marketplace.averageRating : undefined) ?? ('rating' in packageJson ? packageJson.rating : undefined) ?? ('averageRating' in packageJson ? packageJson.averageRating : undefined);
3714
+ };
3715
+ const getRating = extension => {
3716
+ const rating = getRatingValue(extension);
3717
+ if (typeof rating !== 'number') {
3718
+ return 'n/a';
3719
+ }
3720
+ return rating.toFixed(1);
3721
+ };
3722
+
3723
+ const getSize = extension => {
3724
+ if (extension === null || typeof extension !== 'object' || !('size' in extension) || extension.size === 0 || typeof extension.size !== 'number') {
3725
+ return 0;
3726
+ }
3727
+ return extension.size;
3728
+ };
3729
+
3730
+ const getStatus = extension => {
3731
+ if (extension === null || typeof extension !== 'object' || !('status' in extension)) {
3732
+ return undefined;
3733
+ }
3734
+ return typeof extension.status === 'string' ? extension.status : undefined;
3735
+ };
3736
+
3737
+ const getUpdatedDate = extension => {
3738
+ if (extension === null || typeof extension !== 'object' || !('updatedDate' in extension) || !extension.updatedDate || typeof extension.updatedDate !== 'number') {
3739
+ return 0;
3740
+ }
3741
+ return extension.updatedDate;
3742
+ };
3743
+
3744
+ const normalizeExtension = (extension, platform, assetDir) => {
3745
+ return {
3746
+ builtin: getBuiltin(extension),
3747
+ categories: getCategories(extension),
3748
+ description: getDescription(extension),
3749
+ disabled: getDisabled(extension),
3750
+ downloadCount: getDownloadCount(extension),
3751
+ icon: getIcon(extension, platform, assetDir),
3752
+ id: getId(extension),
3753
+ name: getName(extension),
3754
+ publisher: getPublisher(extension),
3755
+ rating: getRating(extension),
3756
+ size: getSize(extension),
3757
+ status: getStatus(extension),
3758
+ updatedDate: getUpdatedDate(extension),
3759
+ uri: ''
3760
+ };
3761
+ };
3762
+
3763
+ const normalizeExtensions = (extensions, platform, assetDir) => {
3764
+ return Array.from(extensions, extension => normalizeExtension(extension, platform, assetDir));
3765
+ };
3766
+
3767
+ const handleExtensionsChanged = async state => {
3768
+ const {
3769
+ assetDir,
3770
+ platform
3771
+ } = state;
3772
+ const allExtensions = await getAllExtensions(assetDir, platform);
3773
+ const normalized = normalizeExtensions(allExtensions, platform, assetDir);
3774
+ return handleChange({
3775
+ ...state,
3776
+ allExtensions: normalized
3777
+ }, {});
3778
+ };
3779
+
3780
+ const handleFocus = async state => {
3781
+ return {
3782
+ ...state,
3783
+ focus: List$2
3784
+ };
3785
+ };
3786
+
3787
+ const handleHeaderContextMenu = async state => {
3788
+ return state;
3789
+ };
3790
+
3791
+ const handleInputFocus = state => {
3792
+ return {
3793
+ ...state,
3794
+ focus: Input
3795
+ };
3796
+ };
3797
+
3798
+ const handleInstall = async (state, id) => {
3799
+ await installExtension(id);
3800
+ return setExtensionStatus(state, id, Enabled);
3801
+ };
3802
+
3803
+ const handleScrollBarCaptureLost = state => {
3804
+ return {
3805
+ ...state,
3806
+ scrollBarActive: false
3807
+ };
3808
+ };
3809
+
3810
+ const getNewDeltaPercent = (height, scrollBarHeight, relativeY) => {
3811
+ const halfScrollBarHeight = scrollBarHeight / 2;
3812
+ if (relativeY <= halfScrollBarHeight) {
3813
+ // clicked at top
3814
+ return {
3815
+ handleOffset: relativeY,
3816
+ percent: 0
3817
+ };
3818
+ }
3819
+ if (relativeY <= height - halfScrollBarHeight) {
3820
+ // clicked in middle
3821
+ return {
3822
+ handleOffset: halfScrollBarHeight,
3823
+ percent: (relativeY - halfScrollBarHeight) / (height - scrollBarHeight)
3824
+ };
3825
+ }
3826
+ // clicked at bottom
3827
+ return {
3828
+ handleOffset: scrollBarHeight - height + relativeY,
3829
+ percent: 1
3830
+ };
3831
+ };
3832
+
3833
+ const clamp = (num, min, max) => {
3834
+ number(num);
3835
+ number(min);
3836
+ number(max);
3837
+ return Math.min(Math.max(num, min), max);
3838
+ };
3839
+
3840
+ const setDeltaY = (state, value) => {
3841
+ object(state);
3842
+ number(value);
3843
+ const {
3844
+ deltaY,
3845
+ finalDeltaY,
3846
+ headerHeight,
3847
+ height,
3848
+ itemHeight,
3849
+ items,
3850
+ minimumSliderSize
3851
+ } = state;
3852
+ const listHeight = height - headerHeight;
3853
+ const newDeltaY = clamp(value, 0, finalDeltaY);
3854
+ if (deltaY === newDeltaY) {
3604
3855
  return state;
3605
3856
  }
3606
3857
  // TODO when it only moves by one px, extensions don't need to be rerendered, only negative margin
@@ -3756,25 +4007,6 @@ const installAnotherVersion = async state => {
3756
4007
  return state;
3757
4008
  };
3758
4009
 
3759
- const Web = 1;
3760
- const Electron = 2;
3761
- const Remote = 3;
3762
-
3763
- const getAllExtensions$1 = async (assetDir, platform) => {
3764
- try {
3765
- return await invoke$1('Extensions.getAllExtensions', assetDir, platform);
3766
- } catch (error) {
3767
- if (platform === Web) {
3768
- return [];
3769
- }
3770
- throw error;
3771
- }
3772
- };
3773
-
3774
- const getAllExtensions = (assetDir, platform) => {
3775
- return getAllExtensions$1(assetDir, platform);
3776
- };
3777
-
3778
4010
  const Small = 1;
3779
4011
  const Normal = 2;
3780
4012
  const Large = 3;
@@ -3794,166 +4026,6 @@ const getIsFirefox = () => {
3794
4026
  return globalWithNavigator.navigator?.userAgent.toLowerCase().includes('firefox') ?? false;
3795
4027
  };
3796
4028
 
3797
- const getRemoteUrl = (extension, platform, assetDir) => {
3798
- if (platform === Remote || platform === Electron) {
3799
- if (extension.builtin) {
3800
- return `${assetDir}/extensions/${extension.id}/${extension.icon}`;
3801
- }
3802
- return `/remote/${extension.path}/${extension.icon}`; // TODO support windows paths
3803
- }
3804
- if (platform === Web) {
3805
- return `${extension.path}/${extension.icon}`;
3806
- }
3807
- return '';
3808
- };
3809
-
3810
- const getExtensionDefaultIcon = assetDir => {
3811
- return `${assetDir}/icons/extensionDefaultIcon.png`;
3812
- };
3813
- const getExtensionLanguageBasicsIcon = assetDir => {
3814
- return `${assetDir}/icons/language-icon.svg`;
3815
- };
3816
- const getExtensionThemeIcon = assetDir => {
3817
- return `${assetDir}/icons/theme-icon.png`;
3818
- };
3819
-
3820
- const isLanguageBasicsExtension = extension => {
3821
- return extension.name && extension.name.startsWith('Language Basics');
3822
- };
3823
- const isThemeExtension = extension => {
3824
- return extension.name && extension.name.endsWith(' Theme');
3825
- };
3826
- const getExtensionIcon = (extension, platform, assetDir) => {
3827
- if (!extension) {
3828
- return getExtensionDefaultIcon(assetDir);
3829
- }
3830
- if (!extension.path || !extension.icon) {
3831
- if (isLanguageBasicsExtension(extension)) {
3832
- return getExtensionLanguageBasicsIcon(assetDir);
3833
- }
3834
- if (isThemeExtension(extension)) {
3835
- return getExtensionThemeIcon(assetDir);
3836
- }
3837
- return getExtensionDefaultIcon(assetDir);
3838
- }
3839
- return getRemoteUrl(extension, platform, assetDir);
3840
- };
3841
-
3842
- const getDownloadCountValue = extension => {
3843
- return extension?.downloadCount ?? extension?.downloads ?? extension?.marketplace?.downloadCount ?? extension?.marketplace?.downloads ?? extension?.packageJSON?.downloadCount ?? extension?.packageJSON?.downloads;
3844
- };
3845
- const getDownloadCount = extension => {
3846
- const downloadCount = getDownloadCountValue(extension);
3847
- if (typeof downloadCount !== 'number') {
3848
- return 'n/a';
3849
- }
3850
- return downloadCount.toLocaleString();
3851
- };
3852
-
3853
- const getRatingValue = extension => {
3854
- return extension?.rating ?? extension?.averageRating ?? extension?.marketplace?.rating ?? extension?.marketplace?.averageRating ?? extension?.packageJSON?.rating ?? extension?.packageJSON?.averageRating;
3855
- };
3856
- const getRating = extension => {
3857
- const rating = getRatingValue(extension);
3858
- if (typeof rating !== 'number') {
3859
- return 'n/a';
3860
- }
3861
- return rating.toFixed(1);
3862
- };
3863
-
3864
- const getBuiltin = extension => {
3865
- return extension?.builtin === true;
3866
- };
3867
- const getDisabled = extension => {
3868
- return extension?.disabled === true;
3869
- };
3870
- const getStatus = extension => {
3871
- return typeof extension?.status === 'string' ? extension.status : undefined;
3872
- };
3873
- const getIcon = (extension, platform, assetDir) => {
3874
- return getExtensionIcon(extension, platform, assetDir);
3875
- };
3876
- const getName = extension => {
3877
- if (extension && extension.name) {
3878
- return extension.name;
3879
- }
3880
- if (extension && extension.id) {
3881
- return extension.id;
3882
- }
3883
- return 'n/a';
3884
- };
3885
- const getDescription = extension => {
3886
- if (!extension || !extension.description) {
3887
- return 'n/a';
3888
- }
3889
- return extension.description;
3890
- };
3891
- const getId$1 = extension => {
3892
- if (!extension || !extension.id) {
3893
- return 'n/a';
3894
- }
3895
- return extension.id;
3896
- };
3897
- const getSize = extension => {
3898
- if (!extension || extension.size === 0 || typeof extension.size !== 'number') {
3899
- return 0;
3900
- }
3901
- return extension.size;
3902
- };
3903
- const getUpdatedDate = extension => {
3904
- if (!extension || !extension.updatedDate || typeof extension.updatedDate !== 'number') {
3905
- return 0;
3906
- }
3907
- return extension.updatedDate;
3908
- };
3909
- const isString = item => {
3910
- return typeof item === 'string';
3911
- };
3912
- const getCategories = extension => {
3913
- if (!extension || !extension.categories || !Array.isArray(extension.categories)) {
3914
- return [];
3915
- }
3916
- return extension.categories.filter(isString);
3917
- };
3918
-
3919
- const RE_PUBLISHER = /^[a-z\d-]+/;
3920
-
3921
- // TODO handle case when extension is of type number|array|null|string
3922
- const getPublisher = extension => {
3923
- if (!extension || !extension.id) {
3924
- return 'n/a';
3925
- }
3926
- // TODO handle case when id is not of type string -> should not crash application
3927
- const match = extension.id.match(RE_PUBLISHER);
3928
- if (!match) {
3929
- return 'n/a';
3930
- }
3931
- return match[0];
3932
- };
3933
-
3934
- const normalizeExtension = (extension, platform, assetDir) => {
3935
- return {
3936
- builtin: getBuiltin(extension),
3937
- categories: getCategories(extension),
3938
- description: getDescription(extension),
3939
- disabled: getDisabled(extension),
3940
- downloadCount: getDownloadCount(extension),
3941
- icon: getIcon(extension, platform, assetDir),
3942
- id: getId$1(extension),
3943
- name: getName(extension),
3944
- publisher: getPublisher(extension),
3945
- rating: getRating(extension),
3946
- size: getSize(extension),
3947
- status: getStatus(extension),
3948
- updatedDate: getUpdatedDate(extension),
3949
- uri: ''
3950
- };
3951
- };
3952
-
3953
- const normalizeExtensions = (extensions, platform, assetDir) => {
3954
- return Array.from(extensions, extension => normalizeExtension(extension, platform, assetDir));
3955
- };
3956
-
3957
4029
  const getSavedValue = savedState => {
3958
4030
  if (savedState && typeof savedState === 'object' && 'searchValue' in savedState && typeof savedState.searchValue === 'string') {
3959
4031
  return savedState.searchValue;
@@ -4313,7 +4385,7 @@ const getCompletionWidgetVirtualDom = (items, focusedIndex) => {
4313
4385
  const Focusable = 0;
4314
4386
 
4315
4387
  const disabledClassName = mergeClassNames(SearchFieldButton, SearchFieldButtonDisabled);
4316
- const getClassName$1 = enabled => {
4388
+ const getClassName = enabled => {
4317
4389
  if (enabled) {
4318
4390
  return SearchFieldButton;
4319
4391
  }
@@ -4328,7 +4400,7 @@ const getSearchFieldButtonVirtualDom = button => {
4328
4400
  } = button;
4329
4401
  return [{
4330
4402
  childCount: 1,
4331
- className: getClassName$1(enabled),
4403
+ className: getClassName(enabled),
4332
4404
  onClick,
4333
4405
  tabIndex: Focusable,
4334
4406
  title,
@@ -4462,7 +4534,7 @@ const getExtensionActions = (builtin, disabled, status) => {
4462
4534
  };
4463
4535
 
4464
4536
  const className = mergeClassNames(ExtensionListItemActionInstall, ExtensionActionButton);
4465
- const getActionVirtualDom$1 = (action, id) => {
4537
+ const getExtensionActionVirtualDom = (action, id) => {
4466
4538
  return [{
4467
4539
  childCount: 1,
4468
4540
  className,
@@ -4472,13 +4544,33 @@ const getActionVirtualDom$1 = (action, id) => {
4472
4544
  type: Button$2
4473
4545
  }, text(action.label)];
4474
4546
  };
4547
+
4475
4548
  const getExtensionActionsVirtualDom = (id, builtin, disabled, status) => {
4476
4549
  const actions = getExtensionActions(builtin, disabled, status);
4477
4550
  return [{
4478
4551
  childCount: actions.length,
4479
4552
  className: ExtensionActions,
4480
4553
  type: Div
4481
- }, ...actions.flatMap(action => getActionVirtualDom$1(action, id))];
4554
+ }, ...actions.flatMap(action => getExtensionActionVirtualDom(action, id))];
4555
+ };
4556
+
4557
+ const getExtensionListItemClassName = (focused, disabled) => {
4558
+ return mergeClassNames(ExtensionListItem, focused ? ExtensionActive : '', disabled ? ExtensionListItemDisabled : '');
4559
+ };
4560
+
4561
+ const getExtensionListItemFooter = hasStatistics => {
4562
+ return {
4563
+ childCount: hasStatistics ? 3 : 2,
4564
+ className: ExtensionListItemFooter,
4565
+ type: Div
4566
+ };
4567
+ };
4568
+
4569
+ const getExtensionListItemId = focused => {
4570
+ if (focused) {
4571
+ return `ExtensionActive`;
4572
+ }
4573
+ return undefined;
4482
4574
  };
4483
4575
 
4484
4576
  const extensionListItemMetadataNode = {
@@ -4500,6 +4592,13 @@ const getExtensionStatisticsVirtualDom = (downloadCount, rating$1) => {
4500
4592
  return [extensionListItemMetadataNode, ...getStatisticVirtualDom(downloads(), downloadCount, ExtensionListItemDownloadCount), ...getStatisticVirtualDom(rating(), rating$1, ExtensionListItemRating)];
4501
4593
  };
4502
4594
 
4595
+ const getExtensionListItemStatisticsVirtualDom = (hasStatistics, downloadCount, rating) => {
4596
+ if (!hasStatistics) {
4597
+ return [];
4598
+ }
4599
+ return getExtensionStatisticsVirtualDom(downloadCount, rating);
4600
+ };
4601
+
4503
4602
  const listItemDetail = {
4504
4603
  childCount: 3,
4505
4604
  className: ExtensionListItemDetail,
@@ -4515,33 +4614,11 @@ const listItemDescription = {
4515
4614
  className: ExtensionListItemDescription,
4516
4615
  type: Div
4517
4616
  };
4518
- const getListItemFooter = hasStatistics => {
4519
- return {
4520
- childCount: hasStatistics ? 3 : 2,
4521
- className: ExtensionListItemFooter,
4522
- type: Div
4523
- };
4524
- };
4525
4617
  const listItemAuthorName = {
4526
4618
  childCount: 1,
4527
4619
  className: ExtensionListItemAuthorName,
4528
4620
  type: Div
4529
4621
  };
4530
- const getClassName = (focused, disabled) => {
4531
- return mergeClassNames(ExtensionListItem, focused ? ExtensionActive : '', disabled ? ExtensionListItemDisabled : '');
4532
- };
4533
- const getId = focused => {
4534
- if (focused) {
4535
- return `ExtensionActive`;
4536
- }
4537
- return undefined;
4538
- };
4539
- const getStatisticsVirtualDom = (hasStatistics, downloadCount, rating) => {
4540
- if (!hasStatistics) {
4541
- return [];
4542
- }
4543
- return getExtensionStatisticsVirtualDom(downloadCount, rating);
4544
- };
4545
4622
  const getExtensionListItemVirtualDom = extension => {
4546
4623
  const {
4547
4624
  builtin = false,
@@ -4565,8 +4642,8 @@ const getExtensionListItemVirtualDom = extension => {
4565
4642
  ariaRoleDescription: Extension,
4566
4643
  ariaSetSize: setSize,
4567
4644
  childCount: 2,
4568
- className: getClassName(focused, disabled),
4569
- id: getId(focused),
4645
+ className: getExtensionListItemClassName(focused, disabled),
4646
+ id: getExtensionListItemId(focused),
4570
4647
  role: ListItem,
4571
4648
  type: Div
4572
4649
  }, {
@@ -4575,16 +4652,19 @@ const getExtensionListItemVirtualDom = extension => {
4575
4652
  role: None,
4576
4653
  src: icon,
4577
4654
  type: Img
4578
- }, listItemDetail, listItemName, text(name), listItemDescription, text(description), getListItemFooter(hasStatistics), listItemAuthorName, text(publisher), ...getStatisticsVirtualDom(hasStatistics, downloadCount, rating), ...actionsDom];
4655
+ }, listItemDetail, listItemName, text(name), listItemDescription, text(description), getExtensionListItemFooter(hasStatistics), listItemAuthorName, text(publisher), ...getExtensionListItemStatisticsVirtualDom(hasStatistics, downloadCount, rating), ...actionsDom];
4579
4656
  return dom;
4580
4657
  };
4581
4658
 
4582
- const getExtensionsListVirtualDom = (visibleExtensions, focusOutline) => {
4659
+ const getListClassName = focusOutline => {
4583
4660
  const className = focusOutline ? mergeClassNames(ListItems, FocusOutline) : ListItems;
4661
+ return className;
4662
+ };
4663
+ const getExtensionsListVirtualDom = (visibleExtensions, focusOutline) => {
4584
4664
  const dom = [{
4585
4665
  ariaLabel: extensions(),
4586
4666
  childCount: visibleExtensions.length,
4587
- className,
4667
+ className: getListClassName(focusOutline),
4588
4668
  onBlur: HandleBlur,
4589
4669
  onContextmenu: HandleContextMenu,
4590
4670
  onContextMenu: HandleContextMenu,
@@ -5125,6 +5205,7 @@ const commandMap = {
5125
5205
  'SearchExtensions.handleDisableWorkspace': wrapCommand(handleDisableWorkspace),
5126
5206
  'SearchExtensions.handleEnable': wrapCommand(handleEnable),
5127
5207
  'SearchExtensions.handleEnableWorkspace': wrapCommand(handleEnableWorkspace),
5208
+ 'SearchExtensions.handleExtensionsChanged': wrapCommand(handleExtensionsChanged),
5128
5209
  'SearchExtensions.handleFocus': wrapCommand(handleFocus),
5129
5210
  'SearchExtensions.handleHeaderContextMenu': wrapCommand(handleHeaderContextMenu),
5130
5211
  'SearchExtensions.handleInput': wrapAsyncCommand(handleInputWithContext),
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@lvce-editor/extension-search-view",
3
- "version": "7.13.1",
3
+ "version": "7.13.2",
4
4
  "description": "Extension Search View Worker",
5
5
  "repository": {
6
6
  "type": "git",