sitegen/framework/meta/nextjs/generate/opengraph.tsx
chloe caruso af60d1172f i accidentally deleted the repo, but recovered it. i'll start committing
it was weird. i pressed delete on a subfolder, i think one of the
pages.off folders that i was using. and then, suddenly, nvim on windows
7 decided to delete every file in the directory. they weren't shred off
the space time continuum, but just marked deleted. i had to pay $80 to
get access to a software that could see them. bleh!

just seeing all my work, a little over a week, was pretty heart
shattering. but i remembered that long ago, a close friend said i could
call them whenever i was feeling sad. i finally took them up on that
offer. the first time i've ever called someone for emotional support.
but it's ok. i got it back. and the site framework is better than ever.

i'm gonna commit and push more often. the repo is private anyways.
2025-06-06 23:38:02 -07:00

316 lines
10 KiB
TypeScript

import type { ResolvedMetadata } from "../types/metadata-interface";
import type { TwitterAppDescriptor } from "../types/twitter-types";
import React from "react";
import { Meta, MultiMeta } from "./meta";
export function OpenGraphMetadata({
openGraph,
}: {
openGraph: ResolvedMetadata["openGraph"];
}) {
if (!openGraph) {
return null;
}
let typedOpenGraph;
if ("type" in openGraph) {
switch (openGraph.type) {
case "website":
typedOpenGraph = <Meta property="og:type" content="website" />;
break;
case "article":
typedOpenGraph = (
<>
<Meta property="og:type" content="article" />
<Meta
property="article:published_time"
content={openGraph.publishedTime?.toString()}
/>
<Meta
property="article:modified_time"
content={openGraph.modifiedTime?.toString()}
/>
<Meta
property="article:expiration_time"
content={openGraph.expirationTime?.toString()}
/>
<MultiMeta
propertyPrefix="article:author"
contents={openGraph.authors}
/>
<Meta property="article:section" content={openGraph.section} />
<MultiMeta propertyPrefix="article:tag" contents={openGraph.tags} />
</>
);
break;
case "book":
typedOpenGraph = (
<>
<Meta property="og:type" content="book" />
<Meta property="book:isbn" content={openGraph.isbn} />
<Meta
property="book:release_date"
content={openGraph.releaseDate}
/>
<MultiMeta
propertyPrefix="book:author"
contents={openGraph.authors}
/>
<MultiMeta propertyPrefix="book:tag" contents={openGraph.tags} />
</>
);
break;
case "profile":
typedOpenGraph = (
<>
<Meta property="og:type" content="profile" />
<Meta property="profile:first_name" content={openGraph.firstName} />
<Meta property="profile:last_name" content={openGraph.lastName} />
<Meta property="profile:username" content={openGraph.username} />
<Meta property="profile:gender" content={openGraph.gender} />
</>
);
break;
case "music.song":
typedOpenGraph = (
<>
<Meta property="og:type" content="music.song" />
<Meta
property="music:duration"
content={openGraph.duration?.toString()}
/>
<MultiMeta
propertyPrefix="music:album"
contents={openGraph.albums}
/>
<MultiMeta
propertyPrefix="music:musician"
contents={openGraph.musicians}
/>
</>
);
break;
case "music.album":
typedOpenGraph = (
<>
<Meta property="og:type" content="music.album" />
<MultiMeta propertyPrefix="music:song" contents={openGraph.songs} />
<MultiMeta
propertyPrefix="music:musician"
contents={openGraph.musicians}
/>
<Meta
property="music:release_date"
content={openGraph.releaseDate}
/>
</>
);
break;
case "music.playlist":
typedOpenGraph = (
<>
<Meta property="og:type" content="music.playlist" />
<MultiMeta propertyPrefix="music:song" contents={openGraph.songs} />
<MultiMeta
propertyPrefix="music:creator"
contents={openGraph.creators}
/>
</>
);
break;
case "music.radio_station":
typedOpenGraph = (
<>
<Meta property="og:type" content="music.radio_station" />
<MultiMeta
propertyPrefix="music:creator"
contents={openGraph.creators}
/>
</>
);
break;
case "video.movie":
typedOpenGraph = (
<>
<Meta property="og:type" content="video.movie" />
<MultiMeta
propertyPrefix="video:actor"
contents={openGraph.actors}
/>
<MultiMeta
propertyPrefix="video:director"
contents={openGraph.directors}
/>
<MultiMeta
propertyPrefix="video:writer"
contents={openGraph.writers}
/>
<Meta property="video:duration" content={openGraph.duration} />
<Meta
property="video:release_date"
content={openGraph.releaseDate}
/>
<MultiMeta propertyPrefix="video:tag" contents={openGraph.tags} />
</>
);
break;
case "video.episode":
typedOpenGraph = (
<>
<Meta property="og:type" content="video.episode" />
<MultiMeta
propertyPrefix="video:actor"
contents={openGraph.actors}
/>
<MultiMeta
propertyPrefix="video:director"
contents={openGraph.directors}
/>
<MultiMeta
propertyPrefix="video:writer"
contents={openGraph.writers}
/>
<Meta property="video:duration" content={openGraph.duration} />
<Meta
property="video:release_date"
content={openGraph.releaseDate}
/>
<MultiMeta propertyPrefix="video:tag" contents={openGraph.tags} />
<Meta property="video:series" content={openGraph.series} />
</>
);
break;
case "video.tv_show":
typedOpenGraph = <Meta property="og:type" content="video.tv_show" />;
break;
case "video.other":
typedOpenGraph = <Meta property="og:type" content="video.other" />;
break;
default:
throw new Error("Invalid OpenGraph type: " + (openGraph as any).type);
}
}
return (
<>
<Meta property="og:determiner" content={openGraph.determiner} />
<Meta property="og:title" content={openGraph.title?.absolute} />
<Meta property="og:description" content={openGraph.description} />
<Meta property="og:url" content={openGraph.url?.toString()} />
<Meta property="og:site_name" content={openGraph.siteName} />
<Meta property="og:locale" content={openGraph.locale} />
<Meta property="og:country_name" content={openGraph.countryName} />
<Meta property="og:ttl" content={openGraph.ttl?.toString()} />
<MultiMeta propertyPrefix="og:image" contents={openGraph.images} />
<MultiMeta propertyPrefix="og:video" contents={openGraph.videos} />
<MultiMeta propertyPrefix="og:audio" contents={openGraph.audio} />
<MultiMeta propertyPrefix="og:email" contents={openGraph.emails} />
<MultiMeta
propertyPrefix="og:phone_number"
contents={openGraph.phoneNumbers}
/>
<MultiMeta
propertyPrefix="og:fax_number"
contents={openGraph.faxNumbers}
/>
<MultiMeta
propertyPrefix="og:locale:alternate"
contents={openGraph.alternateLocale}
/>
{typedOpenGraph}
</>
);
}
function TwitterAppItem({
app,
type,
}: {
app: TwitterAppDescriptor;
type: "iphone" | "ipad" | "googleplay";
}) {
return (
<>
<Meta name={`twitter:app:name:${type}`} content={app.name} />
<Meta name={`twitter:app:id:${type}`} content={app.id[type]} />
<Meta
name={`twitter:app:url:${type}`}
content={app.url?.[type]?.toString()}
/>
</>
);
}
export function TwitterMetadata({
twitter,
}: {
twitter: ResolvedMetadata["twitter"];
}) {
if (!twitter) return null;
const { card } = twitter;
return (
<>
<Meta name="twitter:card" content={card} />
<Meta name="twitter:site" content={twitter.site} />
<Meta name="twitter:site:id" content={twitter.siteId} />
<Meta name="twitter:creator" content={twitter.creator} />
<Meta name="twitter:creator:id" content={twitter.creatorId} />
<Meta name="twitter:title" content={twitter.title?.absolute} />
<Meta name="twitter:description" content={twitter.description} />
<MultiMeta namePrefix="twitter:image" contents={twitter.images} />
{card === "player"
? twitter.players.map((player, index) => (
<React.Fragment key={index}>
<Meta
name="twitter:player"
content={player.playerUrl.toString()}
/>
<Meta
name="twitter:player:stream"
content={player.streamUrl.toString()}
/>
<Meta name="twitter:player:width" content={player.width} />
<Meta name="twitter:player:height" content={player.height} />
</React.Fragment>
))
: null}
{card === "app"
? (
<>
<TwitterAppItem app={twitter.app} type="iphone" />
<TwitterAppItem app={twitter.app} type="ipad" />
<TwitterAppItem app={twitter.app} type="googleplay" />
</>
)
: null}
</>
);
}
export function AppLinksMeta({
appLinks,
}: {
appLinks: ResolvedMetadata["appLinks"];
}) {
if (!appLinks) return null;
return (
<>
<MultiMeta propertyPrefix="al:ios" contents={appLinks.ios} />
<MultiMeta propertyPrefix="al:iphone" contents={appLinks.iphone} />
<MultiMeta propertyPrefix="al:ipad" contents={appLinks.ipad} />
<MultiMeta propertyPrefix="al:android" contents={appLinks.android} />
<MultiMeta
propertyPrefix="al:windows_phone"
contents={appLinks.windows_phone}
/>
<MultiMeta propertyPrefix="al:windows" contents={appLinks.windows} />
<MultiMeta
propertyPrefix="al:windows_universal"
contents={appLinks.windows_universal}
/>
<MultiMeta propertyPrefix="al:web" contents={appLinks.web} />
</>
);
}