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)
+}