@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,193 @@
1
+ {
2
+ "nav": {
3
+ "menu": "打开导航菜单",
4
+ "scrollLeft": "向左滚动导航",
5
+ "scrollRight": "向右滚动导航",
6
+ "search": "搜索"
7
+ },
8
+ "search": {
9
+ "title": "搜索",
10
+ "close": "关闭搜索",
11
+ "placeholder": "输入关键词搜索...",
12
+ "inputLabel": "搜索输入",
13
+ "noResults": "未找到相关结果",
14
+ "typePost": "文章",
15
+ "typeAbout": "关于",
16
+ "typeWord": "一言"
17
+ },
18
+ "page404": {
19
+ "title": "404 - 页面未找到",
20
+ "description": "抱歉,您访问的页面不存在。",
21
+ "pageNotFound": "页面未找到",
22
+ "countdown": "{n} 秒后自动返回首页",
23
+ "backHome": "返回首页"
24
+ },
25
+ "post": {
26
+ "publishTime": "发布时间:",
27
+ "updateTime": "更新时间:",
28
+ "readingTime": "🕒 阅读时间:",
29
+ "wordCount": "📝 字数:",
30
+ "viewCount": "👀 阅读量:",
31
+ "prevPost": "上一篇",
32
+ "nextPost": "下一篇",
33
+ "noPrev": "没有更早的文章",
34
+ "noNext": "没有更新的文章",
35
+ "author": "作者:",
36
+ "articleLink": "本文链接:",
37
+ "licensedUnder": "本文采用",
38
+ "licenseSuffix": "进行许可。",
39
+ "viewSource": "查看 Markdown 原文"
40
+ },
41
+ "taxonomy": {
42
+ "tag": "标签",
43
+ "category": "分类",
44
+ "toc": "目录",
45
+ "noTags": "暂无标签",
46
+ "noCategories": "暂无分类",
47
+ "noToc": "暂无目录",
48
+ "backToList": "返回{type}列表",
49
+ "foundPosts": "共找到 {count} 篇相关文章",
50
+ "browseTag": "欢迎访问{title}中“{tag}”标签页面,共有{count}篇相关文章,涵盖该标签下的技术教程与编程实践内容,帮助你深入了解相关主题与技术领域",
51
+ "browseCategory": "欢迎访问{title}中“{category}”分类页面,这里汇集了{count}篇相关文章,涵盖该主题下的技术教程、编程笔记与开发实践等原创内容,帮助你深入了解这一领域"
52
+ },
53
+ "archives": {
54
+ "title": "文章归档",
55
+ "description": "欢迎访问{title}文章归档页面,按发布时间顺序整理了博客所有原创文章,涵盖技术教程、编程开发、Linux运维、开源项目等各个类别的历史内容,方便按时间线回顾与查阅",
56
+ "heading": "文章归档",
57
+ "desc": "时间轴上的所有文章(共 {n} 篇)",
58
+ "postCount": "{n} 篇文章",
59
+ "month": "{n}月",
60
+ "noPosts": "暂无文章",
61
+ "loadMore": "加载更多内容",
62
+ "allLoaded": "已加载全部内容",
63
+ "viewAll": "查看所有文章"
64
+ },
65
+ "footer": {
66
+ "visitors": "本站访客数:",
67
+ "visits": "人次",
68
+ "totalVisits": "本站总访问量:",
69
+ "times": "次",
70
+ "totalWords": "本站总字数:",
71
+ "chars": "字",
72
+ "runningTime": "本站已正常运行",
73
+ "runtimeFormat": "{days}天{hours}时{minutes}分{seconds}秒",
74
+ "rightsReserved": "保留权利.",
75
+ "securityIcon": "公安备案图标"
76
+ },
77
+ "comment": {
78
+ "title": "留言评论",
79
+ "disclaimer": "评论区内容由用户生成,不代表网站观点"
80
+ },
81
+ "randomPost": {
82
+ "title": "随机文章",
83
+ "refresh": "刷新随机文章",
84
+ "loading": "正在加载随机文章...",
85
+ "noPosts": "暂无文章",
86
+ "loadFailed": "加载失败,请重试",
87
+ "loadError": "加载失败"
88
+ },
89
+ "categories": {
90
+ "title": "文章分类",
91
+ "description": "浏览{title}所有文章分类,涵盖日常开发中积累的技术教程、编程笔记、开源项目与Linux运维等内容,按主题分类整理帮你快速定位感兴趣的技术文章与学习笔记",
92
+ "heading": "文章分类",
93
+ "browseByTopic": "按主题分类浏览",
94
+ "postCount": "{n} 篇文章"
95
+ },
96
+ "tags": {
97
+ "title": "标签云",
98
+ "description": "探索{title}全部标签云,通过关键词索引快速找到技术教程、编程开发、Linux运维、开源项目、AI人工智能等各个领域的精彩文章与实用教程资源,发现更多你感兴趣的内容",
99
+ "heading": "标签云",
100
+ "explore": "探索不同主题的文章标签",
101
+ "noTags": "暂无标签"
102
+ },
103
+ "words": {
104
+ "title": "一言",
105
+ "description": "收集的语录与短句",
106
+ "heading": "一言",
107
+ "desc": "只言片语,皆为心声(共 {n} 条)"
108
+ },
109
+ "links": {
110
+ "defaultTitle": "友链",
111
+ "iconAlt": "{name} 图标"
112
+ },
113
+ "rss": {
114
+ "copyright": "除非另有说明,各文章采用其自身标注的 Creative Commons 许可证"
115
+ },
116
+ "common": {
117
+ "uncategorized": "未分类",
118
+ "minute": "{n} 分钟",
119
+ "lessThanOneMinute": "小于 1 分钟",
120
+ "tenThousand": "{n}万",
121
+ "k": "{n}k",
122
+ "dateFormat": "yyyy年MM月dd日"
123
+ },
124
+ "cc": {
125
+ "format": "知识共享{elements} {version} 国际许可协议",
126
+ "zero": "CC0 1.0 通用",
127
+ "BY": "署名",
128
+ "NC": "非商业性使用",
129
+ "SA": "相同方式共享",
130
+ "ND": "禁止演绎"
131
+ },
132
+ "console": {
133
+ "name": "Stalux - 现代 Astro 博客主题 [简称:星博客]",
134
+ "author": "王兴家 (xingwangzhe)",
135
+ "copyright": "© 王兴家. All rights reserved.",
136
+ "certNumber": "软著登字第16914672号",
137
+ "certUrl": "https://stalux.needhelp.icu/软著证明.pdf",
138
+ "regDate": "2025年11月24日",
139
+ "labelVersion": "📦 版本:",
140
+ "labelAuthor": "👤 著作权人:",
141
+ "labelRepo": "🔗 仓库:",
142
+ "labelWebsite": "🌐 官网:",
143
+ "labelCert": "📜 软著证书:",
144
+ "labelCertNumber": "🎫 登记号:",
145
+ "labelRegDate": "📅 登记日期:",
146
+ "labelLicense": "⚖️ 开源协议:",
147
+ "labelAuthNote": "✅ 授权说明:",
148
+ "labelTip": "💡 提示:",
149
+ "labelFeedback": "🐛 问题反馈:",
150
+ "authNote": "本软件遵循 MIT 开源协议。您可以自由地使用、修改和分发本软件,但请保留原始版权声明。",
151
+ "tip": "如果你喜欢这个主题,欢迎在 GitHub 上点个 ⭐️ 支持我们!",
152
+ "feedback": "https://github.com/xingwangzhe/stalux/issues"
153
+ },
154
+ "ai": {
155
+ "contact": "联系",
156
+ "author": "作者",
157
+ "email": "邮箱",
158
+ "socialMedia": "社交媒体",
159
+ "noContact": "暂无公开联系方式",
160
+ "posts": "文章",
161
+ "noPosts": "暂无文章",
162
+ "untitled": "无标题",
163
+ "pages": "页面",
164
+ "about": "关于",
165
+ "aboutDesc": "关于作者",
166
+ "archives": "归档",
167
+ "archivesDesc": "全部文章归档",
168
+ "tags": "标签",
169
+ "tagsDesc": "标签索引",
170
+ "categories": "分类",
171
+ "categoriesDesc": "分类索引",
172
+ "words": "语录",
173
+ "wordsDesc": "语录与片段",
174
+ "links": "友情链接",
175
+ "aiDiscoveryFiles": "AI 发现文件",
176
+ "llmsTxtDesc": "站点摘要与文章索引",
177
+ "llmsFullTxtDesc": "全部文章 Markdown 全文数据集",
178
+ "optional": "可选",
179
+ "morePosts": "查看更多文章",
180
+ "rss": "RSS Feed",
181
+ "atom": "Atom Feed",
182
+ "mdAvailable": "每篇文章均提供 Markdown 源码,链接已指向 .md 版本",
183
+ "siteLicense": "除非另有说明,本站内容采用 CC-BY-NC-SA-4.0 协议。",
184
+ "fullDataset": "LLM 全文数据集",
185
+ "fullDatasetDesc": "本站全部公开文章的 Markdown 全文集合,供大语言模型训练与引用使用。",
186
+ "license": "内容许可证",
187
+ "postCount": "文章数量",
188
+ "markdownSources": "Markdown 源文件",
189
+ "latestPosts": "最新文章",
190
+ "allCategories": "全部分类",
191
+ "allTags": "全部标签"
192
+ }
193
+ }
package/src/index.ts ADDED
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Stalux — Astro 博客主题集成入口
3
+ *
4
+ * 可作为:
5
+ * 1. Astro Integration(插件模式):`integrations: [stalux()]`
6
+ * 2. 源码模板(Template 模式):额外提供 create-stalux CLI 脚手架
7
+ *
8
+ * 基于 Astro 7.1.3 Integration API(astro:config:setup / injectRoute / injectScript)
9
+ */
10
+
11
+ import { fileURLToPath } from "node:url";
12
+ import path from "node:path";
13
+ import type { AstroIntegration } from "astro";
14
+ import type { StaluxOptions } from "./config";
15
+ import { staluxComponentsAlias } from "./internal/components-plugin";
16
+
17
+ // pagefind 是 ESM-only 包,需要在模块顶层导入
18
+ // 因为 astro:build:done 钩子中 Vite module runner 已关闭,无法动态 import
19
+ import { createIndex as pagefindCreateIndex } from "pagefind";
20
+
21
+ // ---------------------------------------------------------------------------
22
+ // 页面条目定义
23
+ // ---------------------------------------------------------------------------
24
+
25
+ interface RouteEntry {
26
+ pattern: string;
27
+ entrypoint: string;
28
+ prerender?: boolean;
29
+ }
30
+
31
+ /**
32
+ * 获取所有需要注入的路由列表
33
+ */
34
+ function getRoutes(baseDir: URL): RouteEntry[] {
35
+ const resolvePage = (relPath: string): string =>
36
+ fileURLToPath(new URL(relPath, baseDir));
37
+
38
+ return [
39
+ // ---- 静态页面 ----
40
+ { pattern: "/", entrypoint: resolvePage("./pages/index.astro") },
41
+ { pattern: "/about/", entrypoint: resolvePage("./pages/about.astro") },
42
+ { pattern: "/archives/", entrypoint: resolvePage("./pages/archives.astro") },
43
+ { pattern: "/links/", entrypoint: resolvePage("./pages/links.astro") },
44
+ { pattern: "/words/", entrypoint: resolvePage("./pages/words.astro") },
45
+ { pattern: "/404", entrypoint: resolvePage("./pages/404.astro") },
46
+
47
+ // ---- 动态页面 ----
48
+ { pattern: "/posts/[post]", entrypoint: resolvePage("./pages/posts/[post].astro") },
49
+ { pattern: "/tags/", entrypoint: resolvePage("./pages/tags/index.astro") },
50
+ { pattern: "/tags/[tag]", entrypoint: resolvePage("./pages/tags/[tag].astro") },
51
+ { pattern: "/categories/", entrypoint: resolvePage("./pages/categories/index.astro") },
52
+ { pattern: "/categories/[category]", entrypoint: resolvePage("./pages/categories/[category].astro") },
53
+
54
+ // ---- API 端点 ----
55
+ { pattern: "/rss.xml", entrypoint: resolvePage("./pages/rss.xml.ts") },
56
+ { pattern: "/atom.xml", entrypoint: resolvePage("./pages/atom.xml.ts") },
57
+ { pattern: "/llms.txt", entrypoint: resolvePage("./pages/llms.txt.ts") },
58
+ { pattern: "/llms-full.txt", entrypoint: resolvePage("./pages/llms-full.txt.ts") },
59
+ { pattern: "/api/post.abbrlink.json", entrypoint: resolvePage("./pages/api/post.abbrlink.json.ts") },
60
+
61
+ // ---- Markdown 导出端点 ----
62
+ { pattern: "/index.md", entrypoint: resolvePage("./pages/index.md.ts") },
63
+ { pattern: "/about.md", entrypoint: resolvePage("./pages/about.md.ts") },
64
+ { pattern: "/archives.md", entrypoint: resolvePage("./pages/archives.md.ts") },
65
+ { pattern: "/links.md", entrypoint: resolvePage("./pages/links.md.ts") },
66
+ { pattern: "/words.md", entrypoint: resolvePage("./pages/words.md.ts") },
67
+ { pattern: "/tags/index.md", entrypoint: resolvePage("./pages/tags/index.md.ts") },
68
+ { pattern: "/tags/[tag].md", entrypoint: resolvePage("./pages/tags/[tag].md.ts") },
69
+ { pattern: "/categories/index.md", entrypoint: resolvePage("./pages/categories/index.md.ts") },
70
+ { pattern: "/categories/[category].md", entrypoint: resolvePage("./pages/categories/[category].md.ts") },
71
+ { pattern: "/posts/[post].md", entrypoint: resolvePage("./pages/posts/[post].md.ts") },
72
+ ];
73
+ }
74
+
75
+ // ---------------------------------------------------------------------------
76
+ // Vite 别名配置(供页面使用 @components etc.)
77
+ // ---------------------------------------------------------------------------
78
+
79
+ function getViteAliases(srcDir: string) {
80
+ return {
81
+ "@components": path.resolve(srcDir, "components"),
82
+ "@assets": path.resolve(srcDir, "assets"),
83
+ "@layouts": path.resolve(srcDir, "layouts"),
84
+ "@scripts": path.resolve(srcDir, "scripts"),
85
+ "@styles": path.resolve(srcDir, "styles"),
86
+ "@utils": path.resolve(srcDir, "utils"),
87
+ "@i18n": path.resolve(srcDir, "i18n"),
88
+ "@plugins": path.resolve(srcDir, "plugins"),
89
+ "@schemas": path.resolve(srcDir, "schemas"),
90
+ };
91
+ }
92
+
93
+ // ---------------------------------------------------------------------------
94
+ // 集成入口
95
+ // ---------------------------------------------------------------------------
96
+
97
+ /**
98
+ * Stalux 博客主题集成
99
+ *
100
+ * @example
101
+ * ```ts
102
+ * // astro.config.mjs
103
+ * import { defineConfig } from "astro/config";
104
+ * import stalux from "stalux";
105
+ *
106
+ * export default defineConfig({
107
+ * integrations: [stalux({ contentDir: "./content" })]
108
+ * });
109
+ * ```
110
+ */
111
+ export function stalux(options: StaluxOptions = {}): AstroIntegration {
112
+ const opt: StaluxOptions = {
113
+ contentDir: options.contentDir ?? "stalux",
114
+ pagefind: options.pagefind ?? true,
115
+ devToolbar: options.devToolbar ?? true,
116
+ ...options,
117
+ };
118
+
119
+ // 探测是否为插件模式(通过 npm 安装)vs 源码开发模式
120
+ // 安装在 node_modules 中时,页面的文件路由不可用,需要通过 injectRoute 注入
121
+ const isPluginMode = import.meta.url.includes("node_modules");
122
+
123
+ return {
124
+ name: "stalux",
125
+ hooks: {
126
+ "astro:config:setup": ({
127
+ injectRoute,
128
+ injectScript,
129
+ updateConfig,
130
+ addDevToolbarApp,
131
+ config,
132
+ logger,
133
+ }) => {
134
+ const srcDir = fileURLToPath(new URL(".", import.meta.url));
135
+
136
+ // 1. 注入 Vite 别名 + 组件覆盖插件 + Vue 特性标记(Waline 依赖)
137
+ updateConfig({
138
+ vite: {
139
+ resolve: {
140
+ alias: getViteAliases(srcDir),
141
+ },
142
+ plugins: [
143
+ staluxComponentsAlias(opt.components),
144
+ ],
145
+ define: {
146
+ __VUE_OPTIONS_API__: true,
147
+ __VUE_PROD_DEVTOOLS__: false,
148
+ __VUE_PROD_HYDRATION_MISMATCH_DETAILS__: false,
149
+ },
150
+ },
151
+ });
152
+
153
+ // 2. 注入全局 CSS
154
+ injectScript("page-ssr", `import "${srcDir}/styles/base/init.css";`);
155
+
156
+ // 3. 注入所有页面路由(仅插件模式,源码模式下使用文件路由)
157
+ if (isPluginMode) {
158
+ const routes = getRoutes(new URL(".", import.meta.url));
159
+ for (const route of routes) {
160
+ injectRoute(route);
161
+ }
162
+ logger.debug(`Stalux: injected ${routes.length} routes`);
163
+ } else {
164
+ logger.info("Stalux: running in source mode, file-based routing active");
165
+ }
166
+
167
+ // 4. 可选:添加 Dev Toolbar 应用
168
+ if (opt.devToolbar) {
169
+ addDevToolbarApp({
170
+ id: "stalux",
171
+ name: "Stalux",
172
+ icon: '<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>',
173
+ entrypoint: fileURLToPath(new URL("./internal/dev-toolbar.ts", import.meta.url)),
174
+ });
175
+ }
176
+
177
+ logger.info(`Stalux initialized (contentDir: ${opt.contentDir})`);
178
+ },
179
+
180
+ "astro:build:done": async ({ dir, logger }) => {
181
+ // 5. 后处理:Pagefind 搜索索引
182
+ if (opt.pagefind) {
183
+ const outDir = fileURLToPath(dir);
184
+ logger.info("Running Pagefind indexer...");
185
+
186
+ try {
187
+ const { index, errors } = await pagefindCreateIndex();
188
+
189
+ if (!index) {
190
+ logger.error("Pagefind failed to create index");
191
+ errors?.forEach((e) => logger.error(e));
192
+ return;
193
+ }
194
+
195
+ const { page_count } = await index.addDirectory({ path: outDir });
196
+ if (page_count === 0) {
197
+ logger.warn("Pagefind: no pages indexed");
198
+ return;
199
+ }
200
+
201
+ const { outputPath } = await index.writeFiles({
202
+ outputPath: path.join(outDir, "pagefind"),
203
+ });
204
+
205
+ logger.info(`Pagefind indexed ${page_count} pages → ${outputPath}`);
206
+ } catch (error) {
207
+ logger.error(`Pagefind indexing failed: ${String(error)}`);
208
+ }
209
+ }
210
+ },
211
+ },
212
+ };
213
+ }
214
+
215
+ export default stalux;
@@ -0,0 +1,54 @@
1
+ /**
2
+ * 组件覆盖解析 Vite 插件
3
+ *
4
+ * 提供 Vite 别名 `@stalux/component/*`,实现可覆盖的组件导入。
5
+ *
6
+ * 页面中使用:
7
+ * ```astro
8
+ * import Navs from "@stalux/component/Navs";
9
+ * ```
10
+ *
11
+ * 用户在集成选项中覆盖:
12
+ * ```ts
13
+ * stalux({ components: { Navs: "./src/CustomNavs.astro" } })
14
+ * ```
15
+ *
16
+ * 插件自动将别名解析为用户提供的路径或包内默认路径。
17
+ */
18
+
19
+ import path from "node:path";
20
+ import { fileURLToPath } from "node:url";
21
+ import type { Plugin } from "vite";
22
+ import type { ComponentOverrideMap } from "../config";
23
+ import { resolveComponentPath, type StaluxComponentKey } from "./override";
24
+
25
+ const VIRTUAL_PREFIX = "@stalux/component/";
26
+
27
+ /**
28
+ * 创建 Vite 别名插件,处理 `@stalux/component/*` → 实际组件路径
29
+ */
30
+ export function staluxComponentsAlias(
31
+ overrides: ComponentOverrideMap = {},
32
+ ): Plugin {
33
+ // 包内 components 目录的绝对路径
34
+ const componentsDir = fileURLToPath(new URL("../components", import.meta.url));
35
+
36
+ return {
37
+ name: "stalux:components-alias",
38
+ resolveId(id: string, importer: string | undefined) {
39
+ if (!id.startsWith(VIRTUAL_PREFIX)) return null;
40
+
41
+ const componentName = id.slice(VIRTUAL_PREFIX.length) as StaluxComponentKey;
42
+
43
+ // 使用 resolveComponentPath 获取实际路径
44
+ const resolvedPath = resolveComponentPath(componentName, overrides, componentsDir);
45
+
46
+ // 如果是用户提供的相对路径,相对于项目根解析
47
+ if (overrides[componentName]) {
48
+ return this.resolve(resolvedPath, importer, { skipSelf: true });
49
+ }
50
+
51
+ return resolvedPath;
52
+ },
53
+ } satisfies Plugin;
54
+ }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Stalux Dev Toolbar 应用
3
+ *
4
+ * 在 Astro 开发工具栏中添加 Stalux 主题的便捷操作。
5
+ * 使用 Astro Dev Toolbar App API(astro@4.0.0+)。
6
+ */
7
+
8
+ export default {
9
+ id: "stalux",
10
+ name: "Stalux",
11
+ icon: '<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 2L2 7l10 5 10-5-10-5z"/><path d="M2 17l10 5 10-5"/><path d="M2 12l10 5 10-5"/></svg>',
12
+
13
+ init(canvas: HTMLElement) {
14
+ const container = document.createElement("div");
15
+ container.innerHTML = `
16
+ <style>
17
+ .stalux-toolbar { padding: 16px; font-family: system-ui, sans-serif; }
18
+ .stalux-toolbar h3 { margin: 0 0 8px; font-size: 14px; font-weight: 600; }
19
+ .stalux-toolbar p { margin: 4px 0; font-size: 12px; color: #888; }
20
+ .stalux-toolbar a { color: #60a5fa; text-decoration: none; }
21
+ .stalux-toolbar a:hover { text-decoration: underline; }
22
+ .stalux-toolbar .version { font-size: 11px; color: #666; }
23
+ </style>
24
+ <div class="stalux-toolbar">
25
+ <h3>✨ Stalux Theme</h3>
26
+ <p class="version">v2.0.0</p>
27
+ <p><a href="https://stalux.needhelp.icu" target="_blank">📖 Documentation</a></p>
28
+ <p><a href="https://github.com/xingwangzhe/stalux" target="_blank">🐙 GitHub</a></p>
29
+ </div>
30
+ `;
31
+ canvas.appendChild(container);
32
+ },
33
+ };
@@ -0,0 +1,99 @@
1
+ /**
2
+ * 组件覆盖解析系统
3
+ *
4
+ * 借鉴 Starlight 的 components override 模式,
5
+ * 允许用户通过集成选项自定义任意主题组件。
6
+ *
7
+ * 所有默认路径相对于包内的 src/components/stalux/ 目录。
8
+ */
9
+
10
+ import type { ComponentOverrideMap } from "../config";
11
+
12
+ // ---------------------------------------------------------------------------
13
+ // 可覆盖组件清单(相对于包内 src/ 目录)
14
+ // ---------------------------------------------------------------------------
15
+
16
+ export const STALUX_COMPONENTS = {
17
+ // Layout
18
+ Head: "layouts/head.astro",
19
+ Footer: "layouts/footer.astro",
20
+ Navs: "layouts/navs.astro",
21
+ ListPage: "layouts/listPage.astro",
22
+
23
+ // Common
24
+ Author: "common/author.astro",
25
+ Date: "common/date.astro",
26
+ Search: "common/search.astro",
27
+ TextType: "common/textType.astro",
28
+ VerCount: "common/verCount.astro",
29
+
30
+ // Home
31
+ SocialMedia: "links/socialMedia.astro",
32
+ ToArchive: "archives/toArchive.astro",
33
+
34
+ // Posts
35
+ PostLeft: "posts/postLeft.astro",
36
+ PostContent: "posts/postContent.astro",
37
+ PostRight: "posts/postRight.astro",
38
+ PostNavigation: "posts/postNavigation.astro",
39
+ PostCC: "posts/postCC.astro",
40
+ WalineComment: "posts/WalineComment.astro",
41
+ PostToc: "posts/postToc.astro",
42
+ PostAuthor: "posts/postAuthor.astro",
43
+ PostCard: "posts/postCard.astro",
44
+ PostList: "posts/postList.astro",
45
+ PostTaxonomy: "posts/PostTaxonomy.astro",
46
+ PhotoSwipeStyle: "posts/PhotoSwipeStyle.astro",
47
+ RandomPost: "posts/randomPost.astro",
48
+
49
+ // Archives
50
+ ArchivesList: "archives/archivesList.astro",
51
+
52
+ // Categories
53
+ CategoriesCard: "categories/categoriesCard.astro",
54
+ CategoriesList: "categories/categoriesList.astro",
55
+
56
+ // Tags
57
+ TagHeader: "tags/tagHeader.astro",
58
+ TagsCloud: "tags/tagsCloud.astro",
59
+
60
+ // Words
61
+ WordCard: "words/wordCard.astro",
62
+ WordList: "words/wordList.astro",
63
+
64
+ // Links
65
+ LinkCard: "links/linkCard.astro",
66
+ LinkList: "links/linkList.astro",
67
+
68
+ // Footer
69
+ FooterBadges: "footer/FooterBadges.astro",
70
+ FooterBeian: "footer/FooterBeian.astro",
71
+ FooterCopyright: "footer/FooterCopyright.astro",
72
+ FooterStats: "footer/FooterStats.astro",
73
+ FooterThemeInfo: "footer/FooterThemeInfo.astro",
74
+
75
+ // Analytics
76
+ Clarity: "analytics/clarity.astro",
77
+ Google: "analytics/google.astro",
78
+ Umami: "analytics/umami.astro",
79
+ } as const;
80
+
81
+ /** 组件键名联合类型 */
82
+ export type StaluxComponentKey = keyof typeof STALUX_COMPONENTS;
83
+
84
+ /**
85
+ * 获取组件的完整包内路径
86
+ *
87
+ * @param key 组件键名
88
+ * @param overrides 用户覆盖映射
89
+ * @param componentsDir 包内 components 目录的绝对路径
90
+ * @returns 组件的绝对路径
91
+ */
92
+ export function resolveComponentPath(
93
+ key: StaluxComponentKey,
94
+ overrides: ComponentOverrideMap = {},
95
+ componentsDir: string,
96
+ ): string {
97
+ if (overrides[key]) return overrides[key]!;
98
+ return componentsDir + "/stalux/" + STALUX_COMPONENTS[key];
99
+ }
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Pagefind 搜索索引生成器
3
+ *
4
+ * 从原 src/integrations/pagefind.ts 迁移而来,
5
+ * 变为集成的一个内部模块,在构建完成时自动运行。
6
+ */
7
+
8
+ import path from "node:path";
9
+ import { fileURLToPath } from "node:url";
10
+ import type { AstroIntegrationLogger } from "astro";
11
+
12
+ export async function pagefind(dir: URL, logger: AstroIntegrationLogger): Promise<void> {
13
+ const outDir = fileURLToPath(dir);
14
+ logger.info("Running Pagefind indexer...");
15
+
16
+ try {
17
+ const { createIndex } = await import("pagefind");
18
+ const { index, errors } = await createIndex();
19
+
20
+ if (!index) {
21
+ logger.error("Pagefind failed to create index");
22
+ errors?.forEach((e) => logger.error(e));
23
+ return;
24
+ }
25
+
26
+ const { page_count } = await index.addDirectory({ path: outDir });
27
+ if (page_count === 0) {
28
+ logger.warn("Pagefind: no pages indexed");
29
+ return;
30
+ }
31
+
32
+ const { outputPath } = await index.writeFiles({
33
+ outputPath: path.join(outDir, "pagefind"),
34
+ });
35
+
36
+ logger.info(`Pagefind indexed ${page_count} pages → ${outputPath}`);
37
+ } catch (error) {
38
+ logger.error(`Pagefind indexing failed: ${error}`);
39
+ }
40
+ }