@xingwangzhe/stalux 1.29.8 → 1.30.1

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 (105) hide show
  1. package/README.md +5 -1
  2. package/package.json +10 -6
  3. package/src/components/stalux/archives/archivesList.astro +19 -15
  4. package/src/components/stalux/archives/toArchive.astro +2 -2
  5. package/src/components/stalux/categories/categoriesCard.astro +8 -7
  6. package/src/components/stalux/categories/categoriesList.astro +3 -2
  7. package/src/components/stalux/common/author.astro +8 -3
  8. package/src/components/stalux/common/date.astro +3 -4
  9. package/src/components/stalux/common/textType.astro +7 -2
  10. package/src/components/stalux/footer/FooterBadges.astro +9 -97
  11. package/src/components/stalux/footer/FooterBeian.astro +2 -44
  12. package/src/components/stalux/footer/FooterCopyright.astro +1 -16
  13. package/src/components/stalux/footer/FooterStats.astro +4 -25
  14. package/src/components/stalux/footer/FooterThemeInfo.astro +1 -28
  15. package/src/components/stalux/layout/footer.astro +3 -3
  16. package/src/components/stalux/layout/listPage.astro +3 -3
  17. package/src/components/stalux/layout/navs.astro +16 -13
  18. package/src/components/stalux/links/linkCard.astro +7 -6
  19. package/src/components/stalux/links/linkList.astro +4 -3
  20. package/src/components/stalux/links/socialMedia.astro +2 -2
  21. package/src/components/stalux/posts/PostTaxonomy.astro +13 -8
  22. package/src/components/stalux/posts/postAuthor.astro +6 -5
  23. package/src/components/stalux/posts/postCC.astro +10 -9
  24. package/src/components/stalux/posts/postCard.astro +19 -15
  25. package/src/components/stalux/posts/postContent.astro +22 -14
  26. package/src/components/stalux/posts/postLeft.astro +5 -4
  27. package/src/components/stalux/posts/postList.astro +2 -3
  28. package/src/components/stalux/posts/postNavigation.astro +24 -23
  29. package/src/components/stalux/posts/postRight.astro +7 -6
  30. package/src/components/stalux/posts/postToc.astro +7 -19
  31. package/src/components/stalux/posts/randomPost.astro +8 -7
  32. package/src/components/stalux/tags/tagHeader.astro +10 -6
  33. package/src/components/stalux/tags/tagsCloud.astro +10 -9
  34. package/src/components/stalux/words/wordCard.astro +11 -10
  35. package/src/components/stalux/words/wordList.astro +4 -3
  36. package/src/index.ts +5 -4
  37. package/src/internal/runtime-cache-key.ts +13 -1
  38. package/src/layouts/PostLayout.astro +3 -4
  39. package/src/layouts/Stalux.astro +0 -17
  40. package/src/pages/404.astro +9 -77
  41. package/src/pages/archives.astro +3 -3
  42. package/src/pages/categories/index.astro +3 -3
  43. package/src/pages/index.astro +6 -18
  44. package/src/pages/tags/index.astro +3 -3
  45. package/src/pages/words.astro +3 -3
  46. package/src/scripts/waline-client.ts +1 -1
  47. package/src/styles/archives.css +1 -0
  48. package/src/styles/article.css +1 -0
  49. package/src/styles/base.css +287 -0
  50. package/src/styles/categories.css +1 -0
  51. package/src/styles/content.css +471 -0
  52. package/src/styles/generated-archives.css +3 -0
  53. package/src/styles/generated-article.css +3 -0
  54. package/src/styles/generated-categories.css +3 -0
  55. package/src/styles/generated-links.css +3 -0
  56. package/src/styles/generated-prose.css +2 -0
  57. package/src/styles/generated-tags.css +3 -0
  58. package/src/styles/generated-waline.css +2 -0
  59. package/src/styles/generated-words.css +3 -0
  60. package/src/styles/generated.css +3 -0
  61. package/src/styles/{components/posts/waline.css → integrations.css} +19 -23
  62. package/src/styles/links.css +1 -0
  63. package/src/styles/{shared/view-transitions.css → motion.css} +96 -0
  64. package/src/styles/prose.css +1 -0
  65. package/src/styles/tags.css +1 -0
  66. package/src/styles/theme.css +1 -0
  67. package/src/styles/words.css +1 -0
  68. package/src/styles/base/init.css +0 -287
  69. package/src/styles/components/archives/archivesList.module.css +0 -203
  70. package/src/styles/components/archives/toArchive.module.css +0 -3
  71. package/src/styles/components/categories/categoriesCard.module.css +0 -88
  72. package/src/styles/components/categories/categoriesList.module.css +0 -23
  73. package/src/styles/components/common/author.module.css +0 -72
  74. package/src/styles/components/common/date.module.css +0 -15
  75. package/src/styles/components/common/textType.module.css +0 -10
  76. package/src/styles/components/footer/footer.module.css +0 -44
  77. package/src/styles/components/layout/navs.module.css +0 -261
  78. package/src/styles/components/links/linkCard.module.css +0 -116
  79. package/src/styles/components/links/linkList.module.css +0 -54
  80. package/src/styles/components/links/socialLinks.module.css +0 -80
  81. package/src/styles/components/markdown.css +0 -523
  82. package/src/styles/components/posts/postAuthor.module.css +0 -31
  83. package/src/styles/components/posts/postCC.module.css +0 -138
  84. package/src/styles/components/posts/postCard.module.css +0 -167
  85. package/src/styles/components/posts/postContent.module.css +0 -238
  86. package/src/styles/components/posts/postLayout.module.css +0 -138
  87. package/src/styles/components/posts/postList.module.css +0 -25
  88. package/src/styles/components/posts/postNavigation.module.css +0 -186
  89. package/src/styles/components/posts/postSidebar.module.css +0 -59
  90. package/src/styles/components/posts/postTaxonomy.module.css +0 -87
  91. package/src/styles/components/posts/postToc.module.css +0 -74
  92. package/src/styles/components/posts/randomPost.module.css +0 -131
  93. package/src/styles/components/tags/tagHeader.module.css +0 -44
  94. package/src/styles/components/tags/tagsCloud.module.css +0 -155
  95. package/src/styles/components/words/wordCard.module.css +0 -136
  96. package/src/styles/components/words/wordList.module.css +0 -26
  97. package/src/styles/pages/archives.module.css +0 -22
  98. package/src/styles/pages/categories.module.css +0 -17
  99. package/src/styles/pages/home.module.css +0 -61
  100. package/src/styles/pages/listPage.module.css +0 -16
  101. package/src/styles/pages/tags.module.css +0 -16
  102. package/src/styles/pages/words.module.css +0 -16
  103. package/src/styles/shared/animations.css +0 -87
  104. package/src/styles/shared/stagger.css +0 -20
  105. /package/src/styles/{base/math.css → math.css} +0 -0
package/README.md CHANGED
@@ -119,7 +119,7 @@ TypeScript uses ESNext. The theme defaults `vite.build.target` to `"esnext"` to
119
119
 
120
120
  ### Initial CSS and search styles
121
121
 
122
- The theme defaults to Astro's `build.inlineStylesheets: "always"`, placing route styles in the HTML to reduce stylesheet requests before the first paint. An explicit consumer setting of `build.inlineStylesheets: "never"` keeps external stylesheets. Inlining increases each HTML response in exchange for a shorter stylesheet request chain on a first visit.
122
+ The theme defaults to Astro's `build.inlineStylesheets: "never"`: hashed shared CSS can be cached across routes, while component styles load on the pages that use them. Normal blocking stylesheets prevent an unstyled first paint. An explicit consumer setting of `build.inlineStylesheets: "always"` restores inline styles at the cost of larger HTML responses.
123
123
 
124
124
  Pagefind dialog CSS is emitted as a separate hashed static file with a `prefetch` hint. Opening search activates the stylesheet and waits for it before displaying the dialog. It does not block the initial content or depend on JavaScript generating a CSS asset. A `<noscript>` stylesheet fallback is included.
125
125
 
@@ -281,3 +281,7 @@ In Astro 7.3, integration `logger.debug()` uses the official `DEBUG/--verbose` c
281
281
  Timing is emitted only as logs, never included in generated pages or cache keys. Switching between normal and verbose builds may require one rebuild; repeated builds in the same mode remain deterministic. Consumers running `astro dev --background` can read terminal output with `astro dev logs`.
282
282
 
283
283
  Keep the TypeScript 6 alias for `astro check`, upgrade Vitest and its coverage provider together, and run `bun run validate` before releasing.
284
+
285
+ ## Style development and output
286
+
287
+ Stalux precompiles its UnoCSS styles; consuming projects need no UnoCSS dependency or configuration. Shared CSS is a cacheable external stylesheet by default. Article/math, archive, category, tag and quote styles load with their components. Explicit Astro `build.inlineStylesheets: "always"` restores inline output. New utilities in consumer override components require the consumer’s own compiler. See [STYLING.md](./docs/STYLING.md) for maintenance and watch mode.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.29.8",
3
+ "version": "1.30.1",
4
4
  "description": "A powerful, modern Astro blog theme — use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -67,14 +67,14 @@
67
67
  "./package.json": "./package.json"
68
68
  },
69
69
  "scripts": {
70
- "dev": "astro dev",
71
- "build": "astro build && node scripts/verify-build.ts",
70
+ "dev": "bun run styles:build && node scripts/dev.ts",
71
+ "build": "bun run styles:build && astro build && node scripts/verify-build.ts",
72
72
  "preview": "astro preview",
73
73
  "astro": "astro",
74
74
  "init": "node scripts/cli.ts init",
75
75
  "node:check": "tsc6 --project tsconfig.node.json",
76
76
  "build:cli": "bun build scripts/cli.ts --target=node --outfile .release/cli.mjs",
77
- "prepack": "bun run build:cli",
77
+ "prepack": "bun run styles:build && bun run build:cli",
78
78
  "check": "biome check .",
79
79
  "check:fix": "biome check --write .",
80
80
  "format": "biome format --write .",
@@ -87,10 +87,12 @@
87
87
  "test:coverage": "vitest run --coverage",
88
88
  "knip": "knip",
89
89
  "verify:build": "node scripts/verify-build.ts",
90
- "validate": "bun run check && bun run node:check && bun run astro:check && bun run knip && bun run test:coverage && bun run build && bun run build:cli",
90
+ "validate": "bun run styles:build && bun run check && bun run node:check && bun run astro:check && bun run knip && bun run test:coverage && bun run build && bun run build:cli",
91
91
  "prepare": "git config core.hooksPath scripts/git-hooks",
92
92
  "dev:debug": "STALUX_DEBUG=1 astro dev --verbose",
93
- "build:debug": "STALUX_DEBUG=1 astro build --verbose && node scripts/verify-build.ts"
93
+ "build:debug": "STALUX_DEBUG=1 astro build --verbose && node scripts/verify-build.ts",
94
+ "styles:build": "node scripts/build-styles.ts",
95
+ "styles:watch": "node scripts/build-styles.ts --watch"
94
96
  },
95
97
  "dependencies": {
96
98
  "@astrojs/markdown-satteri": "0.4.2",
@@ -122,10 +124,12 @@
122
124
  "@astrojs/check": "0.9.10",
123
125
  "@biomejs/biome": "2.5.14",
124
126
  "@types/node": "^26.6.2",
127
+ "@unocss/astro": "^66.10.5",
125
128
  "@vitest/coverage-v8": "5.0.1",
126
129
  "astro": "^7.3.5",
127
130
  "knip": "^6.37.0",
128
131
  "typescript": "npm:@typescript/typescript6@6.0.2",
132
+ "unocss": "^66.10.5",
129
133
  "vite": "8.3.0",
130
134
  "vitest": "5.0.1"
131
135
  },
@@ -1,6 +1,7 @@
1
1
  ---
2
+ import "../../../styles/generated-archives.css";
2
3
  import { type CollectionEntry, getCollection } from "astro:content";
3
- import styles from "@styles/components/archives/archivesList.module.css";
4
+
4
5
  import { getSiteData } from "@utils/config-utils";
5
6
  import { format, parseDate, toTimestamp } from "@utils/dayjs";
6
7
  import { createTranslator } from "@utils/i18n";
@@ -52,41 +53,44 @@ const archiveYears = [...archivesByYearMonth.entries()]
52
53
  }));
53
54
  ---
54
55
 
55
- <section class={styles.archivesContainer}>
56
- <div class={styles.pageHeader}>
57
- <div class={styles.timelineContainer}>
56
+ <section class="stalux-archive-container">
57
+ <div class="stalux-archive-page-header">
58
+ <div class="stalux-archive-timeline-container">
58
59
  {archiveYears.length > 0 ? (
59
60
  archiveYears.map((archiveYear) => (
60
- <div class={styles.yearSection} data-year={String(archiveYear.year)}>
61
- <div class={styles.yearHeader}>
62
- <h2 class={styles.yearTitle}>{archiveYear.year}</h2>
63
- <div class={styles.yearCount}>
61
+ <div class="stalux-archive-year-section" data-year={String(archiveYear.year)}>
62
+ <div class="stalux-archive-year-header">
63
+ <h2 class="stalux-archive-year-title">{archiveYear.year}</h2>
64
+ <div class="stalux-archive-year-count">
64
65
  {t("archives.postCount", { n: archiveYear.count })}
65
66
  </div>
66
67
  </div>
67
68
  {archiveYear.months.map(({ month, posts: monthPosts }) => (
68
69
  <div
69
- class={styles.monthSection}
70
+ class="stalux-archive-month-section"
70
71
  style={{
71
72
  "--archive-estimate": `${Math.ceil(monthPosts.length / 12) * 12 * 48 + 40}px`,
72
73
  }}
73
74
  >
74
- <h3 class={styles.monthTitle}>{t("archives.month", { n: month })}</h3>
75
+ <h3 class="stalux-archive-month-title">{t("archives.month", { n: month })}</h3>
75
76
  {Array.from({ length: Math.ceil(monthPosts.length / 12) }, (_, index) =>
76
77
  monthPosts.slice(index * 12, (index + 1) * 12),
77
78
  ).map((group) => (
78
79
  <ul
79
- class={styles.postList}
80
+ class="stalux-archive-post-list"
80
81
  style={{ "--archive-group-estimate": `${group.length * 48}px` }}
81
82
  >
82
83
  {group.map((post) => (
83
- <li class={styles.postItem}>
84
- <time class={styles.postDate} datetime={post.data.date}>
84
+ <li class="stalux-archive-post-item">
85
+ <time
86
+ class="stalux-archive-post-date"
87
+ datetime={post.data.date}
88
+ >
85
89
  {format(parseDate(post.data.date), "yyyy-MM-dd")}
86
90
  </time>
87
91
  <a
88
92
  href={`/posts/${post.data.abbrlink}/`}
89
- class={styles.postLink}
93
+ class="stalux-archive-post-link"
90
94
  data-astro-prefetch="viewport"
91
95
  >
92
96
  {post.data.title}
@@ -100,7 +104,7 @@ const archiveYears = [...archivesByYearMonth.entries()]
100
104
  </div>
101
105
  ))
102
106
  ) : (
103
- <div class={styles.noPosts}>{t("archives.noPosts")}</div>
107
+ <div class="stalux-archive-no-posts">{t("archives.noPosts")}</div>
104
108
  )}
105
109
  </div>
106
110
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  import { getCollection } from "astro:content";
3
- import styles from "@styles/components/archives/toArchive.module.css";
3
+
4
4
  import { getSiteData } from "@utils/config-utils";
5
5
  import { createTranslator } from "@utils/i18n";
6
6
 
@@ -9,6 +9,6 @@ const siteConfig = getSiteData(configEntries);
9
9
  const { t } = createTranslator(siteConfig.lang || "zh-CN");
10
10
  ---
11
11
 
12
- <div id={styles.archs}>
12
+ <div id={"stalux-to-archive-archs"}>
13
13
  <a href="/archives" data-astro-prefetch>{t("archives.viewAll")}</a>
14
14
  </div>
@@ -1,6 +1,7 @@
1
1
  ---
2
+ import "../../../styles/generated-categories.css";
2
3
  import { getCollection } from "astro:content";
3
- import styles from "@styles/components/categories/categoriesCard.module.css";
4
+
4
5
  import { createTranslator } from "@utils/i18n";
5
6
 
6
7
  interface Props {
@@ -19,13 +20,13 @@ const siteConfig = (configEntries.find((e) => e.id === "site")?.data ?? {}) as R
19
20
  const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
20
21
  ---
21
22
 
22
- <article class={styles.categoryCard}>
23
+ <article class="stalux-category-card">
23
24
  <a
24
25
  href={`/categories/${props.category.name}/`}
25
- class={`${styles.categoryheader} a-none`}
26
+ class="stalux-categoryheader a-none"
26
27
  data-astro-prefetch
27
28
  >
28
- <div class={styles.categoryIcon}>
29
+ <div class="stalux-category-icon">
29
30
  <svg
30
31
  aria-hidden="true"
31
32
  xmlns="http://www.w3.org/2000/svg"
@@ -43,9 +44,9 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
43
44
  ></path>
44
45
  </svg>
45
46
  </div>
46
- <div class={styles.categoryContent}>
47
- <h2 class={styles.categoryName}>{props.category.name}</h2>
48
- <div class={styles.categoryCount}>
47
+ <div class="stalux-category-content">
48
+ <h2 class="categoryName">{props.category.name}</h2>
49
+ <div class="categoryCount">
49
50
  {t("categories.postCount", { n: props.category.count })}
50
51
  </div>
51
52
  </div>
@@ -1,12 +1,13 @@
1
1
  ---
2
+ import "../../../styles/generated-categories.css";
2
3
  import CategoriesCard from "@components/stalux/categories/categoriesCard.astro";
3
- import styles from "@styles/components/categories/categoriesList.module.css";
4
+
4
5
  import { getCategoryCountList } from "@utils/collections-stats";
5
6
 
6
7
  const categoryList = await getCategoryCountList(Astro.logger);
7
8
  ---
8
9
 
9
- <ul class={styles.categoriesList}>
10
+ <ul class="stalux-categories">
10
11
  {categoryList.map((category) => (
11
12
  <li>
12
13
  <CategoriesCard category={category} />
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  import { Image } from "astro:assets";
3
3
  import { getCollection } from "astro:content";
4
- import styles from "@styles/components/common/author.module.css";
4
+
5
5
  import { getAuthorData } from "@utils/config-utils";
6
6
 
7
7
  const configEntries = await getCollection("config");
@@ -17,8 +17,13 @@ const isHomePage = Astro.url.pathname === "/";
17
17
  const navigationHref = isHomePage ? "/about" : "/";
18
18
  ---
19
19
 
20
- <article class={styles.author} transition:persist-props>
21
- <figure class={`${styles.authorFigure} ${props.iscolum ? styles.figureColumn : ""}`}>
20
+ <article
21
+ class="stalux-author stalux-u-flex stalux-u-justify-center stalux-u-flex-col"
22
+ transition:persist-props
23
+ >
24
+ <figure
25
+ class={`stalux-author-figure ${props.iscolum ? "stalux-author-figure-column stalux-u-flex-col" : ""}`}
26
+ >
22
27
  <a href={navigationHref} class="a-none" data-astro-prefetch>
23
28
  <Image src={authorConfig.avatar} alt={authorConfig.name} width={100} height={100} />
24
29
  </a>
@@ -1,10 +1,9 @@
1
1
  ---
2
- import styles from "@styles/components/common/date.module.css";
3
2
  ---
4
3
 
5
- <div id={styles["date-time"]} class="date-time" transition:persist-props>
6
- <time id={styles.date} data-ref="date" datetime=""></time>
7
- <time id={styles.time} data-ref="time" datetime=""></time>
4
+ <div id={"stalux-date-date-time"} class="date-time" transition:persist-props>
5
+ <time id={"stalux-date-date"} data-ref="date" datetime=""></time>
6
+ <time id={"stalux-date-time"} data-ref="time" datetime=""></time>
8
7
  </div>
9
8
 
10
9
  <script is:inline>
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  import { getCollection } from "astro:content";
3
- import styles from "@styles/components/common/textType.module.css";
3
+
4
4
  import { getTypetextsData } from "@utils/config-utils";
5
5
  import Typewriter from "astro-typewriter";
6
6
 
@@ -8,4 +8,9 @@ const configEntries = await getCollection("config");
8
8
  const typetextsConfig = getTypetextsData(configEntries);
9
9
  ---
10
10
 
11
- {typetextsConfig?.items && <Typewriter class={styles.typeWriter} messages={typetextsConfig?.items} />}
11
+ {typetextsConfig?.items && (
12
+ <Typewriter
13
+ class="stalux-typewriter stalux-u-flex stalux-u-justify-center stalux-u-w-full stalux-u-text-center"
14
+ messages={typetextsConfig?.items}
15
+ />
16
+ )}
@@ -22,7 +22,7 @@ function badgeImg(opts: BadgeOptions) {
22
22
  const height = svg.match(/<svg\b[^>]*\bheight="(\d+)"/)?.[1];
23
23
  const dimensions = width && height ? ` width="${width}" height="${height}"` : "";
24
24
  // Closed badge groups should not initialize every SVG document during first paint.
25
- const img = `<img src="${src}" alt="${alt}" class="badge" loading="lazy" decoding="async"${dimensions} />`;
25
+ const img = `<img src="${src}" alt="${alt}" class="stalux-badge" loading="lazy" decoding="async"${dimensions} />`;
26
26
  if (opts.href) {
27
27
  return `<a href="${opts.href}" target="_blank" rel="${opts.rel ?? "noopener"}">${img}</a>`;
28
28
  }
@@ -31,23 +31,23 @@ function badgeImg(opts: BadgeOptions) {
31
31
  ---
32
32
 
33
33
  {badges && badges.length > 0 && (
34
- <div class="badges-wrapper">
34
+ <div class="stalux-badges-wrapper stalux-u-flex stalux-u-items-center stalux-u-justify-center stalux-u-flex-wrap">
35
35
  {badges.map((item: BadgeItem, idx: number) => {
36
36
  if (isBadgeGroup(item)) {
37
37
  const groupId = `badge-group-${idx}`;
38
38
  return (
39
- <details class="badge-group" id={groupId}>
40
- <summary class="badge-group-summary">
41
- <span class="badge-group-arrow">&#9654;</span>
42
- <span class="badge-group-title">{item.title}</span>
43
- <span class="badge-group-hint" data-hint="expanded">
39
+ <details class="stalux-badge-group stalux-u-w-full badge-group" id={groupId}>
40
+ <summary class="stalux-badge-group-summary stalux-u-flex stalux-u-items-center stalux-u-justify-center">
41
+ <span class="stalux-badge-group-arrow">&#9654;</span>
42
+ <span class="stalux-badge-group-title">{item.title}</span>
43
+ <span class="stalux-badge-group-hint" data-hint="expanded">
44
44
  {t("footer.collapse")}
45
45
  </span>
46
- <span class="badge-group-hint" data-hint="collapsed">
46
+ <span class="stalux-badge-group-hint" data-hint="collapsed">
47
47
  {t("footer.expand")}
48
48
  </span>
49
49
  </summary>
50
- <div class="badge-group-items badges">
50
+ <div class="stalux-badge-group-items stalux-badges stalux-u-flex stalux-u-items-center stalux-u-justify-center stalux-u-flex-wrap">
51
51
  {item.items.map((b) => (
52
52
  <Fragment set:html={badgeImg(b)} />
53
53
  ))}
@@ -59,91 +59,3 @@ function badgeImg(opts: BadgeOptions) {
59
59
  })}
60
60
  </div>
61
61
  )}
62
-
63
- <style>
64
- .badges-wrapper {
65
- display: flex;
66
- justify-content: center;
67
- align-items: center;
68
- flex-wrap: wrap;
69
- gap: 0.5rem;
70
- }
71
-
72
- /* Badge HTML is emitted by set:html, so target it through the scoped wrapper. */
73
- .badges-wrapper :global(.badge) {
74
- width: auto;
75
- }
76
-
77
- .badge-group {
78
- width: 100%;
79
- border: none;
80
- }
81
-
82
- .badge-group-summary {
83
- cursor: pointer;
84
- display: flex;
85
- justify-content: center;
86
- align-items: center;
87
- gap: 0.4rem;
88
- padding: 0.2rem 0;
89
- color: var(--white-70p);
90
- font-size: 0.85rem;
91
- user-select: none;
92
- list-style: none;
93
- transition: color 0.2s;
94
- }
95
- .badge-group-summary:hover {
96
- color: var(--white-70p);
97
- }
98
- .badge-group-summary::-webkit-details-marker {
99
- display: none;
100
- }
101
-
102
- .badge-group-arrow {
103
- font-size: 0.65rem;
104
- transition: transform 0.2s;
105
- display: inline-block;
106
- }
107
- .badge-group[open] .badge-group-arrow {
108
- transform: rotate(90deg);
109
- }
110
-
111
- .badge-group-title {
112
- color: var(--white-80p);
113
- }
114
-
115
- .badge-group-hint {
116
- font-size: 0.7rem;
117
- color: var(--white-70p);
118
- }
119
- .badge-group[open] .badge-group-hint[data-hint="collapsed"],
120
- .badge-group:not([open]) .badge-group-hint[data-hint="expanded"] {
121
- display: none;
122
- }
123
-
124
- .badge-group-items {
125
- padding-top: 0.35rem;
126
- }
127
-
128
- .badges {
129
- display: flex;
130
- justify-content: center;
131
- align-items: center;
132
- flex-wrap: wrap;
133
- gap: 0.5rem;
134
- }
135
-
136
- .badge {
137
- height: 20px;
138
- vertical-align: middle;
139
- }
140
-
141
- @media (max-width: 768px) {
142
- .badges {
143
- gap: 0.3rem;
144
- }
145
- .badge {
146
- height: 18px;
147
- }
148
- }
149
- </style>
@@ -19,7 +19,7 @@ const showBeian = !!(icp || pubsec);
19
19
  ---
20
20
 
21
21
  {showBeian && (
22
- <div class="beian-info">
22
+ <div class="stalux-beian-beian-info stalux-u-flex stalux-u-justify-center stalux-u-flex-wrap">
23
23
  {icp && (
24
24
  <a href="https://beian.miit.gov.cn/" target="_blank" rel="noopener noreferrer">
25
25
  {icp}
@@ -30,7 +30,7 @@ const showBeian = !!(icp || pubsec);
30
30
  href={`http://www.beian.gov.cn/portal/registerSystemInfo?recordcode=${pubsecNumber}`}
31
31
  target="_blank"
32
32
  rel="noopener noreferrer"
33
- class="public-security-beian"
33
+ class="stalux-beian-public-security-beian stalux-u-items-center"
34
34
  >
35
35
  <img
36
36
  src="https://beian.mps.gov.cn/img/logo01.dd7ff50e.png"
@@ -41,45 +41,3 @@ const showBeian = !!(icp || pubsec);
41
41
  )}
42
42
  </div>
43
43
  )}
44
-
45
- <style>
46
- .beian-info {
47
- display: flex;
48
- justify-content: center;
49
- flex-wrap: wrap;
50
- gap: 1rem;
51
- }
52
-
53
- .beian-info a {
54
- color: rgba(255, 255, 255, 0.7);
55
- text-decoration: none;
56
- transition: color 0.3s ease;
57
- font-size: 0.9rem;
58
- }
59
-
60
- .beian-info a:hover {
61
- color: rgba(255, 255, 255, 0.9);
62
- text-decoration: none;
63
- }
64
-
65
- .public-security-beian {
66
- display: inline-flex;
67
- align-items: center;
68
- gap: 5px;
69
- color: rgba(255, 255, 255, 0.7);
70
- text-decoration: none;
71
- transition: color 0.3s ease;
72
- font-size: 0.9rem;
73
- }
74
-
75
- .public-security-beian:hover {
76
- color: rgba(255, 255, 255, 0.9);
77
- text-decoration: none;
78
- }
79
-
80
- .public-security-beian img {
81
- width: 15px;
82
- height: 15px;
83
- display: inline-block;
84
- }
85
- </style>
@@ -21,21 +21,6 @@ const copyrightYear =
21
21
  : currentYear;
22
22
  ---
23
23
 
24
- <small class="copyright">
24
+ <small class="stalux-copyright stalux-u-flex stalux-u-justify-center stalux-u-flex-wrap">
25
25
  <span>&copy; {copyrightYear} {props.author || ""}. {t("footer.rightsReserved")}</span>
26
26
  </small>
27
-
28
- <style>
29
- .copyright {
30
- color: var(--white-70p);
31
- font-weight: 500;
32
- display: flex;
33
- gap: 0.3em;
34
- justify-content: center;
35
- flex-wrap: wrap;
36
- }
37
-
38
- .copyright span {
39
- margin: 0;
40
- }
41
- </style>
@@ -16,17 +16,17 @@ const { showStats = true, wordCount, buildtime } = Astro.props;
16
16
  ---
17
17
 
18
18
  {showStats && (
19
- <p class="site-stats">
19
+ <p class="stalux-stats-site-stats stalux-u-flex stalux-u-justify-center stalux-u-flex-wrap">
20
20
  <span id="vercount_container_site_uv">
21
21
  {t("footer.visitors")}
22
22
  <span id="vercount_value_site_uv">Loading...</span> {t("footer.visits")}
23
23
  </span>
24
- <span class="stats-separator">|</span>
24
+ <span class="stalux-stats-stats-separator">|</span>
25
25
  <span id="vercount_container_site_pv">
26
26
  {t("footer.totalVisits")}
27
27
  <span id="vercount_value_site_pv">Loading...</span> {t("footer.times")}
28
28
  </span>
29
- <span class="stats-separator">|</span>
29
+ <span class="stalux-stats-stats-separator">|</span>
30
30
  <span id="word-count-container">
31
31
  {t("footer.totalWords")}
32
32
  <span id="word-count-value">{wordCount ?? "Loading..."}</span> {t("footer.chars")}
@@ -36,7 +36,7 @@ const { showStats = true, wordCount, buildtime } = Astro.props;
36
36
 
37
37
  {buildtime && (
38
38
  <div
39
- class="site-build-time"
39
+ class="stalux-stats-site-build-time stalux-u-text-center"
40
40
  data-stalux-buildtime={buildtime}
41
41
  data-stalux-runtime-format={t("footer.runtimeFormat")}
42
42
  >
@@ -46,24 +46,3 @@ const { showStats = true, wordCount, buildtime } = Astro.props;
46
46
  </span>
47
47
  </div>
48
48
  )}
49
-
50
- <style>
51
- .site-stats {
52
- display: flex;
53
- justify-content: center;
54
- flex-wrap: wrap;
55
- gap: 0.5rem;
56
- font-size: 0.9rem;
57
- }
58
-
59
- .stats-separator {
60
- color: rgba(255, 255, 255, 0.5);
61
- }
62
-
63
- .site-build-time {
64
- margin-top: 0.5rem;
65
- font-size: 0.9rem;
66
- color: rgba(255, 255, 255, 0.8);
67
- text-align: center;
68
- }
69
- </style>
@@ -9,7 +9,7 @@ const showThemeInfoSection = !!(showPoweredBy || showThemeInfo);
9
9
  ---
10
10
 
11
11
  {showThemeInfoSection && (
12
- <div class="theme-info">
12
+ <div class="stalux-theme-info stalux-u-flex stalux-u-justify-center stalux-u-flex-wrap">
13
13
  {showPoweredBy && (
14
14
  <span>
15
15
  Powered by
@@ -33,30 +33,3 @@ const showThemeInfoSection = !!(showPoweredBy || showThemeInfo);
33
33
  )}
34
34
  </div>
35
35
  )}
36
-
37
- <style>
38
- .theme-info {
39
- color: var(--white-70p);
40
- font-size: 0.85rem;
41
- display: flex;
42
- justify-content: center;
43
- gap: 0.3em;
44
- flex-wrap: wrap;
45
- }
46
-
47
- .theme-info span {
48
- margin: 0;
49
- }
50
-
51
- .theme-info a {
52
- color: rgba(255, 255, 255, 0.8);
53
- text-decoration: none;
54
- transition: color 0.3s ease;
55
- margin: 0 0.2em;
56
- }
57
-
58
- .theme-info a:hover {
59
- color: rgba(255, 255, 255, 1);
60
- text-decoration: none;
61
- }
62
- </style>
@@ -5,7 +5,7 @@ import FooterBeian from "@components/stalux/footer/FooterBeian.astro";
5
5
  import FooterCopyright from "@components/stalux/footer/FooterCopyright.astro";
6
6
  import FooterStats from "@components/stalux/footer/FooterStats.astro";
7
7
  import FooterThemeInfo from "@components/stalux/footer/FooterThemeInfo.astro";
8
- import footerStyle from "@styles/components/footer/footer.module.css";
8
+
9
9
  import type { BadgeItem, BadgeOptions } from "@utils/badge-generator";
10
10
  import { getAuthorData, getFooterData, getSiteData } from "@utils/config-utils";
11
11
  import { formatWordCount, getTotalWordCount } from "@utils/word-count-utils";
@@ -50,8 +50,8 @@ const totalWordCount = await getTotalWordCount(Astro.logger);
50
50
  const formattedWordCount = formatWordCount(totalWordCount, siteConfig.lang || "zh-CN");
51
51
  ---
52
52
 
53
- <footer class={footerStyle.siteFooter} transition:persist-props>
54
- <div class={footerStyle.footerContent}>
53
+ <footer class="stalux-footer stalux-u-w-full stalux-u-text-center" transition:persist-props>
54
+ <div class="stalux-footer-content stalux-u-flex stalux-u-flex-col">
55
55
  <!-- 版权信息 -->
56
56
  {footerConfig?.copyright?.enabled && (
57
57
  <FooterCopyright author={author} startYear={footerConfig?.copyright?.startYear} />
@@ -2,7 +2,7 @@
2
2
  import { getCollection } from "astro:content";
3
3
  import Navs from "@components/stalux/layout/navs.astro";
4
4
  import Stalux from "@layouts/Stalux.astro";
5
- import styles from "@styles/pages/listPage.module.css";
5
+
6
6
  import { getSiteData } from "@utils/config-utils";
7
7
 
8
8
  interface Props {
@@ -20,7 +20,7 @@ const siteConfig = getSiteData(configEntries);
20
20
  <Stalux title={`${title} | ${siteConfig.title}`} description={description}>
21
21
  <div style="height: 3em;"></div>
22
22
  <Navs />
23
- <h1 class={styles.title}>{heading}</h1>
24
- {subheading && <div class={styles.description}>{subheading}</div>}
23
+ <h1 class="stalux-page-title stalux-u-text-center">{heading}</h1>
24
+ {subheading && <div class="stalux-page-description stalux-u-text-center">{subheading}</div>}
25
25
  <slot />
26
26
  </Stalux>