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.
124 lines
3 KiB
TypeScript
124 lines
3 KiB
TypeScript
import React from "react";
|
|
|
|
export function Meta({
|
|
name,
|
|
property,
|
|
content,
|
|
media,
|
|
}: {
|
|
name?: string;
|
|
property?: string;
|
|
media?: string;
|
|
content: string | number | URL | null | undefined;
|
|
}): React.ReactElement | null {
|
|
if (typeof content !== "undefined" && content !== null && content !== "") {
|
|
return (
|
|
<meta
|
|
{...(name ? { name } : { property })}
|
|
{...(media ? { media } : undefined)}
|
|
content={typeof content === "string" ? content : content.toString()}
|
|
/>
|
|
);
|
|
}
|
|
return null;
|
|
}
|
|
|
|
type ExtendMetaContent = Record<
|
|
string,
|
|
undefined | string | URL | number | boolean | null | undefined
|
|
>;
|
|
type MultiMetaContent =
|
|
| (ExtendMetaContent | string | URL | number)[]
|
|
| null
|
|
| undefined;
|
|
|
|
function camelToSnake(camelCaseStr: string) {
|
|
return camelCaseStr.replace(/([A-Z])/g, function (match) {
|
|
return "_" + match.toLowerCase();
|
|
});
|
|
}
|
|
|
|
function getMetaKey(prefix: string, key: string) {
|
|
// Use `twitter:image` and `og:image` instead of `twitter:image:url` and `og:image:url`
|
|
// to be more compatible as it's a more common format
|
|
if ((prefix === "og:image" || prefix === "twitter:image") && key === "url") {
|
|
return prefix;
|
|
}
|
|
if (prefix.startsWith("og:") || prefix.startsWith("twitter:")) {
|
|
key = camelToSnake(key);
|
|
}
|
|
return prefix + ":" + key;
|
|
}
|
|
|
|
function ExtendMeta({
|
|
content,
|
|
namePrefix,
|
|
propertyPrefix,
|
|
}: {
|
|
content?: ExtendMetaContent;
|
|
namePrefix?: string;
|
|
propertyPrefix?: string;
|
|
}) {
|
|
const keyPrefix = namePrefix || propertyPrefix;
|
|
if (!content) return null;
|
|
return (
|
|
<React.Fragment>
|
|
{Object.entries(content).map(([k, v], index) => {
|
|
return typeof v === "undefined" ? null : (
|
|
<Meta
|
|
key={keyPrefix + ":" + k + "_" + index}
|
|
{...(propertyPrefix && { property: getMetaKey(propertyPrefix, k) })}
|
|
{...(namePrefix && { name: getMetaKey(namePrefix, k) })}
|
|
content={typeof v === "string" ? v : v?.toString()}
|
|
/>
|
|
);
|
|
})}
|
|
</React.Fragment>
|
|
);
|
|
}
|
|
|
|
export function MultiMeta({
|
|
propertyPrefix,
|
|
namePrefix,
|
|
contents,
|
|
}: {
|
|
propertyPrefix?: string;
|
|
namePrefix?: string;
|
|
contents?: MultiMetaContent | null;
|
|
}) {
|
|
if (typeof contents === "undefined" || contents === null) {
|
|
return null;
|
|
}
|
|
|
|
const keyPrefix = propertyPrefix || namePrefix;
|
|
return (
|
|
<>
|
|
{contents.map((content, index) => {
|
|
if (
|
|
typeof content === "string" ||
|
|
typeof content === "number" ||
|
|
content instanceof URL
|
|
) {
|
|
return (
|
|
<Meta
|
|
key={keyPrefix + "_" + index}
|
|
{...(propertyPrefix
|
|
? { property: propertyPrefix }
|
|
: { name: namePrefix })}
|
|
content={content}
|
|
/>
|
|
);
|
|
} else {
|
|
return (
|
|
<ExtendMeta
|
|
key={keyPrefix + "_" + index}
|
|
namePrefix={namePrefix}
|
|
propertyPrefix={propertyPrefix}
|
|
content={content}
|
|
/>
|
|
);
|
|
}
|
|
})}
|
|
</>
|
|
);
|
|
}
|