@xingwangzhe/stalux 1.24.3 → 1.24.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.24.3",
3
+ "version": "1.24.4",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -43,8 +43,6 @@ interface Props {
43
43
  }
44
44
 
45
45
  const props = Astro.props as Props;
46
- const effectiveTitle = siteConfig.seoTitle || props.title;
47
- const effectiveDescription = props.description;
48
46
  const isArticle = props.isArticle ?? false;
49
47
 
50
48
  const canonicalBase = siteConfig.canonical || siteConfig.url;
@@ -68,12 +66,20 @@ const isNotFoundPage =
68
66
  Astro.url.pathname === "/404" || Astro.url.pathname === "/404/";
69
67
  const routeKind = getRouteKind(Astro.url.pathname);
70
68
  const isCollectionPage = routeKind.endsWith("-index") || routeKind.endsWith("-detail");
69
+ // seoTitle 是首页的搜索标题,不应覆盖文章/分类等内页标题。
70
+ const effectiveTitle = routeKind === "home" && siteConfig.seoTitle ? siteConfig.seoTitle : props.title;
71
+ const effectiveDescription = props.description;
72
+ const siteTitleSuffix = siteConfig.title ? ` | ${siteConfig.title}` : "";
73
+ const contentTitle =
74
+ siteTitleSuffix && effectiveTitle.endsWith(siteTitleSuffix)
75
+ ? effectiveTitle.slice(0, -siteTitleSuffix.length)
76
+ : effectiveTitle;
71
77
  const resolvedNoindex = Boolean(siteConfig.noindex) || isNotFoundPage || Boolean(props.noindex);
72
78
  const resolvedNofollow = Boolean(siteConfig.nofollow) || isNotFoundPage;
73
79
 
74
80
  const openGraphConfig: Record<string, unknown> = {
75
81
  basic: {
76
- title: effectiveTitle,
82
+ title: contentTitle,
77
83
  type: isArticle ? "article" : "website",
78
84
  image: ogImagePath,
79
85
  url: canonicalUrl,
@@ -85,7 +91,7 @@ const openGraphConfig: Record<string, unknown> = {
85
91
  },
86
92
  image: {
87
93
  url: ogImagePath,
88
- alt: effectiveTitle,
94
+ alt: contentTitle,
89
95
  },
90
96
  };
91
97
 
@@ -101,11 +107,11 @@ if (isArticle) {
101
107
  }
102
108
 
103
109
  const twitterConfig = {
104
- card: "summary_large_image" as TwitterCardType,
105
- title: effectiveTitle,
110
+ card: (props.cover ? "summary_large_image" : "summary") as TwitterCardType,
111
+ title: contentTitle,
106
112
  description: effectiveDescription,
107
113
  image: ogImagePath,
108
- imageAlt: effectiveTitle,
114
+ imageAlt: contentTitle,
109
115
  ...(siteConfig.twitterSite ? { site: siteConfig.twitterSite } : {}),
110
116
  };
111
117
 
@@ -140,6 +146,14 @@ const extendedLink = [
140
146
  const extendedMeta = [
141
147
  { name: "viewport", content: "width=device-width, initial-scale=1" },
142
148
  { name: "color-scheme", content: "dark" },
149
+ ...(!resolvedNoindex
150
+ ? [
151
+ {
152
+ name: "googlebot",
153
+ content: "max-image-preview:large, max-snippet:-1, max-video-preview:-1",
154
+ },
155
+ ]
156
+ : []),
143
157
  ];
144
158
 
145
159
  let schema: Record<string, unknown>;
@@ -148,55 +162,111 @@ const sameAs = mediaLinksConfig?.items
148
162
  .filter((link) => /^https?:\/\//i.test(link));
149
163
  const authorEntity = {
150
164
  "@type": "Person",
165
+ "@id": `${siteUrl}/#author`,
151
166
  name: authorConfig.name,
167
+ url: `${siteUrl}/about/`,
152
168
  ...(toAbsolute(authorConfig.avatar) ? { image: toAbsolute(authorConfig.avatar) } : {}),
153
169
  ...(sameAs.length ? { sameAs } : {}),
154
170
  };
155
171
  const publisher = {
156
172
  "@type": "Organization",
173
+ "@id": `${siteUrl}/#publisher`,
157
174
  name: siteName,
158
175
  url: siteUrl,
159
176
  ...(authorConfig.avatar ? { logo: toAbsolute(authorConfig.avatar) } : {}),
160
177
  };
178
+ const websiteEntity = {
179
+ "@type": "WebSite",
180
+ "@id": `${siteUrl}/#website`,
181
+ url: `${siteUrl}/`,
182
+ name: siteName,
183
+ description: siteConfig.description,
184
+ inLanguage: siteConfig.lang || "zh-CN",
185
+ publisher: { "@id": `${siteUrl}/#publisher` },
186
+ };
187
+ const breadcrumbItems: Record<string, unknown>[] = [
188
+ {
189
+ "@type": "ListItem",
190
+ position: 1,
191
+ name: siteName,
192
+ item: `${siteUrl}/`,
193
+ },
194
+ ];
195
+ if (isArticle && props.categories?.[0]) {
196
+ breadcrumbItems.push({
197
+ "@type": "ListItem",
198
+ position: breadcrumbItems.length + 1,
199
+ name: props.categories[0],
200
+ item: `${siteUrl}/categories/${encodeURIComponent(props.categories[0])}/`,
201
+ });
202
+ }
203
+ if (routeKind !== "home") {
204
+ breadcrumbItems.push({
205
+ "@type": "ListItem",
206
+ position: breadcrumbItems.length + 1,
207
+ name: contentTitle,
208
+ item: canonicalUrl,
209
+ });
210
+ }
211
+ const breadcrumbEntity = {
212
+ "@type": "BreadcrumbList",
213
+ "@id": `${canonicalUrl}#breadcrumb`,
214
+ itemListElement: breadcrumbItems,
215
+ };
161
216
  if (isArticle) {
162
217
  schema = {
163
218
  "@context": "https://schema.org",
164
- "@type": "BlogPosting",
165
- headline: effectiveTitle,
166
- description: effectiveDescription,
167
- url: canonicalUrl,
168
- ...(ogImagePath ? { image: ogImagePath } : {}),
169
- ...(props.date ? { datePublished: props.date } : {}),
170
- ...(props.updated || props.date ? { dateModified: props.updated || props.date } : {}),
171
- ...(props.tags?.length ? { keywords: props.tags.join(", ") } : {}),
172
- author: props.author ? { ...authorEntity, name: props.author } : authorEntity,
173
- publisher,
174
- inLanguage: siteConfig.lang || "zh-CN",
175
- mainEntityOfPage: {
176
- "@type": "WebPage",
177
- "@id": canonicalUrl,
178
- },
219
+ "@graph": [
220
+ websiteEntity,
221
+ authorEntity,
222
+ publisher,
223
+ breadcrumbEntity,
224
+ {
225
+ "@type": "BlogPosting",
226
+ "@id": `${canonicalUrl}#article`,
227
+ headline: contentTitle,
228
+ description: effectiveDescription,
229
+ url: canonicalUrl,
230
+ ...(ogImagePath ? { image: ogImagePath } : {}),
231
+ ...(props.date ? { datePublished: props.date } : {}),
232
+ ...(props.updated || props.date ? { dateModified: props.updated || props.date } : {}),
233
+ ...(props.tags?.length ? { keywords: props.tags.join(", ") } : {}),
234
+ ...(props.categories?.length ? { articleSection: props.categories } : {}),
235
+ author: { "@id": `${siteUrl}/#author`, ...(props.author ? { name: props.author } : {}) },
236
+ publisher: { "@id": `${siteUrl}/#publisher` },
237
+ isPartOf: { "@id": `${siteUrl}/#website` },
238
+ inLanguage: siteConfig.lang || "zh-CN",
239
+ mainEntityOfPage: {
240
+ "@type": "WebPage",
241
+ "@id": canonicalUrl,
242
+ },
243
+ },
244
+ ],
179
245
  };
180
246
  } else if (routeKind === "home") {
181
247
  schema = {
182
248
  "@context": "https://schema.org",
183
- "@type": "WebSite",
184
- url: canonicalUrl,
185
- name: effectiveTitle,
186
- description: effectiveDescription,
187
- inLanguage: siteConfig.lang || "zh-CN",
188
- publisher,
189
- author: authorEntity,
249
+ "@graph": [websiteEntity, authorEntity, publisher],
190
250
  };
191
251
  } else {
192
252
  schema = {
193
253
  "@context": "https://schema.org",
194
- "@type": isCollectionPage ? "CollectionPage" : routeKind === "about" ? "AboutPage" : "WebPage",
195
- url: canonicalUrl,
196
- name: effectiveTitle,
197
- description: effectiveDescription,
198
- inLanguage: siteConfig.lang || "zh-CN",
199
- isPartOf: { "@type": "WebSite", url: siteUrl, name: siteName },
254
+ "@graph": [
255
+ websiteEntity,
256
+ authorEntity,
257
+ publisher,
258
+ breadcrumbEntity,
259
+ {
260
+ "@type": isCollectionPage ? "CollectionPage" : routeKind === "about" ? "AboutPage" : "WebPage",
261
+ "@id": canonicalUrl,
262
+ url: canonicalUrl,
263
+ name: contentTitle,
264
+ description: effectiveDescription,
265
+ inLanguage: siteConfig.lang || "zh-CN",
266
+ isPartOf: { "@id": `${siteUrl}/#website` },
267
+ breadcrumb: { "@id": `${canonicalUrl}#breadcrumb` },
268
+ },
269
+ ],
200
270
  };
201
271
  }
202
272
  const ldJson = JSON.stringify(schema, null, 2).replace(/<\//g, "<\\/");
@@ -233,4 +303,3 @@ const ldJson = JSON.stringify(schema, null, 2).replace(/<\//g, "<\\/");
233
303
  <script type="application/ld+json" set:html={ldJson} />
234
304
  <VerCount />
235
305
  </head>
236
-
@@ -7,17 +7,16 @@ import { getSiteData, getLinksData } from "@utils/config-utils";
7
7
  const configEntries = await getCollection("config");
8
8
  const siteConfig = getSiteData(configEntries);
9
9
  const linksConfig = getLinksData(configEntries)!;
10
- const siteTitle = siteConfig.title;
11
10
  const siteDescription = siteConfig.description;
12
11
  const linksTitle = linksConfig.title;
13
12
  const linksDescription = linksConfig.description;
14
13
  ---
15
14
 
16
- <ListPage
17
- title={siteTitle}
18
- description={siteDescription}
19
- heading={linksTitle}
20
- subheading={linksDescription}
21
- >
15
+ <ListPage
16
+ title={linksTitle}
17
+ description={linksDescription || siteDescription}
18
+ heading={linksTitle}
19
+ subheading={linksDescription}
20
+ >
22
21
  <LinkList />
23
22
  </ListPage>