@xingwangzhe/stalux 1.35.0 β†’ 1.35.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/README.md CHANGED
@@ -93,6 +93,7 @@ bun run dev
93
93
  - πŸ—ΊοΈ **Sitemap** (bundled; `.md` source endpoints auto-filtered)
94
94
  - πŸ–ΌοΈ **PhotoSwipe** image lightbox
95
95
  - πŸ“Š **Mermaid** diagrams and flowcharts
96
+ Uses Merman through `@xingwangzhe/satteri-mermaid@0.8.1`, with the `dark` theme and a transparent canvas by default. The plugin supports 11 theme presets; see the [configuration reference](https://github.com/xingwangzhe/satteri-mermaid/blob/v0.8.1/docs/configuration.md). Rendering failures throw by default.
96
97
  - πŸ“ **Math formula rendering** (Temml β†’ MathML)
97
98
  - πŸ’¬ **Waline** comment system
98
99
  - πŸ€– **LLM discovery files** (llms.txt / llms-full.txt)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@xingwangzhe/stalux",
3
- "version": "1.35.0",
3
+ "version": "1.35.2",
4
4
  "description": "A powerful, modern Astro blog theme β€” use as template or install as plugin",
5
5
  "keywords": [
6
6
  "astro",
@@ -95,47 +95,47 @@
95
95
  "styles:watch": "node scripts/build-styles.ts --watch"
96
96
  },
97
97
  "dependencies": {
98
- "@astrojs/compiler": "2.13.1",
99
- "@astrojs/markdown-satteri": "0.4.2",
100
- "@astrojs/partytown": "2.1.8",
98
+ "@astrojs/compiler": "^4.0.0",
99
+ "@astrojs/markdown-satteri": "^0.4.3",
100
+ "@astrojs/partytown": "^2.1.8",
101
101
  "@astrojs/rss": "^4.0.19",
102
102
  "@astrojs/sitemap": "^3.7.4",
103
- "@babel/parser": "7.29.9",
103
+ "@babel/parser": "^8.0.6",
104
104
  "@expressive-code/plugin-line-numbers": "^0.44.2",
105
- "@lucide/astro": "^1.47.0",
105
+ "@lucide/astro": "^1.52.0",
106
106
  "@mcp-b/webmcp-polyfill": "^5.1.0",
107
107
  "@pagefind/component-ui": "^1.5.2",
108
- "@waline/client": "3.16.0",
109
- "@xingwangzhe/cjk-font-split-native": "0.2.0",
110
- "@xingwangzhe/satteri-mermaid": "0.7.8",
111
- "@xingwangzhe/satteri-photoswipe": "^0.2.5",
112
- "@xingwangzhe/tags-cloud": "^1.2.8",
108
+ "@waline/client": "^3.16.0",
109
+ "@xingwangzhe/cjk-font-split-native": "^0.2.0",
110
+ "@xingwangzhe/satteri-mermaid": "^0.8.1",
111
+ "@xingwangzhe/satteri-photoswipe": "^0.2.6",
112
+ "@xingwangzhe/tags-cloud": "^1.2.9",
113
113
  "astro-expressive-code": "^0.44.2",
114
114
  "astro-seo": "^1.2.0",
115
115
  "badge-maker": "^6.0.0",
116
- "css-tree": "3.2.1",
117
- "magic-string": "0.30.21",
116
+ "css-tree": "^3.2.1",
117
+ "magic-string": "^1.4.3",
118
118
  "pagefind": "^1.5.2",
119
- "parse5": "8.0.1",
119
+ "parse5": "^8.0.1",
120
120
  "photoswipe": "^5.4.4",
121
121
  "satteri": "^0.10.5",
122
- "simple-icons": "^16.32.0",
122
+ "simple-icons": "^16.34.0",
123
123
  "temml": "^0.13.5",
124
124
  "yaml": "^2.9.1"
125
125
  },
126
126
  "devDependencies": {
127
- "@astrojs/check": "0.9.10",
128
- "@biomejs/biome": "2.5.14",
127
+ "@astrojs/check": "^0.9.10",
128
+ "@biomejs/biome": "^2.5.15",
129
129
  "@types/css-tree": "^3.2.0",
130
- "@types/node": "^26.6.2",
130
+ "@types/node": "^26.6.4",
131
131
  "@unocss/astro": "^66.10.5",
132
- "@vitest/coverage-v8": "5.0.1",
133
- "astro": "^7.3.5",
134
- "knip": "^6.37.0",
132
+ "@vitest/coverage-v8": "^5.0.3",
133
+ "astro": "^7.3.6",
134
+ "knip": "^6.40.0",
135
135
  "typescript": "npm:@typescript/typescript6@6.0.2",
136
136
  "unocss": "^66.10.5",
137
- "vite": "8.3.0",
138
- "vitest": "5.0.1"
137
+ "vite": "^8.3.3",
138
+ "vitest": "^5.0.3"
139
139
  },
140
140
  "peerDependencies": {
141
141
  "astro": "^7.3.5"
@@ -57,57 +57,65 @@ const archiveYears = [...archivesByYearMonth.entries()]
57
57
  <div class="stalux-archive-page-header">
58
58
  <div class="stalux-archive-timeline-container">
59
59
  {archiveYears.length > 0 ? (
60
- archiveYears.map((archiveYear) => (
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">
65
- {t("archives.postCount", { n: archiveYear.count })}
66
- </div>
67
- </div>
68
- {archiveYear.months.map(({ month, posts: monthPosts }) => (
69
- <div
70
- class="stalux-archive-month-section"
71
- data-archive-month
72
- style={{
73
- "--archive-estimate": `${Math.ceil(monthPosts.length / 12) * 12 * 48 + 40}px`,
74
- }}
75
- >
76
- <h3 class="stalux-archive-month-title">{t("archives.month", { n: month })}</h3>
77
- {Array.from({ length: Math.ceil(monthPosts.length / 12) }, (_, index) =>
78
- monthPosts.slice(index * 12, (index + 1) * 12),
79
- ).map((group) => (
80
- <ul
81
- class="stalux-archive-post-list"
82
- style={{ "--archive-group-estimate": `${group.length * 48}px` }}
83
- >
84
- {group.map((post) => (
85
- <li class="stalux-archive-post-item">
86
- <time
87
- class="stalux-archive-post-date"
88
- datetime={post.data.date}
60
+ archiveYears.map((archiveYear) => (
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">
65
+ {t("archives.postCount", { n: archiveYear.count })}
66
+ </div>
67
+ </div>
68
+ {archiveYear.months.map(({ month, posts: monthPosts }) => (
69
+ <div
70
+ class="stalux-archive-month-section"
71
+ data-archive-month
72
+ style={{
73
+ "--archive-estimate": `${Math.ceil(monthPosts.length / 12) * 12 * 48 + 40}px`,
74
+ }}
75
+ >
76
+ <h3 class="stalux-archive-month-title">
77
+ {t("archives.month", { n: month })}
78
+ </h3>
79
+ {Array.from(
80
+ { length: Math.ceil(monthPosts.length / 12) },
81
+ (_, index) => monthPosts.slice(index * 12, (index + 1) * 12),
82
+ ).map((group) => (
83
+ <ul
84
+ class="stalux-archive-post-list"
85
+ style={{
86
+ "--archive-group-estimate": `${group.length * 48}px`,
87
+ }}
89
88
  >
90
- {format(parseDate(post.data.date), "yyyy-MM-dd")}
91
- </time>
92
- <a
93
- href={`/posts/${post.data.abbrlink}/`}
94
- class="stalux-archive-post-link"
95
- data-archive-description={post.data.desc || ""}
96
- data-astro-prefetch="viewport"
97
- >
98
- {post.data.title}
99
- </a>
100
- </li>
101
- ))}
102
- </ul>
103
- ))}
104
- </div>
105
- ))}
106
- </div>
107
- ))
108
- ) : (
109
- <div class="stalux-archive-no-posts">{t("archives.noPosts")}</div>
110
- )}
89
+ {group.map((post) => (
90
+ <li class="stalux-archive-post-item">
91
+ <time
92
+ class="stalux-archive-post-date"
93
+ datetime={post.data.date}
94
+ >
95
+ {format(
96
+ parseDate(post.data.date),
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
+ </div>
113
+ ))}
114
+ </div>
115
+ ))
116
+ ) : (
117
+ <div class="stalux-archive-no-posts">{t("archives.noPosts")}</div>
118
+ )}
111
119
  </div>
112
120
 
113
121
  <slot name="main" />
@@ -9,8 +9,8 @@ const categoryList = await getCategoryCountList(Astro.logger);
9
9
 
10
10
  <ul class="stalux-categories">
11
11
  {categoryList.map((category) => (
12
- <li>
13
- <CategoriesCard category={category} />
14
- </li>
15
- ))}
12
+ <li>
13
+ <CategoriesCard category={category} />
14
+ </li>
15
+ ))}
16
16
  </ul>
@@ -55,8 +55,8 @@ const formattedWordCount = formatWordCount(totalWordCount, siteConfig.lang || "z
55
55
  <div class="stalux-footer-content stalux-u-flex stalux-u-flex-col">
56
56
  <!-- η‰ˆζƒδΏ‘ζ― -->
57
57
  {footerConfig?.copyright?.enabled && (
58
- <FooterCopyright author={author} startYear={footerConfig?.copyright?.startYear} />
59
- )}
58
+ <FooterCopyright author={author} startYear={footerConfig?.copyright?.startYear} />
59
+ )}
60
60
 
61
61
  <!-- 徽章展瀺 -->
62
62
  <FooterBadges badges={badges} />
@@ -64,8 +64,12 @@ const formattedWordCount = formatWordCount(totalWordCount, siteConfig.lang || "z
64
64
  <!-- ε€‡ζ‘ˆδΏ‘ζ― -->
65
65
  <FooterBeian
66
66
  icp={footerConfig?.beian?.icp?.enabled ? footerConfig?.beian?.icp?.number : undefined}
67
- pubsec={footerConfig?.beian?.security?.enabled ? footerConfig?.beian?.security?.text : undefined}
68
- pubsecNumber={footerConfig?.beian?.security?.enabled ? footerConfig?.beian?.security?.number : undefined}
67
+ pubsec={footerConfig?.beian?.security?.enabled
68
+ ? footerConfig?.beian?.security?.text
69
+ : undefined}
70
+ pubsecNumber={footerConfig?.beian?.security?.enabled
71
+ ? footerConfig?.beian?.security?.number
72
+ : undefined}
69
73
  />
70
74
 
71
75
  <!-- 主钘俑息 -->
@@ -52,9 +52,9 @@ const ldJson = JSON.stringify(seo.schema).replace(/<\//g, "<\\/");
52
52
  openGraph={seo.openGraph}
53
53
  twitter={seo.twitter}
54
54
  extend={{
55
- link: seo.links,
56
- meta: seo.meta,
57
- }}
55
+ link: seo.links,
56
+ meta: seo.meta,
57
+ }}
58
58
  />
59
59
  <!-- 代码字体由 Astro Fonts API 注ε…₯οΌ›ζ­£ζ–‡ζŒ‰ι‘΅ι’η”Ÿζˆ native CJK 子集。 -->
60
60
  <Font cssVariable="--font-code" />
@@ -48,21 +48,21 @@ const navs = navsConfig?.items ?? [];
48
48
  class="stalux-nav-list stalux-u-flex stalux-u-items-center stalux-u-justify-center stalux-u-flex-wrap stalux-u-w-full stalux-u-min-w-0"
49
49
  >
50
50
  {navs.map((item) => {
51
- const NavIcon = item.icon ? getLucideIcon(item.icon, Astro.logger) : null;
52
- return (
53
- <li class="stalux-nav-item stalux-u-flex stalux-u-items-center">
54
- <a
55
- href={item.link}
56
- class="stalux-nav-link"
57
- data-ref="stalux-nav-link"
58
- data-astro-prefetch
59
- >
60
- {NavIcon && <NavIcon size={20} stroke-width={2} class="nav-icon" />}
61
- <span class="stalux-nav-text">{item.title}</span>
62
- </a>
63
- </li>
64
- );
65
- })}
51
+ const NavIcon = item.icon ? getLucideIcon(item.icon, Astro.logger) : null;
52
+ return (
53
+ <li class="stalux-nav-item stalux-u-flex stalux-u-items-center">
54
+ <a
55
+ href={item.link}
56
+ class="stalux-nav-link"
57
+ data-ref="stalux-nav-link"
58
+ data-astro-prefetch
59
+ >
60
+ {NavIcon && <NavIcon size={20} stroke-width={2} class="nav-icon" />}
61
+ <span class="stalux-nav-text">{item.title}</span>
62
+ </a>
63
+ </li>
64
+ );
65
+ })}
66
66
  <li class="stalux-nav-item stalux-u-flex stalux-u-items-center">
67
67
  <a
68
68
  href="#search"
@@ -12,8 +12,8 @@ const links = linksConfig?.sites ?? [];
12
12
 
13
13
  <ul class="stalux-links">
14
14
  {links.map((link) => (
15
- <li class="stalux-link-list-item">
16
- <LinkCard link={link} />
17
- </li>
18
- ))}
15
+ <li class="stalux-link-list-item">
16
+ <LinkCard link={link} />
17
+ </li>
18
+ ))}
19
19
  </ul>
@@ -42,40 +42,40 @@ function getIconByTitle(iconName: string): SimpleIcon | undefined {
42
42
  >
43
43
  <ul>
44
44
  {mediaLinks.map((item) => {
45
- const icon = item.icon ? getIconByTitle(item.icon) : undefined;
46
- return (
47
- <li class="social_icon">
48
- <a
49
- href={item.link}
50
- target="_blank"
51
- aria-label={item.icon}
52
- rel="noopener noreferrer"
53
- title={item.icon}
54
- class="a-none"
55
- >
56
- {icon ? (
57
- <div class="icon-container">
58
- <svg
59
- role="img"
60
- viewBox="0 0 24 24"
61
- xmlns="http://www.w3.org/2000/svg"
62
- width="24"
63
- height="24"
64
- fill="currentColor"
65
- aria-hidden="true"
66
- >
67
- <title>{icon.title}</title>
68
- <path d={icon.path} />
69
- </svg>
70
- </div>
71
- ) : (
72
- <span class="custom-icon">
73
- {item.icon ? item.icon.charAt(0).toUpperCase() : ""}
74
- </span>
75
- )}
76
- </a>
77
- </li>
78
- );
79
- })}
45
+ const icon = item.icon ? getIconByTitle(item.icon) : undefined;
46
+ return (
47
+ <li class="social_icon">
48
+ <a
49
+ href={item.link}
50
+ target="_blank"
51
+ aria-label={item.icon}
52
+ rel="noopener noreferrer"
53
+ title={item.icon}
54
+ class="a-none"
55
+ >
56
+ {icon ? (
57
+ <div class="icon-container">
58
+ <svg
59
+ role="img"
60
+ viewBox="0 0 24 24"
61
+ xmlns="http://www.w3.org/2000/svg"
62
+ width="24"
63
+ height="24"
64
+ fill="currentColor"
65
+ aria-hidden="true"
66
+ >
67
+ <title>{icon.title}</title>
68
+ <path d={icon.path} />
69
+ </svg>
70
+ </div>
71
+ ) : (
72
+ <span class="custom-icon">
73
+ {item.icon ? item.icon.charAt(0).toUpperCase() : ""}
74
+ </span>
75
+ )}
76
+ </a>
77
+ </li>
78
+ );
79
+ })}
80
80
  </ul>
81
81
  </nav>
@@ -50,14 +50,18 @@ const cfg = {
50
50
  >
51
51
  {items.length > 0 && <h3 class="stalux-post-taxonomy-title">{title ?? cfg.heading}</h3>}
52
52
  {items.length > 0 ? (
53
- <div class={cfg.listClass} transition:name={cfg.contentName}>
54
- {items.map((item) => (
55
- <a href={`${cfg.prefix}${item}/`} class={`${cfg.itemClass} a-none`} data-astro-prefetch>
56
- {item}
57
- </a>
58
- ))}
59
- </div>
60
- ) : (
61
- <div class="stalux-post-taxonomy-empty">{cfg.empty}</div>
62
- )}
53
+ <div class={cfg.listClass} transition:name={cfg.contentName}>
54
+ {items.map((item) => (
55
+ <a
56
+ href={`${cfg.prefix}${item}/`}
57
+ class={`${cfg.itemClass} a-none`}
58
+ data-astro-prefetch
59
+ >
60
+ {item}
61
+ </a>
62
+ ))}
63
+ </div>
64
+ ) : (
65
+ <div class="stalux-post-taxonomy-empty">{cfg.empty}</div>
66
+ )}
63
67
  </nav>
@@ -30,13 +30,13 @@ const licenseName = buildCCName(cc, t);
30
30
  <p class="stalux-license-title">{title}</p>
31
31
  <p class="stalux-license-author">{t("post.author")}{author}</p>
32
32
  {url && (
33
- <p class="stalux-license-url">
34
- {t("post.articleLink")}
35
- <a href={url} target="_blank" rel="noopener noreferrer">
36
- {url}
37
- </a>
38
- </p>
39
- )}
33
+ <p class="stalux-license-url">
34
+ {t("post.articleLink")}
35
+ <a href={url} target="_blank" rel="noopener noreferrer">
36
+ {url}
37
+ </a>
38
+ </p>
39
+ )}
40
40
  <p class="stalux-license-license">
41
41
  {t("post.licensedUnder")}
42
42
  <a href={licenseLink} target="_blank" rel="noopener noreferrer">
@@ -23,25 +23,25 @@ const description = post.data.desc || "";
23
23
  <article class="stalux-post-card-shell block h-full text-inherit no-underline">
24
24
  <div class="stalux-post-card stalux-u-flex stalux-u-flex-col stalux-u-w-full stalux-u-min-w-0">
25
25
  {post.data.cover && (
26
- <a
27
- href={`/posts/${post.data.abbrlink}/`}
28
- class="a-none"
29
- data-astro-prefetch="viewport"
30
- aria-label={post.data.title}
31
- >
32
- <div class="stalux-card-post-cover stalux-u-w-full stalux-u-min-w-0">
33
- <img
34
- src={post.data.cover}
35
- alt={post.data.title}
36
- loading={priority ? "eager" : "lazy"}
37
- decoding="async"
38
- fetchpriority={priority ? "high" : "auto"}
39
- width="640"
40
- height="360"
41
- />
42
- </div>
43
- </a>
44
- )}
26
+ <a
27
+ href={`/posts/${post.data.abbrlink}/`}
28
+ class="a-none"
29
+ data-astro-prefetch="viewport"
30
+ aria-label={post.data.title}
31
+ >
32
+ <div class="stalux-card-post-cover stalux-u-w-full stalux-u-min-w-0">
33
+ <img
34
+ src={post.data.cover}
35
+ alt={post.data.title}
36
+ loading={priority ? "eager" : "lazy"}
37
+ decoding="async"
38
+ fetchpriority={priority ? "high" : "auto"}
39
+ width="640"
40
+ height="360"
41
+ />
42
+ </div>
43
+ </a>
44
+ )}
45
45
  <h2
46
46
  class="stalux-card-post-title"
47
47
  transition:name={priority ? getPostTitleTransitionName(post.data.abbrlink) : undefined}
@@ -52,21 +52,27 @@ const description = post.data.desc || "";
52
52
  </h2>
53
53
  <div class="stalux-card-time stalux-u-items-center stalux-u-flex-wrap">
54
54
  {post.data.date && (
55
- <time
56
- class="stalux-card-post-date"
57
- datetime={timezone ? toMachineDateTime(post.data.date, timezone) : post.data.date}
58
- >
59
- {post.data.date}
60
- </time>
61
- )}
55
+ <time
56
+ class="stalux-card-post-date"
57
+ datetime={
58
+ timezone ? toMachineDateTime(post.data.date, timezone) : post.data.date
59
+ }
60
+ >
61
+ {post.data.date}
62
+ </time>
63
+ )}
62
64
  {post.data.updated && (
63
- <time
64
- class="stalux-card-post-updated"
65
- datetime={timezone ? toMachineDateTime(post.data.updated, timezone) : post.data.updated}
66
- >
67
- {post.data.updated}
68
- </time>
69
- )}
65
+ <time
66
+ class="stalux-card-post-updated"
67
+ datetime={
68
+ timezone
69
+ ? toMachineDateTime(post.data.updated, timezone)
70
+ : post.data.updated
71
+ }
72
+ >
73
+ {post.data.updated}
74
+ </time>
75
+ )}
70
76
  </div>
71
77
  <div class="stalux-card-post-description stalux-u-min-w-0">{description}</div>
72
78
  <div class="stalux-card-post-meta stalux-u-flex stalux-u-flex-col">
@@ -74,19 +80,19 @@ const description = post.data.desc || "";
74
80
  class="stalux-card-post-tags stalux-u-flex stalux-u-items-center stalux-u-flex-wrap"
75
81
  >
76
82
  {post.data.tags?.map((tag) => (
77
- <a class="a-none" href={`/tags/${tag}`} data-astro-prefetch>
78
- <span class="stalux-card-post-tag">{tag}</span>
79
- </a>
80
- ))}
83
+ <a class="a-none" href={`/tags/${tag}`} data-astro-prefetch>
84
+ <span class="stalux-card-post-tag">{tag}</span>
85
+ </a>
86
+ ))}
81
87
  </div>
82
88
  <div
83
89
  class="stalux-card-post-categories stalux-u-flex stalux-u-items-center stalux-u-flex-wrap"
84
90
  >
85
91
  {post.data.categories?.map((category) => (
86
- <a class="a-none" href={`/categories/${category}`} data-astro-prefetch>
87
- <span class="stalux-card-post-category">{category}</span>
88
- </a>
89
- ))}
92
+ <a class="a-none" href={`/categories/${category}`} data-astro-prefetch>
93
+ <span class="stalux-card-post-category">{category}</span>
94
+ </a>
95
+ ))}
90
96
  </div>
91
97
  </div>
92
98
  <a
@@ -47,61 +47,61 @@ const mdSourceUrl = exportMd ? `${Astro.url.pathname.replace(/\/$/, "")}.md` : "
47
47
  </h1>
48
48
  <div class="stalux-post-metadata">
49
49
  {props.date && (
50
- <time
51
- class="stalux-post-meta-item"
52
- datetime={timezone ? toMachineDateTime(props.date, timezone) : props.date}
53
- >
54
- {t("post.publishTime")}
55
- {props.date}
56
- </time>
57
- )}
50
+ <time
51
+ class="stalux-post-meta-item"
52
+ datetime={timezone ? toMachineDateTime(props.date, timezone) : props.date}
53
+ >
54
+ {t("post.publishTime")}
55
+ {props.date}
56
+ </time>
57
+ )}
58
58
 
59
59
  {props.updated && (
60
- <time
61
- class="stalux-post-meta-item"
62
- datetime={timezone ? toMachineDateTime(props.updated, timezone) : props.updated}
63
- >
64
- {t("post.updateTime")}
65
- {props.updated}
66
- </time>
67
- )}
60
+ <time
61
+ class="stalux-post-meta-item"
62
+ datetime={timezone ? toMachineDateTime(props.updated, timezone) : props.updated}
63
+ >
64
+ {t("post.updateTime")}
65
+ {props.updated}
66
+ </time>
67
+ )}
68
68
  </div>
69
69
  {(
70
- <div class="stalux-post-page-stats">
71
- {(props.readingMinutes ?? 0) > 0 && (
72
- <span class="stalux-post-reading-time">
73
- {t("post.readingTime")}
74
- {props.readingMinutes && props.readingMinutes > 0
75
- ? props.readingMinutes < 1
76
- ? t("common.lessThanOneMinute")
77
- : t("common.minute", { n: props.readingMinutes })
78
- : ""}
79
- </span>
70
+ <div class="stalux-post-page-stats">
71
+ {(props.readingMinutes ?? 0) > 0 && (
72
+ <span class="stalux-post-reading-time">
73
+ {t("post.readingTime")}
74
+ {props.readingMinutes && props.readingMinutes > 0
75
+ ? props.readingMinutes < 1
76
+ ? t("common.lessThanOneMinute")
77
+ : t("common.minute", { n: props.readingMinutes })
78
+ : ""}
79
+ </span>
80
+ )}
81
+ {(props.wordCount ?? 0) > 0 && (
82
+ <span class="wordCount">
83
+ {t("post.wordCount")}
84
+ {props.wordCount}
85
+ </span>
86
+ )}
87
+ <span id="vercount_container_page_pv">
88
+ {t("post.viewCount")}
89
+ <span id="vercount_value_page_pv">Loading...</span>
90
+ </span>
91
+ </div>
80
92
  )}
81
- {(props.wordCount ?? 0) > 0 && (
82
- <span class="wordCount">
83
- {t("post.wordCount")}
84
- {props.wordCount}
85
- </span>
86
- )}
87
- <span id="vercount_container_page_pv">
88
- {t("post.viewCount")}
89
- <span id="vercount_value_page_pv">Loading...</span>
90
- </span>
91
- </div>
92
- )}
93
93
  {exportMd && (
94
- <div class="stalux-post-source-link-row">
95
- <a
96
- class="stalux-post-source-link"
97
- href={mdSourceUrl}
98
- target="_blank"
99
- rel="noopener noreferrer"
100
- >
101
- {t("post.viewSource")}
102
- </a>
103
- </div>
104
- )}
94
+ <div class="stalux-post-source-link-row">
95
+ <a
96
+ class="stalux-post-source-link"
97
+ href={mdSourceUrl}
98
+ target="_blank"
99
+ rel="noopener noreferrer"
100
+ >
101
+ {t("post.viewSource")}
102
+ </a>
103
+ </div>
104
+ )}
105
105
  </header>
106
106
 
107
107
  <ArticleSummary description={props.description} label={t("post.summary")} />
@@ -14,9 +14,9 @@ const posts = props.posts ?? (await getCollection("posts", ({ data }) => !data.d
14
14
  <div data-stalux="postlist" class="stalux-post-list-container">
15
15
  <ul class="post-list">
16
16
  {posts.map((post, index) => (
17
- <li>
18
- <PostCard post={post} priority={index === 0} />
19
- </li>
20
- ))}
17
+ <li>
18
+ <PostCard post={post} priority={index === 0} />
19
+ </li>
20
+ ))}
21
21
  </ul>
22
22
  </div>
@@ -36,22 +36,22 @@ const tocItems = headings
36
36
  >
37
37
  <h3 class="stalux-toc-title">{title}</h3>
38
38
  {tocItems.length > 0 ? (
39
- <ul class="stalux-toc-list" transition:name="toc-content">
40
- {tocItems.map((heading) => (
41
- <li>
42
- <a
43
- class={`stalux-toc-item ${({ 1: "stalux-toc-depth-1", 2: "stalux-toc-depth-2", 3: "stalux-toc-depth-3", 4: "stalux-toc-depth-4", 5: "stalux-toc-depth-5", 6: "stalux-toc-depth-6" } as Record<number, string>)[heading.depth] || ""} a-none`}
44
- href={`#${heading.slug}`}
45
- data-toc-link
46
- >
47
- {heading.text}
48
- </a>
49
- </li>
50
- ))}
51
- </ul>
52
- ) : (
53
- <div class="stalux-toc-empty">{t("taxonomy.noToc")}</div>
54
- )}
39
+ <ul class="stalux-toc-list" transition:name="toc-content">
40
+ {tocItems.map((heading) => (
41
+ <li>
42
+ <a
43
+ class={`stalux-toc-item ${({ 1: "stalux-toc-depth-1", 2: "stalux-toc-depth-2", 3: "stalux-toc-depth-3", 4: "stalux-toc-depth-4", 5: "stalux-toc-depth-5", 6: "stalux-toc-depth-6" } as Record<number, string>)[heading.depth] || ""} a-none`}
44
+ href={`#${heading.slug}`}
45
+ data-toc-link
46
+ >
47
+ {heading.text}
48
+ </a>
49
+ </li>
50
+ ))}
51
+ </ul>
52
+ ) : (
53
+ <div class="stalux-toc-empty">{t("taxonomy.noToc")}</div>
54
+ )}
55
55
  </nav>
56
56
 
57
57
  <script src="../../../scripts/toc-scrollspy.ts"></script>
@@ -24,26 +24,26 @@ const tagLinks = tagList.map((t) => ({
24
24
  <!-- 移动端:SSR 卑片 -->
25
25
  <div class="stalux-cloud-cards" id="tags-cards">
26
26
  {tagList.length > 0 ? (
27
- tagGroups.map((group) => (
28
- <div class="stalux-cloud-tag-group">
29
- {group.map(({ name, count }) => (
30
- <a
31
- href={`/tags/${name}/`}
32
- class="stalux-cloud-tag-card"
33
- data-stalux-card
34
- data-stalux-tag-card
35
- data-count={count}
36
- data-astro-prefetch
37
- >
38
- <span class="stalux-cloud-tag-name">{name}</span>
39
- <span class="stalux-cloud-tag-count">{count}</span>
40
- </a>
41
- ))}
42
- </div>
43
- ))
44
- ) : (
45
- <div class="stalux-cloud-no-tags">{t("tags.noTags")}</div>
46
- )}
27
+ tagGroups.map((group) => (
28
+ <div class="stalux-cloud-tag-group">
29
+ {group.map(({ name, count }) => (
30
+ <a
31
+ href={`/tags/${name}/`}
32
+ class="stalux-cloud-tag-card"
33
+ data-stalux-card
34
+ data-stalux-tag-card
35
+ data-count={count}
36
+ data-astro-prefetch
37
+ >
38
+ <span class="stalux-cloud-tag-name">{name}</span>
39
+ <span class="stalux-cloud-tag-count">{count}</span>
40
+ </a>
41
+ ))}
42
+ </div>
43
+ ))
44
+ ) : (
45
+ <div class="stalux-cloud-no-tags">{t("tags.noTags")}</div>
46
+ )}
47
47
  </div>
48
48
 
49
49
  <!-- 摌青端:Canvas ζ ‡η­ΎδΊ‘ -->
@@ -23,32 +23,32 @@ const machineDate = date && timezone ? toMachineDateTime(date, timezone) : date;
23
23
  <Content />
24
24
  </div>
25
25
  {(date || source || sourceDate) && (
26
- <footer class="stalux-word-footer">
27
- {date ? (
28
- <time class="stalux-word-date" datetime={machineDate}>
29
- {date}
30
- </time>
31
- ) : (
32
- <span />
33
- )}
34
- {(source || sourceDate) && (
35
- <div class="stalux-word-source-meta">
36
- {sourceDate && <span class="stalux-word-source-date">{sourceDate}</span>}
37
- {source &&
38
- (link ? (
39
- <a
40
- href={link}
41
- target="_blank"
42
- rel="noopener noreferrer"
43
- class="stalux-word-source-link"
44
- >
45
- β€” {source}
46
- </a>
47
- ) : (
48
- <span class="stalux-word-source-text">β€” {source}</span>
49
- ))}
50
- </div>
51
- )}
52
- </footer>
53
- )}
26
+ <footer class="stalux-word-footer">
27
+ {date ? (
28
+ <time class="stalux-word-date" datetime={machineDate}>
29
+ {date}
30
+ </time>
31
+ ) : (
32
+ <span />
33
+ )}
34
+ {(source || sourceDate) && (
35
+ <div class="stalux-word-source-meta">
36
+ {sourceDate && <span class="stalux-word-source-date">{sourceDate}</span>}
37
+ {source &&
38
+ (link ? (
39
+ <a
40
+ href={link}
41
+ target="_blank"
42
+ rel="noopener noreferrer"
43
+ class="stalux-word-source-link"
44
+ >
45
+ β€” {source}
46
+ </a>
47
+ ) : (
48
+ <span class="stalux-word-source-text">β€” {source}</span>
49
+ ))}
50
+ </div>
51
+ )}
52
+ </footer>
53
+ )}
54
54
  </article>
@@ -21,24 +21,24 @@ const sorted = [...entries].sort((a, b) => {
21
21
 
22
22
  <ul class="stalux-word-list-list">
23
23
  {sorted.map((entry) => {
24
- const hash = entry.data.abbrlink ? `#word-${entry.data.abbrlink}` : undefined;
25
- return (
26
- <li class="stalux-word-list-item">
27
- {hash ? (
28
- <a
29
- href={hash}
30
- class="a-none"
31
- data-word-hash={hash}
32
- aria-label={`Jump to ${entry.data.abbrlink}`}
33
- >
24
+ const hash = entry.data.abbrlink ? `#word-${entry.data.abbrlink}` : undefined;
25
+ return (
26
+ <li class="stalux-word-list-item">
27
+ {hash ? (
28
+ <a
29
+ href={hash}
30
+ class="a-none"
31
+ data-word-hash={hash}
32
+ aria-label={`Jump to ${entry.data.abbrlink}`}
33
+ >
34
+ <WordCard entry={entry} timezone={timezone} />
35
+ </a>
36
+ ) : (
34
37
  <WordCard entry={entry} timezone={timezone} />
35
- </a>
36
- ) : (
37
- <WordCard entry={entry} timezone={timezone} />
38
- )}
39
- </li>
40
- );
41
- })}
38
+ )}
39
+ </li>
40
+ );
41
+ })}
42
42
  </ul>
43
43
 
44
44
  <script src="../../../scripts/word-list.ts"></script>
package/src/index.ts CHANGED
@@ -291,6 +291,7 @@ export function stalux(options: StaluxOptions = {}): AstroIntegration[] {
291
291
  mermaidHast({
292
292
  responsive: true,
293
293
  theme: "dark",
294
+ themeVariables: { background: "transparent" },
294
295
  themeOverrides: { clusterBorder: "#cccccc" },
295
296
  }),
296
297
  seen,
@@ -60,7 +60,9 @@ const walineConfig = walineSection?.serverURL
60
60
  <PostContent
61
61
  title={props.title}
62
62
  description={props.description}
63
- titleTransitionName={props.postId === undefined ? undefined : getPostTitleTransitionName(props.postId)}
63
+ titleTransitionName={props.postId === undefined
64
+ ? undefined
65
+ : getPostTitleTransitionName(props.postId)}
64
66
  date={props.date}
65
67
  updated={props.updated}
66
68
  readingMinutes={props.readingMinutes}
@@ -71,12 +73,12 @@ const walineConfig = walineSection?.serverURL
71
73
  <PostCC title={props.title} author={author} url={Astro.url.href} cc={props.cc} />
72
74
  <PostNavigation prev={props.prev} next={props.next} />
73
75
  {commentEnabled && walineConfig?.serverURL && (
74
- <WalineComment
75
- {...buildWalineProps(walineConfig)}
76
- path={Astro.url.pathname}
77
- title={props.title}
78
- />
79
- )}
76
+ <WalineComment
77
+ {...buildWalineProps(walineConfig)}
78
+ path={Astro.url.pathname}
79
+ title={props.title}
80
+ />
81
+ )}
80
82
  </PostContent>
81
83
 
82
84
  <!-- Right Sidebar -->
@@ -83,10 +83,10 @@ const routeAnimation = getRouteAnimation(routeKind);
83
83
  data-stalux-umami-url={headConfig?.umami?.url}
84
84
  >
85
85
  {llmPromote && (
86
- <section class="stalux-ai-prompt" data-stalux-ai-prompt aria-label="AI site context">
87
- <p>{llmPromote}</p>
88
- </section>
89
- )}
86
+ <section class="stalux-ai-prompt" data-stalux-ai-prompt aria-label="AI site context">
87
+ <p>{llmPromote}</p>
88
+ </section>
89
+ )}
90
90
  <div
91
91
  class="bg-layer bg-a"
92
92
  data-stalux-background="a"
@@ -47,12 +47,12 @@ const author = authorConfig.name;
47
47
  cc="CC-BY-NC-SA-4.0"
48
48
  />
49
49
  {commentEnabled && walineConfig?.serverURL && (
50
- <WalineComment
51
- {...buildWalineProps(walineConfig)}
52
- path={Astro.url.pathname}
53
- title={aboutPage.data.title}
54
- />
55
- )}
50
+ <WalineComment
51
+ {...buildWalineProps(walineConfig)}
52
+ path={Astro.url.pathname}
53
+ title={aboutPage.data.title}
54
+ />
55
+ )}
56
56
  </PostContent>
57
57
  </div>
58
58
  </Stalux>
@@ -28,10 +28,10 @@ const props = Astro.props as Props;
28
28
  <Stalux
29
29
  title={`${t("taxonomy.category")}: ${props.category} | ${siteConfig.title}`}
30
30
  description={t("taxonomy.browseCategory", {
31
- title: siteConfig.title,
32
- category: props.category,
33
- count: props.count,
34
- })}
31
+ title: siteConfig.title,
32
+ category: props.category,
33
+ count: props.count,
34
+ })}
35
35
  >
36
36
  <div style="height: 3em;"></div>
37
37
  <Navs />
@@ -28,7 +28,11 @@ const props = Astro.props as Props;
28
28
 
29
29
  <Stalux
30
30
  title={`${t("taxonomy.tag")}: ${props.tag} | ${siteConfig.title}`}
31
- description={t("taxonomy.browseTag", { title: siteConfig.title, tag: props.tag, count: props.count })}
31
+ description={t("taxonomy.browseTag", {
32
+ title: siteConfig.title,
33
+ tag: props.tag,
34
+ count: props.count,
35
+ })}
32
36
  noindex={props.count < 3}
33
37
  >
34
38
  <div style="height: 3em;"></div>