@jet-w/astro-blog 0.2.6 → 0.2.8
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/README.md +267 -0
- package/package.json +3 -2
- package/src/pages/posts/[...slug].astro +72 -1
package/README.md
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
# @jet-w/astro-blog
|
|
2
|
+
|
|
3
|
+
A modern, feature-rich Astro blog theme with Vue and Tailwind CSS support. Provides a complete blogging solution with multi-language support, rich markdown capabilities, and interactive components.
|
|
4
|
+
|
|
5
|
+
**Official Website**: [https://jet-w.github.io/jet-w.astro-blog/](https://jet-w.github.io/jet-w.astro-blog/)
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Multi-Language Support (i18n)** - Built-in internationalization with configurable locales
|
|
10
|
+
- **Blog System** - Posts, tags, categories, archives, and pagination
|
|
11
|
+
- **Search** - Full-text search powered by Fuse.js
|
|
12
|
+
- **RSS Feed** - Automatic RSS feed generation
|
|
13
|
+
- **Dark Mode** - Theme switching support
|
|
14
|
+
- **Rich Markdown** - Code highlighting, math equations (KaTeX), Mermaid diagrams, custom containers
|
|
15
|
+
- **Interactive Components** - Slides, ECharts, video embeds (YouTube, Bilibili)
|
|
16
|
+
- **Responsive Design** - Mobile-friendly layouts with Tailwind CSS
|
|
17
|
+
|
|
18
|
+
## Installation
|
|
19
|
+
|
|
20
|
+
```bash
|
|
21
|
+
npm install @jet-w/astro-blog
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Peer Dependencies
|
|
25
|
+
|
|
26
|
+
Make sure you have these packages installed:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
npm install astro @astrojs/mdx @astrojs/rss @astrojs/tailwind @astrojs/vue tailwindcss vue
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Quick Start
|
|
33
|
+
|
|
34
|
+
### 1. Configure Astro
|
|
35
|
+
|
|
36
|
+
Add the integration to your `astro.config.mjs`:
|
|
37
|
+
|
|
38
|
+
```js
|
|
39
|
+
import { defineConfig } from 'astro/config';
|
|
40
|
+
import { astroBlog } from '@jet-w/astro-blog';
|
|
41
|
+
|
|
42
|
+
export default defineConfig({
|
|
43
|
+
integrations: [astroBlog()],
|
|
44
|
+
});
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
### 2. Set Up Content Collections
|
|
48
|
+
|
|
49
|
+
Create `src/content/config.ts`:
|
|
50
|
+
|
|
51
|
+
```ts
|
|
52
|
+
import { defineCollection, z } from 'astro:content';
|
|
53
|
+
|
|
54
|
+
const posts = defineCollection({
|
|
55
|
+
type: 'content',
|
|
56
|
+
schema: z.object({
|
|
57
|
+
title: z.string(),
|
|
58
|
+
description: z.string().optional(),
|
|
59
|
+
date: z.date(),
|
|
60
|
+
tags: z.array(z.string()).optional(),
|
|
61
|
+
categories: z.array(z.string()).optional(),
|
|
62
|
+
draft: z.boolean().optional(),
|
|
63
|
+
}),
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
export const collections = { posts };
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### 3. Create Your First Post
|
|
70
|
+
|
|
71
|
+
Create a markdown file in `src/content/posts/`:
|
|
72
|
+
|
|
73
|
+
```markdown
|
|
74
|
+
---
|
|
75
|
+
title: Hello World
|
|
76
|
+
date: 2024-01-01
|
|
77
|
+
tags: [hello, first-post]
|
|
78
|
+
---
|
|
79
|
+
|
|
80
|
+
Welcome to my blog!
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Configuration
|
|
84
|
+
|
|
85
|
+
### Site Configuration
|
|
86
|
+
|
|
87
|
+
Create `src/config/site.ts`:
|
|
88
|
+
|
|
89
|
+
```ts
|
|
90
|
+
import { defineSiteConfig } from '@jet-w/astro-blog/config';
|
|
91
|
+
|
|
92
|
+
export default defineSiteConfig({
|
|
93
|
+
title: 'My Blog',
|
|
94
|
+
description: 'A blog about...',
|
|
95
|
+
author: 'Your Name',
|
|
96
|
+
lang: 'en',
|
|
97
|
+
});
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### i18n Configuration
|
|
101
|
+
|
|
102
|
+
Create `src/config/i18n.ts`:
|
|
103
|
+
|
|
104
|
+
```ts
|
|
105
|
+
import { defineI18nConfig } from '@jet-w/astro-blog/config';
|
|
106
|
+
|
|
107
|
+
export default defineI18nConfig({
|
|
108
|
+
defaultLocale: 'en',
|
|
109
|
+
locales: ['en', 'zh-cn'],
|
|
110
|
+
translations: {
|
|
111
|
+
en: {
|
|
112
|
+
'nav.home': 'Home',
|
|
113
|
+
'nav.blog': 'Blog',
|
|
114
|
+
// ...
|
|
115
|
+
},
|
|
116
|
+
'zh-cn': {
|
|
117
|
+
'nav.home': '首页',
|
|
118
|
+
'nav.blog': '博客',
|
|
119
|
+
// ...
|
|
120
|
+
},
|
|
121
|
+
},
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Sidebar Configuration
|
|
126
|
+
|
|
127
|
+
Create `src/config/sidebar.ts`:
|
|
128
|
+
|
|
129
|
+
```ts
|
|
130
|
+
import { defineSidebarConfig } from '@jet-w/astro-blog/config';
|
|
131
|
+
|
|
132
|
+
export default defineSidebarConfig({
|
|
133
|
+
// Manual configuration
|
|
134
|
+
items: [
|
|
135
|
+
{ label: 'Getting Started', link: '/docs/getting-started' },
|
|
136
|
+
{ label: 'Guide', items: [...] },
|
|
137
|
+
],
|
|
138
|
+
// Or use auto-scan
|
|
139
|
+
autoScan: {
|
|
140
|
+
directory: 'docs',
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
## Layouts
|
|
146
|
+
|
|
147
|
+
The theme provides several layouts:
|
|
148
|
+
|
|
149
|
+
- **BaseLayout** - Standard page layout
|
|
150
|
+
- **PageLayout** - Blog post layout with sidebar
|
|
151
|
+
- **AboutLayout** - Profile/about page layout
|
|
152
|
+
- **SlidesLayout** - Presentation slides layout
|
|
153
|
+
|
|
154
|
+
```astro
|
|
155
|
+
---
|
|
156
|
+
import { PageLayout } from '@jet-w/astro-blog/layouts';
|
|
157
|
+
---
|
|
158
|
+
|
|
159
|
+
<PageLayout title="My Page">
|
|
160
|
+
<p>Page content here</p>
|
|
161
|
+
</PageLayout>
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
## Components
|
|
165
|
+
|
|
166
|
+
Import components as needed:
|
|
167
|
+
|
|
168
|
+
```astro
|
|
169
|
+
---
|
|
170
|
+
import { SearchBox, ThemeToggle, LanguageSwitcher } from '@jet-w/astro-blog/components';
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
<SearchBox />
|
|
174
|
+
<ThemeToggle />
|
|
175
|
+
<LanguageSwitcher />
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### Available Components
|
|
179
|
+
|
|
180
|
+
- **UI**: SearchBox, ThemeToggle, LanguageSwitcher, MobileMenu, Pagination
|
|
181
|
+
- **Blog**: NavigationTabs, RelatedPosts, TagList
|
|
182
|
+
- **Media**: Video, YouTube, Bilibili, Slides
|
|
183
|
+
- **About**: TagCard, SocialLinks, Timeline
|
|
184
|
+
|
|
185
|
+
## Markdown Extensions
|
|
186
|
+
|
|
187
|
+
### Custom Containers
|
|
188
|
+
|
|
189
|
+
```markdown
|
|
190
|
+
:::tip
|
|
191
|
+
This is a tip
|
|
192
|
+
:::
|
|
193
|
+
|
|
194
|
+
:::warning
|
|
195
|
+
This is a warning
|
|
196
|
+
:::
|
|
197
|
+
|
|
198
|
+
:::danger
|
|
199
|
+
This is dangerous
|
|
200
|
+
:::
|
|
201
|
+
|
|
202
|
+
:::details Summary
|
|
203
|
+
Hidden content here
|
|
204
|
+
:::
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Math Equations
|
|
208
|
+
|
|
209
|
+
```markdown
|
|
210
|
+
Inline: $E = mc^2$
|
|
211
|
+
|
|
212
|
+
Block:
|
|
213
|
+
$$
|
|
214
|
+
\int_0^\infty e^{-x^2} dx = \frac{\sqrt{\pi}}{2}
|
|
215
|
+
$$
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
### Mermaid Diagrams
|
|
219
|
+
|
|
220
|
+
````markdown
|
|
221
|
+
```mermaid
|
|
222
|
+
graph TD
|
|
223
|
+
A[Start] --> B{Decision}
|
|
224
|
+
B -->|Yes| C[OK]
|
|
225
|
+
B -->|No| D[Cancel]
|
|
226
|
+
```
|
|
227
|
+
````
|
|
228
|
+
|
|
229
|
+
### Tabs
|
|
230
|
+
|
|
231
|
+
```markdown
|
|
232
|
+
:::tabs
|
|
233
|
+
@tab JavaScript
|
|
234
|
+
console.log('Hello');
|
|
235
|
+
|
|
236
|
+
@tab Python
|
|
237
|
+
print('Hello')
|
|
238
|
+
:::
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
## Project Structure
|
|
242
|
+
|
|
243
|
+
```
|
|
244
|
+
src/
|
|
245
|
+
├── components/ # Vue and Astro components
|
|
246
|
+
├── config/ # Configuration files
|
|
247
|
+
├── layouts/ # Layout templates
|
|
248
|
+
├── pages/ # Route pages
|
|
249
|
+
├── plugins/ # Markdown/MDX plugins
|
|
250
|
+
├── styles/ # Global styles
|
|
251
|
+
├── types/ # TypeScript definitions
|
|
252
|
+
└── utils/ # Utility functions
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## License
|
|
256
|
+
|
|
257
|
+
[Apache 2.0](./LICENSE)
|
|
258
|
+
|
|
259
|
+
## Author
|
|
260
|
+
|
|
261
|
+
Haiyue
|
|
262
|
+
|
|
263
|
+
## Links
|
|
264
|
+
|
|
265
|
+
- [Official Website](https://jet-w.github.io/jet-w.astro-blog/)
|
|
266
|
+
- [GitHub Repository](https://github.com/jet-w/jet-w.astro-blog)
|
|
267
|
+
- [NPM Package](https://www.npmjs.com/package/@jet-w/astro-blog)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jet-w/astro-blog",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.8",
|
|
4
4
|
"description": "A modern Astro blog theme with Vue and Tailwind CSS support",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -44,7 +44,8 @@
|
|
|
44
44
|
"src/types",
|
|
45
45
|
"src/utils",
|
|
46
46
|
"src/config",
|
|
47
|
-
"templates"
|
|
47
|
+
"templates",
|
|
48
|
+
"README.md"
|
|
48
49
|
],
|
|
49
50
|
"scripts": {
|
|
50
51
|
"build": "tsup",
|
|
@@ -325,10 +325,81 @@ const formatDate = (date: Date) => {
|
|
|
325
325
|
</header>
|
|
326
326
|
|
|
327
327
|
<!-- 文章内容 -->
|
|
328
|
-
<div class="prose prose-slate dark:prose-invert max-w-none prose-lg">
|
|
328
|
+
<div class="prose prose-slate dark:prose-invert max-w-none prose-lg" data-prose-content data-locale-prefix={localePrefix} data-base-url={base}>
|
|
329
329
|
{Content && <Content />}
|
|
330
330
|
</div>
|
|
331
331
|
|
|
332
|
+
<!-- 修复文章内容中的链接,添加当前语言前缀 -->
|
|
333
|
+
<script is:inline>
|
|
334
|
+
(function() {
|
|
335
|
+
function fixProseLinks() {
|
|
336
|
+
const proseContent = document.querySelector('[data-prose-content]');
|
|
337
|
+
if (!proseContent) return;
|
|
338
|
+
|
|
339
|
+
const localePrefix = proseContent.getAttribute('data-locale-prefix') || '';
|
|
340
|
+
const baseUrl = proseContent.getAttribute('data-base-url') || '';
|
|
341
|
+
|
|
342
|
+
// 如果没有 locale prefix 或 locale prefix 等于 base url,则不需要修复
|
|
343
|
+
// 这意味着当前是默认语言
|
|
344
|
+
if (!localePrefix || localePrefix === baseUrl) return;
|
|
345
|
+
|
|
346
|
+
// 获取 locale 部分 (从 localePrefix 中提取,例如 /base/zh-CN -> zh-CN)
|
|
347
|
+
const localePart = localePrefix.replace(baseUrl, '').replace(/^\//, '');
|
|
348
|
+
if (!localePart) return;
|
|
349
|
+
|
|
350
|
+
// 修复所有内部链接
|
|
351
|
+
proseContent.querySelectorAll('a[href]').forEach(function(link) {
|
|
352
|
+
const href = link.getAttribute('href');
|
|
353
|
+
if (!href) return;
|
|
354
|
+
|
|
355
|
+
// 跳过外部链接、锚点链接、mailto、tel 等
|
|
356
|
+
if (href.startsWith('http://') ||
|
|
357
|
+
href.startsWith('https://') ||
|
|
358
|
+
href.startsWith('//') ||
|
|
359
|
+
href.startsWith('#') ||
|
|
360
|
+
href.startsWith('mailto:') ||
|
|
361
|
+
href.startsWith('tel:') ||
|
|
362
|
+
href.startsWith('data:')) {
|
|
363
|
+
return;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
// 跳过已经包含 locale 前缀的链接
|
|
367
|
+
if (href.startsWith(localePrefix + '/') || href === localePrefix) {
|
|
368
|
+
return;
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
// 对于以 baseUrl 开头但没有 locale 的链接,添加 locale
|
|
372
|
+
if (baseUrl && href.startsWith(baseUrl + '/')) {
|
|
373
|
+
const pathAfterBase = href.slice(baseUrl.length);
|
|
374
|
+
// 检查是否已经有 locale 前缀
|
|
375
|
+
if (!pathAfterBase.startsWith('/' + localePart + '/') && pathAfterBase !== '/' + localePart) {
|
|
376
|
+
link.setAttribute('href', baseUrl + '/' + localePart + pathAfterBase);
|
|
377
|
+
}
|
|
378
|
+
return;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
// 对于绝对路径链接 (以 / 开头),添加 locale prefix
|
|
382
|
+
if (href.startsWith('/')) {
|
|
383
|
+
// 检查是否已经有 locale 前缀
|
|
384
|
+
if (!href.startsWith('/' + localePart + '/') && href !== '/' + localePart) {
|
|
385
|
+
link.setAttribute('href', localePrefix + href);
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// 页面加载后执行
|
|
392
|
+
if (document.readyState === 'loading') {
|
|
393
|
+
document.addEventListener('DOMContentLoaded', fixProseLinks);
|
|
394
|
+
} else {
|
|
395
|
+
fixProseLinks();
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// 支持 Astro 视图过渡
|
|
399
|
+
document.addEventListener('astro:page-load', fixProseLinks);
|
|
400
|
+
})();
|
|
401
|
+
</script>
|
|
402
|
+
|
|
332
403
|
<!-- 文章底部 -->
|
|
333
404
|
<footer class="not-prose mt-16 pt-8 border-t border-slate-200 dark:border-slate-700">
|
|
334
405
|
<!-- 分类信息 -->
|