@jet-w/astro-blog 0.1.1 → 0.1.3

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 (46) hide show
  1. package/dist/chunk-MQXPSOYB.js +124 -0
  2. package/dist/config/index.d.ts +2 -92
  3. package/dist/index.d.ts +6 -2
  4. package/dist/index.js +6 -0
  5. package/dist/integration.d.ts +25 -0
  6. package/dist/integration.js +8 -0
  7. package/dist/sidebar-DNdiCKBw.d.ts +92 -0
  8. package/dist/utils/sidebar.d.ts +98 -0
  9. package/dist/utils/sidebar.js +305 -0
  10. package/package.json +6 -3
  11. package/src/components/about/SocialLinks.astro +1 -1
  12. package/src/components/blog/Hero.astro +1 -1
  13. package/src/components/layout/Footer.astro +1 -2
  14. package/src/components/layout/Header.astro +4 -4
  15. package/src/components/layout/Sidebar.astro +3 -3
  16. package/src/components/ui/MobileMenu.vue +1 -1
  17. package/src/components/ui/SearchInterface.vue +1 -1
  18. package/src/layouts/BaseLayout.astro +3 -3
  19. package/src/layouts/SlidesLayout.astro +2 -2
  20. package/{templates/default/src → src}/pages/rss.xml.ts +1 -1
  21. package/templates/default/astro.config.mjs +3 -1
  22. package/templates/default/src/config/footer.ts +31 -0
  23. package/templates/default/src/config/index.ts +13 -110
  24. package/templates/default/src/config/sidebar.ts +33 -0
  25. package/templates/default/src/config/site.ts +56 -0
  26. package/templates/default/src/config/social.ts +15 -0
  27. package/src/utils/sidebar.ts +0 -492
  28. /package/{templates/default/src → src}/pages/[...slug].astro +0 -0
  29. /package/{templates/default/src → src}/pages/archives/[year]/[month]/page/[page].astro +0 -0
  30. /package/{templates/default/src → src}/pages/archives/[year]/[month].astro +0 -0
  31. /package/{templates/default/src → src}/pages/archives/index.astro +0 -0
  32. /package/{templates/default/src → src}/pages/categories/[category]/page/[page].astro +0 -0
  33. /package/{templates/default/src → src}/pages/categories/[category].astro +0 -0
  34. /package/{templates/default/src → src}/pages/categories/index.astro +0 -0
  35. /package/{templates/default/src → src}/pages/container-test.astro +0 -0
  36. /package/{templates/default/src → src}/pages/mermaid-direct.html +0 -0
  37. /package/{templates/default/src → src}/pages/posts/[...slug].astro +0 -0
  38. /package/{templates/default/src → src}/pages/posts/index.astro +0 -0
  39. /package/{templates/default/src → src}/pages/posts/page/[page].astro +0 -0
  40. /package/{templates/default/src → src}/pages/search-index.json.ts +0 -0
  41. /package/{templates/default/src → src}/pages/search.astro +0 -0
  42. /package/{templates/default/src → src}/pages/slides/[...slug].astro +0 -0
  43. /package/{templates/default/src → src}/pages/slides/index.astro +0 -0
  44. /package/{templates/default/src → src}/pages/tags/[tag]/page/[page].astro +0 -0
  45. /package/{templates/default/src → src}/pages/tags/[tag].astro +0 -0
  46. /package/{templates/default/src → src}/pages/tags/index.astro +0 -0
@@ -0,0 +1,305 @@
1
+ // src/utils/sidebar.ts
2
+ function buildTreeFromPosts(posts, scanPath = "", options = {}) {
3
+ const { maxDepth, exclude = [], include = [], sortBy = "name", sortOrder = "asc" } = options;
4
+ const filteredPosts = posts.filter((post) => {
5
+ const postPath = post.id.toLowerCase();
6
+ const targetPath = scanPath.toLowerCase();
7
+ if (targetPath && !postPath.startsWith(targetPath + "/") && postPath !== targetPath) {
8
+ return false;
9
+ }
10
+ const pathParts = post.id.split("/");
11
+ for (const part of pathParts) {
12
+ if (exclude.some((pattern) => matchPattern(part, pattern))) {
13
+ return false;
14
+ }
15
+ }
16
+ if (include.length > 0) {
17
+ const matchesInclude = pathParts.some(
18
+ (part) => include.some((pattern) => matchPattern(part, pattern))
19
+ );
20
+ if (!matchesInclude) {
21
+ return false;
22
+ }
23
+ }
24
+ return true;
25
+ });
26
+ const folderTitles = {};
27
+ const folderIcons = {};
28
+ filteredPosts.forEach((post) => {
29
+ const pathParts = post.id.split("/");
30
+ const fileName = pathParts[pathParts.length - 1].toLowerCase();
31
+ if (fileName === "readme" || fileName === "readme.md") {
32
+ const folderPath = pathParts.slice(0, -1).join("/");
33
+ if (folderPath) {
34
+ if (post.data.title) {
35
+ folderTitles[folderPath] = post.data.title;
36
+ }
37
+ if (post.data.icon) {
38
+ folderIcons[folderPath] = post.data.icon;
39
+ }
40
+ }
41
+ }
42
+ });
43
+ const tree = [];
44
+ filteredPosts.forEach((post) => {
45
+ let relativePath = post.id;
46
+ if (scanPath) {
47
+ const scanPathLower = scanPath.toLowerCase();
48
+ const postIdLower = post.id.toLowerCase();
49
+ if (postIdLower.startsWith(scanPathLower + "/")) {
50
+ relativePath = post.id.slice(scanPath.length + 1);
51
+ } else if (postIdLower === scanPathLower) {
52
+ relativePath = post.id.split("/").pop() || post.id;
53
+ }
54
+ }
55
+ const pathParts = relativePath.split("/");
56
+ if (maxDepth !== void 0 && pathParts.length > maxDepth) {
57
+ return;
58
+ }
59
+ let currentLevel = tree;
60
+ let currentPath = scanPath;
61
+ pathParts.forEach((part, index) => {
62
+ const isLast = index === pathParts.length - 1;
63
+ const existing = currentLevel.find((n) => n.name.toLowerCase() === part.toLowerCase());
64
+ currentPath = currentPath ? `${currentPath}/${part}` : part;
65
+ const isReadme = isLast && (part.toLowerCase() === "readme" || part.toLowerCase() === "readme.md");
66
+ if (existing) {
67
+ if (isLast) {
68
+ existing.slug = post.id;
69
+ existing.title = post.data.title;
70
+ existing.icon = post.data.icon;
71
+ existing.isReadme = isReadme;
72
+ } else {
73
+ const folderPath = scanPath ? `${scanPath}/${pathParts.slice(0, index + 1).join("/")}` : pathParts.slice(0, index + 1).join("/");
74
+ if (folderTitles[folderPath]) {
75
+ existing.displayName = folderTitles[folderPath];
76
+ }
77
+ if (folderIcons[folderPath]) {
78
+ existing.icon = folderIcons[folderPath];
79
+ }
80
+ }
81
+ currentLevel = existing.children;
82
+ } else {
83
+ const folderPath = scanPath ? `${scanPath}/${pathParts.slice(0, index + 1).join("/")}` : pathParts.slice(0, index + 1).join("/");
84
+ const newNode = {
85
+ name: part,
86
+ slug: isLast ? post.id : void 0,
87
+ title: isLast ? post.data.title : void 0,
88
+ displayName: isLast ? post.data.title : folderTitles[folderPath],
89
+ icon: isLast ? post.data.icon : folderIcons[folderPath],
90
+ children: [],
91
+ isFolder: !isLast,
92
+ isReadme
93
+ };
94
+ currentLevel.push(newNode);
95
+ currentLevel = newNode.children;
96
+ }
97
+ });
98
+ });
99
+ return sortTree(tree, sortBy, sortOrder);
100
+ }
101
+ function sortTree(nodes, sortBy = "name", sortOrder = "asc") {
102
+ const filtered = nodes.filter((node) => !node.isReadme);
103
+ const sorted = filtered.sort((a, b) => {
104
+ if (a.isFolder && !b.isFolder) return -1;
105
+ if (!a.isFolder && b.isFolder) return 1;
106
+ let comparison = 0;
107
+ switch (sortBy) {
108
+ case "title":
109
+ comparison = (a.displayName || a.title || a.name).localeCompare(
110
+ b.displayName || b.title || b.name,
111
+ "zh-CN"
112
+ );
113
+ break;
114
+ case "name":
115
+ default:
116
+ comparison = a.name.localeCompare(b.name, "zh-CN", { numeric: true });
117
+ break;
118
+ }
119
+ return sortOrder === "desc" ? -comparison : comparison;
120
+ });
121
+ return sorted.map((node) => ({
122
+ ...node,
123
+ children: sortTree(node.children, sortBy, sortOrder)
124
+ }));
125
+ }
126
+ function matchPattern(str, pattern) {
127
+ if (pattern === "*") return true;
128
+ if (pattern.includes("*")) {
129
+ const regex = new RegExp("^" + pattern.replace(/\*/g, ".*") + "$", "i");
130
+ return regex.test(str);
131
+ }
132
+ return str.toLowerCase() === pattern.toLowerCase();
133
+ }
134
+ function matchPathPattern(currentPath, pattern) {
135
+ const normalizedPath = currentPath.replace(/\/$/, "").toLowerCase();
136
+ const normalizedPattern = pattern.replace(/\/$/, "").toLowerCase();
137
+ if (normalizedPattern.endsWith("/**")) {
138
+ const basePath = normalizedPattern.slice(0, -3);
139
+ return normalizedPath === basePath || normalizedPath.startsWith(basePath + "/");
140
+ }
141
+ if (normalizedPattern.endsWith("/*")) {
142
+ const basePath = normalizedPattern.slice(0, -2);
143
+ if (normalizedPath === basePath) return true;
144
+ if (normalizedPath.startsWith(basePath + "/")) {
145
+ const remaining = normalizedPath.slice(basePath.length + 1);
146
+ return !remaining.includes("/");
147
+ }
148
+ return false;
149
+ }
150
+ return normalizedPath === normalizedPattern;
151
+ }
152
+ function shouldShowGroup(group, currentPath) {
153
+ if (!group.showForPaths && !group.hideForPaths) {
154
+ return true;
155
+ }
156
+ if (group.hideForPaths && group.hideForPaths.length > 0) {
157
+ for (const pattern of group.hideForPaths) {
158
+ if (matchPathPattern(currentPath, pattern)) {
159
+ return false;
160
+ }
161
+ }
162
+ }
163
+ if (group.showForPaths && group.showForPaths.length > 0) {
164
+ for (const pattern of group.showForPaths) {
165
+ if (matchPathPattern(currentPath, pattern)) {
166
+ return true;
167
+ }
168
+ }
169
+ return false;
170
+ }
171
+ return true;
172
+ }
173
+ function filterGroupsByPath(groups, currentPath) {
174
+ return groups.filter((group) => shouldShowGroup(group, currentPath));
175
+ }
176
+ function manualItemsToTree(items) {
177
+ return items.map((item) => ({
178
+ name: item.title,
179
+ slug: item.slug,
180
+ title: item.title,
181
+ displayName: item.title,
182
+ icon: item.icon,
183
+ badge: item.badge,
184
+ badgeType: item.badgeType,
185
+ link: item.link,
186
+ children: item.children ? manualItemsToTree(item.children) : [],
187
+ isFolder: !!(item.children && item.children.length > 0),
188
+ collapsed: item.collapsed
189
+ }));
190
+ }
191
+ async function processSidebarConfig(config, posts) {
192
+ const processedGroups = [];
193
+ for (const group of config.groups) {
194
+ const processed = await processGroup(group, posts);
195
+ if (processed) {
196
+ processedGroups.push(processed);
197
+ }
198
+ }
199
+ return processedGroups;
200
+ }
201
+ async function processGroup(group, posts) {
202
+ switch (group.type) {
203
+ case "scan": {
204
+ const scanConfig = group;
205
+ const tree = buildTreeFromPosts(posts, scanConfig.scanPath, {
206
+ maxDepth: scanConfig.maxDepth,
207
+ exclude: scanConfig.exclude,
208
+ include: scanConfig.include,
209
+ sortBy: scanConfig.sortBy,
210
+ sortOrder: scanConfig.sortOrder
211
+ });
212
+ return {
213
+ type: "tree",
214
+ title: scanConfig.title,
215
+ icon: scanConfig.icon,
216
+ collapsed: scanConfig.collapsed,
217
+ tree
218
+ };
219
+ }
220
+ case "manual": {
221
+ const manualConfig = group;
222
+ const tree = manualItemsToTree(manualConfig.items);
223
+ return {
224
+ type: "tree",
225
+ title: manualConfig.title,
226
+ icon: manualConfig.icon,
227
+ collapsed: manualConfig.collapsed,
228
+ tree
229
+ };
230
+ }
231
+ case "mixed": {
232
+ const mixedConfig = group;
233
+ const combinedTree = [];
234
+ for (const section of mixedConfig.sections) {
235
+ const processed = await processGroup(section, posts);
236
+ if (processed && processed.tree) {
237
+ combinedTree.push({
238
+ name: section.title,
239
+ displayName: section.title,
240
+ icon: section.icon,
241
+ children: processed.tree,
242
+ isFolder: true,
243
+ collapsed: section.collapsed
244
+ });
245
+ }
246
+ }
247
+ return {
248
+ type: "tree",
249
+ title: mixedConfig.title,
250
+ icon: mixedConfig.icon,
251
+ collapsed: mixedConfig.collapsed,
252
+ tree: combinedTree
253
+ };
254
+ }
255
+ case "divider": {
256
+ return {
257
+ type: "divider",
258
+ title: group.title || ""
259
+ };
260
+ }
261
+ default:
262
+ return null;
263
+ }
264
+ }
265
+ function getRecentPosts(posts, count = 5) {
266
+ return posts.filter((p) => p.data.pubDate).sort((a, b) => (b.data.pubDate?.getTime() ?? 0) - (a.data.pubDate?.getTime() ?? 0)).slice(0, count);
267
+ }
268
+ function getPopularTags(posts, count = 8) {
269
+ const tagCounts = {};
270
+ posts.forEach((post) => {
271
+ (post.data.tags || []).forEach((tag) => {
272
+ tagCounts[tag] = (tagCounts[tag] || 0) + 1;
273
+ });
274
+ });
275
+ return Object.entries(tagCounts).sort((a, b) => b[1] - a[1]).slice(0, count).map(([name, count2]) => ({
276
+ name,
277
+ count: count2,
278
+ slug: name.toLowerCase().replace(/\s+/g, "-")
279
+ }));
280
+ }
281
+ function getArchives(posts, count = 6) {
282
+ const archiveMap = {};
283
+ posts.forEach((post) => {
284
+ if (post.data.pubDate) {
285
+ const date = new Date(post.data.pubDate);
286
+ const key = `${date.getFullYear()}-${date.getMonth() + 1}`;
287
+ archiveMap[key] = (archiveMap[key] || 0) + 1;
288
+ }
289
+ });
290
+ return Object.entries(archiveMap).sort((a, b) => b[0].localeCompare(a[0])).slice(0, count).map(([key, count2]) => {
291
+ const [year, month] = key.split("-").map(Number);
292
+ return { year, month, count: count2 };
293
+ });
294
+ }
295
+ export {
296
+ buildTreeFromPosts,
297
+ filterGroupsByPath,
298
+ getArchives,
299
+ getPopularTags,
300
+ getRecentPosts,
301
+ manualItemsToTree,
302
+ matchPathPattern,
303
+ processSidebarConfig,
304
+ shouldShowGroup
305
+ };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jet-w/astro-blog",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
4
4
  "description": "A modern Astro blog theme with Vue and Tailwind CSS support",
5
5
  "type": "module",
6
6
  "exports": {
@@ -20,7 +20,10 @@
20
20
  "./styles/*": "./src/styles/*",
21
21
  "./components/*": "./src/components/*",
22
22
  "./layouts/*": "./src/layouts/*",
23
- "./utils/*": "./src/utils/*"
23
+ "./utils/sidebar": {
24
+ "types": "./dist/utils/sidebar.d.ts",
25
+ "import": "./dist/utils/sidebar.js"
26
+ }
24
27
  },
25
28
  "files": [
26
29
  "dist",
@@ -28,7 +31,7 @@
28
31
  "src/styles",
29
32
  "src/components",
30
33
  "src/layouts",
31
- "src/utils",
34
+ "src/pages",
32
35
  "templates"
33
36
  ],
34
37
  "scripts": {
@@ -16,7 +16,7 @@ import {
16
16
  socialLinks as configSocialLinks,
17
17
  defaultIcons,
18
18
  type SocialLink
19
- } from '../../config';
19
+ } from '@jet-w/astro-blog/config';
20
20
 
21
21
  export interface Props {
22
22
  links?: SocialLink[];
@@ -1,5 +1,5 @@
1
1
  ---
2
- import { siteConfig } from '../../config/site';
2
+ import { siteConfig } from '@jet-w/astro-blog/config';
3
3
  ---
4
4
 
5
5
  <section class="py-16 mb-16">
@@ -1,6 +1,5 @@
1
1
  ---
2
- import { siteConfig } from '../../config/site';
3
- import { footerConfig, defaultIcons } from '../../config';
2
+ import { siteConfig, footerConfig, defaultIcons } from '@jet-w/astro-blog/config';
4
3
 
5
4
  const currentYear = new Date().getFullYear();
6
5
 
@@ -1,8 +1,8 @@
1
1
  ---
2
- import { siteConfig } from '../../config/site';
3
- import ThemeToggle from '../../components/ui/ThemeToggle.vue';
4
- import SearchBox from '../../components/ui/SearchBox.vue';
5
- import MobileMenu from '../../components/ui/MobileMenu.vue';
2
+ import { siteConfig } from '@jet-w/astro-blog/config';
3
+ import ThemeToggle from '../ui/ThemeToggle.vue';
4
+ import SearchBox from '../ui/SearchBox.vue';
5
+ import MobileMenu from '../ui/MobileMenu.vue';
6
6
 
7
7
  const currentPath = Astro.url.pathname;
8
8
  ---
@@ -1,14 +1,14 @@
1
1
  ---
2
2
  import { getCollection } from 'astro:content';
3
- import Icon from '../../components/ui/Icon.astro';
4
- import { sidebarConfig } from '../../config/sidebar';
3
+ import Icon from '../ui/Icon.astro';
4
+ import { sidebarConfig } from '@jet-w/astro-blog/config';
5
5
  import {
6
6
  processSidebarConfig,
7
7
  getRecentPosts,
8
8
  getPopularTags,
9
9
  getArchives,
10
10
  filterGroupsByPath,
11
- } from '../../utils/sidebar';
11
+ } from '@jet-w/astro-blog/utils/sidebar';
12
12
 
13
13
  interface Props {
14
14
  currentPath?: string;
@@ -99,7 +99,7 @@
99
99
 
100
100
  <script setup lang="ts">
101
101
  import { ref, onMounted, onUnmounted } from 'vue'
102
- import type { NavigationItem } from '../../types'
102
+ import type { NavigationItem } from '@jet-w/astro-blog/types'
103
103
  import SearchBox from './SearchBox.vue'
104
104
  import ThemeToggle from './ThemeToggle.vue'
105
105
 
@@ -196,7 +196,7 @@
196
196
 
197
197
  <script setup lang="ts">
198
198
  import { ref, computed, onMounted } from 'vue'
199
- import type { SearchResult } from '../../types'
199
+ import type { SearchResult } from '@jet-w/astro-blog/types'
200
200
 
201
201
  const searchQuery = ref('')
202
202
  const selectedTag = ref('')
@@ -1,7 +1,7 @@
1
1
  ---
2
- import type { SEOProps } from '../types';
3
- import { siteConfig, defaultSEO } from '../config/site';
4
- import '../styles/global.css';
2
+ import type { SEOProps } from '@jet-w/astro-blog/types';
3
+ import { siteConfig, defaultSEO } from '@jet-w/astro-blog/config';
4
+ import '@jet-w/astro-blog/styles/global.css';
5
5
  import fs from 'node:fs';
6
6
  import path from 'node:path';
7
7
 
@@ -1,6 +1,6 @@
1
1
  ---
2
- import { siteConfig } from '../config/site';
3
- import '../styles/slides.css';
2
+ import { siteConfig } from '@jet-w/astro-blog/config';
3
+ import '@jet-w/astro-blog/styles/slides.css';
4
4
 
5
5
  export interface Props {
6
6
  title: string;
@@ -1,6 +1,6 @@
1
1
  import rss from '@astrojs/rss';
2
2
  import { getCollection } from 'astro:content';
3
- import { siteConfig } from '@/config';
3
+ import { siteConfig } from '@jet-w/astro-blog/config';
4
4
 
5
5
  export async function GET(context: { site: URL }) {
6
6
  const posts = await getCollection('posts', ({ data }) => !data.draft);
@@ -7,7 +7,8 @@ import remarkMath from 'remark-math';
7
7
  import rehypeKatex from 'rehype-katex';
8
8
  import rehypeRaw from 'rehype-raw';
9
9
 
10
- // Import plugins from @jet-w/astro-blog
10
+ // Import plugins and integration from @jet-w/astro-blog
11
+ import { astroBlog } from '@jet-w/astro-blog';
11
12
  import { remarkContainers } from '@jet-w/astro-blog/plugins/remark-containers.mjs';
12
13
  import { remarkMermaid } from '@jet-w/astro-blog/plugins/remark-mermaid.mjs';
13
14
  import { rehypeCleanContainers } from '@jet-w/astro-blog/plugins/rehype-clean-containers.mjs';
@@ -17,6 +18,7 @@ import { rehypeRelativeLinks } from '@jet-w/astro-blog/plugins/rehype-relative-l
17
18
  // https://astro.build/config
18
19
  export default defineConfig({
19
20
  integrations: [
21
+ astroBlog(),
20
22
  vue(),
21
23
  mdx(),
22
24
  tailwind({
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Footer Configuration
3
+ *
4
+ * Configure footer links, copyright, and display options
5
+ */
6
+
7
+ import type { FooterConfig } from '@jet-w/astro-blog';
8
+ import { socialLinks } from './social';
9
+
10
+ /**
11
+ * Footer configuration
12
+ */
13
+ export const footerConfig: FooterConfig = {
14
+ quickLinksTitle: '快速链接',
15
+ quickLinks: [
16
+ { name: '首页', href: '/' },
17
+ { name: '文章', href: '/posts' },
18
+ { name: '标签', href: '/tags' },
19
+ { name: '归档', href: '/archives' },
20
+ { name: '关于', href: '/about' }
21
+ ],
22
+ contactTitle: '联系方式',
23
+ socialLinks: socialLinks,
24
+ showRss: true,
25
+ rssUrl: '/rss.xml',
26
+ copyright: '© {year} {author}. All rights reserved.',
27
+ poweredBy: {
28
+ text: 'Astro',
29
+ url: 'https://astro.build'
30
+ }
31
+ };
@@ -1,114 +1,17 @@
1
1
  /**
2
- * Blog configuration
2
+ * Blog Configuration
3
3
  *
4
- * Customize your blog settings here
5
- */
6
-
7
- import type { SiteConfig, NavigationItem } from '@jet-w/astro-blog';
8
- import type { SidebarConfig, FooterConfig, SocialLink } from '@jet-w/astro-blog';
9
-
10
- /**
11
- * Site configuration
12
- */
13
- export const siteConfig: SiteConfig = {
14
- title: 'My Astro Blog',
15
- description: '基于 Astro + Vue + Tailwind 构建的个人技术博客',
16
- author: 'Author',
17
- email: 'email@example.com',
18
- avatar: '/images/avatar.svg',
19
- social: {
20
- github: 'https://github.com/username',
21
- twitter: '',
22
- linkedin: '',
23
- email: 'mailto:email@example.com'
24
- },
25
- menu: [
26
- {
27
- name: '首页',
28
- href: '/',
29
- icon: 'home'
30
- },
31
- {
32
- name: '博客教学',
33
- href: '/posts/blog_docs',
34
- icon: 'posts'
35
- },
36
- {
37
- name: '演示',
38
- href: '/slides',
39
- icon: 'slides'
40
- },
41
- {
42
- name: '关于',
43
- href: '/about',
44
- icon: 'about'
45
- }
46
- ]
47
- };
48
-
49
- /**
50
- * Default SEO settings
51
- */
52
- export const defaultSEO = {
53
- title: siteConfig.title,
54
- description: siteConfig.description,
55
- image: '/images/og-image.jpg',
56
- type: 'website' as const
57
- };
58
-
59
- /**
60
- * Sidebar configuration
61
- */
62
- export const sidebarConfig: SidebarConfig = {
63
- enabled: true,
64
- showSearch: true,
65
- showRecentPosts: true,
66
- recentPostsCount: 5,
67
- showPopularTags: true,
68
- popularTagsCount: 8,
69
- showArchives: true,
70
- archivesCount: 6,
71
- showFriendLinks: false,
72
- friendLinks: [],
73
- groups: [
74
- {
75
- type: 'scan',
76
- title: '博客指南',
77
- icon: 'ri:book-open-line',
78
- scanPath: 'blog_docs',
79
- collapsed: true,
80
- showForPaths: ['/posts/blog_docs/**']
81
- }
82
- ]
83
- };
84
-
85
- /**
86
- * Social links
4
+ * This file re-exports all configuration modules for easy access.
5
+ * Each configuration is in its own file for better organization:
6
+ *
7
+ * - site.ts : Site title, description, author, menu
8
+ * - sidebar.ts : Sidebar display options and groups
9
+ * - social.ts : Social media links
10
+ * - footer.ts : Footer links and copyright
87
11
  */
88
- export const socialLinks: SocialLink[] = [
89
- { type: 'github', url: 'https://github.com/username', label: 'GitHub' },
90
- { type: 'email', url: 'mailto:email@example.com', label: 'Email' }
91
- ];
92
12
 
93
- /**
94
- * Footer configuration
95
- */
96
- export const footerConfig: FooterConfig = {
97
- quickLinksTitle: '快速链接',
98
- quickLinks: [
99
- { name: '首页', href: '/' },
100
- { name: '文章', href: '/posts' },
101
- { name: '标签', href: '/tags' },
102
- { name: '归档', href: '/archives' },
103
- { name: '关于', href: '/about' }
104
- ],
105
- contactTitle: '联系方式',
106
- socialLinks: socialLinks,
107
- showRss: true,
108
- rssUrl: '/rss.xml',
109
- copyright: '© {year} {author}. All rights reserved.',
110
- poweredBy: {
111
- text: 'Astro',
112
- url: 'https://astro.build'
113
- }
114
- };
13
+ // Re-export all configurations
14
+ export { siteConfig, defaultSEO } from './site';
15
+ export { sidebarConfig } from './sidebar';
16
+ export { socialLinks } from './social';
17
+ export { footerConfig } from './footer';
@@ -0,0 +1,33 @@
1
+ /**
2
+ * Sidebar Configuration
3
+ *
4
+ * Configure sidebar display options, groups, and widgets
5
+ */
6
+
7
+ import type { SidebarConfig } from '@jet-w/astro-blog';
8
+
9
+ /**
10
+ * Sidebar configuration
11
+ */
12
+ export const sidebarConfig: SidebarConfig = {
13
+ enabled: true,
14
+ showSearch: true,
15
+ showRecentPosts: true,
16
+ recentPostsCount: 5,
17
+ showPopularTags: true,
18
+ popularTagsCount: 8,
19
+ showArchives: true,
20
+ archivesCount: 6,
21
+ showFriendLinks: false,
22
+ friendLinks: [],
23
+ groups: [
24
+ {
25
+ type: 'scan',
26
+ title: '博客指南',
27
+ icon: 'ri:book-open-line',
28
+ scanPath: 'blog_docs',
29
+ collapsed: true,
30
+ showForPaths: ['/posts/blog_docs/**']
31
+ }
32
+ ]
33
+ };