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.
316 lines
10 KiB
TypeScript
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} />
|
|
</>
|
|
);
|
|
}
|