@xingwangzhe/stalux 1.55.4 → 1.55.6

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.
Files changed (53) hide show
  1. package/package.json +1 -1
  2. package/src/components/stalux/archives/archivesList.astro +60 -60
  3. package/src/components/stalux/archives/toArchive.astro +3 -2
  4. package/src/components/stalux/categories/categoriesCard.astro +34 -34
  5. package/src/components/stalux/categories/categoriesList.astro +3 -1
  6. package/src/components/stalux/common/Typewriter.astro +3 -2
  7. package/src/components/stalux/common/Weather.astro +3 -2
  8. package/src/components/stalux/common/date.astro +16 -12
  9. package/src/components/stalux/common/search.astro +3 -2
  10. package/src/components/stalux/footer/FooterBadges.astro +34 -24
  11. package/src/components/stalux/footer/FooterBeian.astro +3 -2
  12. package/src/components/stalux/footer/FooterStats.astro +3 -2
  13. package/src/components/stalux/footer/FooterThemeInfo.astro +3 -2
  14. package/src/components/stalux/layout/PageHeading.astro +5 -4
  15. package/src/components/stalux/layout/navs.astro +4 -3
  16. package/src/components/stalux/links/linkCard.astro +8 -6
  17. package/src/components/stalux/links/socialMedia.astro +2 -2
  18. package/src/components/stalux/posts/PostTaxonomy.astro +14 -11
  19. package/src/components/stalux/posts/WalineComment.astro +2 -2
  20. package/src/components/stalux/posts/postAuthor.astro +6 -6
  21. package/src/components/stalux/posts/postCC.astro +9 -7
  22. package/src/components/stalux/posts/postCard.astro +70 -72
  23. package/src/components/stalux/posts/postContent.astro +7 -6
  24. package/src/components/stalux/posts/postLeft.astro +7 -6
  25. package/src/components/stalux/posts/postList.astro +3 -2
  26. package/src/components/stalux/posts/postNavigation.astro +112 -106
  27. package/src/components/stalux/posts/postRight.astro +10 -8
  28. package/src/components/stalux/posts/postToc.astro +1 -1
  29. package/src/components/stalux/posts/randomPost.astro +3 -2
  30. package/src/components/stalux/tags/tagsCloud.astro +29 -21
  31. package/src/components/stalux/words/wordCard.astro +6 -4
  32. package/src/internal/style-names.generated.ts +224 -219
  33. package/src/pages/404.astro +4 -2
  34. package/src/pages/about.astro +3 -3
  35. package/src/pages/categories/[category].astro +2 -2
  36. package/src/pages/index.astro +9 -4
  37. package/src/pages/posts/[post].astro +0 -1
  38. package/src/pages/tags/[tag].astro +2 -2
  39. package/src/scripts/date-time.ts +15 -7
  40. package/src/scripts/random-posts.ts +26 -11
  41. package/src/styles/base.css +34 -20
  42. package/src/styles/content.css +16 -8
  43. package/src/styles/generated-archives.css +1 -1
  44. package/src/styles/generated-article.css +1 -1
  45. package/src/styles/generated-cards.css +1 -1
  46. package/src/styles/generated-categories.css +1 -1
  47. package/src/styles/generated-home.css +1 -1
  48. package/src/styles/generated-links.css +1 -1
  49. package/src/styles/generated-prose.css +1 -1
  50. package/src/styles/generated-tags.css +1 -1
  51. package/src/styles/generated-words.css +1 -1
  52. package/src/styles/generated.css +1 -1
  53. package/src/styles/module-motion.css +1 -1
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.55.4",
3
+ "version": "1.55.6",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -57,76 +57,76 @@ const archiveYears = [...archivesByYearMonth.entries()]
57
57
  ---
58
58
 
59
59
  <section class="stalux-archive-container" data-stalux-motion-content data-stalux-motion-stage>
60
- <div class="stalux-archive-page-header">
61
- <div class="stalux-archive-timeline-container">
62
- {archiveYears.length > 0 ? (
63
- archiveYears.map((archiveYear) => (
64
- <div class="stalux-archive-year-section" data-year={String(archiveYear.year)}>
65
- <div class="stalux-archive-year-header">
66
- <h2 class="stalux-archive-year-title">{archiveYear.year}</h2>
67
- <div class="stalux-archive-year-count">
68
- {t("archives.postCount", { n: archiveYear.count })}
69
- </div>
70
- </div>
71
- {archiveYear.months.map(({ month, posts: monthPosts }) => (
72
- <div class="stalux-archive-month-section" data-archive-month>
73
- <h3 class="stalux-archive-month-title">
74
- {t("archives.month", { n: month })}
75
- </h3>
76
- {Array.from(
77
- { length: Math.ceil(monthPosts.length / 12) },
78
- (_, index) => monthPosts.slice(index * 12, (index + 1) * 12),
79
- ).map((group) => (
80
- <ul class="stalux-archive-post-list" data-stalux-reveal>
81
- {group.map((post) => (
82
- <li
83
- class="stalux-archive-post-item"
84
- data-stalux-reveal-item
60
+ <!-- Modern Web Guidance (html): 年份/月份是带标题的内容分组 => <section> + <header>;
61
+ 文章条目用 <ul>/<li>;计数与空态是纯文字 => <p>。
62
+ 仅剩的 <div> 是时间轴装饰容器(::before 画线 + --tl-* 变量),没有语义对等元素。 -->
63
+ <div class="stalux-archive-timeline-container stalux-archive-page-header">
64
+ {archiveYears.length > 0 ? (
65
+ archiveYears.map((archiveYear) => (
66
+ <section class="stalux-archive-year-section" data-year={String(archiveYear.year)}>
67
+ <header class="stalux-archive-year-header">
68
+ <h2 class="stalux-archive-year-title">{archiveYear.year}</h2>
69
+ <p class="stalux-archive-year-count">
70
+ {t("archives.postCount", { n: archiveYear.count })}
71
+ </p>
72
+ </header>
73
+ {archiveYear.months.map(({ month, posts: monthPosts }) => (
74
+ <section class="stalux-archive-month-section" data-archive-month>
75
+ <h3 class="stalux-archive-month-title">
76
+ {t("archives.month", { n: month })}
77
+ </h3>
78
+ {Array.from({ length: Math.ceil(monthPosts.length / 12) }, (_, index) =>
79
+ monthPosts.slice(index * 12, (index + 1) * 12),
80
+ ).map((group) => (
81
+ <ul class="stalux-archive-post-list" data-stalux-reveal>
82
+ {group.map((post) => (
83
+ <li
84
+ class="stalux-archive-post-item"
85
+ data-stalux-reveal-item
86
+ >
87
+ <time
88
+ class="stalux-archive-post-date"
89
+ datetime={toMachineDateTime(
90
+ post.data.date,
91
+ timezone,
92
+ )}
85
93
  >
86
- <time
87
- class="stalux-archive-post-date"
88
- datetime={toMachineDateTime(
89
- post.data.date,
90
- timezone,
91
- )}
92
- >
93
- {formatInTimeZone(
94
- parseDate(post.data.date, timezone),
95
- timezone,
96
- "yyyy-MM-dd",
97
- )}
98
- </time>
99
- <a
100
- href={`/posts/${post.data.abbrlink}/`}
101
- class="stalux-archive-post-link"
102
- data-archive-description={post.data.desc || ""}
103
- data-astro-prefetch="viewport"
104
- >
105
- {post.data.title}
106
- </a>
107
- </li>
108
- ))}
109
- </ul>
110
- ))}
111
- </div>
112
- ))}
113
- </div>
114
- ))
115
- ) : (
116
- <div class="stalux-archive-no-posts">{t("archives.noPosts")}</div>
117
- )}
118
- </div>
94
+ {formatInTimeZone(
95
+ parseDate(post.data.date, timezone),
96
+ timezone,
97
+ "yyyy-MM-dd",
98
+ )}
99
+ </time>
100
+ <a
101
+ href={`/posts/${post.data.abbrlink}/`}
102
+ class="stalux-archive-post-link"
103
+ data-archive-description={post.data.desc || ""}
104
+ data-astro-prefetch="viewport"
105
+ >
106
+ {post.data.title}
107
+ </a>
108
+ </li>
109
+ ))}
110
+ </ul>
111
+ ))}
112
+ </section>
113
+ ))}
114
+ </section>
115
+ ))
116
+ ) : (
117
+ <p class="stalux-archive-no-posts">{t("archives.noPosts")}</p>
118
+ )}
119
119
 
120
120
  <slot name="main" />
121
121
  </div>
122
122
  </section>
123
- <div
123
+ <p
124
124
  id="stalux-archive-description"
125
125
  class="stalux-archive-description"
126
126
  data-archive-tooltip
127
127
  role="tooltip"
128
128
  hidden
129
- ></div>
129
+ ></p>
130
130
 
131
131
  <script>
132
132
  import { mountArchiveDescriptions } from "../../../scripts/archive-descriptions";
@@ -9,6 +9,7 @@ const siteConfig = getSiteData(configEntries);
9
9
  const { t } = createTranslator(siteConfig.lang || "zh-CN");
10
10
  ---
11
11
 
12
- <div id={"stalux-to-archive-archs"}>
12
+ <!-- Modern Web Guidance (html): 一行“查看全部归档”文字 + 链接 => <p>。 -->
13
+ <p id={"stalux-to-archive-archs"}>
13
14
  <a data-stalux-control="button" href="/archives" data-astro-prefetch>{t("archives.viewAll")}</a>
14
- </div>
15
+ </p>
@@ -20,37 +20,37 @@ const siteConfig = (configEntries.find((e) => e.id === "site")?.data ?? {}) as R
20
20
  const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
21
21
  ---
22
22
 
23
- <div class="stalux-category-shell">
24
- <article class="stalux-category-card" data-stalux-control="category-card">
25
- <a
26
- href={`/categories/${props.category.name}/`}
27
- class="stalux-categoryheader a-none"
28
- data-astro-prefetch
29
- >
30
- <div class="stalux-category-icon">
31
- <svg
32
- aria-hidden="true"
33
- xmlns="http://www.w3.org/2000/svg"
34
- viewBox="0 0 24 24"
35
- width="24"
36
- height="24"
37
- fill="none"
38
- stroke="currentColor"
39
- stroke-width="2"
40
- stroke-linecap="round"
41
- stroke-linejoin="round"
42
- >
43
- <path
44
- d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
45
- ></path>
46
- </svg>
47
- </div>
48
- <div class="stalux-category-content">
49
- <h2 class="categoryName">{props.category.name}</h2>
50
- <div class="categoryCount">
51
- {t("categories.postCount", { n: props.category.count })}
52
- </div>
53
- </div>
54
- </a>
55
- </article>
56
- </div>
23
+ <!-- Modern Web Guidance (html): 分类卡本身即 <article>;外层曾经的 <div class="stalux-category-shell">
24
+ 已上移到列表的 <li>(见 categoriesList.astro),避免多一层无语义容器。 -->
25
+ <article class="stalux-category-card" data-stalux-control="category-card">
26
+ <a
27
+ href={`/categories/${props.category.name}/`}
28
+ class="stalux-categoryheader a-none"
29
+ data-astro-prefetch
30
+ >
31
+ <span class="stalux-category-icon">
32
+ <svg
33
+ aria-hidden="true"
34
+ xmlns="http://www.w3.org/2000/svg"
35
+ viewBox="0 0 24 24"
36
+ width="24"
37
+ height="24"
38
+ fill="none"
39
+ stroke="currentColor"
40
+ stroke-width="2"
41
+ stroke-linecap="round"
42
+ stroke-linejoin="round"
43
+ >
44
+ <path
45
+ d="M22 19a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2V5a2 2 0 0 1 2-2h5l2 3h9a2 2 0 0 1 2 2z"
46
+ ></path>
47
+ </svg>
48
+ </span>
49
+ <section class="stalux-category-content">
50
+ <h2 class="categoryName">{props.category.name}</h2>
51
+ <p class="categoryCount">
52
+ {t("categories.postCount", { n: props.category.count })}
53
+ </p>
54
+ </section>
55
+ </a>
56
+ </article>
@@ -14,7 +14,9 @@ const categoryList = await getCategoryCountList(Astro.logger);
14
14
  data-stalux-reveal
15
15
  >
16
16
  {categoryList.map((category) => (
17
- <li data-stalux-reveal-item>
17
+ /* Modern Web Guidance (html): shell 的 hover/focus-within 作用范围由 <li> 承担,
18
+ 卡片组件本身不再输出多余的包裹 <div>。 */
19
+ <li class="stalux-category-shell" data-stalux-reveal-item>
18
20
  <CategoriesCard category={category} />
19
21
  </li>
20
22
  ))}
@@ -10,7 +10,8 @@ const texts = normalizeMessages(messages);
10
10
  ---
11
11
 
12
12
  {texts.length > 0 && (
13
- <div class={className} data-stalux-typewriter data-messages={JSON.stringify(texts)}>
13
+ /* Modern Web Guidance (html): 打字机输出是一段文字 => <p>,内部只用行内 <span>。 */
14
+ <p class={className} data-stalux-typewriter data-messages={JSON.stringify(texts)}>
14
15
  <span class="stalux-typewriter-accessible">{texts.join(", ")}</span>
15
16
  <span class="stalux-typewriter-reserve" aria-hidden="true">
16
17
  {texts.map((text) => (
@@ -20,7 +21,7 @@ const texts = normalizeMessages(messages);
20
21
  <span class="stalux-typewriter-text" data-typewriter-text aria-hidden="true">
21
22
  {texts[0]}
22
23
  </span>
23
- </div>
24
+ </p>
24
25
  )}
25
26
 
26
27
  <script>
@@ -19,10 +19,10 @@ const zh = (site.lang || "zh-CN").startsWith("zh");
19
19
  data-lang={site.lang || "zh-CN"}
20
20
  aria-label={zh ? "附近城市天气" : "Nearby weather"}
21
21
  >
22
- <div class="stalux-weather-heading">
22
+ <p class="stalux-weather-heading">
23
23
  <CloudSun size={18} aria-hidden="true" />
24
24
  <span>{zh ? "附近天气" : "Nearby weather"}</span>
25
- </div>
25
+ </p>
26
26
  <p class="stalux-weather-main" data-weather-output role="status">
27
27
  {zh ? "正在获取附近城市天气…" : "Loading nearby weather…"}
28
28
  </p>
@@ -96,6 +96,7 @@ registerPageLifecycle("weather", () => {
96
96
  display: flex;
97
97
  align-items: center;
98
98
  gap: 0.5rem;
99
+ margin: 0;
99
100
  color: var(--accent-90p);
100
101
  font-size: 0.85rem;
101
102
  }
@@ -1,7 +1,7 @@
1
- <div id={"stalux-date-date-time"} class="date-time">
1
+ <p id={"stalux-date-date-time"} class="date-time">
2
2
  <time id={"stalux-date-date"} data-ref="date" datetime=""></time>
3
3
  <time id={"stalux-date-time"} data-ref="time" datetime=""></time>
4
- </div>
4
+ </p>
5
5
 
6
6
  <script is:inline>
7
7
  (() => {
@@ -11,16 +11,20 @@
11
11
  const now = new Date();
12
12
  const pad = (value) => String(value).padStart(2, "0");
13
13
  const lang = document.documentElement.lang || "zh-CN";
14
- dateElement.textContent = lang.startsWith("zh")
15
- ? `${now.getFullYear()}年${pad(now.getMonth() + 1)}月${pad(now.getDate())}日`
16
- : new Intl.DateTimeFormat("en-US", {
17
- year: "numeric",
18
- month: "short",
19
- day: "2-digit",
20
- }).format(now);
21
- dateElement.dateTime = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
22
- timeElement.textContent = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
23
- timeElement.dateTime = timeElement.textContent;
14
+ const zh = lang.toLowerCase().startsWith("zh");
15
+ // Modern Web Guidance (javascript): 本地化文案交给 Intl.DateTimeFormat,
16
+ // 不再按语言手写拼接年月日;只有机器可读的 datetime 值仍按本地日历拼装。
17
+ dateElement.textContent = new Intl.DateTimeFormat(lang, {
18
+ year: "numeric",
19
+ month: zh ? "long" : "short",
20
+ day: "2-digit",
21
+ }).format(now);
22
+ // datetime 必须是访客本地日历值:toISOString() 给的是 UTC,跨时区会差一天。
23
+ const machineDate = `${now.getFullYear()}-${pad(now.getMonth() + 1)}-${pad(now.getDate())}`;
24
+ dateElement.dateTime = machineDate;
25
+ const machineTime = `${pad(now.getHours())}:${pad(now.getMinutes())}:${pad(now.getSeconds())}`;
26
+ timeElement.textContent = machineTime;
27
+ timeElement.dateTime = machineTime;
24
28
  })();
25
29
  </script>
26
30
 
@@ -5,7 +5,8 @@
5
5
  import { sitePath } from "../../../utils/site-path";
6
6
  ---
7
7
 
8
- <div data-pf-theme="dark">
8
+ <!-- Modern Web Guidance (html): <search> 包裹搜索与过滤机制,自带 search 地标。 -->
9
+ <search data-pf-theme="dark">
9
10
  <pagefind-config bundle-path={sitePath("pagefind-enhanced/")}></pagefind-config>
10
11
  <pagefind-modal id="search"></pagefind-modal>
11
- </div>
12
+ </search>
@@ -42,35 +42,45 @@ function badgeImg(opts: BadgeOptions) {
42
42
  ---
43
43
 
44
44
  {badges && badges.length > 0 && (
45
- <div class="stalux-badges-wrapper stalux-u-flex stalux-u-items-center stalux-u-justify-center stalux-u-flex-wrap">
45
+ /* Modern Web Guidance (html): 徽章集合是一组条目 => <ul>/<li>;分组用原生的
46
+ <details>/<summary> 折叠,无需 ARIA 模拟。 */
47
+ <ul class="stalux-badges-wrapper stalux-u-flex stalux-u-items-center stalux-u-justify-center stalux-u-flex-wrap">
46
48
  {badges.map((item: BadgeItem, idx: number) => {
47
49
  if (isBadgeGroup(item)) {
48
50
  const groupId = `badge-group-${idx}`;
49
51
  return (
50
- <details
51
- data-stalux-module="badge-group"
52
- class="stalux-badge-group stalux-u-w-full badge-group"
53
- id={groupId}
54
- >
55
- <summary class="stalux-badge-group-summary stalux-u-flex stalux-u-items-center stalux-u-justify-center">
56
- <span class="stalux-badge-group-arrow">&#9654;</span>
57
- <span class="stalux-badge-group-title">{item.title}</span>
58
- <span class="stalux-badge-group-hint" data-hint="expanded">
59
- {t("footer.collapse")}
60
- </span>
61
- <span class="stalux-badge-group-hint" data-hint="collapsed">
62
- {t("footer.expand")}
63
- </span>
64
- </summary>
65
- <div class="stalux-badge-group-items stalux-badges stalux-u-flex stalux-u-items-center stalux-u-justify-center stalux-u-flex-wrap">
66
- {item.items.map((b) => (
67
- <Fragment set:html={badgeImg(b)} />
68
- ))}
69
- </div>
70
- </details>
52
+ <li class="stalux-badge-group-item stalux-u-w-full">
53
+ <details
54
+ data-stalux-module="badge-group"
55
+ class="stalux-badge-group stalux-u-w-full badge-group"
56
+ id={groupId}
57
+ >
58
+ <summary class="stalux-badge-group-summary stalux-u-flex stalux-u-items-center stalux-u-justify-center">
59
+ <span class="stalux-badge-group-arrow">&#9654;</span>
60
+ <span class="stalux-badge-group-title">{item.title}</span>
61
+ <span class="stalux-badge-group-hint" data-hint="expanded">
62
+ {t("footer.collapse")}
63
+ </span>
64
+ <span class="stalux-badge-group-hint" data-hint="collapsed">
65
+ {t("footer.expand")}
66
+ </span>
67
+ </summary>
68
+ <ul class="stalux-badge-group-items stalux-badges stalux-u-flex stalux-u-items-center stalux-u-justify-center stalux-u-flex-wrap">
69
+ {item.items.map((b) => (
70
+ <li>
71
+ <Fragment set:html={badgeImg(b)} />
72
+ </li>
73
+ ))}
74
+ </ul>
75
+ </details>
76
+ </li>
71
77
  );
72
78
  }
73
- return <Fragment set:html={badgeImg(item)} />;
79
+ return (
80
+ <li>
81
+ <Fragment set:html={badgeImg(item)} />
82
+ </li>
83
+ );
74
84
  })}
75
- </div>
85
+ </ul>
76
86
  )}
@@ -19,7 +19,8 @@ const showBeian = !!(icp || pubsec);
19
19
  ---
20
20
 
21
21
  {showBeian && (
22
- <div class="stalux-beian-beian-info stalux-u-flex stalux-u-justify-center stalux-u-flex-wrap">
22
+ /* Modern Web Guidance (html): 备案号是一行文字链接 => <p>。 */
23
+ <p class="stalux-beian-beian-info stalux-u-flex stalux-u-justify-center stalux-u-flex-wrap">
23
24
  {icp && (
24
25
  <a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer">
25
26
  {icp}
@@ -41,5 +42,5 @@ const showBeian = !!(icp || pubsec);
41
42
  {pubsec}
42
43
  </a>
43
44
  )}
44
- </div>
45
+ </p>
45
46
  )}
@@ -41,7 +41,8 @@ const machineBuildtime = buildtime
41
41
  )}
42
42
 
43
43
  {machineBuildtime && (
44
- <div
44
+ /* Modern Web Guidance (html): 构建时间是一行统计文字,用 <p> 而非通用 <div>。 */
45
+ <p
45
46
  class="stalux-stats-site-build-time stalux-u-text-center"
46
47
  data-stalux-buildtime={machineBuildtime}
47
48
  data-stalux-runtime-format={t("footer.runtimeFormat")}
@@ -50,5 +51,5 @@ const machineBuildtime = buildtime
50
51
  {t("footer.runningTime")}
51
52
  <span id="runtime-counter" />
52
53
  </span>
53
- </div>
54
+ </p>
54
55
  )}
@@ -9,7 +9,8 @@ const showThemeInfoSection = !!(showPoweredBy || showThemeInfo);
9
9
  ---
10
10
 
11
11
  {showThemeInfoSection && (
12
- <div class="stalux-theme-info stalux-u-flex stalux-u-justify-center stalux-u-flex-wrap">
12
+ /* Modern Web Guidance (html): 一行主题署名文字 => <p>。 */
13
+ <p class="stalux-theme-info stalux-u-flex stalux-u-justify-center stalux-u-flex-wrap">
13
14
  {showPoweredBy && (
14
15
  <span>
15
16
  Powered by
@@ -31,5 +32,5 @@ const showThemeInfoSection = !!(showPoweredBy || showThemeInfo);
31
32
  </a>
32
33
  </span>
33
34
  )}
34
- </div>
35
+ </p>
35
36
  )}
@@ -7,13 +7,14 @@ interface Props {
7
7
  const { heading, description } = Astro.props;
8
8
  ---
9
9
 
10
- <div data-stalux-motion-region>
10
+ <!-- Modern Web Guidance (html): 页面标题块是列表页的 header,描述是 <p>。 -->
11
+ <header data-stalux-motion-region>
11
12
  <h1 class="stalux-page-title stalux-u-text-center" data-stalux-motion-focus>
12
13
  {heading}
13
14
  </h1>
14
15
  {description && (
15
- <div class="stalux-page-description stalux-u-text-center" data-stalux-motion-content>
16
+ <p class="stalux-page-description stalux-u-text-center" data-stalux-motion-content>
16
17
  {description}
17
- </div>
18
+ </p>
18
19
  )}
19
- </div>
20
+ </header>
@@ -67,15 +67,16 @@ const navs = navsConfig?.items ?? [];
67
67
  );
68
68
  })}
69
69
  <li class="stalux-nav-item stalux-u-flex stalux-u-items-center">
70
- <a
71
- href="#search"
70
+ <!-- Modern Web Guidance (html): 页内交互一律用 <button>,<a> 只负责 URL 导航 -->
71
+ <button
72
+ type="button"
72
73
  class="stalux-nav-link"
73
74
  data-ref="stalux-search-btn"
74
75
  aria-label={t("search.title")}
75
76
  >
76
77
  {SearchIcon && <SearchIcon size={20} stroke-width={2} class="nav-icon" />}
77
78
  <span class="stalux-nav-text">{t("nav.search")}</span>
78
- </a>
79
+ </button>
79
80
  </li>
80
81
  </ul>
81
82
 
@@ -29,6 +29,8 @@ const desc = link.description ?? "";
29
29
  const icon = link.icon ?? link.avatar ?? "/favicon.ico";
30
30
  ---
31
31
 
32
+ <!-- Modern Web Guidance (html): 友链卡是自包含内容 => <article>;
33
+ 头像是 <figure>(无题注的独立图像),标题 + 描述是卡片 <header>。 -->
32
34
  <a
33
35
  data-stalux-control="link-card"
34
36
  class="stalux-link-shell a-none"
@@ -36,8 +38,8 @@ const icon = link.icon ?? link.avatar ?? "/favicon.ico";
36
38
  target="_blank"
37
39
  rel="noopener"
38
40
  >
39
- <div class="stalux-link-card">
40
- <div class="stalux-link-card-avatar">
41
+ <article class="stalux-link-card">
42
+ <figure class="stalux-link-card-avatar">
41
43
  <img
42
44
  src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
43
45
  data-src={icon}
@@ -49,10 +51,10 @@ const icon = link.icon ?? link.avatar ?? "/favicon.ico";
49
51
  width="80"
50
52
  height="80"
51
53
  >
52
- </div>
53
- <div class="stalux-link-card-content">
54
+ </figure>
55
+ <header class="stalux-link-card-content">
54
56
  <h2 class="stalux-link-card-title">{title}</h2>
55
57
  {desc && <p class="stalux-link-card-description">{desc}</p>}
56
- </div>
57
- </div>
58
+ </header>
59
+ </article>
58
60
  </a>
@@ -50,7 +50,7 @@ function getIconByTitle(iconName: string): SimpleIcon | undefined {
50
50
  class="a-none"
51
51
  >
52
52
  {icon ? (
53
- <div class="icon-container">
53
+ <span class="icon-container">
54
54
  <svg
55
55
  role="img"
56
56
  viewBox="0 0 24 24"
@@ -63,7 +63,7 @@ function getIconByTitle(iconName: string): SimpleIcon | undefined {
63
63
  <title>{icon.title}</title>
64
64
  <path d={icon.path} />
65
65
  </svg>
66
- </div>
66
+ </span>
67
67
  ) : (
68
68
  <span class="custom-icon">
69
69
  {item.icon ? item.icon.charAt(0).toUpperCase() : ""}
@@ -45,20 +45,23 @@ const cfg = {
45
45
 
46
46
  <nav class="stalux-post-taxonomy-container" aria-label={title ?? cfg.heading}>
47
47
  <h3 class="stalux-post-taxonomy-title">{title ?? cfg.heading}</h3>
48
+ <!-- Modern Web Guidance (html): 标签/分类是导航链接集合 => <ul>/<li>;
49
+ 无条目时是一句提示 => <p>。reveal 钩子挂在 <li> 上(:scope > 直接子元素)。 -->
48
50
  {items.length > 0 ? (
49
- <div class={cfg.listClass} data-stalux-reveal>
51
+ <ul class={cfg.listClass} data-stalux-reveal>
50
52
  {items.map((item) => (
51
- <a
52
- href={`${cfg.prefix}${item}/`}
53
- class={`${cfg.itemClass} a-none`}
54
- data-astro-prefetch
55
- data-stalux-reveal-item
56
- >
57
- {item}
58
- </a>
53
+ <li data-stalux-reveal-item>
54
+ <a
55
+ href={`${cfg.prefix}${item}/`}
56
+ class={`${cfg.itemClass} a-none`}
57
+ data-astro-prefetch
58
+ >
59
+ {item}
60
+ </a>
61
+ </li>
59
62
  ))}
60
- </div>
63
+ </ul>
61
64
  ) : (
62
- <div class="stalux-post-taxonomy-empty">{cfg.empty}</div>
65
+ <p class="stalux-post-taxonomy-empty">{cfg.empty}</p>
63
66
  )}
64
67
  </nav>
@@ -64,9 +64,9 @@ const walineConfig = {
64
64
  <button type="button" class="waline-retry" data-waline-retry hidden>
65
65
  {t("comment.retry")}
66
66
  </button>
67
- <div class="comments-seo-notice" style="display:none">
67
+ <p class="comments-seo-notice" style="display:none">
68
68
  {t("comment.disclaimer")}
69
- </div>
69
+ </p>
70
70
  </section>
71
71
  )}
72
72