@getvitops/astro 0.1.1 → 0.3.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.
Files changed (37) hide show
  1. package/dist/index.d.mts +2 -120
  2. package/dist/index.d.mts.map +1 -1
  3. package/dist/index.mjs +3 -181
  4. package/dist/index.mjs.map +1 -1
  5. package/package.json +30 -9
  6. package/src/components/Cards.astro +32 -0
  7. package/src/components/Details.astro +76 -0
  8. package/src/components/Drawer.astro +65 -0
  9. package/src/components/NodeRenderer.astro +27 -0
  10. package/src/components/Popover.astro +90 -0
  11. package/src/components/Subgrid.astro +32 -0
  12. package/src/components/WebComponentLoader.astro +48 -0
  13. package/src/schemas/Article.astro +69 -0
  14. package/src/schemas/BookActions.astro +81 -0
  15. package/src/schemas/Breadcrumb.astro +26 -0
  16. package/src/schemas/Carousel.astro +34 -0
  17. package/src/schemas/CourseList.astro +122 -0
  18. package/src/schemas/Dataset.astro +127 -0
  19. package/src/schemas/DiscussionForum.astro +82 -0
  20. package/src/schemas/EducationQA.astro +63 -0
  21. package/src/schemas/EmployerAggregateRating.astro +54 -0
  22. package/src/schemas/Event.astro +115 -0
  23. package/src/schemas/FAQ.astro +34 -0
  24. package/src/schemas/FactCheck.astro +84 -0
  25. package/src/schemas/ImageMetadata.astro +56 -0
  26. package/src/schemas/JobPosting.astro +138 -0
  27. package/src/schemas/LocalBusiness.astro +155 -0
  28. package/src/schemas/MathSolver.astro +54 -0
  29. package/src/schemas/MovieCarousel.astro +92 -0
  30. package/src/schemas/Organization.astro +140 -0
  31. package/src/schemas/Product.astro +250 -0
  32. package/src/schemas/ProfilePage.astro +147 -0
  33. package/src/schemas/QAPage.astro +71 -0
  34. package/src/schemas/Recipe.astro +178 -0
  35. package/src/schemas/Review.astro +138 -0
  36. package/src/schemas/SoftwareApp.astro +172 -0
  37. /package/{Head.astro → src/components/Head.astro} +0 -0
@@ -0,0 +1,82 @@
1
+ ---
2
+ export interface ForumPost {
3
+ headline: string;
4
+ text: string;
5
+ url: string;
6
+ datePublished: string;
7
+ author: {
8
+ name: string;
9
+ url?: string;
10
+ };
11
+ interactionStatistic?: {
12
+ type: 'ReplyAction' | 'LikeAction' | 'ViewAction';
13
+ count: number;
14
+ }[];
15
+ comment?: {
16
+ text: string;
17
+ datePublished: string;
18
+ author: {
19
+ name: string;
20
+ url?: string;
21
+ };
22
+ }[];
23
+ }
24
+
25
+ export interface Props {
26
+ name: string;
27
+ url: string;
28
+ description?: string;
29
+ mainEntity?: ForumPost[];
30
+ }
31
+
32
+ const { name, url, description, mainEntity } = Astro.props;
33
+
34
+ const jsonLd = {
35
+ '@context': 'https://schema.org',
36
+ '@type': 'DiscussionForumPosting',
37
+ ...(mainEntity && mainEntity.length > 0
38
+ ? {
39
+ mainEntity: mainEntity.map(post => ({
40
+ '@type': 'DiscussionForumPosting',
41
+ headline: post.headline,
42
+ text: post.text,
43
+ url: post.url,
44
+ datePublished: post.datePublished,
45
+ author: {
46
+ '@type': 'Person',
47
+ name: post.author.name,
48
+ ...(post.author.url && { url: post.author.url }),
49
+ },
50
+ ...(post.interactionStatistic && {
51
+ interactionStatistic: post.interactionStatistic.map(stat => ({
52
+ '@type': 'InteractionCounter',
53
+ interactionType: { '@type': stat.type },
54
+ userInteractionCount: stat.count,
55
+ })),
56
+ }),
57
+ ...(post.comment && {
58
+ comment: post.comment.map(c => ({
59
+ '@type': 'Comment',
60
+ text: c.text,
61
+ datePublished: c.datePublished,
62
+ author: {
63
+ '@type': 'Person',
64
+ name: c.author.name,
65
+ ...(c.author.url && { url: c.author.url }),
66
+ },
67
+ })),
68
+ }),
69
+ })),
70
+ }
71
+ : {}),
72
+ isPartOf: {
73
+ '@type': 'WebPage',
74
+ '@id': url,
75
+ name,
76
+ ...(description && { description }),
77
+ },
78
+ };
79
+ ---
80
+
81
+ <script is:inline type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
82
+ <slot />
@@ -0,0 +1,63 @@
1
+ ---
2
+ export interface Props {
3
+ mainEntity: {
4
+ question: string;
5
+ answer: {
6
+ text: string;
7
+ author?: {
8
+ name: string;
9
+ type?: 'Person' | 'Organization';
10
+ };
11
+ dateCreated?: string;
12
+ upvoteCount?: number;
13
+ url?: string;
14
+ };
15
+ eduQuestionType?: 'Practice' | 'Test' | 'Homework' | 'Quiz' | 'Exam';
16
+ learningResourceType?: string;
17
+ assesses?: string;
18
+ educationalLevel?: string;
19
+ }[];
20
+ about?: {
21
+ name: string;
22
+ url?: string;
23
+ };
24
+ }
25
+
26
+ const { mainEntity, about } = Astro.props;
27
+
28
+ const jsonLd = {
29
+ '@context': 'https://schema.org',
30
+ '@type': 'Quiz',
31
+ ...(about && {
32
+ about: {
33
+ '@type': 'Thing',
34
+ name: about.name,
35
+ ...(about.url && { url: about.url }),
36
+ },
37
+ }),
38
+ hasPart: mainEntity.map(qa => ({
39
+ '@type': 'Question',
40
+ eduQuestionType: qa.eduQuestionType || 'Practice',
41
+ ...(qa.learningResourceType && { learningResourceType: qa.learningResourceType }),
42
+ ...(qa.assesses && { assesses: qa.assesses }),
43
+ ...(qa.educationalLevel && { educationalLevel: qa.educationalLevel }),
44
+ text: qa.question,
45
+ acceptedAnswer: {
46
+ '@type': 'Answer',
47
+ text: qa.answer.text,
48
+ ...(qa.answer.author && {
49
+ author: {
50
+ '@type': qa.answer.author.type || 'Person',
51
+ name: qa.answer.author.name,
52
+ },
53
+ }),
54
+ ...(qa.answer.dateCreated && { dateCreated: qa.answer.dateCreated }),
55
+ ...(qa.answer.upvoteCount !== undefined && { upvoteCount: qa.answer.upvoteCount }),
56
+ ...(qa.answer.url && { url: qa.answer.url }),
57
+ },
58
+ })),
59
+ };
60
+ ---
61
+
62
+ <script is:inline type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
63
+ <slot />
@@ -0,0 +1,54 @@
1
+ ---
2
+ export interface Props {
3
+ name: string;
4
+ url?: string;
5
+ logo?: string;
6
+ sameAs?: string[];
7
+ aggregateRating: {
8
+ ratingValue: number;
9
+ bestRating?: number;
10
+ worstRating?: number;
11
+ ratingCount?: number;
12
+ reviewCount?: number;
13
+ };
14
+ address?: {
15
+ streetAddress?: string;
16
+ addressLocality?: string;
17
+ addressRegion?: string;
18
+ postalCode?: string;
19
+ addressCountry?: string;
20
+ };
21
+ }
22
+
23
+ const { name, url, logo, sameAs, aggregateRating, address } = Astro.props;
24
+
25
+ const jsonLd = {
26
+ '@context': 'https://schema.org',
27
+ '@type': 'EmployerAggregateRating',
28
+ itemReviewed: {
29
+ '@type': 'Organization',
30
+ name,
31
+ ...(url && { url }),
32
+ ...(logo && { logo }),
33
+ ...(sameAs && { sameAs }),
34
+ ...(address && {
35
+ address: {
36
+ '@type': 'PostalAddress',
37
+ ...(address.streetAddress && { streetAddress: address.streetAddress }),
38
+ ...(address.addressLocality && { addressLocality: address.addressLocality }),
39
+ ...(address.addressRegion && { addressRegion: address.addressRegion }),
40
+ ...(address.postalCode && { postalCode: address.postalCode }),
41
+ ...(address.addressCountry && { addressCountry: address.addressCountry }),
42
+ },
43
+ }),
44
+ },
45
+ ratingValue: aggregateRating.ratingValue,
46
+ bestRating: aggregateRating.bestRating ?? 5,
47
+ worstRating: aggregateRating.worstRating ?? 1,
48
+ ...(aggregateRating.ratingCount && { ratingCount: aggregateRating.ratingCount }),
49
+ ...(aggregateRating.reviewCount && { reviewCount: aggregateRating.reviewCount }),
50
+ };
51
+ ---
52
+
53
+ <script is:inline type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
54
+ <slot />
@@ -0,0 +1,115 @@
1
+ ---
2
+ export interface Props {
3
+ name: string;
4
+ description?: string;
5
+ startDate: string;
6
+ endDate?: string;
7
+ eventStatus?: 'EventScheduled' | 'EventCancelled' | 'EventMovedOnline' | 'EventPostponed' | 'EventRescheduled';
8
+ eventAttendanceMode?: 'OfflineEventAttendanceMode' | 'OnlineEventAttendanceMode' | 'MixedEventAttendanceMode';
9
+ location?: {
10
+ type: 'Place' | 'VirtualLocation';
11
+ name?: string;
12
+ address?: {
13
+ streetAddress?: string;
14
+ addressLocality?: string;
15
+ addressRegion?: string;
16
+ postalCode?: string;
17
+ addressCountry?: string;
18
+ };
19
+ url?: string;
20
+ };
21
+ image?: string | string[];
22
+ performer?: {
23
+ type: 'Person' | 'PerformingGroup' | 'Organization';
24
+ name: string;
25
+ }[];
26
+ organizer?: {
27
+ type: 'Person' | 'Organization';
28
+ name: string;
29
+ url?: string;
30
+ };
31
+ offers?: {
32
+ url?: string;
33
+ price?: number | string;
34
+ priceCurrency?: string;
35
+ availability?: 'InStock' | 'SoldOut' | 'PreOrder';
36
+ validFrom?: string;
37
+ }[];
38
+ previousStartDate?: string;
39
+ }
40
+
41
+ const {
42
+ name,
43
+ description,
44
+ startDate,
45
+ endDate,
46
+ eventStatus = 'EventScheduled',
47
+ eventAttendanceMode = 'OfflineEventAttendanceMode',
48
+ location,
49
+ image,
50
+ performer,
51
+ organizer,
52
+ offers,
53
+ previousStartDate,
54
+ } = Astro.props;
55
+
56
+ const jsonLd = {
57
+ '@context': 'https://schema.org',
58
+ '@type': 'Event',
59
+ name,
60
+ ...(description && { description }),
61
+ startDate,
62
+ ...(endDate && { endDate }),
63
+ eventStatus: `https://schema.org/${eventStatus}`,
64
+ eventAttendanceMode: `https://schema.org/${eventAttendanceMode}`,
65
+ ...(location && {
66
+ location: location.type === 'VirtualLocation'
67
+ ? {
68
+ '@type': 'VirtualLocation',
69
+ url: location.url,
70
+ }
71
+ : {
72
+ '@type': 'Place',
73
+ ...(location.name && { name: location.name }),
74
+ ...(location.address && {
75
+ address: {
76
+ '@type': 'PostalAddress',
77
+ ...(location.address.streetAddress && { streetAddress: location.address.streetAddress }),
78
+ ...(location.address.addressLocality && { addressLocality: location.address.addressLocality }),
79
+ ...(location.address.addressRegion && { addressRegion: location.address.addressRegion }),
80
+ ...(location.address.postalCode && { postalCode: location.address.postalCode }),
81
+ ...(location.address.addressCountry && { addressCountry: location.address.addressCountry }),
82
+ },
83
+ }),
84
+ },
85
+ }),
86
+ ...(image && { image: Array.isArray(image) ? image : [image] }),
87
+ ...(performer && {
88
+ performer: performer.map(p => ({
89
+ '@type': p.type,
90
+ name: p.name,
91
+ })),
92
+ }),
93
+ ...(organizer && {
94
+ organizer: {
95
+ '@type': organizer.type,
96
+ name: organizer.name,
97
+ ...(organizer.url && { url: organizer.url }),
98
+ },
99
+ }),
100
+ ...(offers && {
101
+ offers: offers.map(offer => ({
102
+ '@type': 'Offer',
103
+ ...(offer.url && { url: offer.url }),
104
+ ...(offer.price !== undefined && { price: offer.price }),
105
+ ...(offer.priceCurrency && { priceCurrency: offer.priceCurrency }),
106
+ ...(offer.availability && { availability: `https://schema.org/${offer.availability}` }),
107
+ ...(offer.validFrom && { validFrom: offer.validFrom }),
108
+ })),
109
+ }),
110
+ ...(previousStartDate && { previousStartDate }),
111
+ };
112
+ ---
113
+
114
+ <script is:inline type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
115
+ <slot />
@@ -0,0 +1,34 @@
1
+ ---
2
+ /**
3
+ * FAQ Schema Component
4
+ *
5
+ * NOTE: Google recommends FAQ markup only for authoritative government
6
+ * and health sites. For other sites, consider using QAPage schema instead.
7
+ */
8
+ export interface FAQItem {
9
+ question: string;
10
+ answer: string;
11
+ }
12
+
13
+ export interface Props {
14
+ items: FAQItem[];
15
+ }
16
+
17
+ const { items } = Astro.props;
18
+
19
+ const jsonLd = {
20
+ '@context': 'https://schema.org',
21
+ '@type': 'FAQPage',
22
+ mainEntity: items.map(item => ({
23
+ '@type': 'Question',
24
+ name: item.question,
25
+ acceptedAnswer: {
26
+ '@type': 'Answer',
27
+ text: item.answer,
28
+ },
29
+ })),
30
+ };
31
+ ---
32
+
33
+ <script is:inline type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
34
+ <slot />
@@ -0,0 +1,84 @@
1
+ ---
2
+ export interface Props {
3
+ claimReviewed: string;
4
+ url: string;
5
+ author: {
6
+ name: string;
7
+ url?: string;
8
+ };
9
+ datePublished: string;
10
+ itemReviewed?: {
11
+ type: 'Claim' | 'CreativeWork';
12
+ author?: {
13
+ type: 'Person' | 'Organization';
14
+ name: string;
15
+ url?: string;
16
+ };
17
+ datePublished?: string;
18
+ appearance?: {
19
+ url: string;
20
+ headline?: string;
21
+ }[];
22
+ };
23
+ reviewRating: {
24
+ ratingValue: number;
25
+ bestRating: number;
26
+ worstRating?: number;
27
+ alternateName: string;
28
+ ratingExplanation?: string;
29
+ };
30
+ }
31
+
32
+ const {
33
+ claimReviewed,
34
+ url,
35
+ author,
36
+ datePublished,
37
+ itemReviewed,
38
+ reviewRating,
39
+ } = Astro.props;
40
+
41
+ const jsonLd = {
42
+ '@context': 'https://schema.org',
43
+ '@type': 'ClaimReview',
44
+ claimReviewed,
45
+ url,
46
+ author: {
47
+ '@type': 'Organization',
48
+ name: author.name,
49
+ ...(author.url && { url: author.url }),
50
+ },
51
+ datePublished,
52
+ ...(itemReviewed && {
53
+ itemReviewed: {
54
+ '@type': itemReviewed.type,
55
+ ...(itemReviewed.author && {
56
+ author: {
57
+ '@type': itemReviewed.author.type,
58
+ name: itemReviewed.author.name,
59
+ ...(itemReviewed.author.url && { url: itemReviewed.author.url }),
60
+ },
61
+ }),
62
+ ...(itemReviewed.datePublished && { datePublished: itemReviewed.datePublished }),
63
+ ...(itemReviewed.appearance && {
64
+ appearance: itemReviewed.appearance.map(a => ({
65
+ '@type': 'CreativeWork',
66
+ url: a.url,
67
+ ...(a.headline && { headline: a.headline }),
68
+ })),
69
+ }),
70
+ },
71
+ }),
72
+ reviewRating: {
73
+ '@type': 'Rating',
74
+ ratingValue: reviewRating.ratingValue,
75
+ bestRating: reviewRating.bestRating,
76
+ worstRating: reviewRating.worstRating ?? 1,
77
+ alternateName: reviewRating.alternateName,
78
+ ...(reviewRating.ratingExplanation && { ratingExplanation: reviewRating.ratingExplanation }),
79
+ },
80
+ };
81
+ ---
82
+
83
+ <script is:inline type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
84
+ <slot />
@@ -0,0 +1,56 @@
1
+ ---
2
+ export interface Props {
3
+ contentUrl: string;
4
+ creditText?: string;
5
+ creator?: {
6
+ name: string;
7
+ type?: 'Person' | 'Organization';
8
+ };
9
+ copyrightNotice?: string;
10
+ license?: string;
11
+ acquireLicensePage?: string;
12
+ caption?: string;
13
+ representativeOfPage?: boolean;
14
+ datePublished?: string;
15
+ description?: string;
16
+ name?: string;
17
+ }
18
+
19
+ const {
20
+ contentUrl,
21
+ creditText,
22
+ creator,
23
+ copyrightNotice,
24
+ license,
25
+ acquireLicensePage,
26
+ caption,
27
+ representativeOfPage,
28
+ datePublished,
29
+ description,
30
+ name,
31
+ } = Astro.props;
32
+
33
+ const jsonLd = {
34
+ '@context': 'https://schema.org',
35
+ '@type': 'ImageObject',
36
+ contentUrl,
37
+ ...(creditText && { creditText }),
38
+ ...(creator && {
39
+ creator: {
40
+ '@type': creator.type || 'Person',
41
+ name: creator.name,
42
+ },
43
+ }),
44
+ ...(copyrightNotice && { copyrightNotice }),
45
+ ...(license && { license }),
46
+ ...(acquireLicensePage && { acquireLicensePage }),
47
+ ...(caption && { caption }),
48
+ ...(representativeOfPage !== undefined && { representativeOfPage }),
49
+ ...(datePublished && { datePublished }),
50
+ ...(description && { description }),
51
+ ...(name && { name }),
52
+ };
53
+ ---
54
+
55
+ <script is:inline type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
56
+ <slot />
@@ -0,0 +1,138 @@
1
+ ---
2
+ export interface Props {
3
+ title: string;
4
+ description: string;
5
+ datePosted: string;
6
+ validThrough?: string;
7
+ employmentType?: ('FULL_TIME' | 'PART_TIME' | 'CONTRACTOR' | 'TEMPORARY' | 'INTERN' | 'VOLUNTEER' | 'PER_DIEM' | 'OTHER')[];
8
+ hiringOrganization: {
9
+ name: string;
10
+ sameAs?: string;
11
+ logo?: string;
12
+ };
13
+ jobLocation?: {
14
+ streetAddress?: string;
15
+ addressLocality: string;
16
+ addressRegion?: string;
17
+ postalCode?: string;
18
+ addressCountry: string;
19
+ };
20
+ jobLocationType?: 'TELECOMMUTE';
21
+ applicantLocationRequirements?: {
22
+ type: 'Country' | 'State' | 'City';
23
+ name: string;
24
+ }[];
25
+ baseSalary?: {
26
+ currency: string;
27
+ value: number | { minValue: number; maxValue: number };
28
+ unitText: 'HOUR' | 'DAY' | 'WEEK' | 'MONTH' | 'YEAR';
29
+ };
30
+ identifier?: {
31
+ name: string;
32
+ value: string;
33
+ };
34
+ directApply?: boolean;
35
+ experienceRequirements?: string;
36
+ educationRequirements?: string;
37
+ skills?: string[];
38
+ qualifications?: string[];
39
+ responsibilities?: string[];
40
+ industry?: string;
41
+ occupationalCategory?: string;
42
+ }
43
+
44
+ const {
45
+ title,
46
+ description,
47
+ datePosted,
48
+ validThrough,
49
+ employmentType,
50
+ hiringOrganization,
51
+ jobLocation,
52
+ jobLocationType,
53
+ applicantLocationRequirements,
54
+ baseSalary,
55
+ identifier,
56
+ directApply,
57
+ experienceRequirements,
58
+ educationRequirements,
59
+ skills,
60
+ qualifications,
61
+ responsibilities,
62
+ industry,
63
+ occupationalCategory,
64
+ } = Astro.props;
65
+
66
+ const jsonLd = {
67
+ '@context': 'https://schema.org',
68
+ '@type': 'JobPosting',
69
+ title,
70
+ description,
71
+ datePosted,
72
+ ...(validThrough && { validThrough }),
73
+ ...(employmentType && { employmentType }),
74
+ hiringOrganization: {
75
+ '@type': 'Organization',
76
+ name: hiringOrganization.name,
77
+ ...(hiringOrganization.sameAs && { sameAs: hiringOrganization.sameAs }),
78
+ ...(hiringOrganization.logo && { logo: hiringOrganization.logo }),
79
+ },
80
+ ...(jobLocation && {
81
+ jobLocation: {
82
+ '@type': 'Place',
83
+ address: {
84
+ '@type': 'PostalAddress',
85
+ ...(jobLocation.streetAddress && { streetAddress: jobLocation.streetAddress }),
86
+ addressLocality: jobLocation.addressLocality,
87
+ ...(jobLocation.addressRegion && { addressRegion: jobLocation.addressRegion }),
88
+ ...(jobLocation.postalCode && { postalCode: jobLocation.postalCode }),
89
+ addressCountry: jobLocation.addressCountry,
90
+ },
91
+ },
92
+ }),
93
+ ...(jobLocationType && { jobLocationType }),
94
+ ...(applicantLocationRequirements && {
95
+ applicantLocationRequirements: applicantLocationRequirements.map(req => ({
96
+ '@type': req.type,
97
+ name: req.name,
98
+ })),
99
+ }),
100
+ ...(baseSalary && {
101
+ baseSalary: {
102
+ '@type': 'MonetaryAmount',
103
+ currency: baseSalary.currency,
104
+ value: typeof baseSalary.value === 'number'
105
+ ? { '@type': 'QuantitativeValue', value: baseSalary.value, unitText: baseSalary.unitText }
106
+ : {
107
+ '@type': 'QuantitativeValue',
108
+ minValue: baseSalary.value.minValue,
109
+ maxValue: baseSalary.value.maxValue,
110
+ unitText: baseSalary.unitText,
111
+ },
112
+ },
113
+ }),
114
+ ...(identifier && {
115
+ identifier: {
116
+ '@type': 'PropertyValue',
117
+ name: identifier.name,
118
+ value: identifier.value,
119
+ },
120
+ }),
121
+ ...(directApply !== undefined && { directApply }),
122
+ ...(experienceRequirements && { experienceRequirements }),
123
+ ...(educationRequirements && {
124
+ educationRequirements: {
125
+ '@type': 'EducationalOccupationalCredential',
126
+ credentialCategory: educationRequirements,
127
+ },
128
+ }),
129
+ ...(skills && { skills }),
130
+ ...(qualifications && { qualifications }),
131
+ ...(responsibilities && { responsibilities }),
132
+ ...(industry && { industry }),
133
+ ...(occupationalCategory && { occupationalCategory }),
134
+ };
135
+ ---
136
+
137
+ <script is:inline type="application/ld+json" set:html={JSON.stringify(jsonLd)} />
138
+ <slot />