From 6105577adde41301cc173e7a955b106ce47f1fe1 Mon Sep 17 00:00:00 2001 From: Kero Date: Sun, 26 Jul 2026 07:56:47 +0000 Subject: [PATCH] =?UTF-8?q?SEO=20=E4=BC=98=E5=8C=96=EF=BC=9A=E8=A1=A5?= =?UTF-8?q?=E5=85=A8=20canonical=E3=80=81og:image=E3=80=81JSON-LD=20?= =?UTF-8?q?=E5=8F=8A=E9=A1=B5=E9=9D=A2=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Layout.astro: - 新增 ,og:url / twitter:url 统一使用规范链接 - 新增 og:image / twitter:image:文章封面为绝对或 public URL 时使用封面, 否则回退站点 favicon-192 并将 twitter:card 从 summary_large_image 降级为 summary,避免声明大图卡片却无图 - banner 判断改用 typeof 收窄,兼容 404 页传入 banner={false} 的情况 posts/[...slug].astro (JSON-LD BlogPosting): - 新增 dateModified(读取 frontmatter 的 updated 字段) - 新增 image(仅绝对 URL 封面)和 mainEntityOfPage - 移除遗留的 TODO 注释 页面 meta description: - archive / friends / expenses / series 四个页面补充独立描述, 不再退化为用页面标题填充 astro.config.mjs: - sitemap 增加 filter 排除 /archive/,与 robots.txt 的 Disallow: /archive/ 保持一致,消除收录信号矛盾 --- astro.config.mjs | 4 +++- src/layouts/Layout.astro | 24 +++++++++++++++++++++--- src/pages/archive.astro | 3 ++- src/pages/expenses.astro | 2 +- src/pages/friends.astro | 2 +- src/pages/posts/[...slug].astro | 14 +++++++++++++- src/pages/series.astro | 2 +- 7 files changed, 42 insertions(+), 9 deletions(-) diff --git a/astro.config.mjs b/astro.config.mjs index 6597c0e..698e34c 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -102,7 +102,9 @@ export default defineConfig({ } }), svelte(), - sitemap(), + sitemap({ + filter: (page) => !page.includes("/archive/"), + }), ], markdown: { remarkPlugins: [ diff --git a/src/layouts/Layout.astro b/src/layouts/Layout.astro index a11603f..143cb2b 100644 --- a/src/layouts/Layout.astro +++ b/src/layouts/Layout.astro @@ -30,6 +30,21 @@ interface Props { let { title, banner, description, lang, setOGTypeArticle } = Astro.props; +// canonical URL +const canonicalUrl = new URL(Astro.url.pathname, Astro.site).href; + +// social share image: use the page's own image if it's an absolute or public URL, +// otherwise fall back to the site favicon with a smaller "summary" card +let ogImage: string | undefined; +if (typeof banner === "string" && /^https?:\/\//.test(banner)) { + ogImage = banner; +} else if (typeof banner === "string" && banner.startsWith("/")) { + ogImage = new URL(url(banner), Astro.site).href; +} +const twitterCard = ogImage ? "summary_large_image" : "summary"; +const ogImageUrl = + ogImage ?? new URL(url("/favicon/favicon-light-192.png"), Astro.site).href; + // apply a class to the body element to decide the height of the banner, only used for initial page load // Swup can update the body for each page visit, but it's after the page transition, causing a delay for banner height change // so use Swup hooks instead to change the height immediately when a link is clicked @@ -83,21 +98,24 @@ const bannerOffset = + - + + {setOGTypeArticle ? ( ) : ( )} - - + + + diff --git a/src/pages/archive.astro b/src/pages/archive.astro index 90ede24..8b0111e 100644 --- a/src/pages/archive.astro +++ b/src/pages/archive.astro @@ -3,12 +3,13 @@ import ArchivePanel from "@components/ArchivePanel.svelte"; import I18nKey from "@i18n/i18nKey"; import { i18n } from "@i18n/translation"; import MainGridLayout from "@layouts/MainGridLayout.astro"; +import { siteConfig } from "@/config"; import { getSortedPostsList } from "../utils/content-utils"; const sortedPostsList = await getSortedPostsList(); --- - + diff --git a/src/pages/expenses.astro b/src/pages/expenses.astro index e7413bc..3a0ab2c 100644 --- a/src/pages/expenses.astro +++ b/src/pages/expenses.astro @@ -56,7 +56,7 @@ const historyData = [ ]; --- - +
diff --git a/src/pages/friends.astro b/src/pages/friends.astro index e6b3b59..3d8133e 100644 --- a/src/pages/friends.astro +++ b/src/pages/friends.astro @@ -66,7 +66,7 @@ const friends = [ ]; --- - +
diff --git a/src/pages/posts/[...slug].astro b/src/pages/posts/[...slug].astro index 3248e1a..85b467d 100644 --- a/src/pages/posts/[...slug].astro +++ b/src/pages/posts/[...slug].astro @@ -28,6 +28,11 @@ const { Content, headings } = await entry.render(); const { remarkPluginFrontmatter } = await entry.render(); +const postUrl = new URL(getPostUrlBySlug(entry.slug), Astro.site).href; +const coverImage = /^https?:\/\//.test(entry.data.image) + ? entry.data.image + : undefined; + const jsonLd = { "@context": "https://schema.org", "@type": "BlogPosting", @@ -40,10 +45,17 @@ const jsonLd = { url: Astro.site, }, datePublished: formatDateToYYYYMMDD(entry.data.published), + ...(entry.data.updated && { + dateModified: formatDateToYYYYMMDD(entry.data.updated), + }), + ...(coverImage && { image: coverImage }), + mainEntityOfPage: { + "@type": "WebPage", + "@id": postUrl, + }, inLanguage: entry.data.lang ? entry.data.lang.replace("_", "-") : siteConfig.lang.replace("_", "-"), - // TODO include cover image here }; --- diff --git a/src/pages/series.astro b/src/pages/series.astro index 6a99dce..4ddea04 100644 --- a/src/pages/series.astro +++ b/src/pages/series.astro @@ -5,6 +5,6 @@ import { i18n } from '@i18n/translation' import I18nKey from '@i18n/i18nKey' --- - + \ No newline at end of file