@jet-w/astro-blog 0.2.0 → 0.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-HVQKQN6B.js → chunk-6D3XRDNY.js} +1 -1
- package/dist/{chunk-ATRISB7B.js → chunk-A2E2VSAQ.js} +43 -3
- package/dist/chunk-DAH2XP4W.js +154 -0
- package/dist/{chunk-AZHCNNAC.js → chunk-PG43JO4O.js} +1 -153
- package/dist/chunk-PZICDGJG.js +69 -0
- package/dist/chunk-Z3O3JK56.js +186 -0
- package/dist/config/index.d.ts +2 -2
- package/dist/config/index.js +9 -7
- package/dist/{i18n-5H4W145i.d.ts → i18n-DYYPTq4o.d.ts} +21 -1
- package/dist/index.d.ts +10 -184
- package/dist/index.js +37 -210
- package/dist/integration.d.ts +2 -2
- package/dist/integration.js +2 -2
- package/dist/{sidebar-Da-W_4Lr.d.ts → sidebar-DNdiCKBw.d.ts} +1 -1
- package/dist/utils/i18n.d.ts +133 -0
- package/dist/utils/i18n.js +49 -0
- package/dist/utils/sidebar.d.ts +1 -1
- package/dist/utils/useI18n.d.ts +74 -0
- package/dist/utils/useI18n.js +15 -0
- package/package.json +9 -1
- package/src/components/blog/FloatingToc.vue +11 -3
- package/src/components/blog/Hero.astro +17 -2
- package/src/components/blog/NavigationTabs.vue +46 -15
- package/src/components/blog/PostCard.astro +28 -10
- package/src/components/blog/RelatedPosts.astro +23 -7
- package/src/components/blog/TableOfContents.astro +10 -4
- package/src/components/blog/TagCloud.astro +4 -3
- package/src/components/home/FeaturedPostsSection.astro +22 -6
- package/src/components/home/QuickNavSection.astro +33 -4
- package/src/components/home/RecentPostsSection.astro +22 -6
- package/src/components/home/StatsSection.astro +24 -6
- package/src/components/layout/Header.astro +9 -5
- package/src/components/layout/Sidebar.astro +14 -11
- package/src/components/ui/SearchBox.vue +13 -5
- package/src/components/ui/SearchInterface.vue +49 -25
- package/src/pages/archives/[year]/[month].astro +36 -17
- package/src/pages/archives/index.astro +36 -20
- package/src/pages/categories/[category].astro +33 -16
- package/src/pages/categories/index.astro +37 -14
- package/src/pages/posts/[...slug].astro +125 -18
- package/src/pages/posts/index.astro +59 -37
- package/src/pages/posts/page/[page].astro +65 -27
- package/src/pages/search.astro +50 -14
- package/src/pages/slides/index.astro +25 -6
- package/src/pages/tags/[tag].astro +32 -15
- package/src/pages/tags/index.astro +39 -16
- package/src/plugins/remark-containers.mjs +351 -322
- package/src/plugins/remark-protect-code.mjs +69 -0
- package/src/styles/global.css +35 -1
- package/templates/default/.claude/ralph-loop.local.md +48 -0
- package/templates/default/astro.config.mjs +13 -4
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/01-intro.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/02-install.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/03-create-post.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/04-structure.md +1 -1
- package/templates/default/content/posts/blog_docs_en/01.get-started/05-deploy.md +208 -0
- package/templates/default/content/posts/blog_docs_en/{get-started → 01.get-started}/README.md +1 -1
- package/templates/default/content/posts/blog_docs_en/02.guide/02-containers.md +245 -0
- package/templates/default/content/posts/blog_docs_en/{guide/markdown → 02.guide}/03-code-blocks.md +2 -1
- package/templates/default/content/posts/blog_docs_en/{guide/features/01-mermaid.md → 02.guide/03-mermaid.md} +1 -1
- package/templates/default/content/posts/blog_docs_en/{guide/features → 02.guide}/04-icons.md +4 -2
- package/templates/default/content/posts/blog_docs_en/{guide/features/02-latex.md → 02.guide/06-latex.md} +1 -1
- package/templates/default/content/posts/blog_docs_en/{guide/features/03-video.md → 02.guide/07-video.md} +1 -1
- package/templates/default/content/posts/blog_docs_en/02.guide/08-slides.md +359 -0
- package/templates/default/content/posts/blog_docs_en/{guide/markdown → 02.guide}/README.md +22 -3
- package/templates/default/content/posts/blog_docs_en/{config → 03.config}/01-site.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{config → 03.config}/02-sidebar.md +1 -1
- package/templates/default/content/posts/blog_docs_en/{config → 03.config}/03-i18n.md +88 -24
- package/templates/default/content/posts/blog_docs_en/{config → 03.config}/README.md +1 -1
- package/templates/default/content/posts/blog_docs_en/README.md +2 -1
- package/templates/default/content/posts/blog_docs_zh/01.get-started/01-intro.md +81 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/02-install.md +137 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/03-create-post.md +176 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/04-structure.md +173 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/05-deploy.md +208 -0
- package/templates/default/content/posts/blog_docs_zh/01.get-started/README.md +52 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/02-containers.md +245 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/03-code-blocks.md +206 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/03-mermaid.md +194 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/04-icons.md +229 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/06-latex.md +233 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/07-video.md +184 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/08-slides.md +359 -0
- package/templates/default/content/posts/blog_docs_zh/02.guide/README.md +213 -0
- package/templates/default/content/posts/blog_docs_zh/03.config/01-site.md +208 -0
- package/templates/default/content/posts/blog_docs_zh/03.config/02-sidebar.md +240 -0
- package/templates/default/content/posts/blog_docs_zh/03.config/03-i18n.md +348 -0
- package/templates/default/content/posts/blog_docs_zh/03.config/README.md +85 -0
- package/templates/default/content/posts/blog_docs_zh/README.md +78 -0
- package/templates/default/package.dev.json +31 -0
- package/templates/default/package.json +1 -1
- package/templates/default/src/config/locales/en/index.ts +5 -1
- package/templates/default/src/config/locales/en/menu.ts +3 -1
- package/templates/default/src/config/locales/en/sidebar.ts +18 -2
- package/templates/default/src/config/locales/en/site.ts +1 -1
- package/templates/default/src/config/locales/en/ui.ts +29 -0
- package/templates/default/src/config/locales/zh-CN/index.ts +5 -1
- package/templates/default/src/config/locales/zh-CN/menu.ts +7 -5
- package/templates/default/src/config/locales/zh-CN/sidebar.ts +22 -6
- package/templates/default/src/config/locales/zh-CN/site.ts +2 -2
- package/templates/default/src/config/locales/zh-CN/ui.ts +29 -0
- package/templates/default/src/config/site.ts +2 -2
- package/templates/default/src/content.config.ts +15 -3
- package/templates/default/content/posts/blog_docs/01-quick-start.md +0 -162
- package/templates/default/content/posts/blog_docs/02-frontmatter.md +0 -277
- package/templates/default/content/posts/blog_docs/03-markdown-basic.md +0 -350
- package/templates/default/content/posts/blog_docs/04-containers.md +0 -331
- package/templates/default/content/posts/blog_docs/05-code-blocks.md +0 -388
- package/templates/default/content/posts/blog_docs/06-mermaid.md +0 -431
- package/templates/default/content/posts/blog_docs/07-video.md +0 -243
- package/templates/default/content/posts/blog_docs/08-latex.md +0 -382
- package/templates/default/content/posts/blog_docs/09-icons.md +0 -326
- package/templates/default/content/posts/blog_docs/10-sidebar.md +0 -445
- package/templates/default/content/posts/blog_docs/11-config.md +0 -334
- package/templates/default/content/posts/blog_docs/12-i18n.md +0 -355
- package/templates/default/content/posts/blog_docs/12-slides.mdx +0 -552
- package/templates/default/content/posts/blog_docs/README.md +0 -152
- package/templates/default/content/posts/blog_docs_en/get-started/05-deploy.md +0 -197
- package/templates/default/content/posts/blog_docs_en/guide/README.md +0 -59
- package/templates/default/content/posts/blog_docs_en/guide/features/README.md +0 -51
- package/templates/default/content/posts/blog_docs_en/guide/markdown/02-containers.md +0 -226
|
@@ -1,9 +1,22 @@
|
|
|
1
1
|
---
|
|
2
2
|
import { getCollection } from 'astro:content';
|
|
3
3
|
import PageLayout from '@jet-w/astro-blog/layouts/PageLayout.astro';
|
|
4
|
+
import { i18nConfig as virtualI18nConfig } from 'virtual:astro-blog-i18n';
|
|
5
|
+
import { defaultI18nConfig } from '../../config/i18n';
|
|
6
|
+
import { getLocaleFromPath, getLocaleConfig, getLocalePrefix, filterPostsByLocale } from '../../utils/i18n';
|
|
7
|
+
|
|
8
|
+
// Get i18n config
|
|
9
|
+
const i18nConfig = virtualI18nConfig || defaultI18nConfig;
|
|
10
|
+
const currentLocale = getLocaleFromPath(Astro.url.pathname, i18nConfig);
|
|
11
|
+
const localeConfig = getLocaleConfig(currentLocale, i18nConfig);
|
|
12
|
+
const ui = localeConfig.ui;
|
|
13
|
+
const localePrefix = getLocalePrefix(currentLocale, i18nConfig);
|
|
4
14
|
|
|
5
15
|
// 从文章集合动态获取所有分类
|
|
6
|
-
const
|
|
16
|
+
const allPostsCollection = await getCollection('posts', ({ data }) => !data.draft);
|
|
17
|
+
|
|
18
|
+
// Filter posts by current locale
|
|
19
|
+
const allPosts = filterPostsByLocale(allPostsCollection, currentLocale, i18nConfig);
|
|
7
20
|
|
|
8
21
|
// 统计分类
|
|
9
22
|
const categoryMap = new Map<string, { name: string; count: number }>();
|
|
@@ -55,24 +68,34 @@ const getCategoryIcon = (slug: string) => {
|
|
|
55
68
|
---
|
|
56
69
|
|
|
57
70
|
<PageLayout
|
|
58
|
-
title=
|
|
59
|
-
description=
|
|
71
|
+
title={ui.allCategories}
|
|
72
|
+
description={ui.filterByCategory}
|
|
60
73
|
showSidebar={true}
|
|
74
|
+
i18nConfig={i18nConfig}
|
|
61
75
|
>
|
|
76
|
+
<!-- 面包屑导航 -->
|
|
77
|
+
<nav class="flex items-center space-x-2 text-sm text-slate-600 dark:text-slate-400 mb-8">
|
|
78
|
+
<a href={`${localePrefix}/`} class="hover:text-primary-500 transition-colors">{ui.home}</a>
|
|
79
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
80
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
81
|
+
</svg>
|
|
82
|
+
<span class="text-slate-900 dark:text-slate-100">{ui.allCategories}</span>
|
|
83
|
+
</nav>
|
|
84
|
+
|
|
62
85
|
<!-- 页面头部 -->
|
|
63
86
|
<div class="text-center mb-12">
|
|
64
87
|
<h1 class="text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4">
|
|
65
|
-
|
|
88
|
+
{ui.allCategories}
|
|
66
89
|
</h1>
|
|
67
90
|
<p class="text-xl text-slate-600 dark:text-slate-400 mb-8">
|
|
68
|
-
|
|
91
|
+
{ui.filterByCategory}
|
|
69
92
|
</p>
|
|
70
93
|
|
|
71
94
|
<!-- 统计信息 -->
|
|
72
95
|
<div class="inline-flex items-center space-x-6 text-sm text-slate-500 dark:text-slate-400 bg-slate-50 dark:bg-slate-800 px-6 py-3 rounded-lg">
|
|
73
|
-
<span
|
|
96
|
+
<span>{allCategories.length} {ui.categories}</span>
|
|
74
97
|
<span>•</span>
|
|
75
|
-
<span>{totalPosts}
|
|
98
|
+
<span>{totalPosts} {ui.posts}</span>
|
|
76
99
|
</div>
|
|
77
100
|
</div>
|
|
78
101
|
|
|
@@ -80,7 +103,7 @@ const getCategoryIcon = (slug: string) => {
|
|
|
80
103
|
<div class="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6 mb-16">
|
|
81
104
|
{sortedCategories.map((category) => (
|
|
82
105
|
<a
|
|
83
|
-
href={
|
|
106
|
+
href={`${localePrefix}/categories/${category.slug}`}
|
|
84
107
|
class="group card hover:shadow-lg transform hover:-translate-y-1 transition-all duration-300 h-full"
|
|
85
108
|
>
|
|
86
109
|
<div class="flex flex-col h-full">
|
|
@@ -99,7 +122,7 @@ const getCategoryIcon = (slug: string) => {
|
|
|
99
122
|
<svg class="w-4 h-4 mr-1" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
100
123
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M7 7h.01M7 3h5c.512 0 1.024.195 1.414.586l7 7a2 2 0 010 2.828l-7 7a2 2 0 01-2.828 0l-7-7A1.994 1.994 0 013 12V7a4 4 0 014-4z" />
|
|
101
124
|
</svg>
|
|
102
|
-
<span>{category.count}
|
|
125
|
+
<span>{category.count} {ui.posts}</span>
|
|
103
126
|
</div>
|
|
104
127
|
</div>
|
|
105
128
|
</div>
|
|
@@ -127,12 +150,12 @@ const getCategoryIcon = (slug: string) => {
|
|
|
127
150
|
{sortedCategories.length > 4 && (
|
|
128
151
|
<section class="mb-16">
|
|
129
152
|
<h2 class="text-2xl font-bold text-slate-900 dark:text-slate-100 mb-8">
|
|
130
|
-
|
|
153
|
+
{ui.categories}
|
|
131
154
|
</h2>
|
|
132
155
|
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
|
133
156
|
{sortedCategories.slice(0, 4).map((category) => (
|
|
134
157
|
<a
|
|
135
|
-
href={
|
|
158
|
+
href={`${localePrefix}/categories/${category.slug}`}
|
|
136
159
|
class="group p-6 bg-gradient-to-br from-primary-50 to-secondary-50 dark:from-primary-900/20 dark:to-secondary-900/20 rounded-xl border border-primary-200 dark:border-primary-800 hover:shadow-lg transition-all duration-300"
|
|
137
160
|
>
|
|
138
161
|
<div class="text-center">
|
|
@@ -152,12 +175,12 @@ const getCategoryIcon = (slug: string) => {
|
|
|
152
175
|
<!-- 分类列表 -->
|
|
153
176
|
<section>
|
|
154
177
|
<h2 class="text-2xl font-bold text-slate-900 dark:text-slate-100 mb-8">
|
|
155
|
-
|
|
178
|
+
{ui.allCategories}
|
|
156
179
|
</h2>
|
|
157
180
|
<div class="space-y-3">
|
|
158
181
|
{sortedCategories.map((category) => (
|
|
159
182
|
<a
|
|
160
|
-
href={
|
|
183
|
+
href={`${localePrefix}/categories/${category.slug}`}
|
|
161
184
|
class="flex items-center justify-between p-4 bg-white dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg hover:shadow-md hover:border-primary-300 dark:hover:border-primary-600 transition-all duration-200 group"
|
|
162
185
|
>
|
|
163
186
|
<div class="flex items-center space-x-4">
|
|
@@ -177,7 +200,7 @@ const getCategoryIcon = (slug: string) => {
|
|
|
177
200
|
</div>
|
|
178
201
|
<div class="flex items-center space-x-3">
|
|
179
202
|
<span class="text-sm px-3 py-1 bg-slate-100 dark:bg-slate-700 text-slate-600 dark:text-slate-400 rounded-full">
|
|
180
|
-
{category.count}
|
|
203
|
+
{category.count}
|
|
181
204
|
</span>
|
|
182
205
|
<svg class="w-5 h-5 text-slate-400 group-hover:text-primary-500 transition-colors" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
183
206
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
@@ -3,10 +3,26 @@ import { getCollection, type CollectionEntry, render } from 'astro:content';
|
|
|
3
3
|
import PageLayout from '@jet-w/astro-blog/layouts/PageLayout.astro';
|
|
4
4
|
import SlidesLayout from '@jet-w/astro-blog/layouts/SlidesLayout.astro';
|
|
5
5
|
import FloatingToc from '@jet-w/astro-blog/components/blog/FloatingToc.vue';
|
|
6
|
+
import { i18nConfig as virtualI18nConfig } from 'virtual:astro-blog-i18n';
|
|
7
|
+
import { defaultI18nConfig } from '../../config/i18n';
|
|
8
|
+
import { getLocaleFromPath, getLocaleConfig, getLocalePrefix } from '../../utils/i18n';
|
|
6
9
|
|
|
7
10
|
export async function getStaticPaths() {
|
|
8
11
|
const posts = await getCollection('posts');
|
|
9
12
|
|
|
13
|
+
// Build folder title map from README files (inline function)
|
|
14
|
+
const folderTitles: Record<string, string> = {};
|
|
15
|
+
posts.forEach(post => {
|
|
16
|
+
const pathParts = post.id.split('/');
|
|
17
|
+
const fileName = pathParts[pathParts.length - 1].toLowerCase();
|
|
18
|
+
if (fileName === 'readme' || fileName === 'readme.md' || fileName === 'readme.mdx') {
|
|
19
|
+
const folderPath = pathParts.slice(0, -1).join('/').toLowerCase();
|
|
20
|
+
if (folderPath && post.data.title) {
|
|
21
|
+
folderTitles[folderPath] = post.data.title;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
});
|
|
25
|
+
|
|
10
26
|
// 按文件名称排序,readme.md 排在每个文件夹的最前面
|
|
11
27
|
const sortedPosts = posts.sort((a, b) => {
|
|
12
28
|
// 获取文件夹路径和文件名
|
|
@@ -50,6 +66,7 @@ export async function getStaticPaths() {
|
|
|
50
66
|
prevPost: CollectionEntry<'posts'> | null;
|
|
51
67
|
nextPost: CollectionEntry<'posts'> | null;
|
|
52
68
|
isDirectory: boolean;
|
|
69
|
+
folderTitles: Record<string, string>;
|
|
53
70
|
};
|
|
54
71
|
};
|
|
55
72
|
|
|
@@ -61,6 +78,7 @@ export async function getStaticPaths() {
|
|
|
61
78
|
prevPost: index > 0 ? sortedPosts[index - 1] : null,
|
|
62
79
|
nextPost: index < sortedPosts.length - 1 ? sortedPosts[index + 1] : null,
|
|
63
80
|
isDirectory: false,
|
|
81
|
+
folderTitles,
|
|
64
82
|
},
|
|
65
83
|
}));
|
|
66
84
|
|
|
@@ -83,6 +101,7 @@ export async function getStaticPaths() {
|
|
|
83
101
|
prevPost: null,
|
|
84
102
|
nextPost: null,
|
|
85
103
|
isDirectory: true,
|
|
104
|
+
folderTitles,
|
|
86
105
|
},
|
|
87
106
|
});
|
|
88
107
|
}
|
|
@@ -96,11 +115,59 @@ type Props = {
|
|
|
96
115
|
prevPost: CollectionEntry<'posts'> | null;
|
|
97
116
|
nextPost: CollectionEntry<'posts'> | null;
|
|
98
117
|
isDirectory?: boolean;
|
|
118
|
+
folderTitles: Record<string, string>;
|
|
99
119
|
};
|
|
100
120
|
|
|
101
|
-
|
|
121
|
+
// Build breadcrumb items for a post
|
|
122
|
+
function buildBreadcrumbItems(
|
|
123
|
+
postId: string,
|
|
124
|
+
postTitle: string,
|
|
125
|
+
folderTitles: Record<string, string>
|
|
126
|
+
): Array<{ title: string; path: string; isLast: boolean }> {
|
|
127
|
+
const parts = postId.toLowerCase().split('/');
|
|
128
|
+
const items: Array<{ title: string; path: string; isLast: boolean }> = [];
|
|
129
|
+
let currentPath = '';
|
|
130
|
+
|
|
131
|
+
// Build breadcrumb for each folder level
|
|
132
|
+
for (let i = 0; i < parts.length - 1; i++) {
|
|
133
|
+
currentPath = currentPath ? `${currentPath}/${parts[i]}` : parts[i];
|
|
134
|
+
const title = folderTitles[currentPath] || parts[i];
|
|
135
|
+
items.push({ title, path: currentPath, isLast: false });
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Add the current post/file
|
|
139
|
+
const fileName = parts[parts.length - 1];
|
|
140
|
+
const isReadme = fileName === 'readme' || fileName === 'readme.md' || fileName === 'readme.mdx';
|
|
141
|
+
|
|
142
|
+
if (!isReadme) {
|
|
143
|
+
items.push({ title: postTitle, path: postId.toLowerCase(), isLast: true });
|
|
144
|
+
} else if (items.length > 0) {
|
|
145
|
+
items[items.length - 1].isLast = true;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return items;
|
|
149
|
+
}
|
|
150
|
+
|
|
151
|
+
const { post, prevPost, nextPost, isDirectory, folderTitles } = Astro.props;
|
|
102
152
|
const Content = post ? (await render(post)).Content : null;
|
|
103
153
|
|
|
154
|
+
// Get i18n config
|
|
155
|
+
const i18nConfig = virtualI18nConfig || defaultI18nConfig;
|
|
156
|
+
const currentLocale = getLocaleFromPath(Astro.url.pathname, i18nConfig);
|
|
157
|
+
const localeConfig = getLocaleConfig(currentLocale, i18nConfig);
|
|
158
|
+
const ui = localeConfig.ui;
|
|
159
|
+
const localePrefix = getLocalePrefix(currentLocale, i18nConfig);
|
|
160
|
+
|
|
161
|
+
// Get the current slug from URL
|
|
162
|
+
const urlPath = Astro.url.pathname;
|
|
163
|
+
const postsMatch = urlPath.match(/\/posts\/(.+?)\/?$/);
|
|
164
|
+
const currentSlug = postsMatch ? postsMatch[1] : '';
|
|
165
|
+
|
|
166
|
+
// Build breadcrumb items
|
|
167
|
+
const breadcrumbItems = post
|
|
168
|
+
? buildBreadcrumbItems(post.id, post.data.title, folderTitles)
|
|
169
|
+
: buildBreadcrumbItems(currentSlug, ui.documentTree, folderTitles);
|
|
170
|
+
|
|
104
171
|
// 判断是否使用 slides 布局
|
|
105
172
|
const isSlides = post?.data.layout === 'slides';
|
|
106
173
|
|
|
@@ -157,9 +224,31 @@ const formatDate = (date: Date) => {
|
|
|
157
224
|
title={post.data.title}
|
|
158
225
|
description={post.data.description}
|
|
159
226
|
showSidebar={true}
|
|
227
|
+
i18nConfig={i18nConfig}
|
|
160
228
|
>
|
|
229
|
+
<!-- 面包屑导航 -->
|
|
230
|
+
<nav class="flex items-center flex-wrap gap-y-1 text-sm text-slate-600 dark:text-slate-400 mb-8">
|
|
231
|
+
<a href={`${localePrefix}/`} class="hover:text-primary-500 transition-colors">{ui.home}</a>
|
|
232
|
+
{breadcrumbItems.map((item) => (
|
|
233
|
+
<>
|
|
234
|
+
<svg class="w-4 h-4 mx-2 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
235
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
236
|
+
</svg>
|
|
237
|
+
{item.isLast ? (
|
|
238
|
+
<span class="text-slate-900 dark:text-slate-100 truncate max-w-xs">{item.title}</span>
|
|
239
|
+
) : (
|
|
240
|
+
<a href={`${localePrefix}/posts/${item.path}`} class="hover:text-primary-500 transition-colors">{item.title}</a>
|
|
241
|
+
)}
|
|
242
|
+
</>
|
|
243
|
+
))}
|
|
244
|
+
</nav>
|
|
245
|
+
|
|
161
246
|
<!-- 浮动目录 -->
|
|
162
|
-
<FloatingToc
|
|
247
|
+
<FloatingToc
|
|
248
|
+
client:load
|
|
249
|
+
tocTitle={ui.tableOfContents}
|
|
250
|
+
progressTitle={ui.readingProgress}
|
|
251
|
+
/>
|
|
163
252
|
|
|
164
253
|
<!-- 文章头部 -->
|
|
165
254
|
<article class="prose prose-slate dark:prose-invert max-w-none">
|
|
@@ -198,7 +287,7 @@ const formatDate = (date: Date) => {
|
|
|
198
287
|
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
199
288
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 8v4l3 3m6-3a9 9 0 11-18 0 9 9 0 0118 0z" />
|
|
200
289
|
</svg>
|
|
201
|
-
<span
|
|
290
|
+
<span>{readingTime} {ui.minuteRead}</span>
|
|
202
291
|
</div>
|
|
203
292
|
</div>
|
|
204
293
|
|
|
@@ -207,7 +296,7 @@ const formatDate = (date: Date) => {
|
|
|
207
296
|
<div class="flex flex-wrap justify-center gap-2 mt-6">
|
|
208
297
|
{post.data.tags.map((tag) => (
|
|
209
298
|
<a
|
|
210
|
-
href={
|
|
299
|
+
href={`${localePrefix}/tags/${tag.toLowerCase().replace(/\s+/g, '-')}`}
|
|
211
300
|
class="px-3 py-1 text-xs font-medium bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 rounded-full hover:bg-primary-200 dark:hover:bg-primary-900/50 transition-colors"
|
|
212
301
|
>
|
|
213
302
|
#{tag}
|
|
@@ -241,12 +330,12 @@ const formatDate = (date: Date) => {
|
|
|
241
330
|
{post.data.categories && post.data.categories.length > 0 && (
|
|
242
331
|
<div class="mb-8">
|
|
243
332
|
<h3 class="text-lg font-semibold text-slate-900 dark:text-slate-100 mb-4">
|
|
244
|
-
|
|
333
|
+
{ui.categories}
|
|
245
334
|
</h3>
|
|
246
335
|
<div class="flex flex-wrap gap-2">
|
|
247
336
|
{post.data.categories.map((category) => (
|
|
248
337
|
<a
|
|
249
|
-
href={
|
|
338
|
+
href={`${localePrefix}/categories/${category.toLowerCase().replace(/\s+/g, '-')}`}
|
|
250
339
|
class="px-4 py-2 text-sm font-medium bg-slate-100 dark:bg-slate-800 text-slate-700 dark:text-slate-300 rounded-lg hover:bg-slate-200 dark:hover:bg-slate-700 transition-colors"
|
|
251
340
|
>
|
|
252
341
|
{category}
|
|
@@ -270,10 +359,10 @@ const formatDate = (date: Date) => {
|
|
|
270
359
|
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
|
271
360
|
<!-- 上一篇 -->
|
|
272
361
|
<div class="text-center md:text-left">
|
|
273
|
-
<div class="text-sm text-slate-500 dark:text-slate-400 mb-2"
|
|
362
|
+
<div class="text-sm text-slate-500 dark:text-slate-400 mb-2">{ui.previousPost}</div>
|
|
274
363
|
{prevPost ? (
|
|
275
364
|
<a
|
|
276
|
-
href={
|
|
365
|
+
href={`${localePrefix}/posts/${prevPost.id.toLowerCase()}`}
|
|
277
366
|
class="group inline-flex items-center text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 font-medium transition-colors"
|
|
278
367
|
>
|
|
279
368
|
<svg class="w-4 h-4 mr-2 group-hover:-translate-x-1 transition-transform" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -282,16 +371,16 @@ const formatDate = (date: Date) => {
|
|
|
282
371
|
<span class="line-clamp-1">{prevPost.data.title}</span>
|
|
283
372
|
</a>
|
|
284
373
|
) : (
|
|
285
|
-
<span class="text-slate-400 dark:text-slate-600"
|
|
374
|
+
<span class="text-slate-400 dark:text-slate-600">-</span>
|
|
286
375
|
)}
|
|
287
376
|
</div>
|
|
288
377
|
|
|
289
378
|
<!-- 下一篇 -->
|
|
290
379
|
<div class="text-center md:text-right">
|
|
291
|
-
<div class="text-sm text-slate-500 dark:text-slate-400 mb-2"
|
|
380
|
+
<div class="text-sm text-slate-500 dark:text-slate-400 mb-2">{ui.nextPost}</div>
|
|
292
381
|
{nextPost ? (
|
|
293
382
|
<a
|
|
294
|
-
href={
|
|
383
|
+
href={`${localePrefix}/posts/${nextPost.id.toLowerCase()}`}
|
|
295
384
|
class="group inline-flex items-center justify-end text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 font-medium transition-colors"
|
|
296
385
|
>
|
|
297
386
|
<span class="line-clamp-1">{nextPost.data.title}</span>
|
|
@@ -300,7 +389,7 @@ const formatDate = (date: Date) => {
|
|
|
300
389
|
</svg>
|
|
301
390
|
</a>
|
|
302
391
|
) : (
|
|
303
|
-
<span class="text-slate-400 dark:text-slate-600"
|
|
392
|
+
<span class="text-slate-400 dark:text-slate-600">-</span>
|
|
304
393
|
)}
|
|
305
394
|
</div>
|
|
306
395
|
</div>
|
|
@@ -308,10 +397,28 @@ const formatDate = (date: Date) => {
|
|
|
308
397
|
</PageLayout>
|
|
309
398
|
) : (
|
|
310
399
|
<PageLayout
|
|
311
|
-
title=
|
|
312
|
-
description=
|
|
400
|
+
title={ui.documentTree}
|
|
401
|
+
description={ui.noPostsFound}
|
|
313
402
|
showSidebar={true}
|
|
403
|
+
i18nConfig={i18nConfig}
|
|
314
404
|
>
|
|
405
|
+
<!-- 面包屑导航 -->
|
|
406
|
+
<nav class="flex items-center flex-wrap gap-y-1 text-sm text-slate-600 dark:text-slate-400 mb-8">
|
|
407
|
+
<a href={`${localePrefix}/`} class="hover:text-primary-500 transition-colors">{ui.home}</a>
|
|
408
|
+
{breadcrumbItems.map((item) => (
|
|
409
|
+
<>
|
|
410
|
+
<svg class="w-4 h-4 mx-2 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
411
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
412
|
+
</svg>
|
|
413
|
+
{item.isLast ? (
|
|
414
|
+
<span class="text-slate-900 dark:text-slate-100 truncate max-w-xs">{item.title}</span>
|
|
415
|
+
) : (
|
|
416
|
+
<a href={`${localePrefix}/posts/${item.path}`} class="hover:text-primary-500 transition-colors">{item.title}</a>
|
|
417
|
+
)}
|
|
418
|
+
</>
|
|
419
|
+
))}
|
|
420
|
+
</nav>
|
|
421
|
+
|
|
315
422
|
<div class="text-center py-16">
|
|
316
423
|
<div class="inline-flex items-center justify-center w-20 h-20 bg-slate-100 dark:bg-slate-800 rounded-full mb-6">
|
|
317
424
|
<svg class="w-10 h-10 text-slate-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -319,16 +426,16 @@ const formatDate = (date: Date) => {
|
|
|
319
426
|
</svg>
|
|
320
427
|
</div>
|
|
321
428
|
<h1 class="text-2xl font-bold text-slate-900 dark:text-slate-100 mb-4">
|
|
322
|
-
|
|
429
|
+
{ui.noPostsFound}
|
|
323
430
|
</h1>
|
|
324
431
|
<p class="text-slate-600 dark:text-slate-400 mb-8">
|
|
325
|
-
|
|
432
|
+
{ui.noPostsFound}
|
|
326
433
|
</p>
|
|
327
|
-
<a href=
|
|
434
|
+
<a href={`${localePrefix}/posts`} class="inline-flex items-center px-4 py-2 bg-primary-500 text-white rounded-lg hover:bg-primary-600 transition-colors">
|
|
328
435
|
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
329
436
|
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m-7 7h18" />
|
|
330
437
|
</svg>
|
|
331
|
-
|
|
438
|
+
{ui.postList}
|
|
332
439
|
</a>
|
|
333
440
|
</div>
|
|
334
441
|
</PageLayout>
|
|
@@ -4,10 +4,24 @@ import PostCard from '@jet-w/astro-blog/components/blog/PostCard.astro';
|
|
|
4
4
|
import Pagination from '@jet-w/astro-blog/components/ui/Pagination.astro';
|
|
5
5
|
import NavigationTabs from '@jet-w/astro-blog/components/blog/NavigationTabs.vue';
|
|
6
6
|
import { getCollection } from 'astro:content';
|
|
7
|
+
import { i18nConfig as virtualI18nConfig } from 'virtual:astro-blog-i18n';
|
|
8
|
+
import { defaultI18nConfig } from '../../config/i18n';
|
|
9
|
+
import { getLocaleFromPath, getLocaleConfig, getLocalePrefix, filterPostsByLocale } from '../../utils/i18n';
|
|
10
|
+
|
|
11
|
+
// Get i18n config
|
|
12
|
+
const i18nConfig = virtualI18nConfig || defaultI18nConfig;
|
|
13
|
+
const currentLocale = getLocaleFromPath(Astro.url.pathname, i18nConfig);
|
|
14
|
+
const localeConfig = getLocaleConfig(currentLocale, i18nConfig);
|
|
15
|
+
const ui = localeConfig.ui;
|
|
16
|
+
const localePrefix = getLocalePrefix(currentLocale, i18nConfig);
|
|
7
17
|
|
|
8
18
|
// 从新的内容目录获取文章数据
|
|
9
19
|
const allPostsCollection = await getCollection('posts');
|
|
10
|
-
|
|
20
|
+
|
|
21
|
+
// Filter posts by current locale
|
|
22
|
+
const localeFilteredPosts = filterPostsByLocale(allPostsCollection, currentLocale, i18nConfig);
|
|
23
|
+
|
|
24
|
+
const publishedPosts = localeFilteredPosts
|
|
11
25
|
.filter(post => !post.data.draft)
|
|
12
26
|
.sort((a, b) => (b.data.pubDate?.getTime() ?? 0) - (a.data.pubDate?.getTime() ?? 0));
|
|
13
27
|
|
|
@@ -170,9 +184,9 @@ const allTags = [...new Set(allPosts.flatMap(post => post.tags || []))];
|
|
|
170
184
|
const allCategories = [...new Set(allPosts.flatMap(post => post.categories || []))];
|
|
171
185
|
|
|
172
186
|
// 格式化日期
|
|
173
|
-
const
|
|
187
|
+
const formatDateLocal = (date?: Date) => {
|
|
174
188
|
if (!date) return '';
|
|
175
|
-
return new Intl.DateTimeFormat(
|
|
189
|
+
return new Intl.DateTimeFormat(localeConfig.locale.dateLocale, {
|
|
176
190
|
year: 'numeric',
|
|
177
191
|
month: '2-digit',
|
|
178
192
|
day: '2-digit'
|
|
@@ -181,27 +195,37 @@ const formatDate = (date?: Date) => {
|
|
|
181
195
|
---
|
|
182
196
|
|
|
183
197
|
<PageLayout
|
|
184
|
-
title=
|
|
185
|
-
description=
|
|
198
|
+
title={ui.postList}
|
|
199
|
+
description={localeConfig.site.description}
|
|
186
200
|
showSidebar={true}
|
|
201
|
+
i18nConfig={i18nConfig}
|
|
187
202
|
>
|
|
203
|
+
<!-- 面包屑导航 -->
|
|
204
|
+
<nav class="flex items-center space-x-2 text-sm text-slate-600 dark:text-slate-400 mb-8">
|
|
205
|
+
<a href={`${localePrefix}/`} class="hover:text-primary-500 transition-colors">{ui.home}</a>
|
|
206
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
207
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
|
|
208
|
+
</svg>
|
|
209
|
+
<span class="text-slate-900 dark:text-slate-100">{ui.postList}</span>
|
|
210
|
+
</nav>
|
|
211
|
+
|
|
188
212
|
<!-- 页面头部 -->
|
|
189
213
|
<div class="mb-12">
|
|
190
214
|
<div class="text-center">
|
|
191
215
|
<h1 class="text-4xl font-bold text-slate-900 dark:text-slate-100 mb-4">
|
|
192
|
-
|
|
216
|
+
{ui.postList}
|
|
193
217
|
</h1>
|
|
194
218
|
<p class="text-xl text-slate-600 dark:text-slate-400 mb-8">
|
|
195
|
-
|
|
219
|
+
{localeConfig.site.description}
|
|
196
220
|
</p>
|
|
197
221
|
|
|
198
222
|
<!-- 统计信息 -->
|
|
199
223
|
<div class="inline-flex items-center space-x-6 text-sm text-slate-500 dark:text-slate-400 bg-slate-50 dark:bg-slate-800 px-6 py-3 rounded-lg">
|
|
200
|
-
<span
|
|
224
|
+
<span>{totalPosts} {ui.posts}</span>
|
|
201
225
|
<span>•</span>
|
|
202
|
-
<span>{allTags.length}
|
|
226
|
+
<span>{allTags.length} {ui.tags}</span>
|
|
203
227
|
<span>•</span>
|
|
204
|
-
<span>{allCategories.length}
|
|
228
|
+
<span>{allCategories.length} {ui.categories}</span>
|
|
205
229
|
</div>
|
|
206
230
|
</div>
|
|
207
231
|
</div>
|
|
@@ -223,20 +247,20 @@ const formatDate = (date?: Date) => {
|
|
|
223
247
|
<!-- 按标签筛选 -->
|
|
224
248
|
<div>
|
|
225
249
|
<h3 class="text-sm font-semibold text-slate-900 dark:text-slate-100 mb-3">
|
|
226
|
-
|
|
250
|
+
{ui.filterByTag}
|
|
227
251
|
</h3>
|
|
228
252
|
<div class="flex flex-wrap gap-2">
|
|
229
|
-
<a href=
|
|
230
|
-
|
|
253
|
+
<a href={`${localePrefix}/tags`} class="px-3 py-1 text-xs rounded-full bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 hover:bg-primary-200 dark:hover:bg-primary-900/50 transition-colors">
|
|
254
|
+
{ui.allTags}
|
|
231
255
|
</a>
|
|
232
256
|
{allTags.slice(0, 10).map((tag) => (
|
|
233
|
-
<a href={
|
|
257
|
+
<a href={`${localePrefix}/tags/${tag.toLowerCase().replace(/\s+/g, '-')}`} class="px-3 py-1 text-xs rounded-full bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors">
|
|
234
258
|
{tag}
|
|
235
259
|
</a>
|
|
236
260
|
))}
|
|
237
261
|
{allTags.length > 10 && (
|
|
238
|
-
<a href=
|
|
239
|
-
+{allTags.length - 10}
|
|
262
|
+
<a href={`${localePrefix}/tags`} class="px-3 py-1 text-xs rounded-full bg-slate-100 dark:bg-slate-700 text-slate-500 dark:text-slate-400 hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors">
|
|
263
|
+
+{allTags.length - 10}
|
|
240
264
|
</a>
|
|
241
265
|
)}
|
|
242
266
|
</div>
|
|
@@ -245,20 +269,20 @@ const formatDate = (date?: Date) => {
|
|
|
245
269
|
<!-- 按分类筛选 -->
|
|
246
270
|
<div>
|
|
247
271
|
<h3 class="text-sm font-semibold text-slate-900 dark:text-slate-100 mb-3">
|
|
248
|
-
|
|
272
|
+
{ui.filterByCategory}
|
|
249
273
|
</h3>
|
|
250
274
|
<div class="flex flex-wrap gap-2">
|
|
251
|
-
<a href=
|
|
252
|
-
|
|
275
|
+
<a href={`${localePrefix}/categories`} class="px-3 py-1 text-xs rounded-full bg-primary-100 dark:bg-primary-900/30 text-primary-700 dark:text-primary-300 hover:bg-primary-200 dark:hover:bg-primary-900/50 transition-colors">
|
|
276
|
+
{ui.allCategories}
|
|
253
277
|
</a>
|
|
254
278
|
{allCategories.slice(0, 8).map((category) => (
|
|
255
|
-
<a href={
|
|
279
|
+
<a href={`${localePrefix}/categories/${category.toLowerCase().replace(/\s+/g, '-')}`} class="px-3 py-1 text-xs rounded-full bg-slate-100 dark:bg-slate-700 text-slate-700 dark:text-slate-300 hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors">
|
|
256
280
|
{category}
|
|
257
281
|
</a>
|
|
258
282
|
))}
|
|
259
283
|
{allCategories.length > 8 && (
|
|
260
|
-
<a href=
|
|
261
|
-
+{allCategories.length - 8}
|
|
284
|
+
<a href={`${localePrefix}/categories`} class="px-3 py-1 text-xs rounded-full bg-slate-100 dark:bg-slate-700 text-slate-500 dark:text-slate-400 hover:bg-slate-200 dark:hover:bg-slate-600 transition-colors">
|
|
285
|
+
+{allCategories.length - 8}
|
|
262
286
|
</a>
|
|
263
287
|
)}
|
|
264
288
|
</div>
|
|
@@ -295,21 +319,19 @@ const formatDate = (date?: Date) => {
|
|
|
295
319
|
<!-- 卡片模式 -->
|
|
296
320
|
<div id="card-view" class="view-container">
|
|
297
321
|
{posts.length > 0 ? (
|
|
298
|
-
<div class="
|
|
322
|
+
<div class="grid grid-cols-1 lg:grid-cols-2 gap-6 mb-12">
|
|
299
323
|
{posts.map((post) => (
|
|
300
|
-
<
|
|
301
|
-
<PostCard post={post} layout="horizontal" />
|
|
302
|
-
</div>
|
|
324
|
+
<PostCard post={post} layout="horizontal" localePrefix={localePrefix} locale={localeConfig.locale.dateLocale} ui={ui} />
|
|
303
325
|
))}
|
|
304
326
|
</div>
|
|
305
327
|
) : (
|
|
306
328
|
<div class="text-center py-16">
|
|
307
329
|
<div class="text-6xl mb-4">📝</div>
|
|
308
330
|
<h3 class="text-xl font-semibold text-slate-900 dark:text-slate-100 mb-2">
|
|
309
|
-
|
|
331
|
+
{ui.noPostsFound}
|
|
310
332
|
</h3>
|
|
311
333
|
<p class="text-slate-600 dark:text-slate-400">
|
|
312
|
-
|
|
334
|
+
{ui.noPostsFound}
|
|
313
335
|
</p>
|
|
314
336
|
</div>
|
|
315
337
|
)}
|
|
@@ -352,7 +374,7 @@ const formatDate = (date?: Date) => {
|
|
|
352
374
|
<div class="folder-children hidden">
|
|
353
375
|
{child.children.map((grandChild) => (
|
|
354
376
|
<a
|
|
355
|
-
href={
|
|
377
|
+
href={`${localePrefix}/posts/${grandChild.slug}`}
|
|
356
378
|
class="ml-12 flex items-start gap-4 px-4 py-3 hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors border-b border-slate-100 dark:border-slate-700 group"
|
|
357
379
|
>
|
|
358
380
|
<svg class="w-4 h-4 text-slate-400 mt-1 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -365,7 +387,7 @@ const formatDate = (date?: Date) => {
|
|
|
365
387
|
)}
|
|
366
388
|
</div>
|
|
367
389
|
{grandChild.pubDate && (
|
|
368
|
-
<time class="text-xs text-slate-400 flex-shrink-0">{
|
|
390
|
+
<time class="text-xs text-slate-400 flex-shrink-0">{formatDateLocal(grandChild.pubDate)}</time>
|
|
369
391
|
)}
|
|
370
392
|
</a>
|
|
371
393
|
))}
|
|
@@ -373,7 +395,7 @@ const formatDate = (date?: Date) => {
|
|
|
373
395
|
</div>
|
|
374
396
|
) : (
|
|
375
397
|
<a
|
|
376
|
-
href={
|
|
398
|
+
href={`${localePrefix}/posts/${child.slug}`}
|
|
377
399
|
class="ml-6 flex items-start gap-4 px-4 py-3 hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors border-b border-slate-100 dark:border-slate-700 group"
|
|
378
400
|
>
|
|
379
401
|
<svg class="w-4 h-4 text-slate-400 mt-1 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -386,7 +408,7 @@ const formatDate = (date?: Date) => {
|
|
|
386
408
|
)}
|
|
387
409
|
</div>
|
|
388
410
|
{child.pubDate && (
|
|
389
|
-
<time class="text-xs text-slate-400 flex-shrink-0">{
|
|
411
|
+
<time class="text-xs text-slate-400 flex-shrink-0">{formatDateLocal(child.pubDate)}</time>
|
|
390
412
|
)}
|
|
391
413
|
</a>
|
|
392
414
|
)}
|
|
@@ -396,7 +418,7 @@ const formatDate = (date?: Date) => {
|
|
|
396
418
|
</div>
|
|
397
419
|
) : (
|
|
398
420
|
<a
|
|
399
|
-
href={
|
|
421
|
+
href={`${localePrefix}/posts/${node.slug}`}
|
|
400
422
|
class="flex items-start gap-4 px-4 py-3 hover:bg-slate-50 dark:hover:bg-slate-700/50 transition-colors border-b border-slate-100 dark:border-slate-700 group"
|
|
401
423
|
>
|
|
402
424
|
<svg class="w-4 h-4 text-slate-400 mt-1 flex-shrink-0" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
@@ -409,7 +431,7 @@ const formatDate = (date?: Date) => {
|
|
|
409
431
|
)}
|
|
410
432
|
</div>
|
|
411
433
|
{node.pubDate && (
|
|
412
|
-
<time class="text-xs text-slate-400 flex-shrink-0">{
|
|
434
|
+
<time class="text-xs text-slate-400 flex-shrink-0">{formatDateLocal(node.pubDate)}</time>
|
|
413
435
|
)}
|
|
414
436
|
</a>
|
|
415
437
|
)}
|
|
@@ -421,10 +443,10 @@ const formatDate = (date?: Date) => {
|
|
|
421
443
|
<div class="text-center py-16">
|
|
422
444
|
<div class="text-6xl mb-4">📝</div>
|
|
423
445
|
<h3 class="text-xl font-semibold text-slate-900 dark:text-slate-100 mb-2">
|
|
424
|
-
|
|
446
|
+
{ui.noPostsFound}
|
|
425
447
|
</h3>
|
|
426
448
|
<p class="text-slate-600 dark:text-slate-400">
|
|
427
|
-
|
|
449
|
+
{ui.noPostsFound}
|
|
428
450
|
</p>
|
|
429
451
|
</div>
|
|
430
452
|
)}
|
|
@@ -437,7 +459,7 @@ const formatDate = (date?: Date) => {
|
|
|
437
459
|
<Pagination
|
|
438
460
|
currentPage={currentPage}
|
|
439
461
|
totalPages={totalPages}
|
|
440
|
-
baseUrl=
|
|
462
|
+
baseUrl={`${localePrefix}/posts`}
|
|
441
463
|
/>
|
|
442
464
|
)}
|
|
443
465
|
</div>
|