@xingwangzhe/stalux 1.21.0 → 1.21.2

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.21.0",
3
+ "version": "1.21.2",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -84,6 +84,7 @@
84
84
  "@waline/client": "^3.15.2",
85
85
  "@xingwangzhe/satteri-mermaid": "0.7.3",
86
86
  "@xingwangzhe/satteri-photoswipe": "^0.2.2",
87
+ "@xingwangzhe/stalux": "1.21.0",
87
88
  "@xingwangzhe/tags-cloud": "^1.2.5",
88
89
  "animejs": "^4.5.0",
89
90
  "astro-expressive-code": "^0.44.1",
@@ -8,7 +8,13 @@ import BingClarity from "@components/stalux/analytics/clarity.astro";
8
8
  import "@styles/base/init.css";
9
9
  import Umami from "@components/stalux/analytics/umami.astro";
10
10
  import { langToOpenGraphLocale } from "@utils/i18n";
11
- import { getAuthorData, getHeadData, getPromoteData, getSiteData } from "@utils/config-utils";
11
+ import {
12
+ getAuthorData,
13
+ getHeadData,
14
+ getMediaLinksData,
15
+ getPromoteData,
16
+ getSiteData,
17
+ } from "@utils/config-utils";
12
18
  import { getRouteKind } from "@utils/view-transitions";
13
19
 
14
20
  const configEntries = await getCollection("config");
@@ -16,6 +22,7 @@ const siteConfig = getSiteData(configEntries);
16
22
  const authorConfig = getAuthorData(configEntries);
17
23
  const headConfig = getHeadData(configEntries);
18
24
  const promoteConfig = getPromoteData(configEntries);
25
+ const mediaLinksConfig = getMediaLinksData(configEntries);
19
26
 
20
27
  // Twitter 卡片类型定义
21
28
  type TwitterCardType = "summary" | "summary_large_image";
@@ -35,11 +42,13 @@ interface Props {
35
42
  }
36
43
 
37
44
  const props = Astro.props as Props;
38
- const effectiveTitle = props.title;
45
+ const effectiveTitle = siteConfig.seoTitle || props.title;
39
46
  const effectiveDescription = props.description;
40
47
  const isArticle = props.isArticle ?? false;
41
48
 
42
49
  const canonicalBase = siteConfig.canonical || siteConfig.url;
50
+ const siteUrl = new URL(canonicalBase || Astro.url.origin).href.replace(/\/$/, "");
51
+ const siteName = siteConfig.title || effectiveTitle;
43
52
  const canonicalUrl = canonicalBase
44
53
  ? new URL(Astro.url.pathname, `${canonicalBase.replace(/\/$/, "")}/`).href
45
54
  : new URL(Astro.url.pathname, Astro.url).href;
@@ -71,6 +80,7 @@ const openGraphConfig: Record<string, unknown> = {
71
80
  optional: {
72
81
  description: effectiveDescription,
73
82
  locale: langToOpenGraphLocale(siteConfig.lang || "zh-CN"),
83
+ siteName,
74
84
  },
75
85
  image: {
76
86
  url: ogImagePath,
@@ -132,10 +142,18 @@ const extendedMeta = [
132
142
  ];
133
143
 
134
144
  let schema: Record<string, unknown>;
135
- const siteUrl = canonicalBase || Astro.url.origin;
145
+ const sameAs = mediaLinksConfig?.items
146
+ .map((item) => item.link)
147
+ .filter((link) => /^https?:\/\//i.test(link));
148
+ const authorEntity = {
149
+ "@type": "Person",
150
+ name: authorConfig.name,
151
+ ...(toAbsolute(authorConfig.avatar) ? { image: toAbsolute(authorConfig.avatar) } : {}),
152
+ ...(sameAs.length ? { sameAs } : {}),
153
+ };
136
154
  const publisher = {
137
155
  "@type": "Organization",
138
- name: siteConfig.title || effectiveTitle,
156
+ name: siteName,
139
157
  url: siteUrl,
140
158
  ...(authorConfig.avatar ? { logo: toAbsolute(authorConfig.avatar) } : {}),
141
159
  };
@@ -150,7 +168,7 @@ if (isArticle) {
150
168
  ...(props.date ? { datePublished: props.date } : {}),
151
169
  ...(props.updated || props.date ? { dateModified: props.updated || props.date } : {}),
152
170
  ...(props.tags?.length ? { keywords: props.tags.join(", ") } : {}),
153
- ...(props.author ? { author: { "@type": "Person", name: props.author } } : {}),
171
+ author: props.author ? { ...authorEntity, name: props.author } : authorEntity,
154
172
  publisher,
155
173
  inLanguage: siteConfig.lang || "zh-CN",
156
174
  mainEntityOfPage: {
@@ -167,6 +185,7 @@ if (isArticle) {
167
185
  description: effectiveDescription,
168
186
  inLanguage: siteConfig.lang || "zh-CN",
169
187
  publisher,
188
+ author: authorEntity,
170
189
  };
171
190
  } else {
172
191
  schema = {
@@ -176,7 +195,7 @@ if (isArticle) {
176
195
  name: effectiveTitle,
177
196
  description: effectiveDescription,
178
197
  inLanguage: siteConfig.lang || "zh-CN",
179
- isPartOf: { "@type": "WebSite", url: siteUrl, name: siteConfig.title },
198
+ isPartOf: { "@type": "WebSite", url: siteUrl, name: siteName },
180
199
  };
181
200
  }
182
201
  const ldJson = JSON.stringify(schema, null, 2).replace(/<\//g, "<\\/");
@@ -1,9 +1,11 @@
1
1
  ---
2
2
  import { getCollection } from "astro:content";
3
+ import { createTranslator } from "@utils/i18n";
3
4
  const configEntries = await getCollection("config");
4
5
  const siteConfig = getSiteData(configEntries);
5
6
  const siteTitle = siteConfig.title;
6
7
  const siteDescription = siteConfig.description;
8
+ const { t } = createTranslator(siteConfig.lang || "zh-CN");
7
9
  import Stalux from "@layouts/Stalux.astro";
8
10
  import styles from "@styles/pages/home.module.css";
9
11
  import Navs from "@components/stalux/layout/navs.astro";
@@ -21,6 +23,7 @@ import { getSiteData, getAuthorData, getHeadData, getNavsData, getLinksData, get
21
23
  <div class={styles.homeNavs}>
22
24
  <Navs />
23
25
  </div>
26
+ <h2 class="sr-only" style="position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0,0,0,0);white-space:nowrap;border:0;">{t("ai.about")}</h2>
24
27
  <Author />
25
28
  <TextType />
26
29
  <DateTime />
@@ -16,6 +16,7 @@ export const siteSchema = z.object({
16
16
  title: z.string().min(1, "site.title is required"),
17
17
  url: z.string().url("site.url must be a valid URL"),
18
18
  description: z.string().min(1, "site.description is required"),
19
+ seoTitle: z.string().min(1).optional(),
19
20
  timezone: z.string().optional().default("Asia/Shanghai"),
20
21
  canonical: z.string().url("site.canonical must be a valid URL").optional(),
21
22
  twitterSite: z.string().optional(),