@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 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.6",
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
  <!-- 分类信息 -->