@xingwangzhe/stalux 1.2.0

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 (214) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +192 -0
  3. package/package.json +108 -0
  4. package/scripts/cli.mjs +103 -0
  5. package/src/assets/BiCcCircle.svg +1 -0
  6. package/src/assets/astro.svg +1 -0
  7. package/src/assets/background/README.md +3 -0
  8. package/src/assets/background/pattern-1.min.svg +1 -0
  9. package/src/assets/background/pattern-10.min.svg +1 -0
  10. package/src/assets/background/pattern-11.min.svg +1 -0
  11. package/src/assets/background/pattern-12.min.svg +1 -0
  12. package/src/assets/background/pattern-13.min.svg +1 -0
  13. package/src/assets/background/pattern-14.min.svg +1 -0
  14. package/src/assets/background/pattern-15.min.svg +1 -0
  15. package/src/assets/background/pattern-16.min.svg +1 -0
  16. package/src/assets/background/pattern-17.min.svg +1 -0
  17. package/src/assets/background/pattern-18.min.svg +1 -0
  18. package/src/assets/background/pattern-19.min.svg +1 -0
  19. package/src/assets/background/pattern-2.min.svg +1 -0
  20. package/src/assets/background/pattern-20.min.svg +1 -0
  21. package/src/assets/background/pattern-21.min.svg +1 -0
  22. package/src/assets/background/pattern-22.min.svg +1 -0
  23. package/src/assets/background/pattern-23.min.svg +1 -0
  24. package/src/assets/background/pattern-24.min.svg +1 -0
  25. package/src/assets/background/pattern-25.min.svg +1 -0
  26. package/src/assets/background/pattern-26.min.svg +1 -0
  27. package/src/assets/background/pattern-27.min.svg +1 -0
  28. package/src/assets/background/pattern-28.min.svg +1 -0
  29. package/src/assets/background/pattern-29.min.svg +1 -0
  30. package/src/assets/background/pattern-3.min.svg +1 -0
  31. package/src/assets/background/pattern-30.min.svg +1 -0
  32. package/src/assets/background/pattern-31.min.svg +1 -0
  33. package/src/assets/background/pattern-32.min.svg +1 -0
  34. package/src/assets/background/pattern-33.min.svg +1 -0
  35. package/src/assets/background/pattern-34.min.svg +1 -0
  36. package/src/assets/background/pattern-35.min.svg +1 -0
  37. package/src/assets/background/pattern-36.min.svg +1 -0
  38. package/src/assets/background/pattern-37.min.svg +1 -0
  39. package/src/assets/background/pattern-38.min.svg +1 -0
  40. package/src/assets/background/pattern-39.min.svg +1 -0
  41. package/src/assets/background/pattern-4.min.svg +1 -0
  42. package/src/assets/background/pattern-40.min.svg +1 -0
  43. package/src/assets/background/pattern-41.min.svg +1 -0
  44. package/src/assets/background/pattern-42.min.svg +1 -0
  45. package/src/assets/background/pattern-5.min.svg +1 -0
  46. package/src/assets/background/pattern-6.min.svg +1 -0
  47. package/src/assets/background/pattern-7.min.svg +1 -0
  48. package/src/assets/background/pattern-8.min.svg +1 -0
  49. package/src/assets/background/pattern-9.min.svg +1 -0
  50. package/src/assets/background.svg +1 -0
  51. package/src/assets/cc-icon.svg +4 -0
  52. package/src/assets/fonts/GoogleSansCode-Italic.woff2 +0 -0
  53. package/src/assets/fonts/GoogleSansCode.woff2 +0 -0
  54. package/src/assets/fonts/LXGWWenKai-Regular.ttf +0 -0
  55. package/src/assets/fonts/LXGWWenKai-Regular.woff2 +0 -0
  56. package/src/components/stalux/analytics/clarity.astro +25 -0
  57. package/src/components/stalux/analytics/google.astro +31 -0
  58. package/src/components/stalux/analytics/umami.astro +16 -0
  59. package/src/components/stalux/archives/archivesList.astro +116 -0
  60. package/src/components/stalux/archives/toArchive.astro +14 -0
  61. package/src/components/stalux/categories/categoriesCard.astro +49 -0
  62. package/src/components/stalux/categories/categoriesList.astro +17 -0
  63. package/src/components/stalux/common/author.astro +35 -0
  64. package/src/components/stalux/common/date.astro +59 -0
  65. package/src/components/stalux/common/search.astro +14 -0
  66. package/src/components/stalux/common/textType.astro +16 -0
  67. package/src/components/stalux/common/verCount.astro +10 -0
  68. package/src/components/stalux/footer/FooterBadges.astro +150 -0
  69. package/src/components/stalux/footer/FooterBeian.astro +91 -0
  70. package/src/components/stalux/footer/FooterCopyright.astro +40 -0
  71. package/src/components/stalux/footer/FooterStats.astro +108 -0
  72. package/src/components/stalux/footer/FooterThemeInfo.astro +67 -0
  73. package/src/components/stalux/layout/footer.astro +87 -0
  74. package/src/components/stalux/layout/head.astro +194 -0
  75. package/src/components/stalux/layout/listPage.astro +26 -0
  76. package/src/components/stalux/layout/navs.astro +174 -0
  77. package/src/components/stalux/links/linkCard.astro +50 -0
  78. package/src/components/stalux/links/linkList.astro +20 -0
  79. package/src/components/stalux/links/socialMedia.astro +102 -0
  80. package/src/components/stalux/posts/PhotoSwipeStyle.astro +3 -0
  81. package/src/components/stalux/posts/PostTaxonomy.astro +65 -0
  82. package/src/components/stalux/posts/WalineComment.astro +609 -0
  83. package/src/components/stalux/posts/postAuthor.astro +23 -0
  84. package/src/components/stalux/posts/postCC.astro +52 -0
  85. package/src/components/stalux/posts/postCard.astro +83 -0
  86. package/src/components/stalux/posts/postContent.astro +174 -0
  87. package/src/components/stalux/posts/postLeft.astro +41 -0
  88. package/src/components/stalux/posts/postList.astro +25 -0
  89. package/src/components/stalux/posts/postNavigation.astro +137 -0
  90. package/src/components/stalux/posts/postRight.astro +33 -0
  91. package/src/components/stalux/posts/postToc.astro +88 -0
  92. package/src/components/stalux/posts/randomPost.astro +134 -0
  93. package/src/components/stalux/tags/tagHeader.astro +50 -0
  94. package/src/components/stalux/tags/tagsCloud.astro +100 -0
  95. package/src/components/stalux/words/wordCard.astro +62 -0
  96. package/src/components/stalux/words/wordList.astro +70 -0
  97. package/src/config.ts +58 -0
  98. package/src/i18n/en.json +193 -0
  99. package/src/i18n/zh-CN.json +193 -0
  100. package/src/index.ts +215 -0
  101. package/src/internal/components-plugin.ts +54 -0
  102. package/src/internal/dev-toolbar.ts +33 -0
  103. package/src/internal/override.ts +99 -0
  104. package/src/internal/pagefind.ts +40 -0
  105. package/src/layouts/PostLayout.astro +90 -0
  106. package/src/layouts/Stalux.astro +91 -0
  107. package/src/pages/404.astro +103 -0
  108. package/src/pages/about.astro +59 -0
  109. package/src/pages/about.md.ts +15 -0
  110. package/src/pages/api/post.abbrlink.json.ts +20 -0
  111. package/src/pages/archives.astro +23 -0
  112. package/src/pages/archives.md.ts +24 -0
  113. package/src/pages/atom.xml.ts +29 -0
  114. package/src/pages/categories/[category].astro +35 -0
  115. package/src/pages/categories/[category].md.ts +34 -0
  116. package/src/pages/categories/index.astro +23 -0
  117. package/src/pages/categories/index.md.ts +27 -0
  118. package/src/pages/index.astro +30 -0
  119. package/src/pages/index.md.ts +18 -0
  120. package/src/pages/links.astro +23 -0
  121. package/src/pages/links.md.ts +18 -0
  122. package/src/pages/llms-full.txt.ts +25 -0
  123. package/src/pages/llms.txt.ts +26 -0
  124. package/src/pages/posts/[post].astro +69 -0
  125. package/src/pages/posts/[post].md.ts +109 -0
  126. package/src/pages/rss.xml.ts +29 -0
  127. package/src/pages/tags/[tag].astro +37 -0
  128. package/src/pages/tags/[tag].md.ts +34 -0
  129. package/src/pages/tags/index.astro +23 -0
  130. package/src/pages/tags/index.md.ts +27 -0
  131. package/src/pages/words.astro +24 -0
  132. package/src/pages/words.md.ts +14 -0
  133. package/src/plugins/feature-flags.ts +68 -0
  134. package/src/plugins/satteri-temml.ts +81 -0
  135. package/src/schemas/collections.ts +140 -0
  136. package/src/schemas/config.ts +226 -0
  137. package/src/scripts/background.ts +59 -0
  138. package/src/styles/base/init.css +286 -0
  139. package/src/styles/base/math.css +411 -0
  140. package/src/styles/components/archives/archivesList.module.css +378 -0
  141. package/src/styles/components/archives/toArchive.module.css +3 -0
  142. package/src/styles/components/categories/categoriesCard.module.css +87 -0
  143. package/src/styles/components/categories/categoriesList.module.css +27 -0
  144. package/src/styles/components/common/author.module.css +73 -0
  145. package/src/styles/components/common/date.module.css +15 -0
  146. package/src/styles/components/common/textType.module.css +10 -0
  147. package/src/styles/components/footer/footer.module.css +44 -0
  148. package/src/styles/components/layout/navs.module.css +250 -0
  149. package/src/styles/components/links/linkCard.module.css +99 -0
  150. package/src/styles/components/links/linkList.module.css +67 -0
  151. package/src/styles/components/links/socialLinks.module.css +22 -0
  152. package/src/styles/components/markdown.css +528 -0
  153. package/src/styles/components/posts/postAuthor.module.css +32 -0
  154. package/src/styles/components/posts/postCC.module.css +138 -0
  155. package/src/styles/components/posts/postCard.module.css +156 -0
  156. package/src/styles/components/posts/postCategories.module.css +50 -0
  157. package/src/styles/components/posts/postContent.module.css +230 -0
  158. package/src/styles/components/posts/postLayout.module.css +142 -0
  159. package/src/styles/components/posts/postLeft.module.css +38 -0
  160. package/src/styles/components/posts/postList.module.css +24 -0
  161. package/src/styles/components/posts/postNavigation.module.css +187 -0
  162. package/src/styles/components/posts/postRight.module.css +60 -0
  163. package/src/styles/components/posts/postSidebar.module.css +57 -0
  164. package/src/styles/components/posts/postTags.module.css +51 -0
  165. package/src/styles/components/posts/postTaxonomy.module.css +87 -0
  166. package/src/styles/components/posts/postToc.module.css +74 -0
  167. package/src/styles/components/posts/randomPost.module.css +131 -0
  168. package/src/styles/components/tags/tagHeader.module.css +44 -0
  169. package/src/styles/components/tags/tagsCloud.module.css +124 -0
  170. package/src/styles/components/words/wordCard.module.css +130 -0
  171. package/src/styles/components/words/wordList.module.css +39 -0
  172. package/src/styles/pages/archives.module.css +18 -0
  173. package/src/styles/pages/categories.module.css +13 -0
  174. package/src/styles/pages/home.module.css +51 -0
  175. package/src/styles/pages/listPage.module.css +13 -0
  176. package/src/styles/pages/tags.module.css +12 -0
  177. package/src/styles/pages/words.module.css +13 -0
  178. package/src/styles/shared/animations.css +87 -0
  179. package/src/styles/shared/stagger.css +20 -0
  180. package/src/utils/ai-discovery.ts +547 -0
  181. package/src/utils/badge-generator.ts +68 -0
  182. package/src/utils/cc.ts +46 -0
  183. package/src/utils/collections-stats.ts +48 -0
  184. package/src/utils/config-utils.ts +107 -0
  185. package/src/utils/count-words.ts +20 -0
  186. package/src/utils/dayjs.ts +106 -0
  187. package/src/utils/feed.ts +70 -0
  188. package/src/utils/i18n.ts +64 -0
  189. package/src/utils/lucide-icons.ts +52 -0
  190. package/src/utils/semantic-time.ts +11 -0
  191. package/src/utils/taxonomy.ts +44 -0
  192. package/src/utils/toc-scrollspy.ts +95 -0
  193. package/src/utils/waline.ts +27 -0
  194. package/src/utils/word-count-utils.ts +83 -0
  195. package/template/astro.config.mjs +51 -0
  196. package/template/package.json +27 -0
  197. package/template/public/robots.txt +3 -0
  198. package/template/src/content.config.ts +11 -0
  199. package/template/stalux/about/index.md +14 -0
  200. package/template/stalux/config/ai-discovery.yml +2 -0
  201. package/template/stalux/config/author.yml +4 -0
  202. package/template/stalux/config/comment.yml +5 -0
  203. package/template/stalux/config/footer.yml +13 -0
  204. package/template/stalux/config/head.yml +7 -0
  205. package/template/stalux/config/links.yml +4 -0
  206. package/template/stalux/config/media-links.yml +8 -0
  207. package/template/stalux/config/navs.yml +23 -0
  208. package/template/stalux/config/promote.yml +2 -0
  209. package/template/stalux/config/site.yml +7 -0
  210. package/template/stalux/config/typetexts.yml +5 -0
  211. package/template/stalux/posts/hello-stalux.md +47 -0
  212. package/template/stalux/words/_template.md +12 -0
  213. package/template/stalux/words/einstein-imagination.md +8 -0
  214. package/template/tsconfig.json +9 -0
@@ -0,0 +1,90 @@
1
+ ---
2
+ import PostLeft from "@components/stalux/posts/postLeft.astro";
3
+ import PostContent from "@components/stalux/posts/postContent.astro";
4
+ import PostRight from "@components/stalux/posts/postRight.astro";
5
+ import PostNavigation from "@components/stalux/posts/postNavigation.astro";
6
+ import PostCC from "@components/stalux/posts/postCC.astro";
7
+ import WalineComment from "@components/stalux/posts/WalineComment.astro";
8
+ import { buildWalineProps } from "@utils/waline";
9
+ import PhotoSwipeStyle from "@components/stalux/posts/PhotoSwipeStyle.astro";
10
+ import { getCollection } from "astro:content";
11
+ import "@styles/base/math.css";
12
+ import layoutStyle from "@styles/components/posts/postLayout.module.css";
13
+
14
+ interface Props {
15
+ title: string;
16
+ date?: string;
17
+ updated?: string;
18
+ readingTime?: string;
19
+ readingMinutes?: number;
20
+ wordCount?: number;
21
+ tags?: string[];
22
+ categories?: string[];
23
+ headings?: Array<{ depth: number; slug: string; text: string }>;
24
+ author?: string;
25
+ authorAvatar?: string;
26
+ prev?: { url: string; title: string };
27
+ next?: { url: string; title: string };
28
+ cc?: string;
29
+ hasImage?: boolean;
30
+ }
31
+
32
+ const props = Astro.props as Props;
33
+ const tags = props.tags ?? [];
34
+ const categories = props.categories ?? [];
35
+ const headings = props.headings ?? [];
36
+ const author = props.author ?? "Author";
37
+ // 获取 Waline 配置
38
+ const configEntries = await getCollection("config");
39
+ const commentConfig = (configEntries.find(e => e.id === "comment")?.data ?? {}) as Record<string, unknown>;
40
+ const walineSection = commentConfig.waline as Record<string, unknown> | undefined;
41
+ const commentEnabled = (commentConfig.enabled as boolean) ?? false;
42
+ const walineConfig = walineSection && walineSection.serverURL ? {
43
+ ...walineSection,
44
+ emoji: walineSection.emoji ?? [
45
+ "https://unpkg.com/@waline/emojis@1.1.0/bilibili",
46
+ "https://unpkg.com/@waline/emojis@1.1.0/bmoji",
47
+ ],
48
+ } : undefined;
49
+ ---
50
+
51
+ {props.hasImage && <PhotoSwipeStyle />}
52
+
53
+ <div class={layoutStyle.postLayout}>
54
+ <div class={layoutStyle.container}>
55
+ <!-- Left Sidebar -->
56
+ <PostLeft author={author} authorAvatar={props.authorAvatar} />
57
+
58
+ <!-- Main Content -->
59
+ <PostContent
60
+ title={props.title}
61
+ date={props.date}
62
+ updated={props.updated}
63
+ readingTime={props.readingTime}
64
+ readingMinutes={props.readingMinutes}
65
+ wordCount={props.wordCount}
66
+ hasImage={props.hasImage}
67
+ >
68
+ <slot />
69
+ <PostCC
70
+ title={props.title}
71
+ author={author}
72
+ url={Astro.url.href}
73
+ cc={props.cc}
74
+ />
75
+ <PostNavigation prev={props.prev} next={props.next} />
76
+ {
77
+ commentEnabled && walineConfig?.serverURL && (
78
+ <WalineComment
79
+ {...buildWalineProps(walineConfig)}
80
+ path={Astro.url.pathname}
81
+ title={props.title}
82
+ />
83
+ )
84
+ }
85
+ </PostContent>
86
+
87
+ <!-- Right Sidebar -->
88
+ <PostRight headings={headings} tags={tags} categories={categories} />
89
+ </div>
90
+ </div>
@@ -0,0 +1,91 @@
1
+ ---
2
+ import Head from "@components/stalux/layout/head.astro";
3
+ import Footer from "@components/stalux/layout/footer.astro";
4
+ import { getCollection } from "astro:content";
5
+ import "@styles/base/init.css";
6
+ import "@styles/shared/stagger.css";
7
+ import { getAuthorData, getPromoteData, getSiteData } from "@utils/config-utils";
8
+ const props = Astro.props as Props;
9
+
10
+ interface Props {
11
+ title: string;
12
+ description: string;
13
+ cover?: string;
14
+ isArticle?: boolean;
15
+ date?: string;
16
+ updated?: string;
17
+ tags?: string[];
18
+ categories?: string[];
19
+ author?: string;
20
+ noindex?: boolean;
21
+ }
22
+
23
+ const configEntries = await getCollection("config");
24
+ const siteConfig = getSiteData(configEntries);
25
+ const authorConfig = getAuthorData(configEntries);
26
+ const promoteConfig = getPromoteData(configEntries);
27
+ const htmlLang = siteConfig.lang || "zh-CN";
28
+
29
+ const bgModules = import.meta.glob<{ default: { src: string } }>(
30
+ "../assets/background/pattern-*.min.svg",
31
+ { eager: true },
32
+ );
33
+ const bgUrls = Object.values(bgModules)
34
+ .map((m) => m.default.src)
35
+ .sort((a, b) => {
36
+ const na = parseInt(a.match(/pattern-(\d+)/)?.[1] || "0", 10);
37
+ const nb = parseInt(b.match(/pattern-(\d+)/)?.[1] || "0", 10);
38
+ return na - nb;
39
+ });
40
+ const randomIndex = bgUrls.length > 0 ? Math.floor(Math.random() * bgUrls.length) : 0;
41
+ const initialBg = bgUrls[randomIndex] || "";
42
+ const llmPromoteRaw = promoteConfig?.llm_promote ?? "";
43
+ const llmPromote = llmPromoteRaw
44
+ ?.replace(/\{author\}/g, authorConfig.name)
45
+ ?.replace(/\{url\}/g, siteConfig.url)
46
+ ?.replace(/\{title\}/g, siteConfig.title)
47
+ ?.replace(/\{cc\}/g, "CC-BY-NC-SA-4.0");
48
+ ---
49
+
50
+ <!doctype html>
51
+ <html lang={htmlLang}>
52
+ <Head
53
+ title={props.title}
54
+ description={props.description}
55
+ cover={props.cover}
56
+ isArticle={props.isArticle}
57
+ date={props.date}
58
+ updated={props.updated}
59
+ tags={props.tags}
60
+ categories={props.categories}
61
+ author={props.author}
62
+ noindex={props.noindex}
63
+ />
64
+ <script define:vars={{ bgUrls, randomIndex }}>
65
+ window.__STALUX_BG_URLS__ = bgUrls;
66
+ window.__STALUX_BG_INDEX__ = randomIndex;
67
+ </script>
68
+ <script>
69
+ import "../scripts/background.ts";
70
+ </script>
71
+ <body
72
+ class="stalux-root dark"
73
+ data-stalux-bg-layer="a"
74
+ data-stalux-bg-index={randomIndex}
75
+ >
76
+ {llmPromote && <div style="display:none">{llmPromote}</div>}
77
+ <div
78
+ class="bg-layer bg-a"
79
+ style={`background-image: url('${initialBg}'); opacity: 1;`}
80
+ aria-hidden="true"
81
+ >
82
+ </div>
83
+ <div class="bg-layer bg-b" aria-hidden="true"></div>
84
+ <main class="stalux-main">
85
+ <slot />
86
+ </main>
87
+ <Footer />
88
+ </body>
89
+ </html>
90
+
91
+ <style></style>
@@ -0,0 +1,103 @@
1
+ ---
2
+ import Stalux from "@layouts/Stalux.astro";
3
+ import Navs from "@components/stalux/layout/navs.astro";
4
+ import { getCollection } from "astro:content";
5
+ import { createTranslator } from "@utils/i18n";
6
+ import { getSiteData, getAuthorData, getHeadData, getNavsData, getLinksData, getCommentData, getFooterData, getPromoteData, getTypetextsData, getMediaLinksData } from "@utils/config-utils";
7
+
8
+ const configEntries = await getCollection("config");
9
+ const siteConfig = getSiteData(configEntries);
10
+ const { t } = createTranslator(siteConfig.lang || "zh-CN");
11
+ ---
12
+
13
+ <Stalux
14
+ title={t("page404.title") + " | " + siteConfig.title}
15
+ description={t("page404.description")}
16
+ >
17
+ <div style="height: 3em;"></div>
18
+ <Navs />
19
+ <div class="error-container" data-pagefind-ignore>
20
+ <div class="error-content">
21
+ <h1>404</h1>
22
+ <p>{t("page404.pageNotFound")}</p>
23
+ <p id="countdown" class="countdown-text">{t("page404.countdown", { n: 5 })}</p>
24
+ <a href="/" class="home-btn" data-astro-prefetch>{t("page404.backHome")}</a>
25
+ </div>
26
+ </div>
27
+
28
+ <script define:vars={{ countdownText: t("page404.countdown", { n: "{n}" }) }}>
29
+ let seconds = 5;
30
+ const el = document.getElementById("countdown");
31
+ const timer = setInterval(() => {
32
+ seconds--;
33
+ if (seconds <= 0) {
34
+ clearInterval(timer);
35
+ window.location.href = "/";
36
+ } else {
37
+ el.textContent = countdownText.replace("{n}", String(seconds));
38
+ }
39
+ }, 1000);
40
+ </script>
41
+ </Stalux>
42
+
43
+ <style>
44
+ .error-container {
45
+ text-align: center;
46
+ padding: 2rem;
47
+ min-height: 60vh;
48
+ display: flex;
49
+ align-items: center;
50
+ justify-content: center;
51
+ }
52
+
53
+ .error-content h1 {
54
+ font-size: 6rem;
55
+ font-weight: bold;
56
+ margin: 0;
57
+ color: var(--white-90p);
58
+ text-shadow: 0 2px 10px var(--shadow-medium);
59
+ }
60
+
61
+ .error-content p {
62
+ font-size: 1.5rem;
63
+ margin: 1rem 0 2rem 0;
64
+ color: var(--white-70p);
65
+ }
66
+
67
+ .countdown-text {
68
+ font-size: 0.95rem !important;
69
+ color: var(--white-50p) !important;
70
+ margin: -0.5rem 0 1.5rem 0 !important;
71
+ }
72
+
73
+ .home-btn {
74
+ display: inline-block;
75
+ padding: var(--space-md) var(--space-lg);
76
+ background: var(--black-20p);
77
+ color: var(--white-90p);
78
+ text-decoration: none;
79
+ border-radius: var(--radius-md);
80
+ border: var(--border-thin) solid var(--white-20p);
81
+ transition:
82
+ background-color var(--transition-normal),
83
+ transform var(--transition-normal),
84
+ box-shadow var(--transition-normal);
85
+ font-size: var(--font-size-base);
86
+ }
87
+
88
+ .home-btn:hover {
89
+ background: var(--accent-20p);
90
+ transform: translateY(-2px);
91
+ box-shadow: 0 4px 12px var(--shadow-dark);
92
+ }
93
+
94
+ @media (max-width: 768px) {
95
+ .error-content h1 {
96
+ font-size: 4rem;
97
+ }
98
+
99
+ .error-content p {
100
+ font-size: 1.2rem;
101
+ }
102
+ }
103
+ </style>
@@ -0,0 +1,59 @@
1
+ ---
2
+ import Stalux from "@layouts/Stalux.astro";
3
+ import PostContent from "@components/stalux/posts/postContent.astro";
4
+ import PostCC from "@components/stalux/posts/postCC.astro";
5
+ import WalineComment from "@components/stalux/posts/WalineComment.astro";
6
+ import { buildWalineProps } from "@utils/waline";
7
+ import { getCollection, render } from "astro:content";
8
+ import Navs from "@components/stalux/layout/navs.astro";
9
+ import { getSiteData, getAuthorData, getHeadData, getNavsData, getLinksData, getCommentData, getFooterData, getPromoteData, getTypetextsData, getMediaLinksData } from "@utils/config-utils";
10
+
11
+ // 获取关于页面内容
12
+ const aboutPages = await getCollection("about");
13
+ const aboutPage = aboutPages[0];
14
+ const { Content } = await render(aboutPage);
15
+
16
+ // 获取配置
17
+ const configEntries = await getCollection("config");
18
+ const siteConfig = getSiteData(configEntries);
19
+ const commentConfig = getCommentData(configEntries);
20
+ const walineSection = commentConfig?.waline;
21
+ const commentEnabled = commentConfig?.enabled ?? false;
22
+ const walineConfig = walineSection && walineSection.serverURL ? walineSection : undefined;
23
+ const authorConfig = getAuthorData(configEntries);
24
+ const author = authorConfig.name;
25
+ ---
26
+
27
+ <Stalux
28
+ title={aboutPage.data.title + " | " + siteConfig.title}
29
+ description={aboutPage.data.description}
30
+ >
31
+ <div style="height: 3em;"></div>
32
+ <Navs />
33
+ <div style="height: 3em;"></div>
34
+ <div style="max-width: 900px; margin: 2rem auto; padding: 0 1rem;">
35
+ <PostContent
36
+ title={aboutPage.data.title}
37
+ date={undefined}
38
+ updated={undefined}
39
+ readingTime={undefined}
40
+ >
41
+ <Content />
42
+ <PostCC
43
+ title={aboutPage.data.title}
44
+ author={author}
45
+ url={Astro.url.href}
46
+ cc="CC-BY-NC-SA-4.0"
47
+ />
48
+ {
49
+ commentEnabled && walineConfig?.serverURL && (
50
+ <WalineComment
51
+ {...buildWalineProps(walineConfig)}
52
+ path={Astro.url.pathname}
53
+ title={aboutPage.data.title}
54
+ />
55
+ )
56
+ }
57
+ </PostContent>
58
+ </div>
59
+ </Stalux>
@@ -0,0 +1,15 @@
1
+ import { getSite, isMarkdownExportEnabled, loadConfig, renderAboutMd } from "@utils/ai-discovery";
2
+ import type { APIRoute } from "astro";
3
+
4
+ export const prerender = true;
5
+
6
+ export const GET: APIRoute = async (context) => {
7
+ const config = await loadConfig();
8
+ if (!isMarkdownExportEnabled(config)) return new Response(null, { status: 404 });
9
+
10
+ const site = getSite(config, context.site?.toString());
11
+ const text = await renderAboutMd(site);
12
+ return new Response(text, {
13
+ headers: { "Content-Type": "text/markdown; charset=utf-8" },
14
+ });
15
+ };
@@ -0,0 +1,20 @@
1
+ import type { APIRoute } from "astro";
2
+ import { getCollection } from "astro:content";
3
+
4
+ export const prerender = true;
5
+
6
+ export const GET: APIRoute = async () => {
7
+ const posts = await getCollection("posts", ({ data }) => !data.draft);
8
+
9
+ const payload = posts.map((post) => ({
10
+ title: post.data.title,
11
+ abbrlink: post.data.abbrlink,
12
+ }));
13
+
14
+ return new Response(JSON.stringify(payload), {
15
+ status: 200,
16
+ headers: {
17
+ "Content-Type": "application/json; charset=utf-8",
18
+ },
19
+ });
20
+ };
@@ -0,0 +1,23 @@
1
+ ---
2
+ import Navs from "@components/stalux/layout/navs.astro";
3
+ import Stalux from "@layouts/Stalux.astro";
4
+ import ArchivesList from "@components/stalux/archives/archivesList.astro";
5
+ import { getCollection } from "astro:content";
6
+ import { createTranslator } from "@utils/i18n";
7
+ import styles from "@styles/pages/archives.module.css";
8
+ import { getSiteData, getAuthorData, getHeadData, getNavsData, getLinksData, getCommentData, getFooterData, getPromoteData, getTypetextsData, getMediaLinksData } from "@utils/config-utils";
9
+ const configEntries = await getCollection("config");
10
+ const siteConfig = getSiteData(configEntries);
11
+ const { t } = createTranslator(siteConfig.lang || "zh-CN");
12
+ const posts = await getCollection("posts", ({ data }) => !data.draft);
13
+ ---
14
+
15
+ <Stalux title={t("archives.title") + " | " + siteConfig.title} description={t("archives.description", { title: siteConfig.title })}>
16
+ <div style="height: 3em;"></div>
17
+ <Navs />
18
+ <h1 class={styles.h1}>{t("archives.heading")}</h1>
19
+ <div class={styles.description}>
20
+ {t("archives.desc", { n: posts.length })}
21
+ </div>
22
+ <ArchivesList posts={posts} />
23
+ </Stalux>
@@ -0,0 +1,24 @@
1
+ import {
2
+ getSite,
3
+ isMarkdownExportEnabled,
4
+ loadConfig,
5
+ renderArchivesMd,
6
+ } from "@utils/ai-discovery";
7
+ import { createTranslator } from "@utils/i18n";
8
+ import type { APIRoute } from "astro";
9
+
10
+ export const prerender = true;
11
+
12
+ export const GET: APIRoute = async (context) => {
13
+ const config = await loadConfig();
14
+ const exportMd = isMarkdownExportEnabled(config);
15
+ if (!exportMd) return new Response(null, { status: 404 });
16
+
17
+ const site = getSite(config, context.site?.toString());
18
+ const lang = (config.get("site")?.lang as string) || "zh-CN";
19
+ const { t } = createTranslator(lang);
20
+ const text = await renderArchivesMd(site, exportMd, t);
21
+ return new Response(text, {
22
+ headers: { "Content-Type": "text/markdown; charset=utf-8" },
23
+ });
24
+ };
@@ -0,0 +1,29 @@
1
+ import rss from "@astrojs/rss";
2
+ import { buildFeedItems } from "@utils/feed";
3
+ import { createTranslator, langToFeedLanguage } from "@utils/i18n";
4
+ import type { APIRoute } from "astro";
5
+ import { getCollection } from "astro:content";
6
+
7
+ export const GET: APIRoute = async (context) => {
8
+ const configCollection = await getCollection("config");
9
+ const siteEntry = configCollection.find((e) => e.id === "site");
10
+ if (!siteEntry) throw new Error("Missing site config");
11
+ const stalux = siteEntry.data;
12
+
13
+ const posts = await getCollection("posts", ({ data }) => !data.draft);
14
+ const items = await buildFeedItems(stalux, posts, "updated");
15
+
16
+ const lang = stalux?.lang || "zh-CN";
17
+ const { t } = createTranslator(lang);
18
+
19
+ return rss({
20
+ title: stalux?.title || "Stalux Blog",
21
+ description: stalux?.description || "A blog powered by Stalux theme",
22
+ site: stalux?.url || context.site?.toString(),
23
+ items,
24
+ customData: `<language>${langToFeedLanguage(lang)}</language>\n<copyright>${t("rss.copyright")}</copyright>`,
25
+ xmlns: {
26
+ atom: "http://www.w3.org/2005/Atom",
27
+ },
28
+ });
29
+ };
@@ -0,0 +1,35 @@
1
+ ---
2
+ import PostList from "@components/stalux/posts/postList.astro";
3
+ import TagHeader from "@components/stalux/tags/tagHeader.astro";
4
+ import { getCollection, type CollectionEntry } from "astro:content";
5
+ import Stalux from "@layouts/Stalux.astro";
6
+ import { createTranslator } from "@utils/i18n";
7
+ import { buildTaxonomyStaticPaths } from "@utils/taxonomy";
8
+ import Navs from "@components/stalux/layout/navs.astro";
9
+ import { getSiteData, getAuthorData, getHeadData, getNavsData, getLinksData, getCommentData, getFooterData, getPromoteData, getTypetextsData, getMediaLinksData } from "@utils/config-utils";
10
+ const configEntries = await getCollection("config");
11
+ const siteConfig = getSiteData(configEntries);
12
+ const { t } = createTranslator(siteConfig.lang || "zh-CN");
13
+ export async function getStaticPaths() {
14
+ return buildTaxonomyStaticPaths("categories");
15
+ }
16
+
17
+ interface Props {
18
+ category: string;
19
+ count: number;
20
+ posts: CollectionEntry<"posts">[];
21
+ lastUpdateDate: string;
22
+ }
23
+
24
+ const props = Astro.props as Props;
25
+ ---
26
+
27
+ <Stalux
28
+ title={t("taxonomy.category") + ": " + props.category + " | " + siteConfig.title}
29
+ description={t("taxonomy.browseCategory", { title: siteConfig.title, category: props.category, count: props.count })}
30
+ >
31
+ <div style="height: 3em;"></div>
32
+ <Navs />
33
+ <TagHeader type={t("taxonomy.category")} name={props.category} count={props.count} />
34
+ <PostList posts={props.posts} />
35
+ </Stalux>
@@ -0,0 +1,34 @@
1
+ import {
2
+ getSite,
3
+ isMarkdownExportEnabled,
4
+ loadConfig,
5
+ renderTaxonomyPageMd,
6
+ } from "@utils/ai-discovery";
7
+ import { buildTaxonomyStaticPaths } from "@utils/taxonomy";
8
+ import type { APIRoute } from "astro";
9
+ import type { CollectionEntry } from "astro:content";
10
+
11
+ export const prerender = true;
12
+
13
+ export async function getStaticPaths() {
14
+ const config = await loadConfig();
15
+ if (!isMarkdownExportEnabled(config)) return [];
16
+
17
+ return buildTaxonomyStaticPaths("categories");
18
+ }
19
+
20
+ export const GET: APIRoute = async (context) => {
21
+ const config = await loadConfig();
22
+ const exportMd = isMarkdownExportEnabled(config);
23
+ if (!exportMd) return new Response(null, { status: 404 });
24
+
25
+ const { category, posts } = context.props as {
26
+ category: string;
27
+ posts: CollectionEntry<"posts">[];
28
+ };
29
+ const site = getSite(config, context.site?.toString());
30
+ const text = renderTaxonomyPageMd(category, posts, site, "categories", exportMd);
31
+ return new Response(text, {
32
+ headers: { "Content-Type": "text/markdown; charset=utf-8" },
33
+ });
34
+ };
@@ -0,0 +1,23 @@
1
+ ---
2
+ import Stalux from "@layouts/Stalux.astro";
3
+ import { getCollection } from "astro:content";
4
+ import { createTranslator } from "@utils/i18n";
5
+ import Navs from "@components/stalux/layout/navs.astro";
6
+ import CategoriesList from "@components/stalux/categories/categoriesList.astro";
7
+ import styles from "@styles/pages/categories.module.css";
8
+ import { getSiteData, getAuthorData, getHeadData, getNavsData, getLinksData, getCommentData, getFooterData, getPromoteData, getTypetextsData, getMediaLinksData } from "@utils/config-utils";
9
+ const configEntries2 = await getCollection("config");
10
+ const siteConfig = getSiteData(configEntries2);
11
+ const { t } = createTranslator(siteConfig.lang || "zh-CN");
12
+ ---
13
+
14
+ <Stalux
15
+ title={t("categories.title") + " | " + siteConfig.title}
16
+ description={t("categories.description", { title: siteConfig.title })}
17
+ >
18
+ <div style="height: 3em;"></div>
19
+ <Navs />
20
+ <h1 class={styles.title}>{t("categories.heading")}</h1>
21
+ <div class={styles.description}>{t("categories.browseByTopic")}</div>
22
+ <CategoriesList />
23
+ </Stalux>
@@ -0,0 +1,27 @@
1
+ import {
2
+ buildTaxonomyMap,
3
+ getPublishedPosts,
4
+ getSite,
5
+ isMarkdownExportEnabled,
6
+ loadConfig,
7
+ renderTaxonomyListMd,
8
+ } from "@utils/ai-discovery";
9
+ import { createTranslator } from "@utils/i18n";
10
+ import type { APIRoute } from "astro";
11
+
12
+ export const prerender = true;
13
+
14
+ export const GET: APIRoute = async (context) => {
15
+ const config = await loadConfig();
16
+ if (!isMarkdownExportEnabled(config)) return new Response(null, { status: 404 });
17
+
18
+ const site = getSite(config, context.site?.toString());
19
+ const lang = (config.get("site")?.lang as string) || "zh-CN";
20
+ const { t } = createTranslator(lang);
21
+ const posts = await getPublishedPosts();
22
+ const map = buildTaxonomyMap(posts, "categories");
23
+ const text = renderTaxonomyListMd(map, site, "categories", t("ai.allCategories"));
24
+ return new Response(text, {
25
+ headers: { "Content-Type": "text/markdown; charset=utf-8" },
26
+ });
27
+ };
@@ -0,0 +1,30 @@
1
+ ---
2
+ import { getCollection } from "astro:content";
3
+ const configEntries = await getCollection("config");
4
+ const siteConfig = getSiteData(configEntries);
5
+ const siteTitle = siteConfig.title;
6
+ const siteDescription = siteConfig.description;
7
+ import Stalux from "@layouts/Stalux.astro";
8
+ import styles from "@styles/pages/home.module.css";
9
+ import Navs from "@components/stalux/layout/navs.astro";
10
+ import Author from "@components/stalux/common/author.astro";
11
+ import TextType from "@components/stalux/common/textType.astro";
12
+ import DateTime from "@components/stalux/common/date.astro";
13
+ import SocialMedia from "@components/stalux/links/socialMedia.astro";
14
+ import ToArchive from "@components/stalux/archives/toArchive.astro";
15
+ import { getSiteData, getAuthorData, getHeadData, getNavsData, getLinksData, getCommentData, getFooterData, getPromoteData, getTypetextsData, getMediaLinksData } from "@utils/config-utils";
16
+ ---
17
+
18
+ <Stalux title={siteTitle} description={siteDescription}>
19
+ <div class={styles.homeBody}>
20
+ <h1 class={styles.homeTitle}>{siteTitle}</h1>
21
+ <div class={styles.homeNavs}>
22
+ <Navs />
23
+ </div>
24
+ <Author />
25
+ <TextType />
26
+ <DateTime />
27
+ <SocialMedia />
28
+ <ToArchive />
29
+ </div>
30
+ </Stalux>
@@ -0,0 +1,18 @@
1
+ import { getSite, isMarkdownExportEnabled, loadConfig, renderIndexMd } from "@utils/ai-discovery";
2
+ import { createTranslator } from "@utils/i18n";
3
+ import type { APIRoute } from "astro";
4
+
5
+ export const prerender = true;
6
+
7
+ export const GET: APIRoute = async (context) => {
8
+ const config = await loadConfig();
9
+ if (!isMarkdownExportEnabled(config)) return new Response(null, { status: 404 });
10
+
11
+ const site = getSite(config, context.site?.toString());
12
+ const lang = (config.get("site")?.lang as string) || "zh-CN";
13
+ const { t } = createTranslator(lang);
14
+ const text = await renderIndexMd(config, site, t);
15
+ return new Response(text, {
16
+ headers: { "Content-Type": "text/markdown; charset=utf-8" },
17
+ });
18
+ };
@@ -0,0 +1,23 @@
1
+ ---
2
+ import ListPage from "@components/stalux/layout/listPage.astro";
3
+ import LinkList from "@components/stalux/links/linkList.astro";
4
+ import { getCollection } from "astro:content";
5
+ import { getSiteData, getLinksData } from "@utils/config-utils";
6
+
7
+ const configEntries = await getCollection("config");
8
+ const siteConfig = getSiteData(configEntries);
9
+ const linksConfig = getLinksData(configEntries)!;
10
+ const siteTitle = siteConfig.title;
11
+ const siteDescription = siteConfig.description;
12
+ const linksTitle = linksConfig.title;
13
+ const linksDescription = linksConfig.description;
14
+ ---
15
+
16
+ <ListPage
17
+ title={siteTitle}
18
+ description={siteDescription}
19
+ heading={linksTitle}
20
+ subheading={linksDescription}
21
+ >
22
+ <LinkList />
23
+ </ListPage>