sitegen/framework/meta/nextjs/resolvers/resolve-opengraph.ts
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

147 lines
3.9 KiB
TypeScript

import type { Metadata, ResolvedMetadata } from "../types/metadata-interface";
import type {
OpenGraph,
OpenGraphType,
ResolvedOpenGraph,
} from "../types/opengraph-types";
import type { FieldResolverWithMetadataBase } from "../types/resolvers";
import type { ResolvedTwitterMetadata, Twitter } from "../types/twitter-types";
import { resolveAsArrayOrUndefined } from "../generate/utils";
import { isStringOrURL, resolveUrl } from "./resolve-url";
const OgTypeFields = {
article: ["authors", "tags"],
song: ["albums", "musicians"],
playlist: ["albums", "musicians"],
radio: ["creators"],
video: ["actors", "directors", "writers", "tags"],
basic: [
"emails",
"phoneNumbers",
"faxNumbers",
"alternateLocale",
"audio",
"videos",
],
} as const;
function resolveImages(
images: Twitter["images"],
metadataBase: ResolvedMetadata["metadataBase"],
): NonNullable<ResolvedMetadata["twitter"]>["images"];
function resolveImages(
images: OpenGraph["images"],
metadataBase: ResolvedMetadata["metadataBase"],
): NonNullable<ResolvedMetadata["openGraph"]>["images"];
function resolveImages(
images: OpenGraph["images"] | Twitter["images"],
metadataBase: ResolvedMetadata["metadataBase"],
):
| NonNullable<ResolvedMetadata["twitter"]>["images"]
| NonNullable<ResolvedMetadata["openGraph"]>["images"] {
const resolvedImages = resolveAsArrayOrUndefined(images);
resolvedImages?.forEach((item, index, array) => {
if (isStringOrURL(item)) {
array[index] = {
url: resolveUrl(item, metadataBase)!,
};
} else {
// Update image descriptor url
item.url = resolveUrl(item.url, metadataBase)!;
}
});
return resolvedImages;
}
function getFieldsByOgType(ogType: OpenGraphType | undefined) {
switch (ogType) {
case "article":
case "book":
return OgTypeFields.article;
case "music.song":
case "music.album":
return OgTypeFields.song;
case "music.playlist":
return OgTypeFields.playlist;
case "music.radio_station":
return OgTypeFields.radio;
case "video.movie":
case "video.episode":
return OgTypeFields.video;
default:
return OgTypeFields.basic;
}
}
export const resolveOpenGraph: FieldResolverWithMetadataBase<"openGraph"> = (
openGraph: Metadata["openGraph"],
metadataBase: ResolvedMetadata["metadataBase"],
) => {
if (!openGraph) return null;
const url = resolveUrl(openGraph.url, metadataBase);
const resolved = { ...openGraph } as ResolvedOpenGraph;
function assignProps(og: OpenGraph) {
const ogType = og && "type" in og ? og.type : undefined;
const keys = getFieldsByOgType(ogType);
for (const k of keys) {
const key = k as keyof ResolvedOpenGraph;
if (key in og && key !== "url") {
const value = og[key];
if (value) {
const arrayValue = resolveAsArrayOrUndefined(value); /// TODO: improve typing inferring
(resolved as any)[key] = arrayValue;
}
}
}
resolved.images = resolveImages(og.images, metadataBase);
}
assignProps(openGraph);
resolved.url = url;
return resolved;
};
const TwitterBasicInfoKeys = [
"site",
"siteId",
"creator",
"creatorId",
"description",
] as const;
export const resolveTwitter: FieldResolverWithMetadataBase<"twitter"> = (
twitter,
metadataBase,
) => {
if (!twitter) return null;
const resolved = {
...twitter,
card: "card" in twitter ? twitter.card : "summary",
} as ResolvedTwitterMetadata;
for (const infoKey of TwitterBasicInfoKeys) {
resolved[infoKey] = twitter[infoKey] || null;
}
resolved.images = resolveImages(twitter.images, metadataBase);
if ("card" in resolved) {
switch (resolved.card) {
case "player": {
resolved.players = resolveAsArrayOrUndefined(resolved.players) || [];
break;
}
case "app": {
resolved.app = resolved.app || {};
break;
}
default:
break;
}
}
return resolved;
};