@xingwangzhe/stalux 1.26.2 → 1.27.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.release/cli.mjs +264 -0
- package/README.md +2 -2
- package/package.json +15 -8
- package/src/components/stalux/posts/WalineComment.astro +0 -1
- package/src/components/stalux/posts/postLeft.astro +0 -18
- package/src/components/stalux/posts/postNavigation.astro +1 -1
- package/src/i18n/en.json +1 -0
- package/src/i18n/zh-CN.json +1 -0
- package/src/pages/404.astro +0 -1
- package/src/styles/base/init.css +0 -20
- package/src/styles/components/archives/archivesList.module.css +0 -1
- package/src/styles/components/layout/navs.module.css +2 -1
- package/src/styles/components/posts/postLayout.module.css +0 -4
- package/src/styles/pages/archives.module.css +6 -2
- package/src/styles/pages/categories.module.css +6 -2
- package/src/styles/pages/listPage.module.css +5 -2
- package/src/styles/pages/tags.module.css +6 -2
- package/src/styles/pages/words.module.css +5 -2
- package/src/utils/i18n.ts +16 -5
- package/scripts/cli.mjs +0 -331
package/.release/cli.mjs
ADDED
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
// scripts/cli.ts
|
|
4
|
+
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
5
|
+
import { dirname, join, resolve } from "node:path";
|
|
6
|
+
function timestamp() {
|
|
7
|
+
return new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
8
|
+
}
|
|
9
|
+
function getConfigYamls() {
|
|
10
|
+
const year = new Date().getFullYear();
|
|
11
|
+
const now = new Date().toISOString();
|
|
12
|
+
return {
|
|
13
|
+
"site.yml": `id: site
|
|
14
|
+
lang: en
|
|
15
|
+
title: "My Blog"
|
|
16
|
+
description: "A blog built with Stalux theme"
|
|
17
|
+
url: "https://example.com"
|
|
18
|
+
timezone: "Asia/Shanghai"
|
|
19
|
+
`,
|
|
20
|
+
"author.yml": `id: author
|
|
21
|
+
name: "Your Name"
|
|
22
|
+
avatar: "/avatar.png"
|
|
23
|
+
bio: "Blogger & Developer"
|
|
24
|
+
`,
|
|
25
|
+
"navs.yml": `id: navs
|
|
26
|
+
items:
|
|
27
|
+
- title: "Home"
|
|
28
|
+
link: "/"
|
|
29
|
+
icon: "house"
|
|
30
|
+
- title: "Archives"
|
|
31
|
+
link: "/archives"
|
|
32
|
+
icon: "archive"
|
|
33
|
+
- title: "Tags"
|
|
34
|
+
link: "/tags"
|
|
35
|
+
icon: "tag"
|
|
36
|
+
- title: "Categories"
|
|
37
|
+
link: "/categories"
|
|
38
|
+
icon: "folder"
|
|
39
|
+
- title: "Words"
|
|
40
|
+
link: "/words"
|
|
41
|
+
icon: "quote"
|
|
42
|
+
- title: "Links"
|
|
43
|
+
link: "/links"
|
|
44
|
+
icon: "link"
|
|
45
|
+
`,
|
|
46
|
+
"head.yml": `id: head
|
|
47
|
+
# googleAnalyticsId: "G-XXXXXXXXXX"
|
|
48
|
+
# bingClarityId: "xxxxxxxxxx"
|
|
49
|
+
# umami:
|
|
50
|
+
# id: ""
|
|
51
|
+
# url: ""
|
|
52
|
+
# anyhead: ""
|
|
53
|
+
`,
|
|
54
|
+
"footer.yml": `id: footer
|
|
55
|
+
buildtime: "${now}"
|
|
56
|
+
copyright:
|
|
57
|
+
enabled: true
|
|
58
|
+
startYear: ${year}
|
|
59
|
+
customText: ""
|
|
60
|
+
theme:
|
|
61
|
+
showPoweredBy: true
|
|
62
|
+
showThemeInfo: true
|
|
63
|
+
beian:
|
|
64
|
+
icp:
|
|
65
|
+
enabled: false
|
|
66
|
+
number: ""
|
|
67
|
+
security:
|
|
68
|
+
enabled: false
|
|
69
|
+
text: ""
|
|
70
|
+
number: ""
|
|
71
|
+
badges:
|
|
72
|
+
- label: "Powered by"
|
|
73
|
+
message: "Astro"
|
|
74
|
+
color: "orange"
|
|
75
|
+
style: "flat-square"
|
|
76
|
+
href: "https://astro.build/"
|
|
77
|
+
custom: |
|
|
78
|
+
<div id="custom-footer-hook"></div>
|
|
79
|
+
`,
|
|
80
|
+
"media-links.yml": `id: media-links
|
|
81
|
+
items:
|
|
82
|
+
- icon: "github"
|
|
83
|
+
link: "https://github.com/yourname"
|
|
84
|
+
`,
|
|
85
|
+
"links.yml": `id: links
|
|
86
|
+
title: "Links"
|
|
87
|
+
description: "Friends & Resources"
|
|
88
|
+
sites:
|
|
89
|
+
- name: "Astro"
|
|
90
|
+
description: "The web framework for content-driven websites"
|
|
91
|
+
link: "https://astro.build"
|
|
92
|
+
icon: "https://astro.build/favicon.svg"
|
|
93
|
+
`,
|
|
94
|
+
"comment.yml": `id: comment
|
|
95
|
+
enabled: false
|
|
96
|
+
`,
|
|
97
|
+
"promote.yml": `id: promote
|
|
98
|
+
export_md: false
|
|
99
|
+
# llm_promote: |
|
|
100
|
+
`,
|
|
101
|
+
"ai-discovery.yml": `id: ai-discovery
|
|
102
|
+
conformance: "disabled"
|
|
103
|
+
`,
|
|
104
|
+
"typetexts.yml": `id: typetexts
|
|
105
|
+
items:
|
|
106
|
+
- "Free for free, not free for charge!"
|
|
107
|
+
- "Where's the any key?"
|
|
108
|
+
- "Press F12?"
|
|
109
|
+
- "Hello World!"
|
|
110
|
+
`
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
function getExamplePost() {
|
|
114
|
+
const date = timestamp();
|
|
115
|
+
return `---
|
|
116
|
+
title: Hello Stalux!
|
|
117
|
+
abbrlink: hello-stalux
|
|
118
|
+
date: "${date}"
|
|
119
|
+
tags: [Stalux, Getting Started]
|
|
120
|
+
categories: [Blog]
|
|
121
|
+
desc: Welcome to Stalux!
|
|
122
|
+
cc: CC-BY-NC-SA-4.0
|
|
123
|
+
---
|
|
124
|
+
|
|
125
|
+
Welcome to **Stalux**!
|
|
126
|
+
|
|
127
|
+
This is your first post. Edit or delete it, then start writing your own content.
|
|
128
|
+
|
|
129
|
+
## Features
|
|
130
|
+
|
|
131
|
+
- \uD83C\uDF19 Dark mode with elegant glassmorphism design
|
|
132
|
+
- \uD83D\uDD24 Per-route font subsetting — each page loads only needed characters
|
|
133
|
+
- \uD83D\uDD0D Full-text search (Pagefind)
|
|
134
|
+
- \uD83D\uDCE1 RSS & Atom feeds
|
|
135
|
+
- \uD83D\uDCAC Comment system (Waline)
|
|
136
|
+
- \uD83D\uDCCA Mermaid diagrams
|
|
137
|
+
- \uD83D\uDCD0 Math formula rendering
|
|
138
|
+
- \uD83D\uDDBC️ PhotoSwipe lightbox
|
|
139
|
+
|
|
140
|
+
For more details, visit [Stalux documentation](https://stalux.needhelp.icu).
|
|
141
|
+
`;
|
|
142
|
+
}
|
|
143
|
+
function getAboutMd() {
|
|
144
|
+
return `---
|
|
145
|
+
title: About Me
|
|
146
|
+
description: About this blog and the author
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
Hello! Welcome to my blog.
|
|
150
|
+
|
|
151
|
+
This is my personal space where I share technology, life, and thoughts.
|
|
152
|
+
|
|
153
|
+
## About This Site
|
|
154
|
+
|
|
155
|
+
- Built with [Astro](https://astro.build) + [Stalux](https://stalux.needhelp.icu)
|
|
156
|
+
- Content licensed under CC-BY-NC-SA-4.0
|
|
157
|
+
- Source code hosted on GitHub
|
|
158
|
+
`;
|
|
159
|
+
}
|
|
160
|
+
function getWordsTemplate() {
|
|
161
|
+
const date = timestamp();
|
|
162
|
+
return `---
|
|
163
|
+
source: "Author Name"
|
|
164
|
+
link: "https://example.com"
|
|
165
|
+
sourceDate: ""
|
|
166
|
+
date: "${date}"
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
> A quote or short note...
|
|
170
|
+
`;
|
|
171
|
+
}
|
|
172
|
+
function getWordsExample() {
|
|
173
|
+
const date = timestamp();
|
|
174
|
+
return `---
|
|
175
|
+
source: "Albert Einstein"
|
|
176
|
+
link: "https://example.com"
|
|
177
|
+
sourceDate: ""
|
|
178
|
+
date: "${date}"
|
|
179
|
+
---
|
|
180
|
+
|
|
181
|
+
> Imagination is more important than knowledge.
|
|
182
|
+
`;
|
|
183
|
+
}
|
|
184
|
+
function writeIfMissing(filePath, label, content) {
|
|
185
|
+
if (existsSync(filePath)) {
|
|
186
|
+
console.log(` ⏭ ${label} (exists, skipped)`);
|
|
187
|
+
return;
|
|
188
|
+
}
|
|
189
|
+
mkdirSync(dirname(filePath), { recursive: true });
|
|
190
|
+
writeFileSync(filePath, content);
|
|
191
|
+
console.log(` ✅ ${label}`);
|
|
192
|
+
}
|
|
193
|
+
function main([command, targetArg = "."] = process.argv.slice(2)) {
|
|
194
|
+
if (!command || command === "--help" || command === "-h") {
|
|
195
|
+
printHelp();
|
|
196
|
+
return;
|
|
197
|
+
}
|
|
198
|
+
if (command !== "init") {
|
|
199
|
+
console.error(`❌ Unknown command: ${command}`);
|
|
200
|
+
printHelp();
|
|
201
|
+
process.exitCode = 1;
|
|
202
|
+
return;
|
|
203
|
+
}
|
|
204
|
+
const targetPath = resolve(process.cwd(), targetArg);
|
|
205
|
+
const contentRoot = join(targetPath, "stalux");
|
|
206
|
+
console.log(`\uD83D\uDCE6 Initializing Stalux content in ${targetPath}...
|
|
207
|
+
`);
|
|
208
|
+
for (const dir of ["config", "posts", "about", "words"]) {
|
|
209
|
+
mkdirSync(join(contentRoot, dir), { recursive: true });
|
|
210
|
+
}
|
|
211
|
+
const files = {
|
|
212
|
+
...Object.fromEntries(Object.entries(getConfigYamls()).map(([name, content]) => [`config/${name}`, content])),
|
|
213
|
+
"posts/hello-stalux.md": getExamplePost(),
|
|
214
|
+
"about/index.md": getAboutMd(),
|
|
215
|
+
"words/_template.md": getWordsTemplate(),
|
|
216
|
+
"words/einstein-imagination.md": getWordsExample()
|
|
217
|
+
};
|
|
218
|
+
for (const [file, content] of Object.entries(files)) {
|
|
219
|
+
writeIfMissing(join(contentRoot, file), `stalux/${file}`, content);
|
|
220
|
+
}
|
|
221
|
+
console.log(`
|
|
222
|
+
✅ Done! Stalux content initialized.
|
|
223
|
+
`);
|
|
224
|
+
printNextSteps();
|
|
225
|
+
}
|
|
226
|
+
function printHelp() {
|
|
227
|
+
console.log(`
|
|
228
|
+
Stalux — Modern Astro Blog Theme
|
|
229
|
+
|
|
230
|
+
Usage:
|
|
231
|
+
stalux init Initialize Stalux content (configs, posts, pages)
|
|
232
|
+
stalux init my-blog Initialize in a subdirectory
|
|
233
|
+
|
|
234
|
+
What it does:
|
|
235
|
+
- Creates stalux/config/*.yml (all configuration files)
|
|
236
|
+
- Creates stalux/posts/hello-stalux.md (example post)
|
|
237
|
+
- Creates stalux/about/index.md (about page)
|
|
238
|
+
- Creates stalux/words/ (example quotes)
|
|
239
|
+
- Does NOT overwrite existing files
|
|
240
|
+
|
|
241
|
+
Prerequisites:
|
|
242
|
+
1. Create an Astro project: bun create astro
|
|
243
|
+
2. Install stalux: bun add @xingwangzhe/stalux
|
|
244
|
+
3. Run init: bunx stalux init
|
|
245
|
+
`);
|
|
246
|
+
}
|
|
247
|
+
function printNextSteps() {
|
|
248
|
+
console.log(" \uD83D\uDCDD Next Steps:");
|
|
249
|
+
console.log("");
|
|
250
|
+
console.log(" 1. Add stalux to your astro.config.ts:");
|
|
251
|
+
console.log(' import stalux from "@xingwangzhe/stalux";');
|
|
252
|
+
console.log(' integrations: [stalux({ contentDir: "stalux" })],');
|
|
253
|
+
console.log("");
|
|
254
|
+
console.log(" 2. Add content collections to src/content.config.ts:");
|
|
255
|
+
console.log(' import { defineCollections } from "@xingwangzhe/stalux/schemas/collections";');
|
|
256
|
+
console.log(' export const collections = defineCollections({ contentDir: "stalux" });');
|
|
257
|
+
console.log("");
|
|
258
|
+
console.log(" 3. Start writing content in stalux/posts/");
|
|
259
|
+
console.log(" 4. Run: bun run dev");
|
|
260
|
+
console.log("");
|
|
261
|
+
console.log(" \uD83D\uDCD6 Docs: https://stalux.needhelp.icu");
|
|
262
|
+
console.log("");
|
|
263
|
+
}
|
|
264
|
+
main();
|
package/README.md
CHANGED
|
@@ -23,7 +23,7 @@ bun add @xingwangzhe/stalux # Install theme (all dependencies included)
|
|
|
23
23
|
bunx stalux init # Generate stalux/ content directory
|
|
24
24
|
```
|
|
25
25
|
|
|
26
|
-
Then configure `astro.config.
|
|
26
|
+
Requires Node.js 26 or later. Then configure `astro.config.ts`. All plugins are bundled into the Stalux integration by default — **no manual configuration is needed**:
|
|
27
27
|
|
|
28
28
|
- **Markdown**: Mermaid (MDAST detection + HAST/SVG rendering), math formulas (Temml → MathML), word count / feature flags, and PhotoSwipe image lightbox are injected into the default `satteri()` processor automatically (math / frontmatter / gfm / smart punctuation are enabled by default).
|
|
29
29
|
- **Sitemap**: `@astrojs/sitemap` is bundled (`.md` source endpoints are filtered out by default).
|
|
@@ -88,7 +88,7 @@ bun run dev
|
|
|
88
88
|
- 🤖 **LLM discovery files** (llms.txt / llms-full.txt)
|
|
89
89
|
- 🤝 **WebMCP tools** for AI agents (W3C draft, pure front-end)
|
|
90
90
|
- ⚡ **View transitions** for smooth navigation
|
|
91
|
-
- 🌐 **i18n** (English / Chinese)
|
|
91
|
+
- 🌐 **i18n** (English / Simplified Chinese; missing locale keys fall back to English)
|
|
92
92
|
- 🏷️ **Tags, categories, archives** pages
|
|
93
93
|
- 🎨 **Component override system** (Starlight-style)
|
|
94
94
|
- 🛠️ **Easy YAML configuration** — no coding required
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xingwangzhe/stalux",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.27.1",
|
|
4
4
|
"description": "A powerful, modern Astro blog theme — use as template or install as plugin",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"astro",
|
|
@@ -19,8 +19,11 @@
|
|
|
19
19
|
"type": "git",
|
|
20
20
|
"url": "git+https://github.com/xingwangzhe/stalux.git"
|
|
21
21
|
},
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=26"
|
|
24
|
+
},
|
|
22
25
|
"bin": {
|
|
23
|
-
"stalux": "
|
|
26
|
+
"stalux": ".release/cli.mjs"
|
|
24
27
|
},
|
|
25
28
|
"files": [
|
|
26
29
|
"src/index.ts",
|
|
@@ -40,7 +43,7 @@
|
|
|
40
43
|
"src/scripts/**/*.ts",
|
|
41
44
|
"public/background/**",
|
|
42
45
|
"src/assets/**/*",
|
|
43
|
-
"
|
|
46
|
+
".release/cli.mjs",
|
|
44
47
|
"!src/content.config.ts"
|
|
45
48
|
],
|
|
46
49
|
"type": "module",
|
|
@@ -65,10 +68,13 @@
|
|
|
65
68
|
},
|
|
66
69
|
"scripts": {
|
|
67
70
|
"dev": "astro dev",
|
|
68
|
-
"build": "astro build &&
|
|
71
|
+
"build": "astro build && node scripts/verify-build.ts",
|
|
69
72
|
"preview": "astro preview",
|
|
70
73
|
"astro": "astro",
|
|
71
|
-
"init": "
|
|
74
|
+
"init": "node scripts/cli.ts init",
|
|
75
|
+
"node:check": "tsc6 --project tsconfig.node.json",
|
|
76
|
+
"build:cli": "bun build scripts/cli.ts --target=node --outfile .release/cli.mjs",
|
|
77
|
+
"prepack": "bun run build:cli",
|
|
72
78
|
"check": "biome check .",
|
|
73
79
|
"check:fix": "biome check --write .",
|
|
74
80
|
"format": "biome format --write .",
|
|
@@ -80,11 +86,11 @@
|
|
|
80
86
|
"test:run": "vitest run",
|
|
81
87
|
"test:coverage": "vitest run --coverage",
|
|
82
88
|
"knip": "knip",
|
|
83
|
-
"verify:build": "
|
|
84
|
-
"validate": "bun run check && bun run astro:check && bun run knip && bun run test:coverage && bun run build",
|
|
89
|
+
"verify:build": "node scripts/verify-build.ts",
|
|
90
|
+
"validate": "bun run check && bun run node:check && bun run astro:check && bun run knip && bun run test:coverage && bun run build && bun run build:cli",
|
|
85
91
|
"prepare": "git config core.hooksPath scripts/git-hooks",
|
|
86
92
|
"dev:debug": "STALUX_DEBUG=1 astro dev --verbose",
|
|
87
|
-
"build:debug": "STALUX_DEBUG=1 astro build --verbose &&
|
|
93
|
+
"build:debug": "STALUX_DEBUG=1 astro build --verbose && node scripts/verify-build.ts"
|
|
88
94
|
},
|
|
89
95
|
"dependencies": {
|
|
90
96
|
"@astrojs/markdown-satteri": "0.4.2",
|
|
@@ -112,6 +118,7 @@
|
|
|
112
118
|
"devDependencies": {
|
|
113
119
|
"@astrojs/check": "0.9.10",
|
|
114
120
|
"@biomejs/biome": "2.5.14",
|
|
121
|
+
"@types/node": "^26.6.2",
|
|
115
122
|
"@vitest/coverage-v8": "5.0.1",
|
|
116
123
|
"astro": "^7.3.4",
|
|
117
124
|
"knip": "^6.37.0",
|
|
@@ -18,22 +18,4 @@ import { getSidebarAnimation } from "@utils/view-transitions";
|
|
|
18
18
|
<div class={style.sidebarContainer}>
|
|
19
19
|
<RandomPost />
|
|
20
20
|
</div>
|
|
21
|
-
|
|
22
|
-
<style>
|
|
23
|
-
:global(.stalux-root) {
|
|
24
|
-
--sidebar-width: 280px;
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
@media (max-width: 1200px) {
|
|
28
|
-
:global(.stalux-root) {
|
|
29
|
-
--sidebar-width: 240px;
|
|
30
|
-
}
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
@media (max-width: 768px) {
|
|
34
|
-
:global(.stalux-root) {
|
|
35
|
-
--sidebar-width: 0;
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
</style>
|
|
39
21
|
</aside>
|
|
@@ -18,7 +18,7 @@ const { t } = createTranslator((siteConfig.lang as string) || "zh-CN");
|
|
|
18
18
|
---
|
|
19
19
|
|
|
20
20
|
{(props.prev || props.next) && (
|
|
21
|
-
<nav class={style.postNavigation} aria-label="
|
|
21
|
+
<nav class={style.postNavigation} aria-label={t("post.navigation")}>
|
|
22
22
|
<div class={style.postNavigationInner}>
|
|
23
23
|
{props.prev ? (
|
|
24
24
|
<a
|
package/src/i18n/en.json
CHANGED
package/src/i18n/zh-CN.json
CHANGED
package/src/pages/404.astro
CHANGED
package/src/styles/base/init.css
CHANGED
|
@@ -112,9 +112,6 @@ ul {
|
|
|
112
112
|
--stalux-bg-filter: none;
|
|
113
113
|
--stalux-text-shadow: #64ffda 0.1rem 0.1rem 0.2rem;
|
|
114
114
|
--stalux-accent-color: #64ffda;
|
|
115
|
-
--stalux-search-backdrop: rgba(0, 0, 0, 0.1);
|
|
116
|
-
--stalux-search-box-bg: rgba(0, 0, 0, 0.1);
|
|
117
|
-
--stalux-search-border: rgba(0, 0, 0, 0.2);
|
|
118
115
|
|
|
119
116
|
/* 卡片和标签颜色 Token(可在这里统一调整主题色/透明度) */
|
|
120
117
|
--card-bg: rgba(0, 0, 0, 0.2);
|
|
@@ -146,19 +143,13 @@ ul {
|
|
|
146
143
|
--white-30p: rgba(255, 255, 255, 0.3);
|
|
147
144
|
--white-20p: rgba(255, 255, 255, 0.2);
|
|
148
145
|
--white-15p: rgba(255, 255, 255, 0.15);
|
|
149
|
-
--white-12p: rgba(255, 255, 255, 0.12);
|
|
150
146
|
--white-10p: rgba(255, 255, 255, 0.1);
|
|
151
|
-
--white-8p: rgba(255, 255, 255, 0.08);
|
|
152
147
|
--white-05p: rgba(255, 255, 255, 0.05);
|
|
153
148
|
|
|
154
|
-
--black-full: #000000;
|
|
155
149
|
--black-30p: rgba(0, 0, 0, 0.3);
|
|
156
|
-
--black-28p: rgba(0, 0, 0, 0.28);
|
|
157
150
|
--black-20p: rgba(0, 0, 0, 0.2);
|
|
158
151
|
--black-15p: rgba(0, 0, 0, 0.15);
|
|
159
152
|
--black-10p: rgba(0, 0, 0, 0.1);
|
|
160
|
-
--black-05p: rgba(0, 0, 0, 0.05);
|
|
161
|
-
--black-03p: rgba(0, 0, 0, 0.03);
|
|
162
153
|
|
|
163
154
|
/* 强调色变体 */
|
|
164
155
|
--accent-90p: rgba(100, 255, 218, 0.9);
|
|
@@ -170,7 +161,6 @@ ul {
|
|
|
170
161
|
--accent-40p: rgba(100, 255, 218, 0.4);
|
|
171
162
|
--accent-30p: rgba(100, 255, 218, 0.3);
|
|
172
163
|
--accent-20p: rgba(100, 255, 218, 0.2);
|
|
173
|
-
--accent-10p: rgba(100, 255, 218, 0.1);
|
|
174
164
|
|
|
175
165
|
/* 常用过渡和动画 */
|
|
176
166
|
--transition-fast: 0.18s ease;
|
|
@@ -181,7 +171,6 @@ ul {
|
|
|
181
171
|
--transition-slowest: 0.6s ease;
|
|
182
172
|
|
|
183
173
|
--easing-bounce: cubic-bezier(0.175, 0.885, 0.32, 1.275);
|
|
184
|
-
--easing-smooth: cubic-bezier(0.25, 0.9, 0.2, 1);
|
|
185
174
|
|
|
186
175
|
/* 常用间距值 */
|
|
187
176
|
--space-2xs: 0.25rem;
|
|
@@ -197,9 +186,7 @@ ul {
|
|
|
197
186
|
--radius-sm: 4px;
|
|
198
187
|
--radius-md: 6px;
|
|
199
188
|
--radius-lg: 8px;
|
|
200
|
-
--radius-xl: 10px;
|
|
201
189
|
--radius-full: 9999px;
|
|
202
|
-
--radius-circle: 50%;
|
|
203
190
|
|
|
204
191
|
/* 常用阴影 */
|
|
205
192
|
--shadow-sm: 0 2px 5px rgba(0, 0, 0, 0.1);
|
|
@@ -210,18 +197,12 @@ ul {
|
|
|
210
197
|
--shadow-dark: rgba(0, 0, 0, 0.753);
|
|
211
198
|
|
|
212
199
|
/* 语义化颜色 */
|
|
213
|
-
--date-text-color: #e8f2ff;
|
|
214
|
-
--updated-text-color: #fff7de;
|
|
215
200
|
--muted-text: #bbb;
|
|
216
|
-
--border-color-light: #e5e5e5;
|
|
217
201
|
|
|
218
202
|
/* 字体族栈 */
|
|
219
203
|
/* --font-body 由 Astro Fonts API 提供(--font-code 同理,见集成注入的 fonts 配置) */
|
|
220
|
-
--font-body-serif: "Noto Serif CJK SC", "Source Han Serif SC", "STSong", Georgia, serif;
|
|
221
204
|
|
|
222
205
|
/* 字体大小系统 */
|
|
223
|
-
--font-size-title: 2.8rem;
|
|
224
|
-
--font-size-h2: 2rem;
|
|
225
206
|
--font-size-subtitle: 1.35rem;
|
|
226
207
|
--font-size-base: 1.1rem;
|
|
227
208
|
--font-size-small: 0.95rem;
|
|
@@ -232,7 +213,6 @@ ul {
|
|
|
232
213
|
--border-thin: 1px;
|
|
233
214
|
--border-medium: 2px;
|
|
234
215
|
--border-thick: 3px;
|
|
235
|
-
--border-thicker: 4px;
|
|
236
216
|
}
|
|
237
217
|
::-webkit-scrollbar {
|
|
238
218
|
width: 8px;
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
.h1,
|
|
2
|
+
.description {
|
|
3
|
+
text-align: center;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
.h1 {
|
|
2
7
|
margin-top: 1.5em;
|
|
3
|
-
text-align: center;
|
|
4
8
|
text-shadow: var(--stalux-text-shadow);
|
|
5
9
|
font-size: 2.5em;
|
|
6
10
|
}
|
|
11
|
+
|
|
7
12
|
.description {
|
|
8
|
-
text-align: center;
|
|
9
13
|
margin-bottom: 1.5em;
|
|
10
14
|
font-size: 1.2em;
|
|
11
15
|
color: var(--white-60p);
|
|
@@ -1,12 +1,16 @@
|
|
|
1
|
+
.title,
|
|
2
|
+
.description {
|
|
3
|
+
text-align: center;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
.title {
|
|
2
7
|
margin-top: 1.5em;
|
|
3
|
-
text-align: center;
|
|
4
8
|
justify-content: center;
|
|
5
9
|
text-shadow: var(--stalux-text-shadow);
|
|
6
10
|
font-size: 2.5em;
|
|
7
11
|
}
|
|
12
|
+
|
|
8
13
|
.description {
|
|
9
|
-
text-align: center;
|
|
10
14
|
margin-bottom: 1.5em;
|
|
11
15
|
font-size: 1.2em;
|
|
12
16
|
color: var(--white-60p);
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
.title,
|
|
2
|
+
.description {
|
|
3
|
+
text-align: center;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
.title {
|
|
2
7
|
margin-top: 1.5em;
|
|
3
|
-
text-align: center;
|
|
4
8
|
text-shadow: var(--stalux-text-shadow);
|
|
5
9
|
font-size: 2.5em;
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
.description {
|
|
9
|
-
text-align: center;
|
|
10
13
|
margin-bottom: 1.5em;
|
|
11
14
|
font-size: 1.2em;
|
|
12
15
|
color: var(--white-60p);
|
|
@@ -1,11 +1,15 @@
|
|
|
1
|
+
.title,
|
|
2
|
+
.description {
|
|
3
|
+
text-align: center;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
.title {
|
|
2
7
|
margin-top: 1.5em;
|
|
3
|
-
text-align: center;
|
|
4
8
|
text-shadow: var(--stalux-text-shadow);
|
|
5
9
|
font-size: 2.5em;
|
|
6
10
|
}
|
|
11
|
+
|
|
7
12
|
.description {
|
|
8
|
-
text-align: center;
|
|
9
13
|
margin-bottom: 1.5em;
|
|
10
14
|
font-size: 1.2em;
|
|
11
15
|
color: var(--white-60p);
|
|
@@ -1,12 +1,15 @@
|
|
|
1
|
+
.title,
|
|
2
|
+
.description {
|
|
3
|
+
text-align: center;
|
|
4
|
+
}
|
|
5
|
+
|
|
1
6
|
.title {
|
|
2
7
|
margin-top: 1.5em;
|
|
3
|
-
text-align: center;
|
|
4
8
|
text-shadow: var(--stalux-text-shadow);
|
|
5
9
|
font-size: 2.5em;
|
|
6
10
|
}
|
|
7
11
|
|
|
8
12
|
.description {
|
|
9
|
-
text-align: center;
|
|
10
13
|
margin-bottom: 1.5em;
|
|
11
14
|
font-size: 1.2em;
|
|
12
15
|
color: var(--white-60p);
|
package/src/utils/i18n.ts
CHANGED
|
@@ -12,7 +12,9 @@ export interface Translator {
|
|
|
12
12
|
}
|
|
13
13
|
|
|
14
14
|
export function createTranslator(lang: string): Translator {
|
|
15
|
-
const
|
|
15
|
+
const normalizedLang = lang.toLowerCase();
|
|
16
|
+
const language = normalizedLang.startsWith("en") ? "en" : "zh-CN";
|
|
17
|
+
const dict = dicts[language] ?? dicts["zh-CN"] ?? en;
|
|
16
18
|
|
|
17
19
|
function t(key: string, params?: Record<string, string | number>): string {
|
|
18
20
|
const keys = key.split(".");
|
|
@@ -21,12 +23,12 @@ export function createTranslator(lang: string): Translator {
|
|
|
21
23
|
if (text && typeof text === "object") {
|
|
22
24
|
text = (text as Record<string, unknown>)[k];
|
|
23
25
|
} else {
|
|
24
|
-
return key;
|
|
26
|
+
return lookup(en, key) ?? key;
|
|
25
27
|
}
|
|
26
28
|
}
|
|
27
|
-
if (typeof text !== "string")
|
|
29
|
+
if (typeof text !== "string" || !text.trim()) text = lookup(en, key) ?? key;
|
|
28
30
|
|
|
29
|
-
let result = text;
|
|
31
|
+
let result = text as string;
|
|
30
32
|
if (params) {
|
|
31
33
|
for (const [k, v] of Object.entries(params)) {
|
|
32
34
|
result = result.replace(`{${k}}`, String(v));
|
|
@@ -35,7 +37,16 @@ export function createTranslator(lang: string): Translator {
|
|
|
35
37
|
return result;
|
|
36
38
|
}
|
|
37
39
|
|
|
38
|
-
return { t, lang };
|
|
40
|
+
return { t, lang: language };
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function lookup(dictionary: Record<string, unknown>, key: string): string | undefined {
|
|
44
|
+
let value: unknown = dictionary;
|
|
45
|
+
for (const part of key.split(".")) {
|
|
46
|
+
if (!value || typeof value !== "object") return;
|
|
47
|
+
value = (value as Record<string, unknown>)[part];
|
|
48
|
+
}
|
|
49
|
+
return typeof value === "string" && value.trim() ? value : undefined;
|
|
39
50
|
}
|
|
40
51
|
|
|
41
52
|
/**
|
package/scripts/cli.mjs
DELETED
|
@@ -1,331 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* Stalux CLI — 主题初始化工具
|
|
5
|
-
*
|
|
6
|
-
* 用法:
|
|
7
|
-
* bunx stalux init # 在当前目录初始化内容模板
|
|
8
|
-
* bunx stalux init my-blog # 在子目录初始化项目
|
|
9
|
-
*
|
|
10
|
-
* 说明:
|
|
11
|
-
* - 只在 stalux/ 目录下生成内容配置文件和示例文章
|
|
12
|
-
* - 不会覆盖已有的 package.json、astro.config.mjs、src/content.config.ts
|
|
13
|
-
* - 静默运行,无交互式问答
|
|
14
|
-
* - 静默运行,无交互式问答
|
|
15
|
-
*/
|
|
16
|
-
|
|
17
|
-
import { existsSync, mkdirSync, writeFileSync } from "node:fs";
|
|
18
|
-
import { join, resolve as pathResolve } from "node:path";
|
|
19
|
-
|
|
20
|
-
// ---------------------------------------------------------------------------
|
|
21
|
-
// 默认内容模板数据
|
|
22
|
-
// ---------------------------------------------------------------------------
|
|
23
|
-
|
|
24
|
-
function getConfigYamls() {
|
|
25
|
-
const year = new Date().getFullYear();
|
|
26
|
-
const now = new Date().toISOString();
|
|
27
|
-
return {
|
|
28
|
-
"site.yml": `id: site
|
|
29
|
-
lang: en
|
|
30
|
-
title: "My Blog"
|
|
31
|
-
description: "A blog built with Stalux theme"
|
|
32
|
-
url: "https://example.com"
|
|
33
|
-
timezone: "Asia/Shanghai"
|
|
34
|
-
`,
|
|
35
|
-
"author.yml": `id: author
|
|
36
|
-
name: "Your Name"
|
|
37
|
-
avatar: "/avatar.png"
|
|
38
|
-
bio: "Blogger & Developer"
|
|
39
|
-
`,
|
|
40
|
-
"navs.yml": `id: navs
|
|
41
|
-
items:
|
|
42
|
-
- title: "Home"
|
|
43
|
-
link: "/"
|
|
44
|
-
icon: "house"
|
|
45
|
-
- title: "Archives"
|
|
46
|
-
link: "/archives"
|
|
47
|
-
icon: "archive"
|
|
48
|
-
- title: "Tags"
|
|
49
|
-
link: "/tags"
|
|
50
|
-
icon: "tag"
|
|
51
|
-
- title: "Categories"
|
|
52
|
-
link: "/categories"
|
|
53
|
-
icon: "folder"
|
|
54
|
-
- title: "Words"
|
|
55
|
-
link: "/words"
|
|
56
|
-
icon: "quote"
|
|
57
|
-
- title: "Links"
|
|
58
|
-
link: "/links"
|
|
59
|
-
icon: "link"
|
|
60
|
-
`,
|
|
61
|
-
"head.yml": `id: head
|
|
62
|
-
# googleAnalyticsId: "G-XXXXXXXXXX"
|
|
63
|
-
# bingClarityId: "xxxxxxxxxx"
|
|
64
|
-
# umami:
|
|
65
|
-
# id: ""
|
|
66
|
-
# url: ""
|
|
67
|
-
# anyhead: ""
|
|
68
|
-
`,
|
|
69
|
-
"footer.yml": `id: footer
|
|
70
|
-
buildtime: "${now}"
|
|
71
|
-
copyright:
|
|
72
|
-
enabled: true
|
|
73
|
-
startYear: ${year}
|
|
74
|
-
customText: ""
|
|
75
|
-
theme:
|
|
76
|
-
showPoweredBy: true
|
|
77
|
-
showThemeInfo: true
|
|
78
|
-
beian:
|
|
79
|
-
icp:
|
|
80
|
-
enabled: false
|
|
81
|
-
number: ""
|
|
82
|
-
security:
|
|
83
|
-
enabled: false
|
|
84
|
-
text: ""
|
|
85
|
-
number: ""
|
|
86
|
-
badges:
|
|
87
|
-
- label: "Powered by"
|
|
88
|
-
message: "Astro"
|
|
89
|
-
color: "orange"
|
|
90
|
-
style: "flat-square"
|
|
91
|
-
href: "https://astro.build/"
|
|
92
|
-
custom: |
|
|
93
|
-
<div id="custom-footer-hook"></div>
|
|
94
|
-
`,
|
|
95
|
-
"media-links.yml": `id: media-links
|
|
96
|
-
items:
|
|
97
|
-
- icon: "github"
|
|
98
|
-
link: "https://github.com/yourname"
|
|
99
|
-
`,
|
|
100
|
-
"links.yml": `id: links
|
|
101
|
-
title: "Links"
|
|
102
|
-
description: "Friends & Resources"
|
|
103
|
-
sites:
|
|
104
|
-
- name: "Astro"
|
|
105
|
-
description: "The web framework for content-driven websites"
|
|
106
|
-
link: "https://astro.build"
|
|
107
|
-
icon: "https://astro.build/favicon.svg"
|
|
108
|
-
`,
|
|
109
|
-
"comment.yml": `id: comment
|
|
110
|
-
enabled: false
|
|
111
|
-
`,
|
|
112
|
-
"promote.yml": `id: promote
|
|
113
|
-
export_md: false
|
|
114
|
-
# llm_promote: |
|
|
115
|
-
`,
|
|
116
|
-
"ai-discovery.yml": `id: ai-discovery
|
|
117
|
-
conformance: "disabled"
|
|
118
|
-
`,
|
|
119
|
-
"typetexts.yml": `id: typetexts
|
|
120
|
-
items:
|
|
121
|
-
- "Free for free, not free for charge!"
|
|
122
|
-
- "Where's the any key?"
|
|
123
|
-
- "Press F12?"
|
|
124
|
-
- "Hello World!"
|
|
125
|
-
`,
|
|
126
|
-
};
|
|
127
|
-
}
|
|
128
|
-
|
|
129
|
-
function getExamplePost() {
|
|
130
|
-
const date = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
131
|
-
return `---
|
|
132
|
-
title: Hello Stalux!
|
|
133
|
-
abbrlink: hello-stalux
|
|
134
|
-
date: "${date}"
|
|
135
|
-
tags: [Stalux, Getting Started]
|
|
136
|
-
categories: [Blog]
|
|
137
|
-
desc: Welcome to Stalux!
|
|
138
|
-
cc: CC-BY-NC-SA-4.0
|
|
139
|
-
---
|
|
140
|
-
|
|
141
|
-
Welcome to **Stalux**!
|
|
142
|
-
|
|
143
|
-
This is your first post. Edit or delete it, then start writing your own content.
|
|
144
|
-
|
|
145
|
-
## Features
|
|
146
|
-
|
|
147
|
-
- 🌙 Dark mode with elegant glassmorphism design
|
|
148
|
-
- 🔤 Per-route font subsetting — each page loads only needed characters
|
|
149
|
-
- 🔍 Full-text search (Pagefind)
|
|
150
|
-
- 📡 RSS & Atom feeds
|
|
151
|
-
- 💬 Comment system (Waline)
|
|
152
|
-
- 📊 Mermaid diagrams
|
|
153
|
-
- 📐 Math formula rendering
|
|
154
|
-
- 🖼️ PhotoSwipe lightbox
|
|
155
|
-
|
|
156
|
-
For more details, visit [Stalux documentation](https://stalux.needhelp.icu).
|
|
157
|
-
`;
|
|
158
|
-
}
|
|
159
|
-
|
|
160
|
-
function getAboutMd() {
|
|
161
|
-
return `---
|
|
162
|
-
title: About Me
|
|
163
|
-
description: About this blog and the author
|
|
164
|
-
---
|
|
165
|
-
|
|
166
|
-
Hello! Welcome to my blog.
|
|
167
|
-
|
|
168
|
-
This is my personal space where I share technology, life, and thoughts.
|
|
169
|
-
|
|
170
|
-
## About This Site
|
|
171
|
-
|
|
172
|
-
- Built with [Astro](https://astro.build) + [Stalux](https://stalux.needhelp.icu)
|
|
173
|
-
- Content licensed under CC-BY-NC-SA-4.0
|
|
174
|
-
- Source code hosted on GitHub
|
|
175
|
-
`;
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
function getWordsTemplate() {
|
|
179
|
-
const date = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
180
|
-
return `---
|
|
181
|
-
source: "Author Name"
|
|
182
|
-
link: "https://example.com"
|
|
183
|
-
sourceDate: ""
|
|
184
|
-
date: "${date}"
|
|
185
|
-
---
|
|
186
|
-
|
|
187
|
-
> A quote or short note...
|
|
188
|
-
`;
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
function getWordsExample() {
|
|
192
|
-
const date = new Date().toISOString().replace("T", " ").slice(0, 19);
|
|
193
|
-
return `---
|
|
194
|
-
source: "Albert Einstein"
|
|
195
|
-
link: "https://example.com"
|
|
196
|
-
sourceDate: ""
|
|
197
|
-
date: "${date}"
|
|
198
|
-
---
|
|
199
|
-
|
|
200
|
-
> Imagination is more important than knowledge.
|
|
201
|
-
`;
|
|
202
|
-
}
|
|
203
|
-
|
|
204
|
-
// ---------------------------------------------------------------------------
|
|
205
|
-
// 主流程
|
|
206
|
-
// ---------------------------------------------------------------------------
|
|
207
|
-
|
|
208
|
-
function main() {
|
|
209
|
-
const args = process.argv.slice(2);
|
|
210
|
-
|
|
211
|
-
if (args[0] === "--help" || args[0] === "-h" || !args[0]) {
|
|
212
|
-
printHelp();
|
|
213
|
-
process.exit(0);
|
|
214
|
-
}
|
|
215
|
-
|
|
216
|
-
if (args[0] !== "init") {
|
|
217
|
-
console.error(`❌ Unknown command: ${args[0]}`);
|
|
218
|
-
printHelp();
|
|
219
|
-
process.exit(1);
|
|
220
|
-
}
|
|
221
|
-
|
|
222
|
-
const targetArg = args[1] || ".";
|
|
223
|
-
const targetPath = pathResolve(process.cwd(), targetArg);
|
|
224
|
-
|
|
225
|
-
console.log(`📦 Initializing Stalux content in ${targetPath}...`);
|
|
226
|
-
console.log("");
|
|
227
|
-
|
|
228
|
-
// 创建 stalux/ 目录结构
|
|
229
|
-
const contentRoot = join(targetPath, "stalux");
|
|
230
|
-
const dirs = ["config", "posts", "about", "words"];
|
|
231
|
-
for (const dir of dirs) {
|
|
232
|
-
mkdirSync(join(contentRoot, dir), { recursive: true });
|
|
233
|
-
}
|
|
234
|
-
|
|
235
|
-
// 生成 config YAML 文件(不覆盖已有)
|
|
236
|
-
const configs = getConfigYamls();
|
|
237
|
-
for (const [file, content] of Object.entries(configs)) {
|
|
238
|
-
const filePath = join(contentRoot, "config", file);
|
|
239
|
-
if (existsSync(filePath)) {
|
|
240
|
-
console.log(` ⏭ stalux/config/${file} (exists, skipped)`);
|
|
241
|
-
continue;
|
|
242
|
-
}
|
|
243
|
-
writeFileSync(filePath, content);
|
|
244
|
-
console.log(` ✅ stalux/config/${file}`);
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
// 生成示例文章
|
|
248
|
-
const postPath = join(contentRoot, "posts", "hello-stalux.md");
|
|
249
|
-
if (!existsSync(postPath)) {
|
|
250
|
-
writeFileSync(postPath, getExamplePost());
|
|
251
|
-
console.log(` ✅ stalux/posts/hello-stalux.md`);
|
|
252
|
-
} else {
|
|
253
|
-
console.log(` ⏭ stalux/posts/hello-stalux.md (exists, skipped)`);
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// 生成 about 页面
|
|
257
|
-
const aboutPath = join(contentRoot, "about", "index.md");
|
|
258
|
-
if (!existsSync(aboutPath)) {
|
|
259
|
-
writeFileSync(aboutPath, getAboutMd());
|
|
260
|
-
console.log(` ✅ stalux/about/index.md`);
|
|
261
|
-
} else {
|
|
262
|
-
console.log(` ⏭ stalux/about/index.md (exists, skipped)`);
|
|
263
|
-
}
|
|
264
|
-
|
|
265
|
-
// 生成 words
|
|
266
|
-
const wordsDir = join(contentRoot, "words");
|
|
267
|
-
const wordsTemplatePath = join(wordsDir, "_template.md");
|
|
268
|
-
if (!existsSync(wordsTemplatePath)) {
|
|
269
|
-
writeFileSync(wordsTemplatePath, getWordsTemplate());
|
|
270
|
-
console.log(` ✅ stalux/words/_template.md`);
|
|
271
|
-
} else {
|
|
272
|
-
console.log(` ⏭ stalux/words/_template.md (exists, skipped)`);
|
|
273
|
-
}
|
|
274
|
-
|
|
275
|
-
const einsteinPath = join(wordsDir, "einstein-imagination.md");
|
|
276
|
-
if (!existsSync(einsteinPath)) {
|
|
277
|
-
writeFileSync(einsteinPath, getWordsExample());
|
|
278
|
-
console.log(` ✅ stalux/words/einstein-imagination.md`);
|
|
279
|
-
} else {
|
|
280
|
-
console.log(` ⏭ stalux/words/einstein-imagination.md (exists, skipped)`);
|
|
281
|
-
}
|
|
282
|
-
|
|
283
|
-
console.log("");
|
|
284
|
-
console.log(" ✅ Done! Stalux content initialized.");
|
|
285
|
-
console.log("");
|
|
286
|
-
printNextSteps();
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
function printHelp() {
|
|
290
|
-
console.log(`
|
|
291
|
-
Stalux — Modern Astro Blog Theme
|
|
292
|
-
|
|
293
|
-
Usage:
|
|
294
|
-
stalux init Initialize Stalux content (configs, posts, pages)
|
|
295
|
-
stalux init my-blog Initialize in a subdirectory
|
|
296
|
-
|
|
297
|
-
What it does:
|
|
298
|
-
- Creates stalux/config/*.yml (all configuration files)
|
|
299
|
-
- Creates stalux/posts/hello-stalux.md (example post)
|
|
300
|
-
- Creates stalux/about/index.md (about page)
|
|
301
|
-
- Creates stalux/words/ (example quotes)
|
|
302
|
-
- Does NOT overwrite existing files
|
|
303
|
-
|
|
304
|
-
Prerequisites:
|
|
305
|
-
1. Create an Astro project: bun create astro
|
|
306
|
-
2. Install stalux: bun add @xingwangzhe/stalux
|
|
307
|
-
3. Run init: bunx stalux init
|
|
308
|
-
`);
|
|
309
|
-
}
|
|
310
|
-
|
|
311
|
-
function printNextSteps() {
|
|
312
|
-
console.log(" 📝 Next Steps:");
|
|
313
|
-
console.log("");
|
|
314
|
-
console.log(" 1. Add stalux to your astro.config.mjs:");
|
|
315
|
-
console.log(' import stalux from "@xingwangzhe/stalux";');
|
|
316
|
-
console.log(' integrations: [stalux({ contentDir: "stalux" })],');
|
|
317
|
-
console.log("");
|
|
318
|
-
console.log(" 2. Add content collections to src/content.config.ts:");
|
|
319
|
-
console.log(
|
|
320
|
-
' import { defineCollections } from "@xingwangzhe/stalux/schemas/collections";',
|
|
321
|
-
);
|
|
322
|
-
console.log(' export const collections = defineCollections({ contentDir: "stalux" });');
|
|
323
|
-
console.log("");
|
|
324
|
-
console.log(" 3. Start writing content in stalux/posts/");
|
|
325
|
-
console.log(" 4. Run: bun run dev");
|
|
326
|
-
console.log("");
|
|
327
|
-
console.log(" 📖 Docs: https://stalux.needhelp.icu");
|
|
328
|
-
console.log("");
|
|
329
|
-
}
|
|
330
|
-
|
|
331
|
-
main();
|