@lvce-editor/extension-detail-view 5.14.0 → 6.1.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.
- package/dist/extensionDetailViewWorkerMain.js +1035 -895
- package/package.json +2 -2
|
@@ -100,7 +100,7 @@ const changelog = () => {
|
|
|
100
100
|
const details = () => {
|
|
101
101
|
return i18nString(Details$1);
|
|
102
102
|
};
|
|
103
|
-
const disable = () => {
|
|
103
|
+
const disable$1 = () => {
|
|
104
104
|
return i18nString(Disable$1);
|
|
105
105
|
};
|
|
106
106
|
const features$1 = () => {
|
|
@@ -133,7 +133,7 @@ const status = () => {
|
|
|
133
133
|
const setColorTheme$2 = () => {
|
|
134
134
|
return i18nString(SetColorTheme$1);
|
|
135
135
|
};
|
|
136
|
-
const enable = () => {
|
|
136
|
+
const enable$1 = () => {
|
|
137
137
|
return i18nString(Enable$1);
|
|
138
138
|
};
|
|
139
139
|
const theme = () => {
|
|
@@ -330,7 +330,8 @@ const ClientY = 'event.clientY';
|
|
|
330
330
|
const TargetHref = 'event.target.href';
|
|
331
331
|
const TargetName = 'event.target.name';
|
|
332
332
|
|
|
333
|
-
const
|
|
333
|
+
const LeftArrow = 13;
|
|
334
|
+
const RightArrow = 15;
|
|
334
335
|
|
|
335
336
|
const ExtensionDetailReadme = 20;
|
|
336
337
|
const ExtensionDetailIconContextMenu$3 = 4091;
|
|
@@ -339,10 +340,8 @@ const None$2 = 0;
|
|
|
339
340
|
|
|
340
341
|
const Web$1 = 1;
|
|
341
342
|
|
|
342
|
-
const
|
|
343
|
-
const
|
|
344
|
-
const MarkdownWorker$1 = 300;
|
|
345
|
-
const RendererWorker = 1;
|
|
343
|
+
const FocusElementByName = 'Viewlet.focusElementByName';
|
|
344
|
+
const SetFocusContext = 'Viewlet.setFocusContext';
|
|
346
345
|
|
|
347
346
|
const mergeClassNames = (...classNames) => {
|
|
348
347
|
return classNames.filter(Boolean).join(' ');
|
|
@@ -1030,8 +1029,16 @@ const getFeatureVirtualDomHandler = featureName => {
|
|
|
1030
1029
|
return feature.getVirtualDom;
|
|
1031
1030
|
};
|
|
1032
1031
|
|
|
1032
|
+
const Script$1 = 2;
|
|
1033
|
+
|
|
1034
|
+
const ExtensionHostWorker = 44;
|
|
1035
|
+
const ExtensionManagementWorker = 9006;
|
|
1036
|
+
const FileSystemWorker$1 = 209;
|
|
1037
|
+
const MarkdownWorker$1 = 300;
|
|
1038
|
+
const RendererWorker = 1;
|
|
1039
|
+
|
|
1033
1040
|
const rpcs = Object.create(null);
|
|
1034
|
-
const set$
|
|
1041
|
+
const set$b = (id, rpc) => {
|
|
1035
1042
|
rpcs[id] = rpc;
|
|
1036
1043
|
};
|
|
1037
1044
|
const get$3 = id => {
|
|
@@ -1040,6 +1047,10 @@ const get$3 = id => {
|
|
|
1040
1047
|
|
|
1041
1048
|
const create$7 = rpcId => {
|
|
1042
1049
|
return {
|
|
1050
|
+
async dispose() {
|
|
1051
|
+
const rpc = get$3(rpcId);
|
|
1052
|
+
await rpc.dispose();
|
|
1053
|
+
},
|
|
1043
1054
|
// @ts-ignore
|
|
1044
1055
|
invoke(method, ...params) {
|
|
1045
1056
|
const rpc = get$3(rpcId);
|
|
@@ -1053,11 +1064,7 @@ const create$7 = rpcId => {
|
|
|
1053
1064
|
return rpc.invokeAndTransfer(method, ...params);
|
|
1054
1065
|
},
|
|
1055
1066
|
set(rpc) {
|
|
1056
|
-
set$
|
|
1057
|
-
},
|
|
1058
|
-
async dispose() {
|
|
1059
|
-
const rpc = get$3(rpcId);
|
|
1060
|
-
await rpc.dispose();
|
|
1067
|
+
set$b(rpcId, rpc);
|
|
1061
1068
|
}
|
|
1062
1069
|
};
|
|
1063
1070
|
};
|
|
@@ -1585,7 +1592,7 @@ const create$4 = (method, params) => {
|
|
|
1585
1592
|
};
|
|
1586
1593
|
};
|
|
1587
1594
|
const callbacks = Object.create(null);
|
|
1588
|
-
const set$
|
|
1595
|
+
const set$a = (id, fn) => {
|
|
1589
1596
|
callbacks[id] = fn;
|
|
1590
1597
|
};
|
|
1591
1598
|
const get$2 = id => {
|
|
@@ -1604,7 +1611,7 @@ const registerPromise = () => {
|
|
|
1604
1611
|
resolve,
|
|
1605
1612
|
promise
|
|
1606
1613
|
} = Promise.withResolvers();
|
|
1607
|
-
set$
|
|
1614
|
+
set$a(id, resolve);
|
|
1608
1615
|
return {
|
|
1609
1616
|
id,
|
|
1610
1617
|
promise
|
|
@@ -1949,7 +1956,7 @@ const send = (transport, method, ...params) => {
|
|
|
1949
1956
|
const message = create$4(method, params);
|
|
1950
1957
|
transport.send(message);
|
|
1951
1958
|
};
|
|
1952
|
-
const invoke$
|
|
1959
|
+
const invoke$6 = (ipc, method, ...params) => {
|
|
1953
1960
|
return invokeHelper(ipc, method, params, false);
|
|
1954
1961
|
};
|
|
1955
1962
|
const invokeAndTransfer$4 = (ipc, method, ...params) => {
|
|
@@ -1988,7 +1995,7 @@ const createRpc = ipc => {
|
|
|
1988
1995
|
send(ipc, method, ...params);
|
|
1989
1996
|
},
|
|
1990
1997
|
invoke(method, ...params) {
|
|
1991
|
-
return invoke$
|
|
1998
|
+
return invoke$6(ipc, method, ...params);
|
|
1992
1999
|
},
|
|
1993
2000
|
invokeAndTransfer(method, ...params) {
|
|
1994
2001
|
return invokeAndTransfer$4(ipc, method, ...params);
|
|
@@ -2098,28 +2105,28 @@ const createMockRpc = ({
|
|
|
2098
2105
|
};
|
|
2099
2106
|
|
|
2100
2107
|
const {
|
|
2101
|
-
|
|
2108
|
+
dispose: dispose$4,
|
|
2109
|
+
invoke: invoke$5,
|
|
2102
2110
|
invokeAndTransfer: invokeAndTransfer$3,
|
|
2103
|
-
set: set$
|
|
2104
|
-
dispose: dispose$4
|
|
2111
|
+
set: set$9
|
|
2105
2112
|
} = create$7(ExtensionHostWorker);
|
|
2106
2113
|
const executeReferenceProvider = async (id, offset) => {
|
|
2107
2114
|
// @ts-ignore
|
|
2108
|
-
return invoke$
|
|
2115
|
+
return invoke$5('ExtensionHostReference.executeReferenceProvider', id, offset);
|
|
2109
2116
|
};
|
|
2110
2117
|
const executeFileReferenceProvider = async id => {
|
|
2111
2118
|
// @ts-ignore
|
|
2112
|
-
return invoke$
|
|
2119
|
+
return invoke$5('ExtensionHostReference.executeFileReferenceProvider', id);
|
|
2113
2120
|
};
|
|
2114
2121
|
const getRuntimeStatus$2 = async extensionId => {
|
|
2115
2122
|
// @ts-ignore
|
|
2116
|
-
return invoke$
|
|
2123
|
+
return invoke$5('ExtensionHost.getRuntimeStatus', extensionId);
|
|
2117
2124
|
};
|
|
2118
2125
|
const registerMockRpc$2 = commandMap => {
|
|
2119
2126
|
const mockRpc = createMockRpc({
|
|
2120
2127
|
commandMap
|
|
2121
2128
|
});
|
|
2122
|
-
set$
|
|
2129
|
+
set$9(mockRpc);
|
|
2123
2130
|
return mockRpc;
|
|
2124
2131
|
};
|
|
2125
2132
|
|
|
@@ -2129,17 +2136,28 @@ const ExtensionHost = {
|
|
|
2129
2136
|
executeFileReferenceProvider,
|
|
2130
2137
|
executeReferenceProvider,
|
|
2131
2138
|
getRuntimeStatus: getRuntimeStatus$2,
|
|
2132
|
-
invoke: invoke$
|
|
2139
|
+
invoke: invoke$5,
|
|
2133
2140
|
invokeAndTransfer: invokeAndTransfer$3,
|
|
2134
2141
|
registerMockRpc: registerMockRpc$2,
|
|
2142
|
+
set: set$9
|
|
2143
|
+
};
|
|
2144
|
+
|
|
2145
|
+
const {
|
|
2146
|
+
invoke: invoke$4,
|
|
2135
2147
|
set: set$8
|
|
2148
|
+
} = create$7(ExtensionManagementWorker);
|
|
2149
|
+
const enable = id => {
|
|
2150
|
+
return invoke$4(`Extensions.enable`, id);
|
|
2151
|
+
};
|
|
2152
|
+
const disable = id => {
|
|
2153
|
+
return invoke$4(`Extensions.disable`, id);
|
|
2136
2154
|
};
|
|
2137
2155
|
|
|
2138
2156
|
const {
|
|
2157
|
+
dispose: dispose$3,
|
|
2139
2158
|
invoke: invoke$3,
|
|
2140
2159
|
invokeAndTransfer: invokeAndTransfer$2,
|
|
2141
|
-
set: set$7
|
|
2142
|
-
dispose: dispose$3
|
|
2160
|
+
set: set$7
|
|
2143
2161
|
} = create$7(FileSystemWorker$1);
|
|
2144
2162
|
const remove = async dirent => {
|
|
2145
2163
|
return invoke$3('FileSystem.remove', dirent);
|
|
@@ -2224,10 +2242,10 @@ const FileSystemWorker = {
|
|
|
2224
2242
|
};
|
|
2225
2243
|
|
|
2226
2244
|
const {
|
|
2245
|
+
dispose: dispose$2,
|
|
2227
2246
|
invoke: invoke$2,
|
|
2228
2247
|
invokeAndTransfer: invokeAndTransfer$1,
|
|
2229
|
-
set: set$6
|
|
2230
|
-
dispose: dispose$2
|
|
2248
|
+
set: set$6
|
|
2231
2249
|
} = create$7(MarkdownWorker$1);
|
|
2232
2250
|
const getVirtualDom$1 = async html => {
|
|
2233
2251
|
// @ts-ignore
|
|
@@ -2259,7 +2277,8 @@ const MarkdownWorker = {
|
|
|
2259
2277
|
const {
|
|
2260
2278
|
invoke: invoke$1,
|
|
2261
2279
|
invokeAndTransfer,
|
|
2262
|
-
set: set$5
|
|
2280
|
+
set: set$5
|
|
2281
|
+
} = create$7(RendererWorker);
|
|
2263
2282
|
const showContextMenu2 = async (uid, menuId, x, y, args) => {
|
|
2264
2283
|
number(uid);
|
|
2265
2284
|
number(menuId);
|
|
@@ -2282,14 +2301,6 @@ const sendMessagePortToFileSystemWorker$1 = async (port, rpcId) => {
|
|
|
2282
2301
|
// @ts-ignore
|
|
2283
2302
|
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToFileSystemWorker', port, command, rpcId);
|
|
2284
2303
|
};
|
|
2285
|
-
const disableExtension$1 = async id => {
|
|
2286
|
-
// @ts-ignore
|
|
2287
|
-
return invoke$1('ExtensionManagement.disable', id);
|
|
2288
|
-
};
|
|
2289
|
-
const enableExtension$1 = async id => {
|
|
2290
|
-
// @ts-ignore
|
|
2291
|
-
return invoke$1('ExtensionManagement.enable', id);
|
|
2292
|
-
};
|
|
2293
2304
|
const sendMessagePortToExtensionHostWorker$1 = async (port, rpcId = 0) => {
|
|
2294
2305
|
const command = 'HandleMessagePort.handleMessagePort2';
|
|
2295
2306
|
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionHostWorker', port, command, rpcId);
|
|
@@ -2306,6 +2317,10 @@ const writeClipBoardImage = async blob => {
|
|
|
2306
2317
|
// @ts-ignore
|
|
2307
2318
|
await invoke$1('ClipBoard.writeImage', /* text */blob);
|
|
2308
2319
|
};
|
|
2320
|
+
const sendMessagePortToExtensionManagementWorker = async (port, rpcId) => {
|
|
2321
|
+
const command = 'Extensions.handleMessagePort';
|
|
2322
|
+
await invokeAndTransfer('SendMessagePortToExtensionHostWorker.sendMessagePortToExtensionManagementWorker', port, command, rpcId);
|
|
2323
|
+
};
|
|
2309
2324
|
const getAllExtensions$1 = async () => {
|
|
2310
2325
|
return invoke$1('ExtensionManagement.getAllExtensions');
|
|
2311
2326
|
};
|
|
@@ -2533,6 +2548,7 @@ const HandleTabsClick = 14;
|
|
|
2533
2548
|
const HandleAdditionalDetailContextMenu = 15;
|
|
2534
2549
|
const HandleReadmeClick = 16;
|
|
2535
2550
|
const HandleSelectionChange = 17;
|
|
2551
|
+
const HandleTabFocus = 18;
|
|
2536
2552
|
|
|
2537
2553
|
const ActivationEvents = 'ActivationEvents';
|
|
2538
2554
|
const Changelog = 'Changelog';
|
|
@@ -3119,6 +3135,7 @@ const create = (uid, uri, x, y, width, height, platform, assetDir) => {
|
|
|
3119
3135
|
features: [],
|
|
3120
3136
|
featuresVirtualDom: [],
|
|
3121
3137
|
focus: 0,
|
|
3138
|
+
focusedTabIndex: 0,
|
|
3122
3139
|
folderSize: 0,
|
|
3123
3140
|
hasColorTheme: false,
|
|
3124
3141
|
hasReadme: false,
|
|
@@ -3167,7 +3184,7 @@ const isEqual$3 = (oldState, newState) => {
|
|
|
3167
3184
|
};
|
|
3168
3185
|
|
|
3169
3186
|
const isEqual$2 = (oldState, newState) => {
|
|
3170
|
-
return oldState.focus === newState.focus;
|
|
3187
|
+
return oldState.focus === newState.focus && oldState.focusedTabIndex === newState.focusedTabIndex;
|
|
3171
3188
|
};
|
|
3172
3189
|
|
|
3173
3190
|
const isEqual$1 = (oldState, newState) => {
|
|
@@ -3185,9 +3202,10 @@ const RenderFocus = 2;
|
|
|
3185
3202
|
const RenderItems = 3;
|
|
3186
3203
|
const RenderScrollTop = 4;
|
|
3187
3204
|
const RenderCss = 5;
|
|
3205
|
+
const RenderFocusContext = 6;
|
|
3188
3206
|
|
|
3189
|
-
const modules = [isEqual$1, isEqual$2, isEqual, isEqual$3];
|
|
3190
|
-
const numbers = [RenderItems, RenderFocus, RenderScrollTop, RenderCss];
|
|
3207
|
+
const modules = [isEqual$1, isEqual$2, isEqual, isEqual$3, isEqual$2];
|
|
3208
|
+
const numbers = [RenderItems, RenderFocus, RenderScrollTop, RenderCss, RenderFocusContext];
|
|
3191
3209
|
|
|
3192
3210
|
const diff2 = uid => {
|
|
3193
3211
|
const {
|
|
@@ -3215,6 +3233,41 @@ const executeCopy = async state => {
|
|
|
3215
3233
|
return state;
|
|
3216
3234
|
};
|
|
3217
3235
|
|
|
3236
|
+
const focusNextTab = state => {
|
|
3237
|
+
const {
|
|
3238
|
+
focusedTabIndex
|
|
3239
|
+
} = state;
|
|
3240
|
+
const newFocusedTabIndex = focusedTabIndex >= 1 ? 1 : focusedTabIndex + 1;
|
|
3241
|
+
return {
|
|
3242
|
+
...state,
|
|
3243
|
+
focusedTabIndex: newFocusedTabIndex
|
|
3244
|
+
};
|
|
3245
|
+
};
|
|
3246
|
+
|
|
3247
|
+
const focusPreviousTab = state => {
|
|
3248
|
+
const {
|
|
3249
|
+
focusedTabIndex
|
|
3250
|
+
} = state;
|
|
3251
|
+
const newFocusedTabIndex = focusedTabIndex <= 0 ? 0 : focusedTabIndex - 1;
|
|
3252
|
+
return {
|
|
3253
|
+
...state,
|
|
3254
|
+
focusedTabIndex: newFocusedTabIndex
|
|
3255
|
+
};
|
|
3256
|
+
};
|
|
3257
|
+
|
|
3258
|
+
const focusId$1 = 451;
|
|
3259
|
+
const getKeyBindings = () => {
|
|
3260
|
+
return [{
|
|
3261
|
+
command: 'ExtensionDetail.focusNextTab',
|
|
3262
|
+
key: RightArrow,
|
|
3263
|
+
when: focusId$1
|
|
3264
|
+
}, {
|
|
3265
|
+
command: 'ExtensionDetail.focusPreviousTab',
|
|
3266
|
+
key: LeftArrow,
|
|
3267
|
+
when: focusId$1
|
|
3268
|
+
}];
|
|
3269
|
+
};
|
|
3270
|
+
|
|
3218
3271
|
const getMenuEntriesImage = (state, props) => {
|
|
3219
3272
|
return [{
|
|
3220
3273
|
args: [],
|
|
@@ -3379,7 +3432,7 @@ const handleClickCategory = async (state, categoryId) => {
|
|
|
3379
3432
|
};
|
|
3380
3433
|
|
|
3381
3434
|
const disableExtension = id => {
|
|
3382
|
-
return
|
|
3435
|
+
return disable(id);
|
|
3383
3436
|
};
|
|
3384
3437
|
|
|
3385
3438
|
const Web = 1;
|
|
@@ -3405,6 +3458,12 @@ const getExtension$1 = async (id, platform) => {
|
|
|
3405
3458
|
};
|
|
3406
3459
|
|
|
3407
3460
|
const getExtensionNew = async id => {
|
|
3461
|
+
try {
|
|
3462
|
+
const rpc = get$3(ExtensionManagementWorker);
|
|
3463
|
+
return await rpc.invoke('Extensions.getExtension', id);
|
|
3464
|
+
} catch {
|
|
3465
|
+
// ignore
|
|
3466
|
+
}
|
|
3408
3467
|
return getExtension$2(id);
|
|
3409
3468
|
};
|
|
3410
3469
|
const getExtension = async (id, platform) => {
|
|
@@ -3423,12 +3482,12 @@ const getExtensionDetailButtons = (hasColorTheme, isBuiltin, isDisabled) => {
|
|
|
3423
3482
|
onClick: HandleClickSetColorTheme
|
|
3424
3483
|
}, {
|
|
3425
3484
|
enabled: isDisabled,
|
|
3426
|
-
label: enable(),
|
|
3485
|
+
label: enable$1(),
|
|
3427
3486
|
name: Enable,
|
|
3428
3487
|
onClick: HandleClickEnable
|
|
3429
3488
|
}, {
|
|
3430
3489
|
enabled: !isDisabled,
|
|
3431
|
-
label: disable(),
|
|
3490
|
+
label: disable$1(),
|
|
3432
3491
|
name: Disable,
|
|
3433
3492
|
onClick: HandleClickDisable
|
|
3434
3493
|
}, {
|
|
@@ -3466,7 +3525,7 @@ const handleClickDisable = async state => {
|
|
|
3466
3525
|
};
|
|
3467
3526
|
|
|
3468
3527
|
const enableExtension = id => {
|
|
3469
|
-
return
|
|
3528
|
+
return enable(id);
|
|
3470
3529
|
};
|
|
3471
3530
|
|
|
3472
3531
|
const handleClickEnable = async state => {
|
|
@@ -3569,155 +3628,253 @@ const handleClickUninstall = async state => {
|
|
|
3569
3628
|
return state;
|
|
3570
3629
|
};
|
|
3571
3630
|
|
|
3572
|
-
const
|
|
3573
|
-
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
}
|
|
3631
|
+
const existsFile = async uri => {
|
|
3632
|
+
try {
|
|
3633
|
+
return await exists(uri);
|
|
3634
|
+
} catch {
|
|
3635
|
+
return false;
|
|
3636
|
+
}
|
|
3578
3637
|
};
|
|
3579
3638
|
|
|
3580
|
-
|
|
3581
|
-
|
|
3582
|
-
};
|
|
3583
|
-
|
|
3584
|
-
|
|
3639
|
+
class ExtensionNotFoundError extends Error {
|
|
3640
|
+
constructor(extensionId) {
|
|
3641
|
+
super(`extension not found: ${extensionId}`);
|
|
3642
|
+
this.name = 'ExtensionNotFoundError';
|
|
3643
|
+
}
|
|
3644
|
+
}
|
|
3645
|
+
|
|
3646
|
+
const getRemoteSrc = uri => {
|
|
3647
|
+
const src = `/remote${uri}`;
|
|
3648
|
+
return src;
|
|
3585
3649
|
};
|
|
3586
|
-
|
|
3587
|
-
|
|
3650
|
+
|
|
3651
|
+
const getBaseUrl = (extensionPath, platform) => {
|
|
3652
|
+
switch (platform) {
|
|
3653
|
+
case Electron:
|
|
3654
|
+
case Remote:
|
|
3655
|
+
return getRemoteSrc(extensionPath + '/');
|
|
3656
|
+
default:
|
|
3657
|
+
return extensionPath;
|
|
3658
|
+
}
|
|
3588
3659
|
};
|
|
3589
3660
|
|
|
3590
|
-
const
|
|
3591
|
-
|
|
3592
|
-
|
|
3593
|
-
|
|
3594
|
-
}
|
|
3595
|
-
|
|
3596
|
-
return state;
|
|
3661
|
+
const getCommit = async () => {
|
|
3662
|
+
try {
|
|
3663
|
+
const commit = await invoke$1('Layout.getCommit');
|
|
3664
|
+
return commit;
|
|
3665
|
+
} catch {
|
|
3666
|
+
return '';
|
|
3597
3667
|
}
|
|
3598
|
-
return {
|
|
3599
|
-
...state,
|
|
3600
|
-
iconSrc: extensionDefaultIcon(assetDir)
|
|
3601
|
-
};
|
|
3602
3668
|
};
|
|
3603
3669
|
|
|
3604
|
-
const
|
|
3670
|
+
const getExtensionIdFromUri = uri => {
|
|
3671
|
+
const id = uri.slice('extension-detail://'.length);
|
|
3672
|
+
return id;
|
|
3673
|
+
};
|
|
3605
3674
|
|
|
3606
|
-
const
|
|
3607
|
-
const
|
|
3608
|
-
|
|
3609
|
-
|
|
3610
|
-
|
|
3611
|
-
menuId: ExtensionDetailIconContextMenu
|
|
3612
|
-
});
|
|
3613
|
-
return state;
|
|
3675
|
+
const interpolate = (value, inMin, inMax, outMin, outMax) => {
|
|
3676
|
+
const clamped = Math.min(Math.max(value, inMin), inMax);
|
|
3677
|
+
const ratio = (clamped - inMin) / (inMax - inMin);
|
|
3678
|
+
const mapped = outMin + ratio * (outMax - outMin);
|
|
3679
|
+
return Math.round(mapped);
|
|
3614
3680
|
};
|
|
3615
3681
|
|
|
3616
|
-
const
|
|
3617
|
-
|
|
3682
|
+
const getPadding = width => {
|
|
3683
|
+
if (width < 600) {
|
|
3684
|
+
return 10;
|
|
3685
|
+
}
|
|
3686
|
+
if (width < 800) {
|
|
3687
|
+
return 10;
|
|
3688
|
+
}
|
|
3689
|
+
if (width < 1200) {
|
|
3690
|
+
return interpolate(width, 800, 1200, 10, 30);
|
|
3691
|
+
}
|
|
3692
|
+
return 30;
|
|
3618
3693
|
};
|
|
3619
|
-
const
|
|
3620
|
-
if (
|
|
3621
|
-
return
|
|
3694
|
+
const getSideBarWidth = width => {
|
|
3695
|
+
if (width < 490) {
|
|
3696
|
+
return 0;
|
|
3622
3697
|
}
|
|
3623
|
-
|
|
3624
|
-
|
|
3625
|
-
|
|
3626
|
-
|
|
3627
|
-
|
|
3698
|
+
if (width < 650) {
|
|
3699
|
+
return Math.max(175 + Math.round(20 * (width / 100)), Math.round(width / 4));
|
|
3700
|
+
}
|
|
3701
|
+
if (width < 800) {
|
|
3702
|
+
return Math.max(175 + Math.round(20 * (width / 100)), Math.round(width / 4));
|
|
3703
|
+
}
|
|
3704
|
+
return Math.max(175 + Math.round(20 * (width / 100)), Math.round(width / 4));
|
|
3628
3705
|
};
|
|
3629
3706
|
|
|
3630
|
-
const
|
|
3631
|
-
const {
|
|
3632
|
-
|
|
3633
|
-
|
|
3634
|
-
|
|
3635
|
-
|
|
3636
|
-
|
|
3637
|
-
|
|
3638
|
-
|
|
3639
|
-
|
|
3640
|
-
|
|
3641
|
-
|
|
3707
|
+
const getTabs = (selectedTab, hasReadme, hasFeatures, hasChangelog) => {
|
|
3708
|
+
const tabs = [{
|
|
3709
|
+
enabled: hasReadme,
|
|
3710
|
+
label: details(),
|
|
3711
|
+
name: Details,
|
|
3712
|
+
selected: selectedTab === Details
|
|
3713
|
+
}, {
|
|
3714
|
+
enabled: hasFeatures,
|
|
3715
|
+
label: features$1(),
|
|
3716
|
+
name: Features,
|
|
3717
|
+
selected: selectedTab === Features
|
|
3718
|
+
}, {
|
|
3719
|
+
enabled: hasChangelog,
|
|
3720
|
+
label: changelog(),
|
|
3721
|
+
name: Changelog,
|
|
3722
|
+
selected: selectedTab === Changelog
|
|
3723
|
+
}];
|
|
3724
|
+
return tabs;
|
|
3642
3725
|
};
|
|
3643
3726
|
|
|
3644
|
-
const
|
|
3645
|
-
|
|
3646
|
-
|
|
3647
|
-
...state,
|
|
3648
|
-
readmeScrollTop: newScrollTop,
|
|
3649
|
-
scrollSource
|
|
3650
|
-
};
|
|
3651
|
-
};
|
|
3727
|
+
const Small = 1;
|
|
3728
|
+
const Normal = 2;
|
|
3729
|
+
const Large = 3;
|
|
3652
3730
|
|
|
3653
|
-
const
|
|
3654
|
-
|
|
3655
|
-
|
|
3731
|
+
const getViewletSize = width => {
|
|
3732
|
+
if (width < 180) {
|
|
3733
|
+
return Small;
|
|
3734
|
+
}
|
|
3735
|
+
if (width < 768) {
|
|
3736
|
+
return Normal;
|
|
3737
|
+
}
|
|
3738
|
+
return Large;
|
|
3656
3739
|
};
|
|
3657
3740
|
|
|
3658
|
-
const
|
|
3659
|
-
return
|
|
3741
|
+
const extensionDefaultIcon = assetDir => {
|
|
3742
|
+
return `${assetDir}/icons/extensionDefaultIcon.png`;
|
|
3660
3743
|
};
|
|
3661
|
-
|
|
3662
|
-
|
|
3663
|
-
|
|
3664
|
-
const isEnoentError = error => {
|
|
3665
|
-
return error && error.code === ENOENT;
|
|
3744
|
+
const extensionLanguageBasics = assetDir => {
|
|
3745
|
+
return `${assetDir}/icons/language-icon.svg`;
|
|
3666
3746
|
};
|
|
3667
|
-
|
|
3668
|
-
|
|
3669
|
-
// TODO send message to error worker or log worker
|
|
3670
|
-
// @ts-ignore
|
|
3671
|
-
console.error(error);
|
|
3747
|
+
const extensionTheme = assetDir => {
|
|
3748
|
+
return `${assetDir}/icons/theme-icon.png`;
|
|
3672
3749
|
};
|
|
3673
3750
|
|
|
3674
|
-
const
|
|
3675
|
-
return
|
|
3751
|
+
const isLanguageBasicsExtension = extension => {
|
|
3752
|
+
return extension.name && extension.name.startsWith('Language Basics');
|
|
3676
3753
|
};
|
|
3677
3754
|
|
|
3678
|
-
const
|
|
3679
|
-
|
|
3680
|
-
const changelogUrl = join(path, 'CHANGELOG.md');
|
|
3681
|
-
const changelogContent = await readFile(changelogUrl);
|
|
3682
|
-
return changelogContent;
|
|
3683
|
-
} catch (error$1) {
|
|
3684
|
-
if (isEnoentError(error$1)) {
|
|
3685
|
-
return '';
|
|
3686
|
-
}
|
|
3687
|
-
await error(new VError(error$1, 'Failed to load Changelog content'));
|
|
3688
|
-
return `${error$1}`;
|
|
3689
|
-
}
|
|
3755
|
+
const isThemeExtension = extension => {
|
|
3756
|
+
return extension.name && extension.name.endsWith(' Theme');
|
|
3690
3757
|
};
|
|
3691
3758
|
|
|
3692
|
-
const
|
|
3693
|
-
|
|
3694
|
-
|
|
3695
|
-
|
|
3696
|
-
|
|
3697
|
-
|
|
3759
|
+
const getIcon = (extension, platform, assetDir) => {
|
|
3760
|
+
if (!extension) {
|
|
3761
|
+
return extensionDefaultIcon(assetDir);
|
|
3762
|
+
}
|
|
3763
|
+
if (!extension.path || !extension.icon) {
|
|
3764
|
+
if (isLanguageBasicsExtension(extension)) {
|
|
3765
|
+
return extensionLanguageBasics(assetDir);
|
|
3766
|
+
}
|
|
3767
|
+
if (isThemeExtension(extension)) {
|
|
3768
|
+
return extensionTheme(assetDir);
|
|
3769
|
+
}
|
|
3770
|
+
return extensionDefaultIcon(assetDir);
|
|
3771
|
+
}
|
|
3772
|
+
if (platform === Remote || platform === Electron) {
|
|
3773
|
+
if (extension.builtin) {
|
|
3774
|
+
return `${assetDir}/extensions/${extension.id}/${extension.icon}`;
|
|
3775
|
+
}
|
|
3776
|
+
return `/remote/${extension.path}/${extension.icon}`; // TODO support windows paths
|
|
3777
|
+
}
|
|
3778
|
+
return '';
|
|
3779
|
+
};
|
|
3780
|
+
|
|
3781
|
+
const getDescription = extension => {
|
|
3782
|
+
if (!extension || !extension.description) {
|
|
3783
|
+
return 'n/a';
|
|
3784
|
+
}
|
|
3785
|
+
return extension.description;
|
|
3786
|
+
};
|
|
3787
|
+
|
|
3788
|
+
const getName = extension => {
|
|
3789
|
+
if (extension && extension.name) {
|
|
3790
|
+
return extension.name;
|
|
3791
|
+
}
|
|
3792
|
+
if (extension && extension.id) {
|
|
3793
|
+
return extension.id;
|
|
3794
|
+
}
|
|
3795
|
+
return 'n/a';
|
|
3796
|
+
};
|
|
3797
|
+
|
|
3798
|
+
const getDownloadCount = extension => {
|
|
3799
|
+
if (!extension) {
|
|
3800
|
+
return 'n/a';
|
|
3801
|
+
}
|
|
3802
|
+
|
|
3803
|
+
// Check for download count in various possible locations
|
|
3804
|
+
const downloadCount = extension.downloadCount || extension.downloads || extension.marketplace?.downloadCount || extension.marketplace?.downloads || extension.packageJSON?.downloadCount || extension.packageJSON?.downloads;
|
|
3805
|
+
if (!downloadCount) {
|
|
3806
|
+
return 'n/a';
|
|
3807
|
+
}
|
|
3808
|
+
|
|
3809
|
+
// Format the number with commas for better readability
|
|
3810
|
+
return downloadCount.toLocaleString();
|
|
3811
|
+
};
|
|
3812
|
+
|
|
3813
|
+
const getRating = extension => {
|
|
3814
|
+
if (!extension) {
|
|
3815
|
+
return 'n/a';
|
|
3816
|
+
}
|
|
3817
|
+
|
|
3818
|
+
// Check for rating in various possible locations
|
|
3819
|
+
const rating = extension.rating || extension.averageRating || extension.marketplace?.rating || extension.marketplace?.averageRating || extension.packageJSON?.rating || extension.packageJSON?.averageRating;
|
|
3820
|
+
if (!rating) {
|
|
3821
|
+
return 'n/a';
|
|
3822
|
+
}
|
|
3823
|
+
|
|
3824
|
+
// Format rating to one decimal place
|
|
3825
|
+
return rating.toFixed(1);
|
|
3826
|
+
};
|
|
3827
|
+
|
|
3828
|
+
const getBadge = (builtin, badgeEnabled) => {
|
|
3829
|
+
if (builtin && badgeEnabled) {
|
|
3830
|
+
return 'builtin';
|
|
3831
|
+
}
|
|
3832
|
+
return '';
|
|
3833
|
+
};
|
|
3834
|
+
|
|
3835
|
+
const hasColorThemes = extension => {
|
|
3836
|
+
return Boolean(extension && extension.colorThemes && extension.colorThemes.length > 0);
|
|
3837
|
+
};
|
|
3838
|
+
|
|
3839
|
+
const loadHeaderContent = (state, platform, extension) => {
|
|
3840
|
+
const {
|
|
3841
|
+
assetDir,
|
|
3842
|
+
builtinExtensionsBadgeEnabled
|
|
3698
3843
|
} = state;
|
|
3699
|
-
const
|
|
3700
|
-
const
|
|
3701
|
-
|
|
3702
|
-
|
|
3703
|
-
|
|
3704
|
-
const
|
|
3705
|
-
const
|
|
3706
|
-
|
|
3707
|
-
|
|
3708
|
-
|
|
3709
|
-
|
|
3710
|
-
});
|
|
3844
|
+
const iconSrc = getIcon(extension, platform, assetDir);
|
|
3845
|
+
const description = getDescription(extension);
|
|
3846
|
+
const name = getName(extension);
|
|
3847
|
+
const extensionUri = extension.uri || extension.path;
|
|
3848
|
+
const extensionId = extension?.id || 'n/a';
|
|
3849
|
+
const extensionVersion = extension?.version || 'n/a';
|
|
3850
|
+
const hasColorTheme = hasColorThemes(extension);
|
|
3851
|
+
const isBuiltin = extension?.builtin;
|
|
3852
|
+
const badge = getBadge(isBuiltin, builtinExtensionsBadgeEnabled);
|
|
3853
|
+
const downloadCount = getDownloadCount(extension);
|
|
3854
|
+
const rating = getRating(extension);
|
|
3711
3855
|
return {
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3856
|
+
badge,
|
|
3857
|
+
description,
|
|
3858
|
+
downloadCount,
|
|
3859
|
+
extension,
|
|
3860
|
+
extensionId,
|
|
3861
|
+
extensionUri,
|
|
3862
|
+
extensionVersion,
|
|
3863
|
+
hasColorTheme,
|
|
3864
|
+
iconSrc,
|
|
3865
|
+
name,
|
|
3866
|
+
rating
|
|
3716
3867
|
};
|
|
3717
3868
|
};
|
|
3718
3869
|
|
|
3719
|
-
const
|
|
3720
|
-
return
|
|
3870
|
+
const readFile = async uri => {
|
|
3871
|
+
return readFile$1(uri);
|
|
3872
|
+
};
|
|
3873
|
+
|
|
3874
|
+
const ENOENT = 'ENOENT';
|
|
3875
|
+
|
|
3876
|
+
const isEnoentError = error => {
|
|
3877
|
+
return error && error.code === ENOENT;
|
|
3721
3878
|
};
|
|
3722
3879
|
|
|
3723
3880
|
const loadReadmeContent = async readmeUrl => {
|
|
@@ -3735,104 +3892,174 @@ const loadReadmeContent = async readmeUrl => {
|
|
|
3735
3892
|
}
|
|
3736
3893
|
};
|
|
3737
3894
|
|
|
3738
|
-
const
|
|
3739
|
-
|
|
3740
|
-
|
|
3741
|
-
locationProtocol,
|
|
3742
|
-
readmeUrl,
|
|
3743
|
-
tabs
|
|
3744
|
-
} = state;
|
|
3745
|
-
const readmeContent = await loadReadmeContent(readmeUrl);
|
|
3746
|
-
const readmeHtml = await renderMarkdown(readmeContent, {
|
|
3747
|
-
baseUrl,
|
|
3748
|
-
linksExternal: true,
|
|
3749
|
-
locationProtocol
|
|
3750
|
-
});
|
|
3751
|
-
const detailsDom = await getMarkdownVirtualDom(readmeHtml);
|
|
3752
|
-
const newTabs = tabs.map(tab => {
|
|
3753
|
-
return {
|
|
3754
|
-
...tab,
|
|
3755
|
-
selected: tab.name === Details
|
|
3756
|
-
};
|
|
3757
|
-
});
|
|
3758
|
-
return {
|
|
3759
|
-
...state,
|
|
3760
|
-
detailsVirtualDom: detailsDom,
|
|
3761
|
-
selectedTab: Details,
|
|
3762
|
-
tabs: newTabs
|
|
3763
|
-
};
|
|
3764
|
-
};
|
|
3765
|
-
|
|
3766
|
-
const selectTabFeatures = async state => {
|
|
3767
|
-
const {
|
|
3768
|
-
baseUrl,
|
|
3769
|
-
extension,
|
|
3770
|
-
features,
|
|
3771
|
-
locationProtocol,
|
|
3772
|
-
selectedFeature,
|
|
3773
|
-
tabs
|
|
3774
|
-
} = state;
|
|
3775
|
-
if (features.length === 0) {
|
|
3776
|
-
return state;
|
|
3895
|
+
const stringifyCategory = category => {
|
|
3896
|
+
if (typeof category === 'string') {
|
|
3897
|
+
return category;
|
|
3777
3898
|
}
|
|
3778
|
-
|
|
3779
|
-
|
|
3780
|
-
|
|
3781
|
-
const newTabs = tabs.map(tab => {
|
|
3782
|
-
return {
|
|
3783
|
-
...tab,
|
|
3784
|
-
selected: tab.name === Features
|
|
3785
|
-
};
|
|
3786
|
-
});
|
|
3787
|
-
const newFeatures = features.map(feature => {
|
|
3788
|
-
if (feature.id === actualSelectedFeature) {
|
|
3789
|
-
return {
|
|
3790
|
-
...feature,
|
|
3791
|
-
selected: true
|
|
3792
|
-
};
|
|
3793
|
-
}
|
|
3794
|
-
return {
|
|
3795
|
-
...feature,
|
|
3796
|
-
selected: false
|
|
3797
|
-
};
|
|
3798
|
-
});
|
|
3899
|
+
return JSON.stringify(category);
|
|
3900
|
+
};
|
|
3901
|
+
const toCategory = categoryString => {
|
|
3799
3902
|
return {
|
|
3800
|
-
|
|
3801
|
-
|
|
3802
|
-
features: newFeatures,
|
|
3803
|
-
selectedFeature: features[0].id || '',
|
|
3804
|
-
selectedTab: Features,
|
|
3805
|
-
tabs: newTabs
|
|
3903
|
+
id: categoryString.toLowerCase(),
|
|
3904
|
+
label: categoryString
|
|
3806
3905
|
};
|
|
3807
3906
|
};
|
|
3808
|
-
|
|
3809
|
-
|
|
3810
|
-
|
|
3811
|
-
case Changelog:
|
|
3812
|
-
return selectTabChangelog;
|
|
3813
|
-
case Details:
|
|
3814
|
-
return selectTabDetails;
|
|
3815
|
-
case Features:
|
|
3816
|
-
return selectTabFeatures;
|
|
3817
|
-
default:
|
|
3818
|
-
return selectTabDefault;
|
|
3907
|
+
const getCategories = extension => {
|
|
3908
|
+
if (!hasProperty(extension, 'categories') || !Array.isArray(extension.categories)) {
|
|
3909
|
+
return [];
|
|
3819
3910
|
}
|
|
3911
|
+
const categoryStrings = extension.categories.map(stringifyCategory);
|
|
3912
|
+
const categories = categoryStrings.map(toCategory);
|
|
3913
|
+
return categories;
|
|
3820
3914
|
};
|
|
3821
3915
|
|
|
3822
|
-
const
|
|
3823
|
-
|
|
3824
|
-
|
|
3825
|
-
|
|
3916
|
+
const BYTE_UNITS = ['B', 'kB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
|
3917
|
+
const BIBYTE_UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
|
3918
|
+
const BIT_UNITS = ['b', 'kbit', 'Mbit', 'Gbit', 'Tbit', 'Pbit', 'Ebit', 'Zbit', 'Ybit'];
|
|
3919
|
+
const BIBIT_UNITS = ['b', 'kibit', 'Mibit', 'Gibit', 'Tibit', 'Pibit', 'Eibit', 'Zibit', 'Yibit'];
|
|
3826
3920
|
|
|
3827
|
-
|
|
3828
|
-
|
|
3921
|
+
/*
|
|
3922
|
+
Formats the given number using `Number#toLocaleString`.
|
|
3923
|
+
- If locale is a string, the value is expected to be a locale-key (for example: `de`).
|
|
3924
|
+
- If locale is true, the system default locale is used for translation.
|
|
3925
|
+
- If no value for locale is specified, the number is returned unmodified.
|
|
3926
|
+
*/
|
|
3927
|
+
const toLocaleString = (number, locale, options) => {
|
|
3928
|
+
let result = number;
|
|
3929
|
+
if (typeof locale === 'string' || Array.isArray(locale)) {
|
|
3930
|
+
result = number.toLocaleString(locale, options);
|
|
3931
|
+
} else if (locale === true || options !== undefined) {
|
|
3932
|
+
result = number.toLocaleString(undefined, options);
|
|
3933
|
+
}
|
|
3934
|
+
return result;
|
|
3829
3935
|
};
|
|
3830
|
-
|
|
3831
|
-
|
|
3832
|
-
|
|
3833
|
-
return [];
|
|
3936
|
+
const log10 = numberOrBigInt => {
|
|
3937
|
+
if (typeof numberOrBigInt === 'number') {
|
|
3938
|
+
return Math.log10(numberOrBigInt);
|
|
3834
3939
|
}
|
|
3835
|
-
|
|
3940
|
+
const string = numberOrBigInt.toString(10);
|
|
3941
|
+
return string.length + Math.log10(`0.${string.slice(0, 15)}`);
|
|
3942
|
+
};
|
|
3943
|
+
const log = numberOrBigInt => {
|
|
3944
|
+
if (typeof numberOrBigInt === 'number') {
|
|
3945
|
+
return Math.log(numberOrBigInt);
|
|
3946
|
+
}
|
|
3947
|
+
return log10(numberOrBigInt) * Math.log(10);
|
|
3948
|
+
};
|
|
3949
|
+
const divide = (numberOrBigInt, divisor) => {
|
|
3950
|
+
if (typeof numberOrBigInt === 'number') {
|
|
3951
|
+
return numberOrBigInt / divisor;
|
|
3952
|
+
}
|
|
3953
|
+
const integerPart = numberOrBigInt / BigInt(divisor);
|
|
3954
|
+
const remainder = numberOrBigInt % BigInt(divisor);
|
|
3955
|
+
return Number(integerPart) + Number(remainder) / divisor;
|
|
3956
|
+
};
|
|
3957
|
+
const applyFixedWidth = (result, fixedWidth) => {
|
|
3958
|
+
if (fixedWidth === undefined) {
|
|
3959
|
+
return result;
|
|
3960
|
+
}
|
|
3961
|
+
if (typeof fixedWidth !== 'number' || !Number.isSafeInteger(fixedWidth) || fixedWidth < 0) {
|
|
3962
|
+
throw new TypeError(`Expected fixedWidth to be a non-negative integer, got ${typeof fixedWidth}: ${fixedWidth}`);
|
|
3963
|
+
}
|
|
3964
|
+
if (fixedWidth === 0) {
|
|
3965
|
+
return result;
|
|
3966
|
+
}
|
|
3967
|
+
return result.length < fixedWidth ? result.padStart(fixedWidth, ' ') : result;
|
|
3968
|
+
};
|
|
3969
|
+
const buildLocaleOptions = options => {
|
|
3970
|
+
const {
|
|
3971
|
+
minimumFractionDigits,
|
|
3972
|
+
maximumFractionDigits
|
|
3973
|
+
} = options;
|
|
3974
|
+
if (minimumFractionDigits === undefined && maximumFractionDigits === undefined) {
|
|
3975
|
+
return undefined;
|
|
3976
|
+
}
|
|
3977
|
+
return {
|
|
3978
|
+
...(minimumFractionDigits !== undefined && {
|
|
3979
|
+
minimumFractionDigits
|
|
3980
|
+
}),
|
|
3981
|
+
...(maximumFractionDigits !== undefined && {
|
|
3982
|
+
maximumFractionDigits
|
|
3983
|
+
}),
|
|
3984
|
+
roundingMode: 'trunc'
|
|
3985
|
+
};
|
|
3986
|
+
};
|
|
3987
|
+
function prettyBytes(number, options) {
|
|
3988
|
+
if (typeof number !== 'bigint' && !Number.isFinite(number)) {
|
|
3989
|
+
throw new TypeError(`Expected a finite number, got ${typeof number}: ${number}`);
|
|
3990
|
+
}
|
|
3991
|
+
options = {
|
|
3992
|
+
bits: false,
|
|
3993
|
+
binary: false,
|
|
3994
|
+
space: true,
|
|
3995
|
+
nonBreakingSpace: false,
|
|
3996
|
+
...options
|
|
3997
|
+
};
|
|
3998
|
+
const UNITS = options.bits ? options.binary ? BIBIT_UNITS : BIT_UNITS : options.binary ? BIBYTE_UNITS : BYTE_UNITS;
|
|
3999
|
+
const separator = options.space ? options.nonBreakingSpace ? '\u00A0' : ' ' : '';
|
|
4000
|
+
|
|
4001
|
+
// Handle signed zero case
|
|
4002
|
+
const isZero = typeof number === 'number' ? number === 0 : number === 0n;
|
|
4003
|
+
if (options.signed && isZero) {
|
|
4004
|
+
const result = ` 0${separator}${UNITS[0]}`;
|
|
4005
|
+
return applyFixedWidth(result, options.fixedWidth);
|
|
4006
|
+
}
|
|
4007
|
+
const isNegative = number < 0;
|
|
4008
|
+
const prefix = isNegative ? '-' : options.signed ? '+' : '';
|
|
4009
|
+
if (isNegative) {
|
|
4010
|
+
number = -number;
|
|
4011
|
+
}
|
|
4012
|
+
const localeOptions = buildLocaleOptions(options);
|
|
4013
|
+
let result;
|
|
4014
|
+
if (number < 1) {
|
|
4015
|
+
const numberString = toLocaleString(number, options.locale, localeOptions);
|
|
4016
|
+
result = prefix + numberString + separator + UNITS[0];
|
|
4017
|
+
} else {
|
|
4018
|
+
const exponent = Math.min(Math.floor(options.binary ? log(number) / Math.log(1024) : log10(number) / 3), UNITS.length - 1);
|
|
4019
|
+
number = divide(number, (options.binary ? 1024 : 1000) ** exponent);
|
|
4020
|
+
if (!localeOptions) {
|
|
4021
|
+
const minPrecision = Math.max(3, Math.floor(number).toString().length);
|
|
4022
|
+
number = number.toPrecision(minPrecision);
|
|
4023
|
+
}
|
|
4024
|
+
const numberString = toLocaleString(Number(number), options.locale, localeOptions);
|
|
4025
|
+
const unit = UNITS[exponent];
|
|
4026
|
+
result = prefix + numberString + separator + unit;
|
|
4027
|
+
}
|
|
4028
|
+
return applyFixedWidth(result, options.fixedWidth);
|
|
4029
|
+
}
|
|
4030
|
+
|
|
4031
|
+
const getDisplaySize = size => {
|
|
4032
|
+
return prettyBytes(size, {
|
|
4033
|
+
maximumFractionDigits: 1
|
|
4034
|
+
});
|
|
4035
|
+
};
|
|
4036
|
+
|
|
4037
|
+
const supportsFileSize = uri => {
|
|
4038
|
+
if (uri.startsWith('http:') || uri.startsWith('https://')) {
|
|
4039
|
+
return false;
|
|
4040
|
+
}
|
|
4041
|
+
return true;
|
|
4042
|
+
};
|
|
4043
|
+
const getFolderSize = async uri => {
|
|
4044
|
+
if (!uri) {
|
|
4045
|
+
throw new VError(`uri is required`);
|
|
4046
|
+
}
|
|
4047
|
+
if (!supportsFileSize(uri)) {
|
|
4048
|
+
return 0;
|
|
4049
|
+
}
|
|
4050
|
+
try {
|
|
4051
|
+
// @ts-ignore
|
|
4052
|
+
return await invoke('FileSystem.getFolderSize', uri);
|
|
4053
|
+
} catch {
|
|
4054
|
+
return 0;
|
|
4055
|
+
}
|
|
4056
|
+
};
|
|
4057
|
+
|
|
4058
|
+
const getSizeEntries = (showSizeLink, displaySize, extensionUri) => {
|
|
4059
|
+
if (!showSizeLink) {
|
|
4060
|
+
return [];
|
|
4061
|
+
}
|
|
4062
|
+
return [{
|
|
3836
4063
|
key: size(),
|
|
3837
4064
|
onClick: HandleClickSize,
|
|
3838
4065
|
title: extensionUri,
|
|
@@ -3858,739 +4085,610 @@ const getInstallationEntries = (displaySize, extensionId, extensionVersion, exte
|
|
|
3858
4085
|
return entries;
|
|
3859
4086
|
};
|
|
3860
4087
|
|
|
3861
|
-
const
|
|
3862
|
-
|
|
3863
|
-
|
|
3864
|
-
|
|
3865
|
-
|
|
3866
|
-
|
|
3867
|
-
|
|
3868
|
-
|
|
3869
|
-
|
|
3870
|
-
|
|
3871
|
-
|
|
3872
|
-
|
|
3873
|
-
showSizeLink: newShowSizeLink
|
|
3874
|
-
};
|
|
4088
|
+
const getMarketplaceEntries = isBuiltin => {
|
|
4089
|
+
if (isBuiltin) {
|
|
4090
|
+
return [];
|
|
4091
|
+
}
|
|
4092
|
+
return [{
|
|
4093
|
+
key: published(),
|
|
4094
|
+
odd: true,
|
|
4095
|
+
value: 'n/a'
|
|
4096
|
+
}, {
|
|
4097
|
+
key: lastReleased(),
|
|
4098
|
+
value: 'n/a'
|
|
4099
|
+
}];
|
|
3875
4100
|
};
|
|
3876
4101
|
|
|
3877
|
-
const
|
|
3878
|
-
|
|
4102
|
+
const getLicenseLink = extension => {
|
|
4103
|
+
// TODO
|
|
4104
|
+
return '#';
|
|
3879
4105
|
};
|
|
3880
4106
|
|
|
3881
|
-
const
|
|
4107
|
+
const ensureValidLink = link => {
|
|
4108
|
+
if (!link) {
|
|
4109
|
+
return '';
|
|
4110
|
+
}
|
|
3882
4111
|
try {
|
|
3883
|
-
const
|
|
3884
|
-
|
|
3885
|
-
|
|
3886
|
-
}
|
|
3887
|
-
return
|
|
3888
|
-
} catch
|
|
3889
|
-
|
|
4112
|
+
const parsed = new URL(link);
|
|
4113
|
+
if (parsed.protocol !== 'https:') {
|
|
4114
|
+
return '';
|
|
4115
|
+
}
|
|
4116
|
+
return link;
|
|
4117
|
+
} catch {
|
|
4118
|
+
return '';
|
|
3890
4119
|
}
|
|
3891
4120
|
};
|
|
3892
4121
|
|
|
3893
|
-
const
|
|
3894
|
-
|
|
3895
|
-
|
|
4122
|
+
const getRepositoryLinkRaw = extension => {
|
|
4123
|
+
if (extension && hasProperty(extension, 'repository') && typeof extension.repository === 'string') {
|
|
4124
|
+
return extension.repository; // TODO watch out for javascript: or other invalid links or path traversal
|
|
4125
|
+
}
|
|
4126
|
+
return '';
|
|
4127
|
+
};
|
|
4128
|
+
const getRepositoryLink = extension => {
|
|
4129
|
+
const raw = getRepositoryLinkRaw(extension);
|
|
4130
|
+
const validLink = ensureValidLink(raw);
|
|
4131
|
+
return validLink;
|
|
4132
|
+
};
|
|
4133
|
+
const getIssuesLink = extension => {
|
|
4134
|
+
const repositoryLink = getRepositoryLink(extension);
|
|
4135
|
+
if (!repositoryLink) {
|
|
4136
|
+
return '';
|
|
4137
|
+
}
|
|
4138
|
+
if (repositoryLink && repositoryLink.startsWith('https://github.com')) {
|
|
4139
|
+
return `${repositoryLink}/issues`;
|
|
4140
|
+
}
|
|
4141
|
+
return '';
|
|
3896
4142
|
};
|
|
3897
4143
|
|
|
3898
|
-
const
|
|
3899
|
-
|
|
4144
|
+
const getResources = (isBuiltin, extension) => {
|
|
4145
|
+
const repositoryLink = getRepositoryLink(extension);
|
|
4146
|
+
const issueLink = getIssuesLink(extension);
|
|
4147
|
+
const licenseLink = getLicenseLink();
|
|
4148
|
+
// TODO hide marketplace link for builtin extensions
|
|
4149
|
+
return [{
|
|
4150
|
+
icon: 'LinkExternal',
|
|
4151
|
+
label: marketplace(),
|
|
4152
|
+
url: '#'
|
|
4153
|
+
}, {
|
|
4154
|
+
icon: 'LinkExternal',
|
|
4155
|
+
label: issues(),
|
|
4156
|
+
url: issueLink
|
|
4157
|
+
}, {
|
|
4158
|
+
icon: 'Repo',
|
|
4159
|
+
label: repository(),
|
|
4160
|
+
url: repositoryLink
|
|
4161
|
+
}, {
|
|
4162
|
+
icon: 'LinkExternal',
|
|
4163
|
+
label: license(),
|
|
4164
|
+
url: licenseLink
|
|
4165
|
+
}];
|
|
3900
4166
|
};
|
|
3901
4167
|
|
|
3902
|
-
const
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3906
|
-
|
|
3907
|
-
|
|
3908
|
-
|
|
3909
|
-
|
|
3910
|
-
|
|
3911
|
-
|
|
4168
|
+
const loadSideBarContent = async (extensionId, extensionVersion, extensionUri, isBuiltin, extension, showSizeLink) => {
|
|
4169
|
+
const folderSize = await getFolderSize(extensionUri);
|
|
4170
|
+
const displaySize = getDisplaySize(folderSize);
|
|
4171
|
+
const installationEntries = getInstallationEntries(displaySize, extensionId, extensionVersion, extensionUri, showSizeLink);
|
|
4172
|
+
const marketplaceEntries = getMarketplaceEntries(isBuiltin);
|
|
4173
|
+
const categories = getCategories(extension);
|
|
4174
|
+
const resources = getResources(isBuiltin, extension);
|
|
4175
|
+
return {
|
|
4176
|
+
categories,
|
|
4177
|
+
displaySize,
|
|
4178
|
+
folderSize,
|
|
4179
|
+
installationEntries,
|
|
4180
|
+
marketplaceEntries,
|
|
4181
|
+
resources
|
|
4182
|
+
};
|
|
3912
4183
|
};
|
|
3913
4184
|
|
|
3914
|
-
const
|
|
3915
|
-
|
|
3916
|
-
set$1(rpc);
|
|
4185
|
+
const join = (...parts) => {
|
|
4186
|
+
return parts.join('/');
|
|
3917
4187
|
};
|
|
3918
4188
|
|
|
3919
|
-
const
|
|
3920
|
-
|
|
4189
|
+
const getSavedChangelogScrollTop = savedState => {
|
|
4190
|
+
if (savedState && typeof savedState === 'object' && 'changelogScrollTop' in savedState && typeof savedState.changelogScrollTop === 'number') {
|
|
4191
|
+
return savedState.changelogScrollTop;
|
|
4192
|
+
}
|
|
4193
|
+
return 0;
|
|
3921
4194
|
};
|
|
3922
4195
|
|
|
3923
|
-
const
|
|
3924
|
-
|
|
3925
|
-
|
|
3926
|
-
commandMap: {},
|
|
3927
|
-
send: sendMessagePortToMarkdownWorker
|
|
3928
|
-
});
|
|
3929
|
-
return rpc;
|
|
3930
|
-
} catch (error) {
|
|
3931
|
-
throw new VError(error, `Failed to create markdown worker rpc`);
|
|
4196
|
+
const getSavedReadmeScrollTop = savedState => {
|
|
4197
|
+
if (savedState && typeof savedState === 'object' && 'readmeScrollTop' in savedState && typeof savedState.readmeScrollTop === 'number') {
|
|
4198
|
+
return savedState.readmeScrollTop;
|
|
3932
4199
|
}
|
|
4200
|
+
return 0;
|
|
3933
4201
|
};
|
|
3934
4202
|
|
|
3935
|
-
const
|
|
3936
|
-
|
|
3937
|
-
|
|
4203
|
+
const getSavedSelectedFeature = savedState => {
|
|
4204
|
+
if (savedState && typeof savedState === 'object' && 'selectedFeature' in savedState && typeof savedState.selectedFeature === 'string') {
|
|
4205
|
+
return savedState.selectedFeature;
|
|
4206
|
+
}
|
|
4207
|
+
return Details;
|
|
3938
4208
|
};
|
|
3939
4209
|
|
|
3940
|
-
const
|
|
3941
|
-
|
|
3942
|
-
|
|
4210
|
+
const getSavedSelectedTab = savedState => {
|
|
4211
|
+
if (savedState && typeof savedState === 'object' && 'selectedTab' in savedState && typeof savedState.selectedTab === 'string') {
|
|
4212
|
+
return savedState.selectedTab;
|
|
4213
|
+
}
|
|
4214
|
+
return Details;
|
|
3943
4215
|
};
|
|
3944
4216
|
|
|
3945
|
-
const
|
|
3946
|
-
|
|
3947
|
-
|
|
3948
|
-
|
|
3949
|
-
|
|
3950
|
-
|
|
4217
|
+
const restoreState = savedState => {
|
|
4218
|
+
const selectedTab = getSavedSelectedTab(savedState);
|
|
4219
|
+
const selectedFeature = getSavedSelectedFeature(savedState);
|
|
4220
|
+
const readmeScrollTop = getSavedReadmeScrollTop(savedState);
|
|
4221
|
+
const changelogScrollTop = getSavedChangelogScrollTop(savedState);
|
|
4222
|
+
return {
|
|
4223
|
+
changelogScrollTop,
|
|
4224
|
+
readmeScrollTop,
|
|
4225
|
+
selectedFeature,
|
|
4226
|
+
selectedTab
|
|
4227
|
+
};
|
|
3951
4228
|
};
|
|
3952
4229
|
|
|
3953
|
-
|
|
3954
|
-
|
|
3955
|
-
|
|
3956
|
-
|
|
4230
|
+
const isEnabled = tab => {
|
|
4231
|
+
return tab.enabled;
|
|
4232
|
+
};
|
|
4233
|
+
const loadContent = async (state, platform, savedState, isTest = false) => {
|
|
4234
|
+
if (isTest) {
|
|
4235
|
+
savedState = undefined;
|
|
3957
4236
|
}
|
|
3958
|
-
|
|
4237
|
+
const {
|
|
4238
|
+
uri,
|
|
4239
|
+
width
|
|
4240
|
+
} = state;
|
|
4241
|
+
const id = getExtensionIdFromUri(uri);
|
|
4242
|
+
const extension = await getExtension(id, platform);
|
|
4243
|
+
if (!extension) {
|
|
4244
|
+
throw new ExtensionNotFoundError(id);
|
|
4245
|
+
}
|
|
4246
|
+
const commit = await getCommit();
|
|
4247
|
+
const headerData = loadHeaderContent(state, platform, extension);
|
|
4248
|
+
const {
|
|
4249
|
+
badge,
|
|
4250
|
+
description,
|
|
4251
|
+
downloadCount,
|
|
4252
|
+
extensionId,
|
|
4253
|
+
extensionUri,
|
|
4254
|
+
extensionVersion,
|
|
4255
|
+
hasColorTheme,
|
|
4256
|
+
iconSrc,
|
|
4257
|
+
name,
|
|
4258
|
+
rating
|
|
4259
|
+
} = headerData;
|
|
4260
|
+
const readmeUrl = join(extensionUri, 'README.md');
|
|
4261
|
+
const changelogUrl = join(extensionUri, 'CHANGELOG.md');
|
|
4262
|
+
const [hasReadme, hasChangelog] = await Promise.all([existsFile(readmeUrl), existsFile(changelogUrl)]);
|
|
4263
|
+
const readmeContent = hasReadme ? await loadReadmeContent(readmeUrl) : noReadmeFound();
|
|
4264
|
+
const baseUrl = getBaseUrl(extension.path, platform);
|
|
4265
|
+
const locationProtocol = location.protocol;
|
|
4266
|
+
const locationHost = location.host;
|
|
4267
|
+
const readmeHtml = await renderMarkdown(readmeContent, {
|
|
4268
|
+
baseUrl,
|
|
4269
|
+
commit,
|
|
4270
|
+
linksExternal: true,
|
|
4271
|
+
locationProtocol
|
|
4272
|
+
});
|
|
4273
|
+
const detailsVirtualDom = await getMarkdownVirtualDom(readmeHtml, {
|
|
4274
|
+
scrollToTopEnabled: true
|
|
4275
|
+
});
|
|
4276
|
+
const isBuiltin = extension?.isBuiltin;
|
|
4277
|
+
const disabled = extension?.disabled;
|
|
4278
|
+
const buttons = getExtensionDetailButtons(hasColorTheme, isBuiltin, disabled);
|
|
4279
|
+
const size = getViewletSize(width);
|
|
4280
|
+
const {
|
|
4281
|
+
changelogScrollTop,
|
|
4282
|
+
readmeScrollTop,
|
|
4283
|
+
selectedFeature,
|
|
4284
|
+
selectedTab
|
|
4285
|
+
} = restoreState(savedState);
|
|
4286
|
+
const features = getFeatures(selectedFeature || Theme, extension);
|
|
4287
|
+
const hasFeatures = features.length > 0;
|
|
4288
|
+
const tabs = getTabs(selectedTab, hasReadme, hasFeatures, hasChangelog);
|
|
4289
|
+
const enabledTabs = tabs.filter(isEnabled);
|
|
4290
|
+
const sizeValue = getViewletSize(width || 0);
|
|
4291
|
+
const showSizeLink = platform !== Web$1;
|
|
4292
|
+
const {
|
|
4293
|
+
categories,
|
|
4294
|
+
displaySize,
|
|
4295
|
+
folderSize,
|
|
4296
|
+
installationEntries,
|
|
4297
|
+
marketplaceEntries,
|
|
4298
|
+
resources
|
|
4299
|
+
} = await loadSideBarContent(extensionId, extensionVersion, extensionUri, isBuiltin, extension, showSizeLink);
|
|
4300
|
+
const padding = getPadding(width);
|
|
4301
|
+
const sideBarWidth = getSideBarWidth(width);
|
|
4302
|
+
const showSideBar = sideBarWidth > 0;
|
|
4303
|
+
return {
|
|
4304
|
+
...state,
|
|
4305
|
+
badge,
|
|
4306
|
+
baseUrl,
|
|
4307
|
+
buttons,
|
|
4308
|
+
categories,
|
|
4309
|
+
changelogScrollTop,
|
|
4310
|
+
commit,
|
|
4311
|
+
description,
|
|
4312
|
+
detailsVirtualDom,
|
|
4313
|
+
disabled,
|
|
4314
|
+
displaySize,
|
|
4315
|
+
downloadCount,
|
|
4316
|
+
extension,
|
|
4317
|
+
extensionId,
|
|
4318
|
+
extensionUri,
|
|
4319
|
+
extensionVersion,
|
|
4320
|
+
features,
|
|
4321
|
+
folderSize,
|
|
4322
|
+
hasColorTheme,
|
|
4323
|
+
hasReadme,
|
|
4324
|
+
iconSrc,
|
|
4325
|
+
installationEntries,
|
|
4326
|
+
locationHost,
|
|
4327
|
+
locationProtocol,
|
|
4328
|
+
marketplaceEntries,
|
|
4329
|
+
name,
|
|
4330
|
+
paddingLeft: padding,
|
|
4331
|
+
paddingRight: padding,
|
|
4332
|
+
rating,
|
|
4333
|
+
readmeScrollTop,
|
|
4334
|
+
readmeUrl,
|
|
4335
|
+
resources,
|
|
4336
|
+
scrollSource: Script,
|
|
4337
|
+
scrollToTopButtonEnabled: true,
|
|
4338
|
+
selectedTab,
|
|
4339
|
+
showSideBar,
|
|
4340
|
+
showSizeLink,
|
|
4341
|
+
sideBarWidth,
|
|
4342
|
+
sizeOnDisk: size,
|
|
4343
|
+
sizeValue,
|
|
4344
|
+
tabs: enabledTabs
|
|
4345
|
+
};
|
|
4346
|
+
};
|
|
3959
4347
|
|
|
3960
|
-
const
|
|
3961
|
-
const
|
|
3962
|
-
|
|
4348
|
+
const handleExtensionsChanged = async state => {
|
|
4349
|
+
const {
|
|
4350
|
+
platform
|
|
4351
|
+
} = state;
|
|
4352
|
+
return loadContent(state, platform, {});
|
|
3963
4353
|
};
|
|
3964
4354
|
|
|
3965
|
-
const
|
|
3966
|
-
|
|
3967
|
-
|
|
3968
|
-
|
|
3969
|
-
|
|
3970
|
-
|
|
3971
|
-
|
|
3972
|
-
|
|
4355
|
+
const handleExtensionsStatusUpdate = async state => {
|
|
4356
|
+
const {
|
|
4357
|
+
extension
|
|
4358
|
+
} = state;
|
|
4359
|
+
const details = await getRuntimeStatusDetails(extension);
|
|
4360
|
+
return {
|
|
4361
|
+
...state,
|
|
4362
|
+
...details
|
|
4363
|
+
};
|
|
3973
4364
|
};
|
|
3974
4365
|
|
|
3975
|
-
const
|
|
3976
|
-
|
|
3977
|
-
|
|
3978
|
-
|
|
3979
|
-
}
|
|
3980
|
-
|
|
4366
|
+
const handleIconError = state => {
|
|
4367
|
+
const {
|
|
4368
|
+
assetDir,
|
|
4369
|
+
iconSrc
|
|
4370
|
+
} = state;
|
|
4371
|
+
if (iconSrc === extensionDefaultIcon(assetDir)) {
|
|
4372
|
+
return state;
|
|
3981
4373
|
}
|
|
4374
|
+
return {
|
|
4375
|
+
...state,
|
|
4376
|
+
iconSrc: extensionDefaultIcon(assetDir)
|
|
4377
|
+
};
|
|
3982
4378
|
};
|
|
3983
4379
|
|
|
3984
|
-
const
|
|
3985
|
-
const id = uri.slice('extension-detail://'.length);
|
|
3986
|
-
return id;
|
|
3987
|
-
};
|
|
4380
|
+
const ExtensionDetailIconContextMenu = 4091;
|
|
3988
4381
|
|
|
3989
|
-
const
|
|
3990
|
-
const
|
|
3991
|
-
|
|
3992
|
-
|
|
3993
|
-
|
|
4382
|
+
const handleImageContextMenu = async (state, eventX, eventY) => {
|
|
4383
|
+
const {
|
|
4384
|
+
uid
|
|
4385
|
+
} = state;
|
|
4386
|
+
await show2(uid, ExtensionDetailIconContextMenu, eventX, eventY, {
|
|
4387
|
+
menuId: ExtensionDetailIconContextMenu
|
|
4388
|
+
});
|
|
4389
|
+
return state;
|
|
3994
4390
|
};
|
|
3995
4391
|
|
|
3996
|
-
const
|
|
3997
|
-
|
|
3998
|
-
return 10;
|
|
3999
|
-
}
|
|
4000
|
-
if (width < 800) {
|
|
4001
|
-
return 10;
|
|
4002
|
-
}
|
|
4003
|
-
if (width < 1200) {
|
|
4004
|
-
return interpolate(width, 800, 1200, 10, 30);
|
|
4005
|
-
}
|
|
4006
|
-
return 30;
|
|
4392
|
+
const isExternalLink = href => {
|
|
4393
|
+
return href.startsWith('http://') || href.startsWith('https://');
|
|
4007
4394
|
};
|
|
4008
|
-
const
|
|
4009
|
-
if (
|
|
4010
|
-
return
|
|
4011
|
-
}
|
|
4012
|
-
if (width < 650) {
|
|
4013
|
-
return Math.max(175 + Math.round(20 * (width / 100)), Math.round(width / 4));
|
|
4014
|
-
}
|
|
4015
|
-
if (width < 800) {
|
|
4016
|
-
return Math.max(175 + Math.round(20 * (width / 100)), Math.round(width / 4));
|
|
4395
|
+
const handleReadmeClick = async (state, nodeName, href) => {
|
|
4396
|
+
if (!href || !isExternalLink(href)) {
|
|
4397
|
+
return state;
|
|
4017
4398
|
}
|
|
4018
|
-
|
|
4399
|
+
// TODO what to do about relative links? open them in editor?
|
|
4400
|
+
// TODO what to do about mail links?
|
|
4401
|
+
await openUrl$1(href);
|
|
4402
|
+
// TODO check node name and href
|
|
4403
|
+
return state;
|
|
4019
4404
|
};
|
|
4020
4405
|
|
|
4021
|
-
const
|
|
4022
|
-
const
|
|
4023
|
-
|
|
4024
|
-
|
|
4025
|
-
|
|
4026
|
-
|
|
4027
|
-
|
|
4028
|
-
|
|
4029
|
-
|
|
4030
|
-
|
|
4031
|
-
|
|
4032
|
-
|
|
4033
|
-
enabled: hasChangelog,
|
|
4034
|
-
label: changelog(),
|
|
4035
|
-
name: Changelog,
|
|
4036
|
-
selected: selectedTab === Changelog
|
|
4037
|
-
}];
|
|
4038
|
-
return tabs;
|
|
4039
|
-
};
|
|
4040
|
-
|
|
4041
|
-
const Small = 1;
|
|
4042
|
-
const Normal = 2;
|
|
4043
|
-
const Large = 3;
|
|
4044
|
-
|
|
4045
|
-
const getViewletSize = width => {
|
|
4046
|
-
if (width < 180) {
|
|
4047
|
-
return Small;
|
|
4048
|
-
}
|
|
4049
|
-
if (width < 768) {
|
|
4050
|
-
return Normal;
|
|
4051
|
-
}
|
|
4052
|
-
return Large;
|
|
4053
|
-
};
|
|
4054
|
-
|
|
4055
|
-
const isLanguageBasicsExtension = extension => {
|
|
4056
|
-
return extension.name && extension.name.startsWith('Language Basics');
|
|
4057
|
-
};
|
|
4058
|
-
|
|
4059
|
-
const isThemeExtension = extension => {
|
|
4060
|
-
return extension.name && extension.name.endsWith(' Theme');
|
|
4061
|
-
};
|
|
4062
|
-
|
|
4063
|
-
const getIcon = (extension, platform, assetDir) => {
|
|
4064
|
-
if (!extension) {
|
|
4065
|
-
return extensionDefaultIcon(assetDir);
|
|
4066
|
-
}
|
|
4067
|
-
if (!extension.path || !extension.icon) {
|
|
4068
|
-
if (isLanguageBasicsExtension(extension)) {
|
|
4069
|
-
return extensionLanguageBasics(assetDir);
|
|
4070
|
-
}
|
|
4071
|
-
if (isThemeExtension(extension)) {
|
|
4072
|
-
return extensionTheme(assetDir);
|
|
4073
|
-
}
|
|
4074
|
-
return extensionDefaultIcon(assetDir);
|
|
4075
|
-
}
|
|
4076
|
-
if (platform === Remote || platform === Electron) {
|
|
4077
|
-
if (extension.builtin) {
|
|
4078
|
-
return `${assetDir}/extensions/${extension.id}/${extension.icon}`;
|
|
4079
|
-
}
|
|
4080
|
-
return `/remote/${extension.path}/${extension.icon}`; // TODO support windows paths
|
|
4081
|
-
}
|
|
4082
|
-
return '';
|
|
4406
|
+
const handleReadmeContextMenu = async (state, x, y, nodeName, href) => {
|
|
4407
|
+
const {
|
|
4408
|
+
uid
|
|
4409
|
+
} = state;
|
|
4410
|
+
// TODO maybe also pass other args
|
|
4411
|
+
await show2(uid, ExtensionDetailReadme, x, y, {
|
|
4412
|
+
href,
|
|
4413
|
+
menuId: ExtensionDetailReadme,
|
|
4414
|
+
nodeName
|
|
4415
|
+
});
|
|
4416
|
+
// TODO
|
|
4417
|
+
return state;
|
|
4083
4418
|
};
|
|
4084
4419
|
|
|
4085
|
-
const
|
|
4086
|
-
|
|
4087
|
-
|
|
4088
|
-
|
|
4089
|
-
|
|
4420
|
+
const handleScroll = (state, scrollTop, scrollSource = Script) => {
|
|
4421
|
+
const newScrollTop = Math.max(0, scrollTop);
|
|
4422
|
+
return {
|
|
4423
|
+
...state,
|
|
4424
|
+
readmeScrollTop: newScrollTop,
|
|
4425
|
+
scrollSource
|
|
4426
|
+
};
|
|
4090
4427
|
};
|
|
4091
4428
|
|
|
4092
|
-
const
|
|
4093
|
-
|
|
4094
|
-
|
|
4095
|
-
}
|
|
4096
|
-
if (extension && extension.id) {
|
|
4097
|
-
return extension.id;
|
|
4098
|
-
}
|
|
4099
|
-
return 'n/a';
|
|
4429
|
+
const handleSelectionChange = async (state, selection) => {
|
|
4430
|
+
// console.log('selection change')
|
|
4431
|
+
return state;
|
|
4100
4432
|
};
|
|
4101
4433
|
|
|
4102
|
-
const
|
|
4103
|
-
|
|
4104
|
-
|
|
4105
|
-
|
|
4106
|
-
|
|
4107
|
-
|
|
4108
|
-
|
|
4109
|
-
|
|
4110
|
-
|
|
4111
|
-
}
|
|
4112
|
-
|
|
4113
|
-
// Format the number with commas for better readability
|
|
4114
|
-
return downloadCount.toLocaleString();
|
|
4434
|
+
const focusId = 451;
|
|
4435
|
+
const handleTabFocus = (state, name) => {
|
|
4436
|
+
const tabIndex = state.tabs.findIndex(tab => tab.name === name);
|
|
4437
|
+
const newFocusedTabIndex = tabIndex === -1 ? state.focusedTabIndex : tabIndex;
|
|
4438
|
+
return {
|
|
4439
|
+
...state,
|
|
4440
|
+
focus: focusId,
|
|
4441
|
+
focusedTabIndex: newFocusedTabIndex
|
|
4442
|
+
};
|
|
4115
4443
|
};
|
|
4116
4444
|
|
|
4117
|
-
const
|
|
4118
|
-
|
|
4119
|
-
|
|
4120
|
-
|
|
4121
|
-
|
|
4122
|
-
// Check for rating in various possible locations
|
|
4123
|
-
const rating = extension.rating || extension.averageRating || extension.marketplace?.rating || extension.marketplace?.averageRating || extension.packageJSON?.rating || extension.packageJSON?.averageRating;
|
|
4124
|
-
if (!rating) {
|
|
4125
|
-
return 'n/a';
|
|
4126
|
-
}
|
|
4127
|
-
|
|
4128
|
-
// Format rating to one decimal place
|
|
4129
|
-
return rating.toFixed(1);
|
|
4445
|
+
const error = async error => {
|
|
4446
|
+
// TODO send message to error worker or log worker
|
|
4447
|
+
// @ts-ignore
|
|
4448
|
+
console.error(error);
|
|
4130
4449
|
};
|
|
4131
4450
|
|
|
4132
|
-
const
|
|
4133
|
-
|
|
4134
|
-
|
|
4451
|
+
const loadChangelogContent = async path => {
|
|
4452
|
+
try {
|
|
4453
|
+
const changelogUrl = join(path, 'CHANGELOG.md');
|
|
4454
|
+
const changelogContent = await readFile(changelogUrl);
|
|
4455
|
+
return changelogContent;
|
|
4456
|
+
} catch (error$1) {
|
|
4457
|
+
if (isEnoentError(error$1)) {
|
|
4458
|
+
return '';
|
|
4459
|
+
}
|
|
4460
|
+
await error(new VError(error$1, 'Failed to load Changelog content'));
|
|
4461
|
+
return `${error$1}`;
|
|
4135
4462
|
}
|
|
4136
|
-
return '';
|
|
4137
|
-
};
|
|
4138
|
-
|
|
4139
|
-
const hasColorThemes = extension => {
|
|
4140
|
-
return Boolean(extension && extension.colorThemes && extension.colorThemes.length > 0);
|
|
4141
4463
|
};
|
|
4142
4464
|
|
|
4143
|
-
const
|
|
4465
|
+
const selectTabChangelog = async state => {
|
|
4144
4466
|
const {
|
|
4145
|
-
|
|
4146
|
-
|
|
4467
|
+
baseUrl,
|
|
4468
|
+
extension,
|
|
4469
|
+
locationProtocol,
|
|
4470
|
+
tabs
|
|
4147
4471
|
} = state;
|
|
4148
|
-
const
|
|
4149
|
-
const
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
const
|
|
4154
|
-
const
|
|
4155
|
-
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
|
|
4472
|
+
const changelogContent = await loadChangelogContent(extension.path); // TODO use uri
|
|
4473
|
+
const changelogMarkdownHtml = await renderMarkdown(changelogContent, {
|
|
4474
|
+
baseUrl,
|
|
4475
|
+
locationProtocol
|
|
4476
|
+
});
|
|
4477
|
+
const changelogDom = await getMarkdownVirtualDom(changelogMarkdownHtml);
|
|
4478
|
+
const newTabs = tabs.map(tab => {
|
|
4479
|
+
return {
|
|
4480
|
+
...tab,
|
|
4481
|
+
selected: tab.name === Changelog
|
|
4482
|
+
};
|
|
4483
|
+
});
|
|
4159
4484
|
return {
|
|
4160
|
-
|
|
4161
|
-
|
|
4162
|
-
|
|
4163
|
-
|
|
4164
|
-
extensionId,
|
|
4165
|
-
extensionUri,
|
|
4166
|
-
extensionVersion,
|
|
4167
|
-
hasColorTheme,
|
|
4168
|
-
iconSrc,
|
|
4169
|
-
name,
|
|
4170
|
-
rating
|
|
4485
|
+
...state,
|
|
4486
|
+
changelogVirtualDom: changelogDom,
|
|
4487
|
+
selectedTab: Changelog,
|
|
4488
|
+
tabs: newTabs
|
|
4171
4489
|
};
|
|
4172
4490
|
};
|
|
4173
4491
|
|
|
4174
|
-
const
|
|
4175
|
-
|
|
4176
|
-
return category;
|
|
4177
|
-
}
|
|
4178
|
-
return JSON.stringify(category);
|
|
4179
|
-
};
|
|
4180
|
-
const toCategory = categoryString => {
|
|
4181
|
-
return {
|
|
4182
|
-
id: categoryString.toLowerCase(),
|
|
4183
|
-
label: categoryString
|
|
4184
|
-
};
|
|
4185
|
-
};
|
|
4186
|
-
const getCategories = extension => {
|
|
4187
|
-
if (!hasProperty(extension, 'categories') || !Array.isArray(extension.categories)) {
|
|
4188
|
-
return [];
|
|
4189
|
-
}
|
|
4190
|
-
const categoryStrings = extension.categories.map(stringifyCategory);
|
|
4191
|
-
const categories = categoryStrings.map(toCategory);
|
|
4192
|
-
return categories;
|
|
4492
|
+
const selectTabDefault = async state => {
|
|
4493
|
+
return state;
|
|
4193
4494
|
};
|
|
4194
4495
|
|
|
4195
|
-
const
|
|
4196
|
-
const BIBYTE_UNITS = ['B', 'KiB', 'MiB', 'GiB', 'TiB', 'PiB', 'EiB', 'ZiB', 'YiB'];
|
|
4197
|
-
const BIT_UNITS = ['b', 'kbit', 'Mbit', 'Gbit', 'Tbit', 'Pbit', 'Ebit', 'Zbit', 'Ybit'];
|
|
4198
|
-
const BIBIT_UNITS = ['b', 'kibit', 'Mibit', 'Gibit', 'Tibit', 'Pibit', 'Eibit', 'Zibit', 'Yibit'];
|
|
4199
|
-
|
|
4200
|
-
/*
|
|
4201
|
-
Formats the given number using `Number#toLocaleString`.
|
|
4202
|
-
- If locale is a string, the value is expected to be a locale-key (for example: `de`).
|
|
4203
|
-
- If locale is true, the system default locale is used for translation.
|
|
4204
|
-
- If no value for locale is specified, the number is returned unmodified.
|
|
4205
|
-
*/
|
|
4206
|
-
const toLocaleString = (number, locale, options) => {
|
|
4207
|
-
let result = number;
|
|
4208
|
-
if (typeof locale === 'string' || Array.isArray(locale)) {
|
|
4209
|
-
result = number.toLocaleString(locale, options);
|
|
4210
|
-
} else if (locale === true || options !== undefined) {
|
|
4211
|
-
result = number.toLocaleString(undefined, options);
|
|
4212
|
-
}
|
|
4213
|
-
return result;
|
|
4214
|
-
};
|
|
4215
|
-
const log10 = numberOrBigInt => {
|
|
4216
|
-
if (typeof numberOrBigInt === 'number') {
|
|
4217
|
-
return Math.log10(numberOrBigInt);
|
|
4218
|
-
}
|
|
4219
|
-
const string = numberOrBigInt.toString(10);
|
|
4220
|
-
return string.length + Math.log10(`0.${string.slice(0, 15)}`);
|
|
4221
|
-
};
|
|
4222
|
-
const log = numberOrBigInt => {
|
|
4223
|
-
if (typeof numberOrBigInt === 'number') {
|
|
4224
|
-
return Math.log(numberOrBigInt);
|
|
4225
|
-
}
|
|
4226
|
-
return log10(numberOrBigInt) * Math.log(10);
|
|
4227
|
-
};
|
|
4228
|
-
const divide = (numberOrBigInt, divisor) => {
|
|
4229
|
-
if (typeof numberOrBigInt === 'number') {
|
|
4230
|
-
return numberOrBigInt / divisor;
|
|
4231
|
-
}
|
|
4232
|
-
const integerPart = numberOrBigInt / BigInt(divisor);
|
|
4233
|
-
const remainder = numberOrBigInt % BigInt(divisor);
|
|
4234
|
-
return Number(integerPart) + Number(remainder) / divisor;
|
|
4235
|
-
};
|
|
4236
|
-
const applyFixedWidth = (result, fixedWidth) => {
|
|
4237
|
-
if (fixedWidth === undefined) {
|
|
4238
|
-
return result;
|
|
4239
|
-
}
|
|
4240
|
-
if (typeof fixedWidth !== 'number' || !Number.isSafeInteger(fixedWidth) || fixedWidth < 0) {
|
|
4241
|
-
throw new TypeError(`Expected fixedWidth to be a non-negative integer, got ${typeof fixedWidth}: ${fixedWidth}`);
|
|
4242
|
-
}
|
|
4243
|
-
if (fixedWidth === 0) {
|
|
4244
|
-
return result;
|
|
4245
|
-
}
|
|
4246
|
-
return result.length < fixedWidth ? result.padStart(fixedWidth, ' ') : result;
|
|
4247
|
-
};
|
|
4248
|
-
const buildLocaleOptions = options => {
|
|
4496
|
+
const selectTabDetails = async state => {
|
|
4249
4497
|
const {
|
|
4250
|
-
|
|
4251
|
-
|
|
4252
|
-
|
|
4253
|
-
|
|
4254
|
-
|
|
4255
|
-
|
|
4498
|
+
baseUrl,
|
|
4499
|
+
locationProtocol,
|
|
4500
|
+
readmeUrl,
|
|
4501
|
+
tabs
|
|
4502
|
+
} = state;
|
|
4503
|
+
const readmeContent = await loadReadmeContent(readmeUrl);
|
|
4504
|
+
const readmeHtml = await renderMarkdown(readmeContent, {
|
|
4505
|
+
baseUrl,
|
|
4506
|
+
linksExternal: true,
|
|
4507
|
+
locationProtocol
|
|
4508
|
+
});
|
|
4509
|
+
const detailsDom = await getMarkdownVirtualDom(readmeHtml);
|
|
4510
|
+
const newTabs = tabs.map(tab => {
|
|
4511
|
+
return {
|
|
4512
|
+
...tab,
|
|
4513
|
+
selected: tab.name === Details
|
|
4514
|
+
};
|
|
4515
|
+
});
|
|
4256
4516
|
return {
|
|
4257
|
-
...
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
maximumFractionDigits
|
|
4262
|
-
}),
|
|
4263
|
-
roundingMode: 'trunc'
|
|
4517
|
+
...state,
|
|
4518
|
+
detailsVirtualDom: detailsDom,
|
|
4519
|
+
selectedTab: Details,
|
|
4520
|
+
tabs: newTabs
|
|
4264
4521
|
};
|
|
4265
4522
|
};
|
|
4266
|
-
function prettyBytes(number, options) {
|
|
4267
|
-
if (typeof number !== 'bigint' && !Number.isFinite(number)) {
|
|
4268
|
-
throw new TypeError(`Expected a finite number, got ${typeof number}: ${number}`);
|
|
4269
|
-
}
|
|
4270
|
-
options = {
|
|
4271
|
-
bits: false,
|
|
4272
|
-
binary: false,
|
|
4273
|
-
space: true,
|
|
4274
|
-
nonBreakingSpace: false,
|
|
4275
|
-
...options
|
|
4276
|
-
};
|
|
4277
|
-
const UNITS = options.bits ? options.binary ? BIBIT_UNITS : BIT_UNITS : options.binary ? BIBYTE_UNITS : BYTE_UNITS;
|
|
4278
|
-
const separator = options.space ? options.nonBreakingSpace ? '\u00A0' : ' ' : '';
|
|
4279
4523
|
|
|
4280
|
-
|
|
4281
|
-
const
|
|
4282
|
-
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4289
|
-
|
|
4290
|
-
|
|
4291
|
-
const localeOptions = buildLocaleOptions(options);
|
|
4292
|
-
let result;
|
|
4293
|
-
if (number < 1) {
|
|
4294
|
-
const numberString = toLocaleString(number, options.locale, localeOptions);
|
|
4295
|
-
result = prefix + numberString + separator + UNITS[0];
|
|
4296
|
-
} else {
|
|
4297
|
-
const exponent = Math.min(Math.floor(options.binary ? log(number) / Math.log(1024) : log10(number) / 3), UNITS.length - 1);
|
|
4298
|
-
number = divide(number, (options.binary ? 1024 : 1000) ** exponent);
|
|
4299
|
-
if (!localeOptions) {
|
|
4300
|
-
const minPrecision = Math.max(3, Math.floor(number).toString().length);
|
|
4301
|
-
number = number.toPrecision(minPrecision);
|
|
4302
|
-
}
|
|
4303
|
-
const numberString = toLocaleString(Number(number), options.locale, localeOptions);
|
|
4304
|
-
const unit = UNITS[exponent];
|
|
4305
|
-
result = prefix + numberString + separator + unit;
|
|
4524
|
+
const selectTabFeatures = async state => {
|
|
4525
|
+
const {
|
|
4526
|
+
baseUrl,
|
|
4527
|
+
extension,
|
|
4528
|
+
features,
|
|
4529
|
+
locationProtocol,
|
|
4530
|
+
selectedFeature,
|
|
4531
|
+
tabs
|
|
4532
|
+
} = state;
|
|
4533
|
+
if (features.length === 0) {
|
|
4534
|
+
return state;
|
|
4306
4535
|
}
|
|
4307
|
-
|
|
4308
|
-
|
|
4309
|
-
|
|
4310
|
-
const
|
|
4311
|
-
|
|
4312
|
-
|
|
4536
|
+
const actualSelectedFeature = selectedFeature || Theme;
|
|
4537
|
+
const fn = getFeatureDetailsHandler(actualSelectedFeature);
|
|
4538
|
+
const partialNewState = await fn(extension, baseUrl, locationProtocol);
|
|
4539
|
+
const newTabs = tabs.map(tab => {
|
|
4540
|
+
return {
|
|
4541
|
+
...tab,
|
|
4542
|
+
selected: tab.name === Features
|
|
4543
|
+
};
|
|
4313
4544
|
});
|
|
4314
|
-
|
|
4315
|
-
|
|
4316
|
-
|
|
4317
|
-
|
|
4318
|
-
|
|
4319
|
-
|
|
4320
|
-
return true;
|
|
4321
|
-
};
|
|
4322
|
-
const getFolderSize = async uri => {
|
|
4323
|
-
if (!uri) {
|
|
4324
|
-
throw new VError(`uri is required`);
|
|
4325
|
-
}
|
|
4326
|
-
if (!supportsFileSize(uri)) {
|
|
4327
|
-
return 0;
|
|
4328
|
-
}
|
|
4329
|
-
try {
|
|
4330
|
-
// @ts-ignore
|
|
4331
|
-
return await invoke('FileSystem.getFolderSize', uri);
|
|
4332
|
-
} catch {
|
|
4333
|
-
return 0;
|
|
4334
|
-
}
|
|
4335
|
-
};
|
|
4336
|
-
|
|
4337
|
-
const getMarketplaceEntries = isBuiltin => {
|
|
4338
|
-
if (isBuiltin) {
|
|
4339
|
-
return [];
|
|
4340
|
-
}
|
|
4341
|
-
return [{
|
|
4342
|
-
key: published(),
|
|
4343
|
-
odd: true,
|
|
4344
|
-
value: 'n/a'
|
|
4345
|
-
}, {
|
|
4346
|
-
key: lastReleased(),
|
|
4347
|
-
value: 'n/a'
|
|
4348
|
-
}];
|
|
4349
|
-
};
|
|
4350
|
-
|
|
4351
|
-
const getLicenseLink = extension => {
|
|
4352
|
-
// TODO
|
|
4353
|
-
return '#';
|
|
4354
|
-
};
|
|
4355
|
-
|
|
4356
|
-
const ensureValidLink = link => {
|
|
4357
|
-
if (!link) {
|
|
4358
|
-
return '';
|
|
4359
|
-
}
|
|
4360
|
-
try {
|
|
4361
|
-
const parsed = new URL(link);
|
|
4362
|
-
if (parsed.protocol !== 'https:') {
|
|
4363
|
-
return '';
|
|
4545
|
+
const newFeatures = features.map(feature => {
|
|
4546
|
+
if (feature.id === actualSelectedFeature) {
|
|
4547
|
+
return {
|
|
4548
|
+
...feature,
|
|
4549
|
+
selected: true
|
|
4550
|
+
};
|
|
4364
4551
|
}
|
|
4365
|
-
return
|
|
4366
|
-
|
|
4367
|
-
|
|
4368
|
-
|
|
4369
|
-
};
|
|
4370
|
-
|
|
4371
|
-
|
|
4372
|
-
|
|
4373
|
-
|
|
4374
|
-
|
|
4375
|
-
|
|
4376
|
-
|
|
4377
|
-
|
|
4378
|
-
const raw = getRepositoryLinkRaw(extension);
|
|
4379
|
-
const validLink = ensureValidLink(raw);
|
|
4380
|
-
return validLink;
|
|
4381
|
-
};
|
|
4382
|
-
const getIssuesLink = extension => {
|
|
4383
|
-
const repositoryLink = getRepositoryLink(extension);
|
|
4384
|
-
if (!repositoryLink) {
|
|
4385
|
-
return '';
|
|
4386
|
-
}
|
|
4387
|
-
if (repositoryLink && repositoryLink.startsWith('https://github.com')) {
|
|
4388
|
-
return `${repositoryLink}/issues`;
|
|
4389
|
-
}
|
|
4390
|
-
return '';
|
|
4552
|
+
return {
|
|
4553
|
+
...feature,
|
|
4554
|
+
selected: false
|
|
4555
|
+
};
|
|
4556
|
+
});
|
|
4557
|
+
return {
|
|
4558
|
+
...state,
|
|
4559
|
+
...partialNewState,
|
|
4560
|
+
features: newFeatures,
|
|
4561
|
+
selectedFeature: features[0].id || '',
|
|
4562
|
+
selectedTab: Features,
|
|
4563
|
+
tabs: newTabs
|
|
4564
|
+
};
|
|
4391
4565
|
};
|
|
4392
4566
|
|
|
4393
|
-
const
|
|
4394
|
-
|
|
4395
|
-
|
|
4396
|
-
|
|
4397
|
-
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
|
|
4401
|
-
|
|
4402
|
-
|
|
4403
|
-
|
|
4404
|
-
url: '#'
|
|
4405
|
-
}, {
|
|
4406
|
-
icon: 'LinkExternal',
|
|
4407
|
-
label: issues(),
|
|
4408
|
-
url: issueLink
|
|
4409
|
-
}, {
|
|
4410
|
-
icon: 'Repo',
|
|
4411
|
-
label: repository(),
|
|
4412
|
-
url: repositoryLink
|
|
4413
|
-
}, {
|
|
4414
|
-
icon: 'LinkExternal',
|
|
4415
|
-
label: license(),
|
|
4416
|
-
url: licenseLink
|
|
4417
|
-
}];
|
|
4567
|
+
const getSelectTabHandler = name => {
|
|
4568
|
+
switch (name) {
|
|
4569
|
+
case Changelog:
|
|
4570
|
+
return selectTabChangelog;
|
|
4571
|
+
case Details:
|
|
4572
|
+
return selectTabDetails;
|
|
4573
|
+
case Features:
|
|
4574
|
+
return selectTabFeatures;
|
|
4575
|
+
default:
|
|
4576
|
+
return selectTabDefault;
|
|
4577
|
+
}
|
|
4418
4578
|
};
|
|
4419
4579
|
|
|
4420
|
-
const
|
|
4421
|
-
const
|
|
4422
|
-
|
|
4423
|
-
|
|
4424
|
-
|
|
4425
|
-
|
|
4426
|
-
|
|
4427
|
-
|
|
4428
|
-
|
|
4580
|
+
const selectTab = (state, name) => {
|
|
4581
|
+
const fn = getSelectTabHandler(name);
|
|
4582
|
+
return fn(state);
|
|
4583
|
+
};
|
|
4584
|
+
|
|
4585
|
+
const handleTabsClick = (state, name) => {
|
|
4586
|
+
return selectTab(state, name);
|
|
4587
|
+
};
|
|
4588
|
+
|
|
4589
|
+
const hideSizeLink = state => {
|
|
4590
|
+
const {
|
|
4429
4591
|
displaySize,
|
|
4430
|
-
|
|
4592
|
+
extensionId,
|
|
4593
|
+
extensionUri,
|
|
4594
|
+
extensionVersion
|
|
4595
|
+
} = state;
|
|
4596
|
+
const newShowSizeLink = false;
|
|
4597
|
+
const installationEntries = getInstallationEntries(displaySize, extensionId, extensionVersion, extensionUri, newShowSizeLink);
|
|
4598
|
+
return {
|
|
4599
|
+
...state,
|
|
4431
4600
|
installationEntries,
|
|
4432
|
-
|
|
4433
|
-
resources
|
|
4601
|
+
showSizeLink: newShowSizeLink
|
|
4434
4602
|
};
|
|
4435
4603
|
};
|
|
4436
4604
|
|
|
4437
|
-
const
|
|
4438
|
-
|
|
4439
|
-
|
|
4605
|
+
const sendMessagePortToExtensionHostWorker = async port => {
|
|
4606
|
+
await sendMessagePortToExtensionHostWorker$1(port, 0);
|
|
4607
|
+
};
|
|
4608
|
+
|
|
4609
|
+
const createExtensionHostWorkerRpc = async () => {
|
|
4610
|
+
try {
|
|
4611
|
+
const rpc = await TransferMessagePortRpcParent.create({
|
|
4612
|
+
commandMap: {},
|
|
4613
|
+
send: sendMessagePortToExtensionHostWorker
|
|
4614
|
+
});
|
|
4615
|
+
return rpc;
|
|
4616
|
+
} catch (error) {
|
|
4617
|
+
throw new VError(error, `Failed to create extension host rpc`);
|
|
4440
4618
|
}
|
|
4441
|
-
return 0;
|
|
4442
4619
|
};
|
|
4443
4620
|
|
|
4444
|
-
const
|
|
4445
|
-
|
|
4446
|
-
|
|
4621
|
+
const initializeExtensionHostWorker = async () => {
|
|
4622
|
+
const rpc = await createExtensionHostWorkerRpc();
|
|
4623
|
+
set$4(rpc);
|
|
4624
|
+
};
|
|
4625
|
+
|
|
4626
|
+
const createExtensionManagementWorkerRpc = async () => {
|
|
4627
|
+
try {
|
|
4628
|
+
const rpc = await TransferMessagePortRpcParent.create({
|
|
4629
|
+
commandMap: {},
|
|
4630
|
+
send: port => sendMessagePortToExtensionManagementWorker(port, 0)
|
|
4631
|
+
});
|
|
4632
|
+
return rpc;
|
|
4633
|
+
} catch (error) {
|
|
4634
|
+
throw new VError(error, `Failed to create extension management rpc`);
|
|
4447
4635
|
}
|
|
4448
|
-
return 0;
|
|
4449
4636
|
};
|
|
4450
4637
|
|
|
4451
|
-
const
|
|
4452
|
-
|
|
4453
|
-
|
|
4638
|
+
const initializeExtensionManagementWorker = async () => {
|
|
4639
|
+
try {
|
|
4640
|
+
const rpc = await createExtensionManagementWorkerRpc();
|
|
4641
|
+
set$8(rpc);
|
|
4642
|
+
} catch {
|
|
4643
|
+
// ignore
|
|
4454
4644
|
}
|
|
4455
|
-
return Details;
|
|
4456
4645
|
};
|
|
4457
4646
|
|
|
4458
|
-
const
|
|
4459
|
-
|
|
4460
|
-
|
|
4647
|
+
const sendMessagePortToFileSystemWorker = async port => {
|
|
4648
|
+
await sendMessagePortToFileSystemWorker$1(port, 0);
|
|
4649
|
+
};
|
|
4650
|
+
|
|
4651
|
+
const createFileSystemWorkerRpc = async () => {
|
|
4652
|
+
try {
|
|
4653
|
+
const rpc = await TransferMessagePortRpcParent.create({
|
|
4654
|
+
commandMap: {},
|
|
4655
|
+
send: sendMessagePortToFileSystemWorker
|
|
4656
|
+
});
|
|
4657
|
+
return rpc;
|
|
4658
|
+
} catch (error) {
|
|
4659
|
+
throw new VError(error, `Failed to create file system worker rpc`);
|
|
4461
4660
|
}
|
|
4462
|
-
return Details;
|
|
4463
4661
|
};
|
|
4464
4662
|
|
|
4465
|
-
const
|
|
4466
|
-
const
|
|
4467
|
-
|
|
4468
|
-
const readmeScrollTop = getSavedReadmeScrollTop(savedState);
|
|
4469
|
-
const changelogScrollTop = getSavedChangelogScrollTop(savedState);
|
|
4470
|
-
return {
|
|
4471
|
-
changelogScrollTop,
|
|
4472
|
-
readmeScrollTop,
|
|
4473
|
-
selectedFeature,
|
|
4474
|
-
selectedTab
|
|
4475
|
-
};
|
|
4663
|
+
const initializeFileSystemWorker = async () => {
|
|
4664
|
+
const rpc = await createFileSystemWorkerRpc();
|
|
4665
|
+
set$1(rpc);
|
|
4476
4666
|
};
|
|
4477
4667
|
|
|
4478
|
-
const
|
|
4479
|
-
|
|
4668
|
+
const sendMessagePortToMarkdownWorker = async port => {
|
|
4669
|
+
await sendMessagePortToMarkdownWorker$1(port, 0);
|
|
4480
4670
|
};
|
|
4481
|
-
|
|
4482
|
-
|
|
4483
|
-
|
|
4484
|
-
|
|
4485
|
-
|
|
4486
|
-
|
|
4487
|
-
|
|
4488
|
-
|
|
4489
|
-
|
|
4490
|
-
|
|
4491
|
-
if (!extension) {
|
|
4492
|
-
throw new ExtensionNotFoundError(id);
|
|
4671
|
+
|
|
4672
|
+
const createMarkdownWorkerRpc = async () => {
|
|
4673
|
+
try {
|
|
4674
|
+
const rpc = await TransferMessagePortRpcParent.create({
|
|
4675
|
+
commandMap: {},
|
|
4676
|
+
send: sendMessagePortToMarkdownWorker
|
|
4677
|
+
});
|
|
4678
|
+
return rpc;
|
|
4679
|
+
} catch (error) {
|
|
4680
|
+
throw new VError(error, `Failed to create markdown worker rpc`);
|
|
4493
4681
|
}
|
|
4494
|
-
|
|
4495
|
-
|
|
4496
|
-
|
|
4497
|
-
|
|
4498
|
-
|
|
4499
|
-
|
|
4500
|
-
|
|
4501
|
-
|
|
4502
|
-
|
|
4503
|
-
|
|
4504
|
-
iconSrc,
|
|
4505
|
-
name,
|
|
4506
|
-
rating
|
|
4507
|
-
} = headerData;
|
|
4508
|
-
const readmeUrl = join(extensionUri, 'README.md');
|
|
4509
|
-
const changelogUrl = join(extensionUri, 'CHANGELOG.md');
|
|
4510
|
-
const [hasReadme, hasChangelog] = await Promise.all([existsFile(readmeUrl), existsFile(changelogUrl)]);
|
|
4511
|
-
const readmeContent = hasReadme ? await loadReadmeContent(readmeUrl) : noReadmeFound();
|
|
4512
|
-
const baseUrl = getBaseUrl(extension.path, platform);
|
|
4513
|
-
const locationProtocol = location.protocol;
|
|
4514
|
-
const locationHost = location.host;
|
|
4515
|
-
const readmeHtml = await renderMarkdown(readmeContent, {
|
|
4516
|
-
baseUrl,
|
|
4517
|
-
commit,
|
|
4518
|
-
linksExternal: true,
|
|
4519
|
-
locationProtocol
|
|
4520
|
-
});
|
|
4521
|
-
const detailsVirtualDom = await getMarkdownVirtualDom(readmeHtml, {
|
|
4522
|
-
scrollToTopEnabled: true
|
|
4523
|
-
});
|
|
4524
|
-
const isBuiltin = extension?.isBuiltin;
|
|
4525
|
-
const disabled = extension?.disabled;
|
|
4526
|
-
const buttons = getExtensionDetailButtons(hasColorTheme, isBuiltin, disabled);
|
|
4527
|
-
const size = getViewletSize(width);
|
|
4528
|
-
const {
|
|
4529
|
-
changelogScrollTop,
|
|
4530
|
-
readmeScrollTop,
|
|
4531
|
-
selectedFeature,
|
|
4532
|
-
selectedTab
|
|
4533
|
-
} = restoreState(savedState);
|
|
4534
|
-
const features = getFeatures(selectedFeature || Theme, extension);
|
|
4535
|
-
const hasFeatures = features.length > 0;
|
|
4536
|
-
const tabs = getTabs(selectedTab, hasReadme, hasFeatures, hasChangelog);
|
|
4537
|
-
const enabledTabs = tabs.filter(isEnabled);
|
|
4538
|
-
const sizeValue = getViewletSize(width || 0);
|
|
4539
|
-
const showSizeLink = platform !== Web$1;
|
|
4540
|
-
const {
|
|
4541
|
-
categories,
|
|
4542
|
-
displaySize,
|
|
4543
|
-
folderSize,
|
|
4544
|
-
installationEntries,
|
|
4545
|
-
marketplaceEntries,
|
|
4546
|
-
resources
|
|
4547
|
-
} = await loadSideBarContent(extensionId, extensionVersion, extensionUri, isBuiltin, extension, showSizeLink);
|
|
4548
|
-
const padding = getPadding(width);
|
|
4549
|
-
const sideBarWidth = getSideBarWidth(width);
|
|
4550
|
-
const showSideBar = sideBarWidth > 0;
|
|
4551
|
-
return {
|
|
4552
|
-
...state,
|
|
4553
|
-
badge,
|
|
4554
|
-
baseUrl,
|
|
4555
|
-
buttons,
|
|
4556
|
-
categories,
|
|
4557
|
-
changelogScrollTop,
|
|
4558
|
-
commit,
|
|
4559
|
-
description,
|
|
4560
|
-
detailsVirtualDom,
|
|
4561
|
-
disabled,
|
|
4562
|
-
displaySize,
|
|
4563
|
-
downloadCount,
|
|
4564
|
-
extension,
|
|
4565
|
-
extensionId,
|
|
4566
|
-
extensionUri,
|
|
4567
|
-
extensionVersion,
|
|
4568
|
-
features,
|
|
4569
|
-
folderSize,
|
|
4570
|
-
hasColorTheme,
|
|
4571
|
-
hasReadme,
|
|
4572
|
-
iconSrc,
|
|
4573
|
-
installationEntries,
|
|
4574
|
-
locationHost,
|
|
4575
|
-
locationProtocol,
|
|
4576
|
-
marketplaceEntries,
|
|
4577
|
-
name,
|
|
4578
|
-
paddingLeft: padding,
|
|
4579
|
-
paddingRight: padding,
|
|
4580
|
-
rating,
|
|
4581
|
-
readmeScrollTop,
|
|
4582
|
-
readmeUrl,
|
|
4583
|
-
resources,
|
|
4584
|
-
scrollSource: Script,
|
|
4585
|
-
scrollToTopButtonEnabled: true,
|
|
4586
|
-
selectedTab,
|
|
4587
|
-
showSideBar,
|
|
4588
|
-
showSizeLink,
|
|
4589
|
-
sideBarWidth,
|
|
4590
|
-
sizeOnDisk: size,
|
|
4591
|
-
sizeValue,
|
|
4592
|
-
tabs: enabledTabs
|
|
4593
|
-
};
|
|
4682
|
+
};
|
|
4683
|
+
|
|
4684
|
+
const initializeMarkdownWorker = async () => {
|
|
4685
|
+
const rpc = await createMarkdownWorkerRpc();
|
|
4686
|
+
set$3(rpc);
|
|
4687
|
+
};
|
|
4688
|
+
|
|
4689
|
+
const initialize = async () => {
|
|
4690
|
+
// TODO load markdown worker only when needed
|
|
4691
|
+
await Promise.all([initializeMarkdownWorker(), initializeFileSystemWorker(), initializeExtensionHostWorker(), initializeExtensionManagementWorker()]);
|
|
4594
4692
|
};
|
|
4595
4693
|
|
|
4596
4694
|
const loadContent2 = async (state, savedState, isTest = false) => {
|
|
@@ -4828,17 +4926,19 @@ const getAdditionalDetailsVirtualDom = (showAdditionalDetails, firstHeading, ent
|
|
|
4828
4926
|
if (!showAdditionalDetails) {
|
|
4829
4927
|
return [];
|
|
4830
4928
|
}
|
|
4929
|
+
const sections = [...getAdditionalDetailsEntryVirtualDom(firstHeading, entries, getMoreInfoVirtualDom), ...(secondEntries.length > 0 ? getAdditionalDetailsEntryVirtualDom(secondHeading, secondEntries, getMoreInfoVirtualDom) : []), ...getAdditionalDetailsEntryVirtualDom(thirdHeading, categories, getCategoriesDom), ...getAdditionalDetailsEntryVirtualDom(fourthHeading, resources, getResourcesVirtualDom)];
|
|
4930
|
+
const childCount = secondEntries.length > 0 ? 4 : 3;
|
|
4831
4931
|
return [{
|
|
4832
4932
|
childCount: 1,
|
|
4833
4933
|
className: Aside,
|
|
4834
4934
|
type: Aside$1
|
|
4835
4935
|
}, {
|
|
4836
|
-
childCount:
|
|
4936
|
+
childCount: childCount,
|
|
4837
4937
|
className: AdditionalDetails,
|
|
4838
4938
|
onContextMenu: HandleAdditionalDetailContextMenu,
|
|
4839
4939
|
tabIndex: 0,
|
|
4840
4940
|
type: Div
|
|
4841
|
-
}, ...
|
|
4941
|
+
}, ...sections];
|
|
4842
4942
|
};
|
|
4843
4943
|
|
|
4844
4944
|
const getNoReadmeVirtualDom = () => {
|
|
@@ -4947,10 +5047,11 @@ const getExtensionDetailDescriptionVirtualDom = description => {
|
|
|
4947
5047
|
}, text(description)];
|
|
4948
5048
|
};
|
|
4949
5049
|
|
|
5050
|
+
const className = mergeClassNames(Button, ButtonPrimary);
|
|
4950
5051
|
const getButtonVirtualDom = (message, onClick, name) => {
|
|
4951
5052
|
return [{
|
|
4952
5053
|
childCount: 1,
|
|
4953
|
-
className
|
|
5054
|
+
className,
|
|
4954
5055
|
name,
|
|
4955
5056
|
onClick,
|
|
4956
5057
|
type: Button$1
|
|
@@ -5038,7 +5139,7 @@ const getTabClassName = isSelected => {
|
|
|
5038
5139
|
return isSelected ? selectedClassName : defaultClassName;
|
|
5039
5140
|
};
|
|
5040
5141
|
|
|
5041
|
-
const getTabVirtualDom = tab => {
|
|
5142
|
+
const getTabVirtualDom = (tab, tabIndex, focusedTabIndex) => {
|
|
5042
5143
|
const {
|
|
5043
5144
|
label,
|
|
5044
5145
|
name,
|
|
@@ -5046,26 +5147,27 @@ const getTabVirtualDom = tab => {
|
|
|
5046
5147
|
} = tab;
|
|
5047
5148
|
const className = getTabClassName(selected);
|
|
5048
5149
|
const ariaSelected = selected;
|
|
5150
|
+
const tabIndexValue = tabIndex === focusedTabIndex ? 0 : -1;
|
|
5049
5151
|
return [{
|
|
5050
5152
|
ariaSelected,
|
|
5051
5153
|
childCount: 1,
|
|
5052
5154
|
className,
|
|
5053
5155
|
name,
|
|
5156
|
+
onFocus: HandleTabFocus,
|
|
5054
5157
|
role: Tab,
|
|
5055
|
-
tabIndex:
|
|
5158
|
+
tabIndex: tabIndexValue,
|
|
5056
5159
|
type: Button$1
|
|
5057
5160
|
}, text(label)];
|
|
5058
5161
|
};
|
|
5059
5162
|
|
|
5060
|
-
const getTabsVirtualDom = tabs => {
|
|
5163
|
+
const getTabsVirtualDom = (tabs, focusedTabIndex) => {
|
|
5061
5164
|
return [{
|
|
5062
5165
|
childCount: tabs.length,
|
|
5063
5166
|
className: ExtensionDetailTabs,
|
|
5064
5167
|
onClick: HandleTabsClick,
|
|
5065
5168
|
role: TabList,
|
|
5066
|
-
tabIndex: 0,
|
|
5067
5169
|
type: Div
|
|
5068
|
-
}, ...tabs.flatMap(getTabVirtualDom)];
|
|
5170
|
+
}, ...tabs.flatMap((tab, index) => getTabVirtualDom(tab, index, focusedTabIndex))];
|
|
5069
5171
|
};
|
|
5070
5172
|
|
|
5071
5173
|
const getClassNames = size => {
|
|
@@ -5094,6 +5196,7 @@ const getExtensionDetailVirtualDom = (newState, selectedTab) => {
|
|
|
5094
5196
|
changelogVirtualDom,
|
|
5095
5197
|
description,
|
|
5096
5198
|
detailsVirtualDom,
|
|
5199
|
+
focusedTabIndex,
|
|
5097
5200
|
iconSrc,
|
|
5098
5201
|
name,
|
|
5099
5202
|
resources,
|
|
@@ -5109,7 +5212,7 @@ const getExtensionDetailVirtualDom = (newState, selectedTab) => {
|
|
|
5109
5212
|
childCount: 3,
|
|
5110
5213
|
className: mergeClassNames(Viewlet, ExtensionDetail, sizeClass),
|
|
5111
5214
|
type: Div
|
|
5112
|
-
}, ...getExtensionDetailHeaderVirtualDom(name, iconSrc, description, badge, buttons, settingsButtonEnabled), ...getTabsVirtualDom(tabs), ...getExtensionDetailContentVirtualDom(detailsVirtualDom, selectedTab, width, scrollToTopButtonEnabled, categories, resources, showAdditionalDetailsBreakpoint, changelogVirtualDom, newState)];
|
|
5215
|
+
}, ...getExtensionDetailHeaderVirtualDom(name, iconSrc, description, badge, buttons, settingsButtonEnabled), ...getTabsVirtualDom(tabs, focusedTabIndex), ...getExtensionDetailContentVirtualDom(detailsVirtualDom, selectedTab, width, scrollToTopButtonEnabled, categories, resources, showAdditionalDetailsBreakpoint, changelogVirtualDom, newState)];
|
|
5113
5216
|
return dom;
|
|
5114
5217
|
};
|
|
5115
5218
|
|
|
@@ -5119,7 +5222,31 @@ const renderDom = (oldState, newState) => {
|
|
|
5119
5222
|
};
|
|
5120
5223
|
|
|
5121
5224
|
const renderFocus = (oldState, newState) => {
|
|
5122
|
-
|
|
5225
|
+
const {
|
|
5226
|
+
focus,
|
|
5227
|
+
focusedTabIndex,
|
|
5228
|
+
tabs,
|
|
5229
|
+
uid
|
|
5230
|
+
} = newState;
|
|
5231
|
+
if (focus === 451) {
|
|
5232
|
+
const {
|
|
5233
|
+
name
|
|
5234
|
+
} = tabs[focusedTabIndex];
|
|
5235
|
+
return [FocusElementByName, uid, name];
|
|
5236
|
+
}
|
|
5237
|
+
return [FocusElementByName, ''];
|
|
5238
|
+
};
|
|
5239
|
+
|
|
5240
|
+
const renderFocusContext = (oldState, newState) => {
|
|
5241
|
+
const {
|
|
5242
|
+
focus,
|
|
5243
|
+
uid
|
|
5244
|
+
} = newState;
|
|
5245
|
+
if (focus === 451) {
|
|
5246
|
+
return [SetFocusContext, uid, focus];
|
|
5247
|
+
}
|
|
5248
|
+
// TODO set focus context
|
|
5249
|
+
return [FocusElementByName, ''];
|
|
5123
5250
|
};
|
|
5124
5251
|
|
|
5125
5252
|
const getScrollTop = (selectedTab, readmeScrollTop, changelogScrollTop) => {
|
|
@@ -5153,6 +5280,8 @@ const getRenderer = diffType => {
|
|
|
5153
5280
|
return renderCss;
|
|
5154
5281
|
case RenderFocus:
|
|
5155
5282
|
return renderFocus;
|
|
5283
|
+
case RenderFocusContext:
|
|
5284
|
+
return renderFocusContext;
|
|
5156
5285
|
case RenderItems:
|
|
5157
5286
|
return renderDom;
|
|
5158
5287
|
case RenderScrollTop:
|
|
@@ -5218,6 +5347,9 @@ const renderEventListeners = () => {
|
|
|
5218
5347
|
}, {
|
|
5219
5348
|
name: HandleClickDisable,
|
|
5220
5349
|
params: ['handleClickDisable']
|
|
5350
|
+
}, {
|
|
5351
|
+
name: HandleClickEnable,
|
|
5352
|
+
params: ['handleClickEnable']
|
|
5221
5353
|
}, {
|
|
5222
5354
|
name: HandleClickScrollToTop,
|
|
5223
5355
|
params: ['handleClickScrollToTop'],
|
|
@@ -5238,6 +5370,9 @@ const renderEventListeners = () => {
|
|
|
5238
5370
|
}, {
|
|
5239
5371
|
name: HandleSelectionChange,
|
|
5240
5372
|
params: ['handleSelectionChange']
|
|
5373
|
+
}, {
|
|
5374
|
+
name: HandleTabFocus,
|
|
5375
|
+
params: ['handleTabFocus', TargetName]
|
|
5241
5376
|
}];
|
|
5242
5377
|
};
|
|
5243
5378
|
|
|
@@ -5278,7 +5413,10 @@ const commandMap = {
|
|
|
5278
5413
|
'ExtensionDetail.diff2': diff2,
|
|
5279
5414
|
'ExtensionDetail.dispose': dispose,
|
|
5280
5415
|
'ExtensionDetail.executeCopy': wrapCommand(executeCopy),
|
|
5416
|
+
'ExtensionDetail.focusNextTab': wrapCommand(focusNextTab),
|
|
5417
|
+
'ExtensionDetail.focusPreviousTab': wrapCommand(focusPreviousTab),
|
|
5281
5418
|
'ExtensionDetail.getCommandIds': getCommandIds,
|
|
5419
|
+
'ExtensionDetail.getKeyBindings': getKeyBindings,
|
|
5282
5420
|
'ExtensionDetail.getMenuEntries': getMenuEntries,
|
|
5283
5421
|
'ExtensionDetail.getMenuEntries2': wrapGetter(getMenuEntries2),
|
|
5284
5422
|
'ExtensionDetail.getMenuIds': getMenuIds,
|
|
@@ -5292,6 +5430,7 @@ const commandMap = {
|
|
|
5292
5430
|
'ExtensionDetail.handleClickSettings': wrapCommand(handleClickSettings),
|
|
5293
5431
|
'ExtensionDetail.handleClickSize': wrapCommand(handleClickSize),
|
|
5294
5432
|
'ExtensionDetail.handleClickUninstall': wrapCommand(handleClickUninstall),
|
|
5433
|
+
'ExtensionDetail.handleExtensionsChanged': wrapCommand(handleExtensionsChanged),
|
|
5295
5434
|
'ExtensionDetail.handleExtensionsStatusUpdate': wrapCommand(handleExtensionsStatusUpdate),
|
|
5296
5435
|
'ExtensionDetail.handleFeaturesClick': wrapCommand(handleClickFeatures),
|
|
5297
5436
|
'ExtensionDetail.handleIconError': wrapCommand(handleIconError),
|
|
@@ -5300,6 +5439,7 @@ const commandMap = {
|
|
|
5300
5439
|
'ExtensionDetail.handleReadmeContextMenu': wrapCommand(handleReadmeContextMenu),
|
|
5301
5440
|
'ExtensionDetail.handleScroll': wrapCommand(handleScroll),
|
|
5302
5441
|
'ExtensionDetail.handleSelectionChange': wrapCommand(handleSelectionChange),
|
|
5442
|
+
'ExtensionDetail.handleTabFocus': wrapCommand(handleTabFocus),
|
|
5303
5443
|
'ExtensionDetail.handleTabsClick': wrapCommand(handleTabsClick),
|
|
5304
5444
|
'ExtensionDetail.handleWheel': wrapCommand(handleScroll),
|
|
5305
5445
|
// deprecated
|