@lvce-editor/extension-detail-view 4.5.0 → 4.7.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.
|
@@ -30,6 +30,7 @@ const Id = 'ID';
|
|
|
30
30
|
const Identifier = 'Identifier';
|
|
31
31
|
const ImportTime = 'Import Time: ';
|
|
32
32
|
const Installation = 'Installation';
|
|
33
|
+
const InvalidLink = 'Invalid link';
|
|
33
34
|
const Issues = 'Issues';
|
|
34
35
|
const JsonValidation$1 = 'Json Validation';
|
|
35
36
|
const Label = 'Label';
|
|
@@ -42,12 +43,14 @@ const NoReadmeFound = 'No Readme Found.';
|
|
|
42
43
|
const OpenImageInNewTab = 'Open Image in New Tab';
|
|
43
44
|
const OpenInNewTab = 'Open in New Tab';
|
|
44
45
|
const ProgrammingLanguages$1 = 'Programming Languages';
|
|
46
|
+
const PropertyMustBeOfTypeString = 'Property must be a string';
|
|
45
47
|
const Published = 'Published';
|
|
46
48
|
const Repository = 'Repository';
|
|
47
49
|
const Resources$1 = 'Resources';
|
|
48
50
|
const RuntimeStatus$1 = 'Runtime Status';
|
|
49
51
|
const SaveImageAs = 'Save Image as';
|
|
50
52
|
const Schema = 'Schema';
|
|
53
|
+
const SchemaNotFound = 'Schema not found';
|
|
51
54
|
const ScrollToTop$1 = 'Scroll to top';
|
|
52
55
|
const SelectedFeatureUnknownOrUnsupported = 'Selected feature is unknown or unsupported';
|
|
53
56
|
const Selector = 'Selector';
|
|
@@ -207,6 +210,15 @@ const repository = () => {
|
|
|
207
210
|
const license = () => {
|
|
208
211
|
return i18nString(License);
|
|
209
212
|
};
|
|
213
|
+
const propertyMustBeOfTypeString = () => {
|
|
214
|
+
return i18nString(PropertyMustBeOfTypeString);
|
|
215
|
+
};
|
|
216
|
+
const schemaNotFound = () => {
|
|
217
|
+
return i18nString(SchemaNotFound);
|
|
218
|
+
};
|
|
219
|
+
const invalidLink = () => {
|
|
220
|
+
return i18nString(InvalidLink);
|
|
221
|
+
};
|
|
210
222
|
|
|
211
223
|
const getActivationEventsDetails = async extension => {
|
|
212
224
|
const activationEvents = extension.activation || [];
|
|
@@ -305,7 +317,7 @@ const Features$1 = 'Features';
|
|
|
305
317
|
const FeaturesList = 'FeaturesList';
|
|
306
318
|
const FeatureWebView = 'FeatureWebView';
|
|
307
319
|
const Large$1 = 'Large';
|
|
308
|
-
const Link = 'Link';
|
|
320
|
+
const Link$1 = 'Link';
|
|
309
321
|
const Markdown = 'Markdown';
|
|
310
322
|
const MoreInfo = 'MoreInfo';
|
|
311
323
|
const MoreInfoEntry = 'MoreInfoEntry';
|
|
@@ -323,6 +335,7 @@ const SettingsIcon = 'SettingsIcon';
|
|
|
323
335
|
const Small$1 = 'Small';
|
|
324
336
|
const Table = 'Table';
|
|
325
337
|
const TableCell = 'TableCell';
|
|
338
|
+
const TableCellInvalid = 'TableCellInvalid';
|
|
326
339
|
const TableHeading = 'TableHeading';
|
|
327
340
|
const Viewlet = 'Viewlet';
|
|
328
341
|
|
|
@@ -363,6 +376,7 @@ const getActivationEventsVirtualDom = state => {
|
|
|
363
376
|
|
|
364
377
|
const Text = 1;
|
|
365
378
|
const Code = 2;
|
|
379
|
+
const Link = 7;
|
|
366
380
|
|
|
367
381
|
const getCommandTableEntry = command => {
|
|
368
382
|
// TODO watch out for command being null/undefined/number/string/array
|
|
@@ -424,31 +438,58 @@ const getTableHeadingVirtualDom = heading => {
|
|
|
424
438
|
}, text(heading)];
|
|
425
439
|
};
|
|
426
440
|
|
|
427
|
-
const getCellCodeVirtualDom = value => {
|
|
441
|
+
const getCellCodeVirtualDom = (value, props) => {
|
|
442
|
+
const tdClassName = props?.className ? `${TableCell} ${props.className}` : TableCell;
|
|
428
443
|
return [{
|
|
429
444
|
type: Td,
|
|
430
|
-
className:
|
|
431
|
-
childCount: 1
|
|
445
|
+
className: tdClassName,
|
|
446
|
+
childCount: 1,
|
|
447
|
+
...(props?.title ? {
|
|
448
|
+
title: props.title
|
|
449
|
+
} : {})
|
|
432
450
|
}, {
|
|
433
451
|
type: Code$2,
|
|
434
452
|
childCount: 1
|
|
435
453
|
}, text(value)];
|
|
436
454
|
};
|
|
437
455
|
|
|
438
|
-
const
|
|
456
|
+
const getCellLinkVirtualDom = (value, props) => {
|
|
457
|
+
const tdClassName = props?.className ? `${TableCell} ${props.className}` : TableCell;
|
|
439
458
|
return [{
|
|
440
459
|
type: Td,
|
|
441
|
-
className:
|
|
460
|
+
className: tdClassName,
|
|
461
|
+
childCount: 1,
|
|
462
|
+
...(props?.title ? {
|
|
463
|
+
title: props.title
|
|
464
|
+
} : {})
|
|
465
|
+
}, {
|
|
466
|
+
type: A,
|
|
467
|
+
className: Link$1,
|
|
468
|
+
href: props?.href,
|
|
442
469
|
childCount: 1
|
|
443
470
|
}, text(value)];
|
|
444
471
|
};
|
|
445
472
|
|
|
473
|
+
const getCellTextVirtualDom = (value, props) => {
|
|
474
|
+
const tdClassName = props?.className ? `${TableCell} ${props.className}` : TableCell;
|
|
475
|
+
return [{
|
|
476
|
+
type: Td,
|
|
477
|
+
className: tdClassName,
|
|
478
|
+
childCount: 1,
|
|
479
|
+
...(props?.title ? {
|
|
480
|
+
title: props.title
|
|
481
|
+
} : {})
|
|
482
|
+
}, text(value)];
|
|
483
|
+
};
|
|
484
|
+
|
|
446
485
|
const getCellRenderer = type => {
|
|
447
486
|
switch (type) {
|
|
448
487
|
case Code:
|
|
449
488
|
return getCellCodeVirtualDom;
|
|
450
489
|
case Text:
|
|
451
490
|
return getCellTextVirtualDom;
|
|
491
|
+
case Link:
|
|
492
|
+
return getCellLinkVirtualDom;
|
|
452
493
|
default:
|
|
453
494
|
throw new Error(`unexpected cell type ${type}`);
|
|
454
495
|
}
|
|
@@ -457,10 +498,11 @@ const getCellRenderer = type => {
|
|
|
457
498
|
const getCellVirtualDom = entry => {
|
|
458
499
|
const {
|
|
459
500
|
value,
|
|
460
|
-
type
|
|
501
|
+
type,
|
|
502
|
+
...props
|
|
461
503
|
} = entry;
|
|
462
504
|
const fn = getCellRenderer(type);
|
|
463
|
-
return fn(value);
|
|
505
|
+
return fn(value, props);
|
|
464
506
|
};
|
|
465
507
|
|
|
466
508
|
const getTableRowVirtualDom = entries => {
|
|
@@ -509,24 +551,187 @@ const getCommandsVirtualDom = state => {
|
|
|
509
551
|
return getFeatureCommandsVirtualDom(state.commands);
|
|
510
552
|
};
|
|
511
553
|
|
|
512
|
-
const
|
|
513
|
-
|
|
554
|
+
const isExternalLink = schema => {
|
|
555
|
+
return schema.startsWith('http://') || schema.startsWith('https://');
|
|
556
|
+
};
|
|
557
|
+
const hasWhitespace = value => {
|
|
558
|
+
return /\s/.test(value);
|
|
559
|
+
};
|
|
560
|
+
const isOnlyDotsOrEmpty = value => {
|
|
561
|
+
const trimmed = value.trim();
|
|
562
|
+
return trimmed === '' || /^\.*$/.test(trimmed);
|
|
563
|
+
};
|
|
564
|
+
const isValidHttpUrl = value => {
|
|
565
|
+
try {
|
|
566
|
+
const url = new URL(value);
|
|
567
|
+
return (url.protocol === 'http:' || url.protocol === 'https:') && !!url.hostname;
|
|
568
|
+
} catch {
|
|
569
|
+
return false;
|
|
570
|
+
}
|
|
571
|
+
};
|
|
572
|
+
const isValidRelativePath = value => {
|
|
573
|
+
// Disallow schemes and whitespace
|
|
574
|
+
if (hasWhitespace(value)) {
|
|
575
|
+
return false;
|
|
576
|
+
}
|
|
577
|
+
if (value.includes('://')) {
|
|
578
|
+
return false;
|
|
579
|
+
}
|
|
580
|
+
if (isOnlyDotsOrEmpty(value)) {
|
|
581
|
+
return false;
|
|
582
|
+
}
|
|
583
|
+
// Allow paths like ./a.json, ../a.json, /a.json, schemas/a.json, a/b.json
|
|
584
|
+
if (!/^[./]?[A-Za-z0-9._\-/]+$/.test(value)) {
|
|
585
|
+
return false;
|
|
586
|
+
}
|
|
587
|
+
// Must contain at least one alphanumeric character
|
|
588
|
+
if (!/[A-Za-z0-9]/.test(value)) {
|
|
589
|
+
return false;
|
|
590
|
+
}
|
|
591
|
+
return true;
|
|
592
|
+
};
|
|
593
|
+
const getSchemaLinkUrl = (schema, extensionUri) => {
|
|
594
|
+
if (!schema || typeof schema !== 'string') {
|
|
595
|
+
return '';
|
|
596
|
+
}
|
|
597
|
+
const trimmed = schema.trim();
|
|
598
|
+
if (trimmed !== schema) {
|
|
599
|
+
return '';
|
|
600
|
+
}
|
|
601
|
+
if (isExternalLink(schema)) {
|
|
602
|
+
return isValidHttpUrl(schema) ? schema : '';
|
|
603
|
+
}
|
|
604
|
+
if (!isValidRelativePath(schema)) {
|
|
605
|
+
return '';
|
|
606
|
+
}
|
|
607
|
+
try {
|
|
608
|
+
return new URL(schema, extensionUri).toString();
|
|
609
|
+
} catch {
|
|
610
|
+
return '';
|
|
611
|
+
}
|
|
612
|
+
};
|
|
613
|
+
|
|
614
|
+
const existsJson = async schemaUrl => {
|
|
615
|
+
try {
|
|
616
|
+
// TODO verify that response header is json
|
|
617
|
+
const response = await fetch(schemaUrl, {
|
|
618
|
+
method: 'HEAD'
|
|
619
|
+
});
|
|
620
|
+
return response.ok;
|
|
621
|
+
} catch {
|
|
622
|
+
return false;
|
|
623
|
+
}
|
|
624
|
+
};
|
|
625
|
+
const getJsonValidationInfos = async (extensionUri, validations) => {
|
|
626
|
+
const validationInfos = [];
|
|
627
|
+
for (const validation of validations) {
|
|
628
|
+
const schema = validation.schema ?? validation.url;
|
|
629
|
+
const schemaLinkUrl = getSchemaLinkUrl(schema, extensionUri);
|
|
630
|
+
const {
|
|
631
|
+
fileMatch
|
|
632
|
+
} = validation;
|
|
633
|
+
if (typeof schema !== 'string') {
|
|
634
|
+
validationInfos.push({
|
|
635
|
+
isValid: false,
|
|
636
|
+
stringValue: JSON.stringify(schema),
|
|
637
|
+
schemaUrl: '',
|
|
638
|
+
errorMessage: propertyMustBeOfTypeString(),
|
|
639
|
+
fileMatch
|
|
640
|
+
});
|
|
641
|
+
} else if (schema && !schemaLinkUrl) {
|
|
642
|
+
validationInfos.push({
|
|
643
|
+
isValid: false,
|
|
644
|
+
stringValue: schema,
|
|
645
|
+
schemaUrl: schemaLinkUrl,
|
|
646
|
+
errorMessage: invalidLink(),
|
|
647
|
+
fileMatch
|
|
648
|
+
});
|
|
649
|
+
} else if (schemaLinkUrl) {
|
|
650
|
+
if (await existsJson(schemaLinkUrl)) {
|
|
651
|
+
validationInfos.push({
|
|
652
|
+
isValid: true,
|
|
653
|
+
stringValue: schema,
|
|
654
|
+
schemaUrl: schemaLinkUrl,
|
|
655
|
+
errorMessage: '',
|
|
656
|
+
fileMatch
|
|
657
|
+
});
|
|
658
|
+
} else {
|
|
659
|
+
validationInfos.push({
|
|
660
|
+
isValid: false,
|
|
661
|
+
stringValue: schema,
|
|
662
|
+
schemaUrl: schemaLinkUrl,
|
|
663
|
+
errorMessage: schemaNotFound(),
|
|
664
|
+
fileMatch
|
|
665
|
+
});
|
|
666
|
+
}
|
|
667
|
+
} else {
|
|
668
|
+
validationInfos.push({
|
|
669
|
+
isValid: true,
|
|
670
|
+
stringValue: schema,
|
|
671
|
+
schemaUrl: schemaLinkUrl,
|
|
672
|
+
errorMessage: '',
|
|
673
|
+
fileMatch
|
|
674
|
+
});
|
|
675
|
+
}
|
|
676
|
+
}
|
|
677
|
+
return validationInfos;
|
|
678
|
+
};
|
|
679
|
+
|
|
680
|
+
const getJsonValidationTableEntry = validationInfo => {
|
|
514
681
|
const {
|
|
682
|
+
isValid,
|
|
683
|
+
errorMessage,
|
|
684
|
+
schemaUrl,
|
|
685
|
+
stringValue,
|
|
515
686
|
fileMatch
|
|
516
|
-
} =
|
|
517
|
-
|
|
687
|
+
} = validationInfo;
|
|
688
|
+
if (!isValid && schemaUrl) {
|
|
689
|
+
return [{
|
|
690
|
+
type: Code,
|
|
691
|
+
value: fileMatch
|
|
692
|
+
}, {
|
|
693
|
+
type: Link,
|
|
694
|
+
value: stringValue,
|
|
695
|
+
href: schemaUrl,
|
|
696
|
+
className: TableCellInvalid,
|
|
697
|
+
title: errorMessage
|
|
698
|
+
}];
|
|
699
|
+
}
|
|
700
|
+
if (!isValid) {
|
|
701
|
+
return [{
|
|
702
|
+
type: Text,
|
|
703
|
+
value: fileMatch
|
|
704
|
+
}, {
|
|
705
|
+
type: Text,
|
|
706
|
+
value: stringValue,
|
|
707
|
+
className: TableCellInvalid,
|
|
708
|
+
title: errorMessage
|
|
709
|
+
}];
|
|
710
|
+
}
|
|
711
|
+
if (schemaUrl) {
|
|
712
|
+
return [{
|
|
713
|
+
type: Code,
|
|
714
|
+
value: fileMatch
|
|
715
|
+
}, {
|
|
716
|
+
type: Link,
|
|
717
|
+
value: stringValue,
|
|
718
|
+
href: schemaUrl
|
|
719
|
+
}];
|
|
720
|
+
}
|
|
518
721
|
return [{
|
|
519
722
|
type: Code,
|
|
520
723
|
value: fileMatch
|
|
521
724
|
}, {
|
|
522
|
-
type:
|
|
523
|
-
value:
|
|
725
|
+
type: Text,
|
|
726
|
+
value: stringValue
|
|
524
727
|
}];
|
|
525
728
|
};
|
|
526
729
|
|
|
527
730
|
const getJsonValidationDetails = async extension => {
|
|
528
731
|
const validations = extension.jsonValidation || [];
|
|
529
|
-
const
|
|
732
|
+
const extensionUri = extension.uri || '';
|
|
733
|
+
const validationInfos = await getJsonValidationInfos(extensionUri, validations);
|
|
734
|
+
const rows = validationInfos.map(getJsonValidationTableEntry);
|
|
530
735
|
return {
|
|
531
736
|
jsonValidation: rows
|
|
532
737
|
};
|
|
@@ -2396,6 +2601,7 @@ const HandleImageContextMenu = 11;
|
|
|
2396
2601
|
const HandleReadmeContextMenu = 12;
|
|
2397
2602
|
const HandleReadmeScroll = 13;
|
|
2398
2603
|
const HandleTabsClick = 14;
|
|
2604
|
+
const HandleAdditionalDetailContextMenu = 15;
|
|
2399
2605
|
|
|
2400
2606
|
const ActivationEvents = 'ActivationEvents';
|
|
2401
2607
|
const Changelog = 'Changelog';
|
|
@@ -2487,12 +2693,13 @@ const getThemeMarkdown = (themes, iconThemes, productIconThemes) => {
|
|
|
2487
2693
|
const supportsNormalCacheKey = locationProtocol => {
|
|
2488
2694
|
return locationProtocol === 'http:' || locationProtocol === 'https:';
|
|
2489
2695
|
};
|
|
2696
|
+
|
|
2490
2697
|
const getMarkdownCacheKey = (hash, locationProtocol) => {
|
|
2491
2698
|
if (supportsNormalCacheKey(locationProtocol)) {
|
|
2492
2699
|
return `/markdown/${hash}`;
|
|
2493
2700
|
}
|
|
2494
2701
|
// workaround for electron bug
|
|
2495
|
-
return `https
|
|
2702
|
+
return `https://-/markdown/${hash}`;
|
|
2496
2703
|
};
|
|
2497
2704
|
|
|
2498
2705
|
const hash = async content => {
|
|
@@ -3134,6 +3341,10 @@ const getMenus = () => {
|
|
|
3134
3341
|
}];
|
|
3135
3342
|
};
|
|
3136
3343
|
|
|
3344
|
+
const handleAdditionalDetailContextMenu = state => {
|
|
3345
|
+
return state;
|
|
3346
|
+
};
|
|
3347
|
+
|
|
3137
3348
|
const openExtensionSearch = async searchValue => {
|
|
3138
3349
|
await openExtensionSearch$1();
|
|
3139
3350
|
await setExtensionsSearchValue(searchValue);
|
|
@@ -4302,7 +4513,7 @@ const getMoreInfoEntryKeyVirtualDom = item => {
|
|
|
4302
4513
|
return [parentNode, text(key)];
|
|
4303
4514
|
};
|
|
4304
4515
|
|
|
4305
|
-
const classLink = mergeClassNames(MoreInfoEntryValue, Link);
|
|
4516
|
+
const classLink = mergeClassNames(MoreInfoEntryValue, Link$1);
|
|
4306
4517
|
const classCode = mergeClassNames(MoreInfoEntryValue, Code$1);
|
|
4307
4518
|
const getMoreInfoEntryValueClassName = (onClick, code) => {
|
|
4308
4519
|
if (onClick) {
|
|
@@ -4324,13 +4535,15 @@ const getMoreInfoEntryValueTag = (onClick, code) => {
|
|
|
4324
4535
|
return Dd;
|
|
4325
4536
|
};
|
|
4326
4537
|
|
|
4327
|
-
const getExtraProps = title => {
|
|
4538
|
+
const getExtraProps = (title, onClick) => {
|
|
4539
|
+
const props = Object.create(null);
|
|
4328
4540
|
if (title) {
|
|
4329
|
-
|
|
4330
|
-
title
|
|
4331
|
-
};
|
|
4541
|
+
props.title = title;
|
|
4332
4542
|
}
|
|
4333
|
-
|
|
4543
|
+
if (onClick) {
|
|
4544
|
+
props.tabIndex = 0;
|
|
4545
|
+
}
|
|
4546
|
+
return props;
|
|
4334
4547
|
};
|
|
4335
4548
|
const getMoreInfoEntryValueVirtualDom = item => {
|
|
4336
4549
|
const {
|
|
@@ -4341,7 +4554,7 @@ const getMoreInfoEntryValueVirtualDom = item => {
|
|
|
4341
4554
|
} = item;
|
|
4342
4555
|
const type = getMoreInfoEntryValueTag(onClick, code);
|
|
4343
4556
|
const className = getMoreInfoEntryValueClassName(onClick, code);
|
|
4344
|
-
const extraProps = getExtraProps(title);
|
|
4557
|
+
const extraProps = getExtraProps(title, onClick);
|
|
4345
4558
|
return [{
|
|
4346
4559
|
type,
|
|
4347
4560
|
className,
|
|
@@ -4410,7 +4623,8 @@ const getAdditionalDetailsVirtualDom = (showAdditionalDetails, firstHeading, ent
|
|
|
4410
4623
|
type: Div,
|
|
4411
4624
|
className: AdditionalDetails,
|
|
4412
4625
|
tabIndex: 0,
|
|
4413
|
-
childCount: 4
|
|
4626
|
+
childCount: 4,
|
|
4627
|
+
onClick: HandleAdditionalDetailContextMenu
|
|
4414
4628
|
}, ...getAdditionalDetailsEntryVirtualDom(firstHeading, entries, getMoreInfoVirtualDom), ...getAdditionalDetailsEntryVirtualDom(secondHeading, secondEntries, getMoreInfoVirtualDom), ...getAdditionalDetailsEntryVirtualDom(thirdHeading, categories, getCategoriesDom), ...getAdditionalDetailsEntryVirtualDom(fourthHeading, resources, getResourcesVirtualDom)];
|
|
4415
4629
|
};
|
|
4416
4630
|
|
|
@@ -4756,6 +4970,10 @@ const render2 = (uid, diffResult) => {
|
|
|
4756
4970
|
// @ts-nocheck
|
|
4757
4971
|
const renderEventListeners = () => {
|
|
4758
4972
|
return [{
|
|
4973
|
+
name: HandleAdditionalDetailContextMenu,
|
|
4974
|
+
params: ['handleAdditionalDetailsContextMenu'],
|
|
4975
|
+
preventDefault: true
|
|
4976
|
+
}, {
|
|
4759
4977
|
name: HandleClickCategory,
|
|
4760
4978
|
params: ['handleClickCategory', TargetName]
|
|
4761
4979
|
}, {
|
|
@@ -4839,6 +5057,7 @@ const commandMap = {
|
|
|
4839
5057
|
'ExtensionDetail.getMenuEntries': getMenuEntries,
|
|
4840
5058
|
'ExtensionDetail.getMenus': getMenus,
|
|
4841
5059
|
'ExtensionDetail.handleClickCategory': wrapCommand(handleClickCategory),
|
|
5060
|
+
'ExtensionDetail.handleAdditionalDetailsContextMenu': wrapCommand(handleAdditionalDetailContextMenu),
|
|
4842
5061
|
'ExtensionDetail.handleClickDisable': wrapCommand(handleClickDisable),
|
|
4843
5062
|
'ExtensionDetail.handleClickEnable': wrapCommand(handleClickEnable),
|
|
4844
5063
|
'ExtensionDetail.handleClickScrollToTop': wrapCommand(handleClickScrollToTop),
|