@@ -2,7 +2,53 @@ import React from "react";
22
33import isAbsoluteUrl from "is-absolute-url" ;
44
5+ import { commaSeparate } from "../utils" ;
6+
7+ export interface TwitterEmbedProps {
8+ /** Summary card size. */
9+ cardSize : "small" | "large" ;
10+
11+ /** A concise title for the related content. */
12+ title ?: string ;
13+
14+ /**
15+ * A description that concisely summarizes the content as appropriate for
16+ * presentation within a Tweet. Should not be the same as title.
17+ */
18+ description ?: string ;
19+
20+ /** The Twitter @username the card should be attributed to. */
21+ siteUsername ?: string ;
22+
23+ /** The Twitter @username for the content creator / author. */
24+ creatorUsername ?: string ;
25+
26+ /**
27+ * Image to show in card. _Should_ only be used if image is different to
28+ * `MetaHeadEmbed` image.
29+ *
30+ * Should be different based on `useLargeCard`:
31+ * - For large cards, use a 2:1 aspect ratio (300x157 px minium or
32+ * 4096x4096 px maximum).
33+ * - For small cards, use a 1:1 aspect ratio (144x144 px minium or
34+ * 4096x4096 px maximum).
35+ *
36+ * Images must be less than 5MB in size.
37+ *
38+ * Supported file types; JPG, PNG, WEBP and GIF.
39+ *
40+ * Note: Only the first frame of an animated GIF will be used.
41+ */
42+ imageUrl ?: string ;
43+
44+ /** Image alt for users who are visually impaired. Maximum 420 characters. */
45+ imageAlt ?: string ;
46+ }
47+
548export interface MetaEmbedProps {
49+ /** Returns meta properties to be rendered. */
50+ render : ( meta : React . ReactNode ) => JSX . Element ;
51+
652 /** Unique page title that describes the page, such as `Home`, `About` etc. */
753 pageTitle : string ;
854
@@ -23,17 +69,17 @@ export interface MetaEmbedProps {
2369 /** Canonical URL of your webpage that will be used as its default app URL. */
2470 canonicalUrl ?: string ;
2571
26- /** Base URL of the site, excluding trailing slash. */
27- siteBaseUrl : string ;
72+ /** Base site URL , excluding trailing slash. */
73+ baseSiteUrl : string ;
2874
2975 /** The path of the page, excluding leading slash. */
3076 pagePath ?: string ;
3177
3278 /**
3379 * List of SEO keywords describing what your webpage does.
34- * For example, `"your, tags"` or `["your", "tags"]`.
80+ * Example: `"your, tags"` or `["your", "tags"]`.
3581 */
36- keywords : string | string [ ] ;
82+ keywords ? : string | string [ ] ;
3783
3884 /**
3985 * Image url of asset to share. Recommended aspect ratio for landscape is
@@ -51,24 +97,26 @@ export interface MetaEmbedProps {
5197 * Defaults to `en_US`.
5298 */
5399 locale ?: string ;
100+
101+ /** Twitter embed properties */
102+ twitter ?: TwitterEmbedProps ;
54103}
55104
56105const MetaHeadEmbed = ( {
106+ render,
57107 pageTitle,
58108 siteTitle,
59109 titleTemplate,
60110 description,
61111 canonicalUrl,
62- siteBaseUrl ,
112+ baseSiteUrl ,
63113 pagePath,
64114 keywords,
65115 imageUrl,
66116 imageAlt,
67117 locale = "en_US" ,
118+ twitter,
68119} : MetaEmbedProps ) => {
69- const joinedKeywords =
70- typeof keywords === "string" ? keywords : keywords ?. join ( ", " ) ;
71-
72120 const title = titleTemplate
73121 ? pageTitle === siteTitle
74122 ? pageTitle
@@ -81,28 +129,78 @@ const MetaHeadEmbed = ({
81129 canonicalUrl &&
82130 ( isAbsoluteUrl ( canonicalUrl )
83131 ? canonicalUrl
84- : `${ siteBaseUrl } /${ canonicalUrl } ` ) ;
85-
86- const pageUrl = pagePath ? `${ siteBaseUrl } /${ pagePath } ` : siteBaseUrl ;
87-
88- return (
89- < >
90- < title > { title } </ title >
91- < meta name = "title" content = { title } />
92- < meta name = "description" content = { description } />
93- < meta name = "keywords" content = { joinedKeywords } />
94- { canonicalUrl && < link rel = "canonical" href = { canonical } /> }
95-
96- < meta property = "og:type" content = "website" />
97- < meta property = "og:url" content = { pageUrl } />
98- < meta property = "og:title" content = { title } />
99- < meta property = "og:description" content = { description } />
100- < meta property = "og:image" content = { imageUrl } />
101- < meta property = "og:image:alt" content = { imageAlt } />
102- < meta property = "og:site_name" content = { siteTitle } />
103- < meta property = "og:locale" content = { locale } />
104- </ >
105- ) ;
132+ : `${ baseSiteUrl } /${ canonicalUrl } ` ) ;
133+
134+ const pageUrl = pagePath ? `${ baseSiteUrl } /${ pagePath } ` : baseSiteUrl ;
135+
136+ const metaEmbed = [
137+ < title key = "title" > { title } </ title > ,
138+ < meta key = "meta:title" name = "title" content = { title } /> ,
139+ < meta key = "meta:description" name = "description" content = { description } /> ,
140+ keywords && (
141+ < meta
142+ key = "meta:keywords"
143+ name = "keywords"
144+ content = { commaSeparate ( keywords ) }
145+ />
146+ ) ,
147+ canonicalUrl && < link key = "canonical" rel = "canonical" href = { canonical } /> ,
148+
149+ < meta key = "og:type" property = "og:type" content = "website" /> ,
150+ < meta key = "og:url" property = "og:url" content = { pageUrl } /> ,
151+ < meta key = "og:title" property = "og:title" content = { title } /> ,
152+ < meta
153+ key = "og:description"
154+ property = "og:description"
155+ content = { description }
156+ /> ,
157+ < meta key = "og:image" property = "og:image" content = { imageUrl } /> ,
158+ < meta key = "og:image:alt" property = "og:image:alt" content = { imageAlt } /> ,
159+ < meta key = "og:site_name" property = "og:site_name" content = { siteTitle } /> ,
160+ < meta key = "og:locale" property = "og:locale" content = { locale } /> ,
161+ ] ;
162+
163+ const twitterEmbed = ( {
164+ cardSize,
165+ title,
166+ description,
167+ siteUsername,
168+ creatorUsername,
169+ imageUrl,
170+ imageAlt,
171+ } : TwitterEmbedProps ) => [
172+ < meta
173+ key = "twitter:card"
174+ name = "twitter:card"
175+ content = { cardSize === "large" ? "summary_large_image" : "summary" }
176+ /> ,
177+ title && < meta key = "twitter:title" name = "twitter:title" content = { title } /> ,
178+ description && (
179+ < meta
180+ key = "twitter:description"
181+ name = "twitter:description"
182+ content = { description }
183+ />
184+ ) ,
185+ siteUsername && (
186+ < meta key = "twitter:site" name = "twitter:site" content = { siteUsername } />
187+ ) ,
188+ creatorUsername && (
189+ < meta
190+ key = "twitter:creator"
191+ name = "twitter:creator"
192+ content = { creatorUsername }
193+ />
194+ ) ,
195+ imageUrl && (
196+ < meta key = "twitter:image" name = "twitter:image" content = { imageUrl } />
197+ ) ,
198+ imageAlt && (
199+ < meta key = "twitter:alt" name = "twitter:image:alt" content = { imageAlt } />
200+ ) ,
201+ ] ;
202+
203+ return render ( [ metaEmbed , twitter && twitterEmbed ( { ...twitter } ) ] ) ;
106204} ;
107205
108206export default MetaHeadEmbed ;
0 commit comments