* style: better reply button. * feat: add astro badge. * chore: drop useless styles. * feat: use new options.ts for global configuration. * fix: the invalid import.meta.env.PROD in astro build. * feat: move og to new assert prefix. * chore: add better og description. * chore: make sure all the images link could be correctly replaced. * feat: add upyun uploader.
155 lines
3.7 KiB
TypeScript
155 lines
3.7 KiB
TypeScript
// This file is copied from https://github.com/flexdinesh/blogster/blob/main/packages/shared/src/seo.ts
|
|
// I just modified it for my personal needs.
|
|
import { urlJoin } from '@/helpers/tools';
|
|
import options from '@/options';
|
|
|
|
export interface PageMeta {
|
|
title: string;
|
|
description: string;
|
|
baseUrl?: string;
|
|
ogImageUrl?: string;
|
|
ogImageAltText: string;
|
|
ogImageWidth?: number;
|
|
ogImageHeight?: number;
|
|
siteOwnerTwitterHandle?: string;
|
|
contentAuthorTwitterHandle?: string;
|
|
}
|
|
|
|
export interface PostMeta {
|
|
title: string;
|
|
description: string;
|
|
pageUrl?: string;
|
|
authorName?: string;
|
|
publishDate: string;
|
|
ogImageUrl?: string;
|
|
ogImageAltText: string;
|
|
ogImageWidth?: number;
|
|
ogImageHeight?: number;
|
|
siteOwnerTwitterHandle?: string;
|
|
contentAuthorTwitterHandle?: string;
|
|
}
|
|
|
|
export interface TwitterOgMeta {
|
|
title: string;
|
|
description?: string;
|
|
card: 'summary_large_image';
|
|
site?: string;
|
|
creator?: string;
|
|
image?: string;
|
|
imageAlt?: string;
|
|
}
|
|
|
|
export interface PageOgMeta {
|
|
title: string;
|
|
description?: string;
|
|
type: 'website';
|
|
url?: string;
|
|
image?: string;
|
|
imageAlt?: string;
|
|
imageWidth?: string;
|
|
imageHeight?: string;
|
|
}
|
|
|
|
export interface PostOgMeta {
|
|
title: string;
|
|
description?: string;
|
|
type: 'article';
|
|
url?: string;
|
|
author?: string;
|
|
siteName?: string;
|
|
publishDate: string;
|
|
image?: string;
|
|
imageAlt?: string;
|
|
imageWidth?: string;
|
|
imageHeight?: string;
|
|
}
|
|
|
|
const parseOgImageUrl = (ogImageUrl?: string): string =>
|
|
typeof ogImageUrl === 'undefined'
|
|
? options.defaultOpenGraph()
|
|
: ogImageUrl.startsWith('/')
|
|
? urlJoin(options.assetsPrefix(), ogImageUrl)
|
|
: ogImageUrl;
|
|
|
|
export const getPageMeta = ({
|
|
title,
|
|
description,
|
|
baseUrl,
|
|
ogImageUrl,
|
|
ogImageAltText,
|
|
ogImageWidth,
|
|
ogImageHeight,
|
|
siteOwnerTwitterHandle,
|
|
contentAuthorTwitterHandle,
|
|
}: PageMeta): { og: PageOgMeta; twitter: TwitterOgMeta } => {
|
|
if (!title) {
|
|
throw Error('title is required for page SEO');
|
|
}
|
|
const ogImageAbsoluteUrl = parseOgImageUrl(ogImageUrl);
|
|
|
|
return {
|
|
og: {
|
|
title: title,
|
|
description: description,
|
|
type: 'website',
|
|
url: baseUrl,
|
|
image: ogImageAbsoluteUrl,
|
|
imageAlt: ogImageAltText,
|
|
imageWidth: ogImageWidth ? String(ogImageWidth) : undefined,
|
|
imageHeight: ogImageHeight ? String(ogImageHeight) : undefined,
|
|
},
|
|
twitter: {
|
|
title: title,
|
|
description: description,
|
|
card: 'summary_large_image',
|
|
site: siteOwnerTwitterHandle,
|
|
creator: contentAuthorTwitterHandle || siteOwnerTwitterHandle,
|
|
image: ogImageAbsoluteUrl,
|
|
imageAlt: ogImageAltText,
|
|
},
|
|
};
|
|
};
|
|
|
|
export const getBlogPostMeta = ({
|
|
title,
|
|
description,
|
|
pageUrl,
|
|
authorName,
|
|
publishDate,
|
|
ogImageUrl,
|
|
ogImageAltText,
|
|
ogImageWidth,
|
|
ogImageHeight,
|
|
siteOwnerTwitterHandle,
|
|
contentAuthorTwitterHandle,
|
|
}: PostMeta): { og: PostOgMeta; twitter: TwitterOgMeta } => {
|
|
if (!title) {
|
|
throw Error('title is required for page SEO');
|
|
}
|
|
const ogImageAbsoluteUrl = parseOgImageUrl(ogImageUrl);
|
|
|
|
return {
|
|
og: {
|
|
title: title,
|
|
description: description,
|
|
type: 'article',
|
|
url: pageUrl,
|
|
author: authorName,
|
|
publishDate: publishDate,
|
|
image: ogImageAbsoluteUrl,
|
|
imageAlt: ogImageAltText,
|
|
imageWidth: ogImageWidth ? String(ogImageWidth) : undefined,
|
|
imageHeight: ogImageHeight ? String(ogImageHeight) : undefined,
|
|
},
|
|
twitter: {
|
|
title: title,
|
|
description: description,
|
|
card: 'summary_large_image',
|
|
site: siteOwnerTwitterHandle,
|
|
creator: contentAuthorTwitterHandle || siteOwnerTwitterHandle,
|
|
image: ogImageAbsoluteUrl,
|
|
imageAlt: ogImageAltText,
|
|
},
|
|
};
|
|
};
|