diff --git a/README.md b/README.md index 1522741..2cb30a4 100644 --- a/README.md +++ b/README.md @@ -1,82 +1,80 @@ -# vhAstro-Theme -一款简约的 Astro 主题 +# 🍥 Astro主题 vhAstro-Theme -# Astro Starter Kit: Blog +## 🚀 vhAstro-Theme:一款基于 Astro 构建的优雅的响应式博客主题 -```sh -npm i pnpm -g +**「当极简主义遇上工程之美」** + +在线演示 ➡️ [https://www.vvhan.com](https://www.vvhan.com) +官方文档 ➡️ [vhAstro-Theme](https://www.vvhan.com/article/astro-theme-vhastro-theme) + +![Astro主题 vhAstro-Theme](https://i0.wp.com/uxiaohan.github.io/v2/2025/03/1740899552.webp) + +## ✨ 功能特性 + +- [x] 简洁的响应式设计 +- [x] 流畅的动画和页面过渡 +- [x] 两列布局 +- [x] 阅读时间 +- [x] 字数统计 +- [x] 代码块 +- [x] 语法高亮 +- [x] 图片懒加载 +- [x] 图片灯箱 +- [x] Twikoo 评论 +- [x] 本地搜索 +- [x] 标签 +- [x] 分类 +- [x] 归档 +- [x] 动态 +- [x] 关于 +- [x] 友情链接 +- [x] 推荐文章 +- [x] 谷歌广告 +- [x] 内置 404 页面 +- [x] Sitemap 支持 +- [x] RSS 支持 +- [x] 活跃的社区支持 +- [x] 广泛的现代框架兼容性 +- [x] 高效的性能优化 +- [x] 优秀的开发体验 + +## 🚀 使用方法 + +- 使用此模板生成新仓库或 Fork 此仓库 +- 进行本地开发,Clone 新的仓库,执行 `pnpm install` 以安装依赖 +- 若未安装 pnpm,执行 `npm install -g pnpm` +- 通过配置文件 `src/config.ts` 自定义博客 +- 执行 pnpm newpost '文章标题' 创建新文章,并在 src/content/posts/ 目录中编辑 +- 参考官方指南将博客部署至 Vercel, Netlify,Cloudflare Pages, GitHub Pages 等 +- 部署前需编辑 `astro.config.mjs` 中的站点设置。 + +## ⚙️ 文章格式 + +```md +--- +title: 标题 +categories: 分类 +tags: + - 标签1 + - 标签2 +id: 文章ID +date: 文章创建日期 +updated: 文章更新日期 +cover: "封面图URL (为空默认随机内置封面 /public/assets/images/banner)" +recommend: false # 是否推荐文章 +hide: false # 是否隐藏文章 +--- ``` -```sh +## 💻 命令 + +```bash # 安装依赖 -pnpm i -``` - -```sh -# 启动开发环境 +pnpm install +# 本地开发 pnpm dev -``` - -```sh -# 编译 +# 构建静态文件 pnpm build -``` - -> 🧑‍🚀 **Seasoned astronaut?** Delete this file. Have fun! - -![blog](https://github.com/withastro/astro/assets/2244813/ff10799f-a816-4703-b967-c78997e8323d) - -Features: - -- ✅ Minimal styling (make it your own!) -- ✅ 100/100 Lighthouse performance -- ✅ SEO-friendly with canonical URLs and OpenGraph data -- ✅ Sitemap support -- ✅ RSS Feed support -- ✅ Markdown & MDX support - -## 🚀 Project Structure - -Inside of your Astro project, you'll see the following folders and files: - -```text -├── public/ -├── src/ -│   ├── components/ -│   ├── content/ -│   ├── layouts/ -│   └── pages/ -├── astro.config.mjs -├── README.md -├── package.json -└── tsconfig.json -``` - -Astro looks for `.astro` or `.md` files in the `src/pages/` directory. Each page is exposed as a route based on its file name. - -There's nothing special about `src/components/`, but that's where we like to put any Astro/React/Vue/Svelte/Preact components. - -The `src/content/` directory contains "collections" of related Markdown and MDX documents. Use `getCollection()` to retrieve posts from `src/content/blog/`, and type-check your frontmatter using an optional schema. See [Astro's Content Collections docs](https://docs.astro.build/en/guides/content-collections/) to learn more. - -Any static assets, like images, can be placed in the `public/` directory. - -## 🧞 Commands - -All commands are run from the root of the project, from a terminal: - -| Command | Action | -| :------------------------ | :----------------------------------------------- | -| `npm install` | Installs dependencies | -| `npm run dev` | Starts local dev server at `localhost:4321` | -| `npm run build` | Build your production site to `./dist/` | -| `npm run preview` | Preview your build locally, before deploying | -| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` | -| `npm run astro -- --help` | Get help using the Astro CLI | - -## 👀 Want to learn more? - -Check out [our documentation](https://docs.astro.build) or jump into our [Discord server](https://astro.build/chat). - -## Credit - -This theme is based off of the lovely [Bear Blog](https://github.com/HermanMartinus/bearblog/). +# 创建新文章 +pnpm newpost '文章标题' +``` \ No newline at end of file diff --git a/astro.config.mjs b/astro.config.mjs index 4bdc23f..9a95b5c 100644 --- a/astro.config.mjs +++ b/astro.config.mjs @@ -4,17 +4,32 @@ import sitemap from '@astrojs/sitemap'; import { defineConfig } from 'astro/config'; import remarkDirective from "remark-directive"; /* Handle directives */ import { remarkNote, addClassNames } from './src/plugins/markdown.formate' - +import swup from '@swup/astro'; // https://astro.build/config export default defineConfig({ site: 'https://www.vvhan.com', - integrations: [mdx(), sitemap({ - changefreq: 'weekly', - priority: 0.7, - lastmod: new Date(), - // 处理末尾带 / 的 url - serialize: (item) => ({ ...item, url: item.url.endsWith('/') ? item.url.slice(0, -1) : item.url }) - })], + integrations: [ + swup({ + theme: false, + animationClass: "vh-animation-", + containers: [".vh-animation"], + smoothScrolling: true, + progress: true, + cache: true, + preload: true, + accessibility: true, + updateHead: true, + updateBodyClass: false, + globalInstance: true + }), + sitemap({ + changefreq: 'weekly', + priority: 0.7, + lastmod: new Date(), + // 处理末尾带 / 的 url + serialize: (item) => ({ ...item, url: item.url.endsWith('/') ? item.url.slice(0, -1) : item.url }) + }), + mdx()], markdown: { rehypePlugins: [addClassNames], remarkPlugins: [remarkDirective, remarkNote], diff --git a/package.json b/package.json index 470d0a0..7929ce1 100644 --- a/package.json +++ b/package.json @@ -10,16 +10,18 @@ "newpost": "node ./script/newpost.js" }, "dependencies": { - "@astrojs/mdx": "^4.0.8", + "@astrojs/mdx": "^4.1.0", "@astrojs/rss": "^4.0.11", "@astrojs/sitemap": "^3.2.1", - "astro": "^5.3.0", + "@swup/astro": "^1.5.0", + "astro": "^5.4.1", "dayjs": "^1.11.13", "dplayer": "^1.27.1", "hls.js": "^1.5.20", - "nprogress": "^0.2.0", - "overlayscrollbars": "^2.11.0", - "remark-directive": "^3.0.1", + "mdast-util-to-string": "^4.0.0", + "overlayscrollbars": "^2.11.1", + "reading-time": "^1.5.0", + "remark-directive": "^4.0.0", "twikoo": "1.6.41", "unist-util-visit": "^5.0.0", "vanilla-lazyload": "^19.1.3", @@ -34,7 +36,8 @@ "pnpm": { "onlyBuiltDependencies": [ "esbuild", - "sharp" + "sharp", + "swup" ] } } \ No newline at end of file diff --git a/script/newpost.js b/script/newpost.js index cdbfea8..919f8b4 100644 --- a/script/newpost.js +++ b/script/newpost.js @@ -1,4 +1,3 @@ - import path from 'path'; import dayjs from 'dayjs'; import crypto from 'crypto'; @@ -8,13 +7,13 @@ const __filename = fileURLToPath(import.meta.url); const __dirname = path.dirname(__filename); // 获取命令行参数 const articleName = process.argv.slice(2).join(''); -const articleID = crypto.createHash('md5').update(String(dayjs().valueOf())).digest('hex'); +const articleID = crypto.createHash('sha256').update(dayjs().valueOf().toString()).digest('hex').slice(0, 16); if (!articleName) { console.error('请提供文章名称,例如:pnpm newpost "第一篇文章"'); process.exit(1); } const ArticleContent = `--- -title: ${articleName} +title: "${articleName.replace(/"/g, '\\"')}" categories: 分类 tags: - 标签 @@ -34,8 +33,22 @@ const init = async () => { // 写文件 const now = dayjs(); const targetDir = path.join(__dirname, '../src/content/blog', `${now.year()}/${now.format('MM')}`); - await fs.mkdir(path.dirname(targetDir), { recursive: true }); - await fs.writeFile(path.join(targetDir, `${articleName}.md`), ArticleContent, 'utf8'); - console.log(`文章 ${articleName} 已创建`); + try { + await fs.mkdir(targetDir, { recursive: true }); + await fs.writeFile(path.join(targetDir, `${articleName}.md`), ArticleContent, 'utf8'); + const filePath = path.join(targetDir, `${articleName}.md`); + await fs.writeFile(path.join(targetDir, `${articleName}.md`), ArticleContent, 'utf8'); + // 友好输出 + console.log('✅ 文章创建成功'); + console.log(`📅 日期:${now.format('YYYY-MM-DD')}`); + console.log(`📂 路径:${filePath}`); + console.log(`🆔 ID:${articleID.slice(0, 16)} (可手动修改)`); + } catch (error) { + // 增强错误处理 + console.error('❌ 创建失败:'); + console.error(`错误类型:${error.code || 'UNKNOWN_ERROR'}`); + console.error(`详细信息:${error.message}`); + process.exit(1); + } } init(); \ No newline at end of file diff --git a/src/components/Archive.astro b/src/components/Archive.astro index 1283c9f..4a9738d 100644 --- a/src/components/Archive.astro +++ b/src/components/Archive.astro @@ -5,7 +5,7 @@ const { articleList } = Astro.props; import "../styles/Archive.less"; --- -
+
{ articleList.map((i: any) => ( @@ -13,7 +13,7 @@ import "../styles/Archive.less";

{i.name} - {i.data.length} total + {i.data.length}篇文章

{i.data.map((_: any) => ( diff --git a/src/components/ArticleCard.astro b/src/components/ArticleCard.astro index e2f6efc..2cb3dcc 100644 --- a/src/components/ArticleCard.astro +++ b/src/components/ArticleCard.astro @@ -11,7 +11,7 @@ const ARTICLE_COVER: string = await getCover(post.data.cover); import "../styles/components/ArticleCard.less"; --- -
+
{post.data.title}
diff --git a/src/components/Aside.astro b/src/components/Aside.astro index 1107ff7..4f4e068 100644 --- a/src/components/Aside.astro +++ b/src/components/Aside.astro @@ -1,8 +1,11 @@ --- +// 静态图片 +import { Image } from "astro:assets"; +// 时间处理 +import { fmtTime } from "../utils/index"; // 获取用户配置数据 import SITE_CONFIG from "../config"; -import { fmtTime } from "../utils/index"; -const { Avatar, Author, Motto, WebSites } = SITE_CONFIG; +const { Avatar, Author, Motto, WebSites, GoogleAds } = SITE_CONFIG; // 获取文章数据 import { getCategories, getTags, getRecommendArticles } from "../utils/getPostInfo"; // 分类列表 @@ -11,8 +14,8 @@ const categories = getCategories(); const tags = getTags(); // 最新文章 const recommendArticles = getRecommendArticles(); -// 静态图片 -import { Image } from "astro:assets"; +// Google 广告组件 +import GoogleAd from "../components/GoogleAd.astro"; // 侧边栏样式 import "../styles/components/Aside.less"; --- @@ -20,10 +23,7 @@ import "../styles/components/Aside.less"; diff --git a/src/components/BackTop.astro b/src/components/BackTop.astro index f9e6b4a..6314ca5 100644 --- a/src/components/BackTop.astro +++ b/src/components/BackTop.astro @@ -14,10 +14,4 @@ import "../styles/components/BackTop.less"; -
- +
\ No newline at end of file diff --git a/src/components/Comment.astro b/src/components/Comment.astro index da5fb38..148541b 100644 --- a/src/components/Comment.astro +++ b/src/components/Comment.astro @@ -3,16 +3,3 @@ import "../styles/components/Comment.less"; ---
- diff --git a/src/components/Footer.astro b/src/components/Footer.astro index 29cd8ab..ec4c53b 100644 --- a/src/components/Footer.astro +++ b/src/components/Footer.astro @@ -11,15 +11,3 @@ import "../styles/Footer.less";

AstrovhAstro-Themesitemaprssicp

- diff --git a/src/components/GoogleAd.astro b/src/components/GoogleAd.astro new file mode 100644 index 0000000..376f46a --- /dev/null +++ b/src/components/GoogleAd.astro @@ -0,0 +1,5 @@ +--- +const { slotID, className } = Astro.props; +--- + +
diff --git a/src/components/Header.astro b/src/components/Header.astro index 5ad9638..89235a3 100644 --- a/src/components/Header.astro +++ b/src/components/Header.astro @@ -1,6 +1,4 @@ --- -// 导航高亮 -const { activeNav } = Astro.props; import SITE_CONFIG from "../config"; const { Navs } = SITE_CONFIG; // 原生图片 @@ -17,10 +15,10 @@ import "../styles/components/Header.less"; Home -