@lvce-editor/extension-detail-view 4.6.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 || [];
|
|
@@ -441,16 +453,19 @@ const getCellCodeVirtualDom = (value, props) => {
|
|
|
441
453
|
}, text(value)];
|
|
442
454
|
};
|
|
443
455
|
|
|
444
|
-
const getCellLinkVirtualDom = (value, {
|
|
445
|
-
|
|
446
|
-
}) => {
|
|
456
|
+
const getCellLinkVirtualDom = (value, props) => {
|
|
457
|
+
const tdClassName = props?.className ? `${TableCell} ${props.className}` : TableCell;
|
|
447
458
|
return [{
|
|
448
459
|
type: Td,
|
|
449
|
-
className:
|
|
450
|
-
childCount: 1
|
|
460
|
+
className: tdClassName,
|
|
461
|
+
childCount: 1,
|
|
462
|
+
...(props?.title ? {
|
|
463
|
+
title: props.title
|
|
464
|
+
} : {})
|
|
451
465
|
}, {
|
|
452
466
|
type: A,
|
|
453
|
-
|
|
467
|
+
className: Link$1,
|
|
468
|
+
href: props?.href,
|
|
454
469
|
childCount: 1
|
|
455
470
|
}, text(value)];
|
|
456
471
|
};
|
|
@@ -536,94 +551,187 @@ const getCommandsVirtualDom = state => {
|
|
|
536
551
|
return getFeatureCommandsVirtualDom(state.commands);
|
|
537
552
|
};
|
|
538
553
|
|
|
539
|
-
const
|
|
540
|
-
return
|
|
554
|
+
const isExternalLink = schema => {
|
|
555
|
+
return schema.startsWith('http://') || schema.startsWith('https://');
|
|
541
556
|
};
|
|
542
|
-
const
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
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;
|
|
555
570
|
}
|
|
556
|
-
return {
|
|
557
|
-
type: Text,
|
|
558
|
-
value: schema
|
|
559
|
-
};
|
|
560
571
|
};
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
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;
|
|
564
592
|
};
|
|
565
593
|
const getSchemaLinkUrl = (schema, extensionUri) => {
|
|
566
|
-
if (!schema) {
|
|
594
|
+
if (!schema || typeof schema !== 'string') {
|
|
567
595
|
return '';
|
|
568
596
|
}
|
|
569
|
-
|
|
597
|
+
const trimmed = schema.trim();
|
|
598
|
+
if (trimmed !== schema) {
|
|
570
599
|
return '';
|
|
571
600
|
}
|
|
572
601
|
if (isExternalLink(schema)) {
|
|
573
|
-
return 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 '';
|
|
574
611
|
}
|
|
575
|
-
return new URL(schema, extensionUri).toString();
|
|
576
612
|
};
|
|
577
613
|
|
|
578
|
-
const
|
|
614
|
+
const existsJson = async schemaUrl => {
|
|
579
615
|
try {
|
|
580
|
-
|
|
616
|
+
// TODO verify that response header is json
|
|
617
|
+
const response = await fetch(schemaUrl, {
|
|
618
|
+
method: 'HEAD'
|
|
619
|
+
});
|
|
620
|
+
return response.ok;
|
|
581
621
|
} catch {
|
|
582
|
-
return
|
|
622
|
+
return false;
|
|
583
623
|
}
|
|
584
624
|
};
|
|
585
|
-
const
|
|
586
|
-
const
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
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 => {
|
|
681
|
+
const {
|
|
682
|
+
isValid,
|
|
683
|
+
errorMessage,
|
|
684
|
+
schemaUrl,
|
|
685
|
+
stringValue,
|
|
686
|
+
fileMatch
|
|
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) {
|
|
592
701
|
return [{
|
|
593
702
|
type: Text,
|
|
594
|
-
value:
|
|
595
|
-
...invalidProps
|
|
703
|
+
value: fileMatch
|
|
596
704
|
}, {
|
|
597
705
|
type: Text,
|
|
598
|
-
value:
|
|
599
|
-
|
|
706
|
+
value: stringValue,
|
|
707
|
+
className: TableCellInvalid,
|
|
708
|
+
title: errorMessage
|
|
600
709
|
}];
|
|
601
710
|
}
|
|
602
|
-
|
|
603
|
-
|
|
604
|
-
|
|
605
|
-
|
|
606
|
-
|
|
607
|
-
|
|
711
|
+
if (schemaUrl) {
|
|
712
|
+
return [{
|
|
713
|
+
type: Code,
|
|
714
|
+
value: fileMatch
|
|
715
|
+
}, {
|
|
716
|
+
type: Link,
|
|
717
|
+
value: stringValue,
|
|
718
|
+
href: schemaUrl
|
|
719
|
+
}];
|
|
720
|
+
}
|
|
721
|
+
return [{
|
|
608
722
|
type: Code,
|
|
609
723
|
value: fileMatch
|
|
610
|
-
}
|
|
611
|
-
type: Text,
|
|
612
|
-
value: stringify(fileMatch),
|
|
613
|
-
...invalidProps
|
|
614
|
-
};
|
|
615
|
-
const rightEntry = typeof schema === 'string' ? getLinkOrTextEntry(schema, schemaLinkUrl) : {
|
|
724
|
+
}, {
|
|
616
725
|
type: Text,
|
|
617
|
-
value:
|
|
618
|
-
|
|
619
|
-
};
|
|
620
|
-
return [leftCell, rightEntry];
|
|
726
|
+
value: stringValue
|
|
727
|
+
}];
|
|
621
728
|
};
|
|
622
729
|
|
|
623
730
|
const getJsonValidationDetails = async extension => {
|
|
624
731
|
const validations = extension.jsonValidation || [];
|
|
625
732
|
const extensionUri = extension.uri || '';
|
|
626
|
-
const
|
|
733
|
+
const validationInfos = await getJsonValidationInfos(extensionUri, validations);
|
|
734
|
+
const rows = validationInfos.map(getJsonValidationTableEntry);
|
|
627
735
|
return {
|
|
628
736
|
jsonValidation: rows
|
|
629
737
|
};
|
|
@@ -835,7 +943,7 @@ class AssertionError extends Error {
|
|
|
835
943
|
const Object$1 = 1;
|
|
836
944
|
const Number$1 = 2;
|
|
837
945
|
const Array$1 = 3;
|
|
838
|
-
const String
|
|
946
|
+
const String = 4;
|
|
839
947
|
const Boolean$1 = 5;
|
|
840
948
|
const Function = 6;
|
|
841
949
|
const Null = 7;
|
|
@@ -847,7 +955,7 @@ const getType = value => {
|
|
|
847
955
|
case 'function':
|
|
848
956
|
return Function;
|
|
849
957
|
case 'string':
|
|
850
|
-
return String
|
|
958
|
+
return String;
|
|
851
959
|
case 'object':
|
|
852
960
|
if (value === null) {
|
|
853
961
|
return Null;
|
|
@@ -864,7 +972,7 @@ const getType = value => {
|
|
|
864
972
|
};
|
|
865
973
|
const string = value => {
|
|
866
974
|
const type = getType(value);
|
|
867
|
-
if (type !== String
|
|
975
|
+
if (type !== String) {
|
|
868
976
|
throw new AssertionError('expected value to be of type string');
|
|
869
977
|
}
|
|
870
978
|
};
|