diff --git a/src/layouts/Head.astro b/src/layouts/Head.astro index 2432dfc..5cbccae 100644 --- a/src/layouts/Head.astro +++ b/src/layouts/Head.astro @@ -9,13 +9,18 @@ interface Props { } const { postTitle, postDescription, postImage } = Astro.props + const { title, subtitle, description, author, url, favicon } = themeConfig.site const { mode, light: { background: lightMode }, dark: { background: darkMode } } = themeConfig.color -const initMetaTheme = mode === 'dark' ? darkMode : lightMode const { locale, moreLocale } = themeConfig.global const { verification = {}, twitterID = '', googleAnalyticsID = '', umamiAnalyticsID = '' } = themeConfig.seo ?? {} const { google = '', bing = '', yandex = '', baidu = '' } = verification const { commentURL = '', imageHostURL = '', customGoogleAnalyticsJS = '', customUmamiAnalyticsJS = '' } = themeConfig.preload + +const initMetaTheme = mode === 'dark' ? darkMode : lightMode +const pageTitle = postTitle ? `${postTitle} | ${title}` : `${title} - ${subtitle}` +const pageDescription = postDescription || description +const pageImage = postImage || favicon --- @@ -25,8 +30,8 @@ const { commentURL = '', imageHostURL = '', customGoogleAnalyticsJS = '', custom {favicon.toLowerCase().endsWith('.webp') && } {favicon.toLowerCase().endsWith('.svg') && } {favicon.toLowerCase().endsWith('.png') && } -{postTitle ? `${postTitle} | ${title}` : `${title} - ${subtitle}`} - +{pageTitle} + @@ -52,18 +57,18 @@ const { commentURL = '', imageHostURL = '', customGoogleAnalyticsJS = '', custom ))} - + - + - + - - - + + + {twitterID && ( <> diff --git a/src/pages/posts/[slug].astro b/src/pages/posts/[slug].astro index 19bfc59..997d5dc 100644 --- a/src/pages/posts/[slug].astro +++ b/src/pages/posts/[slug].astro @@ -3,6 +3,7 @@ import Comments from '@/components/Comments/index.astro' import PostTime from '@/components/PostTime.astro' import Layout from '@/layouts/Layout.astro' import { checkSlugDuplication } from '@/utils/content' +import { generateDescription } from '@/utils/description' import { generatePostPaths } from '@/utils/i18n/route' import { getCollection } from 'astro:content' @@ -18,12 +19,13 @@ export async function getStaticPaths() { } const { post } = Astro.props +const description = generateDescription(post) const { Content, remarkPluginFrontmatter } = await post.render() ---
diff --git a/src/utils/description.ts b/src/utils/description.ts new file mode 100644 index 0000000..361b115 --- /dev/null +++ b/src/utils/description.ts @@ -0,0 +1,34 @@ +import type { CollectionEntry } from 'astro:content' +import MarkdownIt from 'markdown-it' +import sanitizeHtml from 'sanitize-html' + +const parser = new MarkdownIt() + +// Generate an excerpt from Markdown content +export function generateExcerpt(content: string, length: number = 100): string { + if (!content) + return '' + + // Convert Markdown to plain text + const plainText = sanitizeHtml(parser.render(content), { + allowedTags: [], + allowedAttributes: {}, + }) + + // Replace line breaks with spaces + const normalizedText = plainText.replace(/\s+/g, ' ') + const excerpt = normalizedText.slice(0, length).trim() + // Add ellipsis if text was truncated + const needsEllipsis = normalizedText.length > length + return needsEllipsis ? `${excerpt}...` : excerpt +} + +// Automatically generate a description for the article +export function generateDescription(post: CollectionEntry<'posts'>): string { + // If the article already has a description, return it directly + if (post.data.description) + return post.data.description + + // Otherwise, generate an excerpt from the article content as the description + return generateExcerpt(post.body) +}