@jet-w/astro-blog 0.2.5 → 0.2.6

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 (35) hide show
  1. package/package.json +1 -1
  2. package/src/components/blog/Hero.astro +9 -6
  3. package/src/components/blog/PostCard.astro +4 -8
  4. package/src/components/home/FeaturedPostsSection.astro +9 -4
  5. package/src/components/home/QuickNavSection.astro +9 -4
  6. package/src/components/home/RecentPostsSection.astro +9 -4
  7. package/src/components/home/StatsSection.astro +9 -3
  8. package/src/components/layout/Footer.astro +16 -7
  9. package/src/components/layout/Header.astro +15 -12
  10. package/src/components/layout/Sidebar.astro +11 -6
  11. package/src/components/media/Slides.astro +22 -6
  12. package/src/components/ui/LanguageSwitcher.vue +24 -12
  13. package/src/components/ui/MobileMenu.vue +20 -3
  14. package/src/layouts/BaseLayout.astro +14 -7
  15. package/src/layouts/PageLayout.astro +9 -3
  16. package/src/layouts/SlidesLayout.astro +34 -16
  17. package/src/pages/archives/[year]/[month]/page/[page].astro +42 -18
  18. package/src/pages/archives/[year]/[month].astro +7 -2
  19. package/src/pages/archives/index.astro +7 -3
  20. package/src/pages/categories/[category]/page/[page].astro +40 -18
  21. package/src/pages/categories/[category].astro +7 -2
  22. package/src/pages/categories/index.astro +7 -3
  23. package/src/pages/posts/[...slug].astro +7 -3
  24. package/src/pages/posts/index.astro +7 -3
  25. package/src/pages/posts/page/[page].astro +7 -2
  26. package/src/pages/search.astro +9 -3
  27. package/src/pages/slides/index.astro +7 -3
  28. package/src/pages/tags/[tag]/page/[page].astro +39 -17
  29. package/src/pages/tags/[tag].astro +7 -2
  30. package/src/pages/tags/index.astro +7 -3
  31. package/src/plugins/rehype-relative-links.mjs +90 -14
  32. package/templates/default/.claude/ralph-loop.local.md +2 -32
  33. package/templates/default/Makefile +37 -0
  34. package/templates/default/astro.config.mjs +7 -3
  35. package/templates/default/package.prod.json +31 -0
@@ -3,6 +3,9 @@ import { getCollection } from 'astro:content';
3
3
  import PageLayout from '@jet-w/astro-blog/layouts/PageLayout.astro';
4
4
  import PostCard from '@jet-w/astro-blog/components/blog/PostCard.astro';
5
5
  import Pagination from '@jet-w/astro-blog/components/ui/Pagination.astro';
6
+ import { i18nConfig as virtualI18nConfig } from 'virtual:astro-blog-i18n';
7
+ import { defaultI18nConfig } from '../../../../config/i18n';
8
+ import { getLocaleFromPath, getLocaleConfig, getLocalePrefix, filterPostsByLocale, removeBase } from '../../../../utils/i18n';
6
9
 
7
10
  export async function getStaticPaths() {
8
11
  const postsPerPage = 10;
@@ -53,8 +56,23 @@ export async function getStaticPaths() {
53
56
  const { tagSlug, tagName, page: currentPage, totalPages } = Astro.props;
54
57
  const postsPerPage = 10;
55
58
 
59
+ // Get i18n config
60
+ const i18nConfig = virtualI18nConfig || defaultI18nConfig;
61
+ const base = import.meta.env.BASE_URL;
62
+
63
+ // Remove base URL from current path for locale detection
64
+ const pathWithoutBase = removeBase(Astro.url.pathname, base);
65
+
66
+ const currentLocale = getLocaleFromPath(pathWithoutBase, i18nConfig);
67
+ const localeConfig = getLocaleConfig(currentLocale, i18nConfig);
68
+ const ui = localeConfig.ui;
69
+ const localePrefix = getLocalePrefix(currentLocale, i18nConfig, base);
70
+
56
71
  // 获取所有文章并筛选包含该标签的文章
57
- const allPosts = await getCollection('posts', ({ data }) => !data.draft);
72
+ const allPostsCollection = await getCollection('posts', ({ data }) => !data.draft);
73
+
74
+ // Filter posts by current locale
75
+ const allPosts = filterPostsByLocale(allPostsCollection, currentLocale, i18nConfig);
58
76
 
59
77
  // 筛选包含该标签的文章
60
78
  const filteredPosts = allPosts
@@ -95,25 +113,26 @@ const relatedTags = Array.from(relatedTagMap.entries())
95
113
  ---
96
114
 
97
115
  <PageLayout
98
- title={`标签: ${tagName} - ${currentPage} 页`}
99
- description={`浏览所有关于 ${tagName} 的文章 - ${currentPage} 页`}
116
+ title={`${ui.taggedWith}: ${tagName} - ${ui.page} ${currentPage}`}
117
+ description={`${ui.taggedWith} ${tagName} - ${ui.page} ${currentPage}`}
100
118
  showSidebar={true}
119
+ i18nConfig={i18nConfig}
101
120
  >
102
121
  <!-- 面包屑导航 -->
103
122
  <nav class="flex items-center space-x-2 text-sm text-slate-600 dark:text-slate-400 mb-8">
104
- <a href="/" class="hover:text-primary-500 transition-colors">首页</a>
123
+ <a href={`${localePrefix}/`} class="hover:text-primary-500 transition-colors">{ui.home}</a>
105
124
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
106
125
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
107
126
  </svg>
108
- <a href="/tags" class="hover:text-primary-500 transition-colors">标签</a>
127
+ <a href={`${localePrefix}/tags`} class="hover:text-primary-500 transition-colors">{ui.allTags}</a>
109
128
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
110
129
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
111
130
  </svg>
112
- <a href={`/tags/${tagSlug}`} class="hover:text-primary-500 transition-colors">{tagName}</a>
131
+ <a href={`${localePrefix}/tags/${tagSlug}`} class="hover:text-primary-500 transition-colors">{tagName}</a>
113
132
  <svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
114
133
  <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7" />
115
134
  </svg>
116
- <span class="text-slate-900 dark:text-slate-100">第 {currentPage} 页</span>
135
+ <span class="text-slate-900 dark:text-slate-100">{ui.page} {currentPage}</span>
117
136
  </nav>
118
137
 
119
138
  <!-- 页面头部 -->
@@ -129,16 +148,16 @@ const relatedTags = Array.from(relatedTagMap.entries())
129
148
  </h1>
130
149
 
131
150
  <p class="text-xl text-slate-600 dark:text-slate-400 mb-8">
132
- 找到 {totalPosts} 篇关于 {tagName} 的文章
151
+ {totalPosts} {ui.posts}
133
152
  </p>
134
153
 
135
154
  <!-- 标签统计 -->
136
155
  <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">
137
156
  <span>#{tagName}</span>
138
157
  <span>•</span>
139
- <span>{totalPosts} 篇文章</span>
158
+ <span>{totalPosts} {ui.posts}</span>
140
159
  <span>•</span>
141
- <span>第 {currentPage} / {totalPages} 页</span>
160
+ <span>{ui.page} {currentPage} / {totalPages}</span>
142
161
  </div>
143
162
  </div>
144
163
 
@@ -158,6 +177,9 @@ const relatedTags = Array.from(relatedTagMap.entries())
158
177
  image: post.data.image
159
178
  }}
160
179
  layout="horizontal"
180
+ localePrefix={localePrefix}
181
+ locale={localeConfig.locale.dateLocale}
182
+ ui={ui}
161
183
  />
162
184
  ))}
163
185
  </div>
@@ -165,13 +187,13 @@ const relatedTags = Array.from(relatedTagMap.entries())
165
187
  <div class="text-center py-16">
166
188
  <div class="text-6xl mb-4">📝</div>
167
189
  <h3 class="text-xl font-semibold text-slate-900 dark:text-slate-100 mb-2">
168
- 暂无相关文章
190
+ {ui.noPostsFound}
169
191
  </h3>
170
192
  <p class="text-slate-600 dark:text-slate-400 mb-6">
171
- 目前还没有关于 {tagName} 的文章,请查看其他标签。
193
+ {ui.noPostsFound}
172
194
  </p>
173
- <a href="/tags" class="btn-secondary">
174
- 浏览所有标签
195
+ <a href={`${localePrefix}/tags`} class="btn-secondary">
196
+ {ui.allTags}
175
197
  </a>
176
198
  </div>
177
199
  )}
@@ -181,7 +203,7 @@ const relatedTags = Array.from(relatedTagMap.entries())
181
203
  <Pagination
182
204
  currentPage={currentPage}
183
205
  totalPages={totalPages}
184
- baseUrl={`/tags/${tagSlug}`}
206
+ baseUrl={`${localePrefix}/tags/${tagSlug}`}
185
207
  />
186
208
  )}
187
209
 
@@ -189,12 +211,12 @@ const relatedTags = Array.from(relatedTagMap.entries())
189
211
  {relatedTags.length > 0 && (
190
212
  <section class="mt-16 pt-8 border-t border-slate-200 dark:border-slate-700">
191
213
  <h2 class="text-2xl font-bold text-slate-900 dark:text-slate-100 mb-6">
192
- 相关标签
214
+ {ui.popularTags}
193
215
  </h2>
194
216
  <div class="flex flex-wrap gap-3">
195
217
  {relatedTags.map((relatedTag) => (
196
218
  <a
197
- href={`/tags/${relatedTag.slug}`}
219
+ href={`${localePrefix}/tags/${relatedTag.slug}`}
198
220
  class="inline-flex items-center px-4 py-2 bg-white dark:bg-slate-800 border border-slate-300 dark:border-slate-600 rounded-lg hover:border-primary-300 dark:hover:border-primary-600 hover:shadow-md transition-all duration-200 group"
199
221
  >
200
222
  <span class="font-medium text-slate-900 dark:text-slate-100 group-hover:text-primary-500 transition-colors">
@@ -35,10 +35,15 @@ const { tagSlug, tagName, tagCount } = Astro.props;
35
35
 
36
36
  // Get i18n config
37
37
  const i18nConfig = virtualI18nConfig || defaultI18nConfig;
38
- const currentLocale = getLocaleFromPath(Astro.url.pathname, i18nConfig);
38
+ const base = import.meta.env.BASE_URL;
39
+
40
+ // Remove base URL from current path for locale detection
41
+ const { removeBase } = await import('../../utils/i18n');
42
+ const pathWithoutBase = removeBase(Astro.url.pathname, base);
43
+
44
+ const currentLocale = getLocaleFromPath(pathWithoutBase, i18nConfig);
39
45
  const localeConfig = getLocaleConfig(currentLocale, i18nConfig);
40
46
  const ui = localeConfig.ui;
41
- const base = import.meta.env.BASE_URL;
42
47
  const localePrefix = getLocalePrefix(currentLocale, i18nConfig, base);
43
48
 
44
49
  // 获取所有文章并筛选包含该标签的文章
@@ -4,14 +4,18 @@ import PageLayout from '@jet-w/astro-blog/layouts/PageLayout.astro';
4
4
  import TagCloud from '@jet-w/astro-blog/components/blog/TagCloud.astro';
5
5
  import { i18nConfig as virtualI18nConfig } from 'virtual:astro-blog-i18n';
6
6
  import { defaultI18nConfig } from '../../config/i18n';
7
- import { getLocaleFromPath, getLocaleConfig, getLocalePrefix, filterPostsByLocale } from '../../utils/i18n';
7
+ import { getLocaleFromPath, getLocaleConfig, getLocalePrefix, filterPostsByLocale, removeBase } from '../../utils/i18n';
8
8
 
9
9
  // Get i18n config
10
10
  const i18nConfig = virtualI18nConfig || defaultI18nConfig;
11
- const currentLocale = getLocaleFromPath(Astro.url.pathname, i18nConfig);
11
+ const base = import.meta.env.BASE_URL;
12
+
13
+ // Remove base URL from current path for locale detection
14
+ const pathWithoutBase = removeBase(Astro.url.pathname, base);
15
+
16
+ const currentLocale = getLocaleFromPath(pathWithoutBase, i18nConfig);
12
17
  const localeConfig = getLocaleConfig(currentLocale, i18nConfig);
13
18
  const ui = localeConfig.ui;
14
- const base = import.meta.env.BASE_URL;
15
19
  const localePrefix = getLocalePrefix(currentLocale, i18nConfig, base);
16
20
 
17
21
  // 从文章集合动态获取所有标签
@@ -1,10 +1,63 @@
1
1
  /**
2
- * Rehype 插件:修复 Markdown 中的相对链接
3
- * 将相对链接转换为正确的绝对路径
2
+ * Rehype 插件:修复 Markdown 中的相对链接和图片链接
3
+ * 将相对链接转换为正确的绝对路径,支持 base URL
4
+ * 同时处理绝对路径链接,添加 base URL 前缀
4
5
  */
5
6
  import { visit } from 'unist-util-visit';
6
7
 
8
+ /**
9
+ * Helper function to check if a path is a relative link
10
+ * @param {string} path - The path to check
11
+ * @returns {boolean} - True if the path is relative
12
+ */
13
+ function isRelativePath(path) {
14
+ return (
15
+ path.startsWith('./') ||
16
+ path.startsWith('../') ||
17
+ (!path.startsWith('/') &&
18
+ !path.startsWith('#') &&
19
+ !path.startsWith('http://') &&
20
+ !path.startsWith('https://') &&
21
+ !path.startsWith('mailto:') &&
22
+ !path.startsWith('data:'))
23
+ );
24
+ }
25
+
26
+ /**
27
+ * Helper function to check if a path is an internal absolute path
28
+ * (starts with / but not an external URL or special protocol)
29
+ * @param {string} path - The path to check
30
+ * @returns {boolean} - True if the path is an internal absolute path
31
+ */
32
+ function isInternalAbsolutePath(path) {
33
+ return (
34
+ path.startsWith('/') &&
35
+ !path.startsWith('//') // Exclude protocol-relative URLs like //example.com
36
+ );
37
+ }
38
+
39
+ /**
40
+ * Helper function to normalize the base URL
41
+ * @param {string} base - The base URL
42
+ * @returns {string} - Normalized base URL (with leading slash, without trailing slash)
43
+ */
44
+ function normalizeBase(base) {
45
+ if (!base || base === '/') return '';
46
+ // Ensure leading slash, remove trailing slash
47
+ let normalized = base.startsWith('/') ? base : `/${base}`;
48
+ normalized = normalized.endsWith('/') ? normalized.slice(0, -1) : normalized;
49
+ return normalized;
50
+ }
51
+
52
+ /**
53
+ * Rehype plugin to fix relative links in Markdown
54
+ * @param {Object} options - Plugin options
55
+ * @param {string} options.base - The base URL path (e.g., '/blog')
56
+ * @returns {Function} - The plugin function
57
+ */
7
58
  export function rehypeRelativeLinks(options = {}) {
59
+ const base = normalizeBase(options.base || process.env.BASE_PATH || '');
60
+
8
61
  return (tree, file) => {
9
62
  // 获取当前文件的路径信息
10
63
  const filePath = file.history[0] || '';
@@ -12,28 +65,51 @@ export function rehypeRelativeLinks(options = {}) {
12
65
  // 从文件路径中提取目录信息
13
66
  // 例如:/path/to/content/posts/blog_docs/README.md -> blog_docs
14
67
  const match = filePath.match(/content\/posts\/(.+?)\/[^/]+\.(md|mdx)$/i);
15
- if (!match) return;
16
68
 
17
- const dirPath = match[1]; // 例如:blog_docs 或 tech/subfolder
69
+ // dirPath 用于相对链接的解析
70
+ const dirPath = match ? match[1] : ''; // 例如:blog_docs 或 tech/subfolder
18
71
 
19
72
  visit(tree, 'element', (node) => {
73
+ // Handle anchor links
20
74
  if (node.tagName === 'a' && node.properties?.href) {
21
75
  const href = node.properties.href;
22
76
 
23
- // 只处理相对链接(以 ./ 或不以 / # http 开头的链接)
24
- if (href.startsWith('./') ||
25
- (!href.startsWith('/') &&
26
- !href.startsWith('#') &&
27
- !href.startsWith('http://') &&
28
- !href.startsWith('https://') &&
29
- !href.startsWith('mailto:'))) {
30
-
77
+ if (isRelativePath(href) && dirPath) {
31
78
  // 移除 ./ 前缀
32
79
  const cleanHref = href.replace(/^\.\//, '');
33
80
 
34
- // 构建新的绝对路径
35
- const newHref = `/posts/${dirPath}/${cleanHref}`;
81
+ // 构建新的绝对路径(包含 base URL)
82
+ const newHref = `${base}/posts/${dirPath}/${cleanHref}`;
36
83
  node.properties.href = newHref;
84
+ } else if (isInternalAbsolutePath(href) && base) {
85
+ // 处理内部绝对路径:添加 base URL 前缀
86
+ // 例如:/posts/xxx -> /blog/posts/xxx
87
+ // 避免重复添加 base(如果已经包含)
88
+ if (!href.startsWith(base + '/') && href !== base) {
89
+ node.properties.href = base + href;
90
+ }
91
+ }
92
+ }
93
+
94
+ // Handle image links
95
+ if (node.tagName === 'img' && node.properties?.src) {
96
+ const src = node.properties.src;
97
+
98
+ if (isRelativePath(src) && dirPath) {
99
+ // 移除 ./ 前缀
100
+ const cleanSrc = src.replace(/^\.\//, '');
101
+
102
+ // 构建新的绝对路径(包含 base URL)
103
+ // 图片通常相对于当前文档,保持目录结构
104
+ const newSrc = `${base}/posts/${dirPath}/${cleanSrc}`;
105
+ node.properties.src = newSrc;
106
+ } else if (isInternalAbsolutePath(src) && base) {
107
+ // 处理内部绝对路径图片:添加 base URL 前缀
108
+ // 例如:/images/xxx.png -> /blog/images/xxx.png
109
+ // 避免重复添加 base(如果已经包含)
110
+ if (!src.startsWith(base + '/') && src !== base) {
111
+ node.properties.src = base + src;
112
+ }
37
113
  }
38
114
  }
39
115
  });
@@ -3,37 +3,7 @@ active: true
3
3
  iteration: 1
4
4
  max_iterations: 20
5
5
  completion_promise: "DONE"
6
- started_at: "2026-01-29T09:04:01Z"
6
+ started_at: "2026-01-29T23:41:34Z"
7
7
  ---
8
8
 
9
- There is an error happened after running npm run build for default template in github action
10
- 8:27:27 AM [vite] (ssr) Error when evaluating SSR module /home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/astro.config.mjs: Failed to resolve entry for package @jet-w/astro-blog. The package may have incorrect main/module/exports specified in its package.json.
11
- Plugin: vite:import-analysis
12
- File: /home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/astro.config.mjs:11:46
13
- 9 |
14
- 10 | // Import plugins and integration from @jet-w/astro-blog
15
- 11 | import { astroBlog, defineI18nConfig } from '@jet-w/astro-blog';
16
- | ^
17
- 12 | import { remarkProtectCode, rehypeRestoreCode } from '@jet-w/astro-blog/plugins/remark-protect-code.mjs';
18
- 13 | import { remarkContainers } from '@jet-w/astro-blog/plugins/remark-containers.mjs';
19
- at packageEntryFailure (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:16198:15)
20
- at resolvePackageEntry (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:16195:3)
21
- at tryNodeResolve (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:16060:18)
22
- at ResolveIdContext.resolveId (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:15831:19)
23
- at EnvironmentPluginContainer.resolveId (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:42242:17)
24
- at async TransformPluginContext.resolve (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:42449:15)
25
- at async normalizeUrl (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:40492:26)
26
- at async file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:40623:37
27
- at async Promise.all (index 8)
28
- at async TransformPluginContext.transform (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:40550:7)
29
- [astro] Unable to load your Astro config
30
- Failed to resolve entry for package @jet-w/astro-blog. The package may have incorrect main/module/exports specified in its package.json.
31
- Location:
32
- /home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/astro.config.mjs:11:46
33
- Stack trace:
34
- at packageEntryFailure (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:16198:15)
35
- at tryNodeResolve (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:16060:18)
36
- at EnvironmentPluginContainer.resolveId (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:42242:17)
37
- at async normalizeUrl (file:///home/runner/work/jet-w.astro-blog/jet-w.astro-blog/templates/default/node_modules/vite/dist/node/chunks/dep-D4NMHUTW.js:40492:26)
38
- at async Promise.all (index 8)
39
- Error: Process completed with exit code 1.
9
+ When the base url was set up, the hyper link in markdown, such as [/xxx/fse](text) and image link cannot change accordingly, please help to check similar link at the same time. please help to fix it
@@ -0,0 +1,37 @@
1
+ .PHONY: dev prod install clean help
2
+
3
+ # Default target
4
+ help:
5
+ @echo "Usage:"
6
+ @echo " make dev - Switch to development mode (uses local @jet-w/astro-blog)"
7
+ @echo " make prod - Switch to production mode (uses npm package @jet-w/astro-blog)"
8
+ @echo " make install - Run npm install after switching modes"
9
+ @echo " make clean - Remove node_modules and package-lock.json"
10
+
11
+ # Switch to development mode (local package)
12
+ dev:
13
+ @echo "Switching to development mode..."
14
+ @cp package.dev.json package.json
15
+ @echo "Done! Run 'make install' or 'npm install' to install dependencies."
16
+
17
+ # Switch to production mode (npm package)
18
+ prod:
19
+ @echo "Switching to production mode..."
20
+ @cp package.prod.json package.json
21
+ @echo "Done! Run 'make install' or 'npm install' to install dependencies."
22
+
23
+ # Install dependencies
24
+ install:
25
+ npm install
26
+
27
+ # Clean node_modules and package-lock.json
28
+ clean:
29
+ @echo "Cleaning..."
30
+ @rm -rf node_modules package-lock.json
31
+ @echo "Done!"
32
+
33
+ # Switch to dev and install
34
+ dev-install: dev install
35
+
36
+ # Switch to prod and install
37
+ prod-install: prod install
@@ -1,4 +1,5 @@
1
1
  import { defineConfig } from 'astro/config';
2
+ import { loadEnv } from 'vite';
2
3
  import vue from '@astrojs/vue';
3
4
  import tailwind from '@astrojs/tailwind';
4
5
  import mdx from '@astrojs/mdx';
@@ -7,6 +8,9 @@ import remarkMath from 'remark-math';
7
8
  import rehypeKatex from 'rehype-katex';
8
9
  import rehypeRaw from 'rehype-raw';
9
10
 
11
+ // Load environment variables from .env file
12
+ const { SITE_URL, BASE_PATH } = loadEnv(process.env.NODE_ENV || 'production', process.cwd(), '');
13
+
10
14
  // Import plugins and integration from @jet-w/astro-blog
11
15
  import { astroBlog, defineI18nConfig } from '@jet-w/astro-blog';
12
16
  import { remarkProtectCode, rehypeRestoreCode } from '@jet-w/astro-blog/plugins/remark-protect-code.mjs';
@@ -59,7 +63,7 @@ export default defineConfig({
59
63
  rehypeKatex,
60
64
  rehypeCleanContainers,
61
65
  rehypeTabs,
62
- rehypeRelativeLinks,
66
+ [rehypeRelativeLinks, { base: BASE_PATH || process.env.BASE_PATH || '/' }],
63
67
  rehypeRestoreCode, // Must run LAST to restore ::: in code blocks
64
68
  ],
65
69
  shikiConfig: {
@@ -68,8 +72,8 @@ export default defineConfig({
68
72
  wrap: true
69
73
  }
70
74
  },
71
- site: process.env.SITE_URL || 'https://example.com',
72
- base: process.env.BASE_PATH || '/',
75
+ site: SITE_URL || process.env.SITE_URL || 'https://example.com',
76
+ base: BASE_PATH || process.env.BASE_PATH || '/',
73
77
  build: {
74
78
  assets: 'assets'
75
79
  },
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "my-astro-blog",
3
+ "type": "module",
4
+ "version": "0.0.1",
5
+ "scripts": {
6
+ "dev": "astro dev",
7
+ "start": "astro dev",
8
+ "build": "astro build",
9
+ "preview": "astro preview",
10
+ "astro": "astro"
11
+ },
12
+ "dependencies": {
13
+ "@astrojs/mdx": "^4.3.12",
14
+ "@astrojs/rss": "^4.0.14",
15
+ "@astrojs/tailwind": "^5.1.3",
16
+ "@astrojs/vue": "^5.0.6",
17
+ "@jet-w/astro-blog": "^0.2.1",
18
+ "@tailwindcss/typography": "^0.5.15",
19
+ "astro": "^5.14.1",
20
+ "echarts": "^6.0.0",
21
+ "fuse.js": "^7.0.0",
22
+ "mermaid": "^11.12.2",
23
+ "rehype-katex": "^7.0.1",
24
+ "rehype-raw": "^7.0.0",
25
+ "remark-directive": "^4.0.0",
26
+ "remark-math": "^6.0.0",
27
+ "tailwindcss": "^3.4.17",
28
+ "typescript": "^5.7.2",
29
+ "vue": "^3.5.13"
30
+ }
31
+ }