Skip to content
 
📑标签
🏷vite 🏷web 🏷gpt

🗒初墨

🍊Hello,各位好,我是面包!

以为建站只能复制模板?这篇指南让你用Vitepress+GPT组合技,从零搓出会聊天的智能博客!内含防秃指南、代码冷知识,以及如何把ChatGPT调教成你的24小时编程陪练 (◕ᴗ◕✿)

前置条件

环境依赖
  • node.js 构建工程需要
  • vscode 文本编辑器-修改代码
  • git 部署到github page上

Vitepress从零出发

安装Vitepress

首先创建你的博客空文件夹vitepress[你的博客名称]

sh
mkdir vitepress

进入此文件夹

sh
cd vitepress

然后安装vitepress

sh
pnpm add -D vitepress

vitepress初始化

sh
pnpm vitepress init

安装vue库

sh
pnpm add -D vue

本地启动静态网站

sh
pnpm run docs:dev

本地构建网站

sh
pnpm run docs:build
git小技巧

改变github上传仓库的位置太麻烦,可以直接将先前仓库的.git文件夹直接复制到新文件夹里面就可以了

前置依赖

sh
npm|pnpm|yarn

检查安装命令:

sh
npm -v

安装Vitepress

sh
npm add -D vitepress

初始化

sh
npx vitepress init

本地启动静态网站

sh
run docs:dev

本地启动静态网站

sh
run docs:build

小纸条

  1. npm install是用来安装项目依赖的命令。当你克隆一个使用npm管理依赖的项目时,或者想为你的项目添加新的依赖时,你通常需要运行这个命令。这个命令会自动解析项目的package.json文件,安装所有需要的依赖包。安装后的依赖包会被放在项目根目录下的node_modules文件夹中。
  2. npm run dev是一个用于启动开发环境的命令。这个命令通常会运行一些脚本,这些脚本会启动项目的开发服务器,并可能还会运行一些其他的开发相关的任务,比如热更新代码、启动测试服务器等。在开发模式下,由于node会在后台做动态资源转发操作,所以一般不会产生跨域问题。
  3. npm run build是一个用于构建生产环境的命令。这个命令通常会运行一些脚本,这些脚本会打包你的项目,将所有的代码、资源文件压缩合并,然后输出到一个指定的目录中,这个目录通常是用于部署生产的。在生产环境下,由于没有node的动态资源转发操作,如果前后端分离项目中前端和后端的地址不同源,就会产生跨域问题。

指定文档目录

config.mts指定文档目录为docs

ts
export default defineConfigWithTheme({
  srcDir: "docs",
})

代码块常见编程语言

在 Markdown 或代码块语法中,语言名称用于指定代码的编程语言或格式,以便进行语法高亮。以下是常见的语言名称示例:


常见编程语言

语言名称用途示例代码块标记
pythonPython 代码```python
javascriptJavaScript 代码```javascript
javaJava 代码```java
cC 语言代码```c
cppC++ 代码```cpp
csharpC# 代码```csharp
swiftSwift 代码```swift
rubyRuby 代码```ruby
phpPHP 代码```php

脚本与标记语言

语言名称用途示例代码块标记
htmlHTML 标记```html
cssCSS 样式```css
xmlXML 数据```xml
markdownMarkdown 文本```markdown
jsonJSON 数据```json
yamlYAML 配置```yaml

数据与查询语言

语言名称用途示例代码块标记
sqlSQL 查询```sql
graphqlGraphQL 查询```graphql
mongodbMongoDB 查询```mongodb

命令行与配置

语言名称用途示例代码块标记
bashBash 命令行脚本```bash
shellShell 命令```shell
dockerfileDockerfile 配置```dockerfile
nginxNginx 配置```nginx

其他格式

语言名称用途示例代码块标记
plaintext无语法高亮的纯文本```plaintext
diff差异对比文件```diff
latexLaTeX 公式```latex

注意事项

  1. 大小写不敏感:大多数工具支持 pythonPython
  2. 工具兼容性:不同平台(如 GitHub、VS Code)支持的语言名称可能略有差异。
  3. 自定义别名:部分工具允许使用别名,例如:
    • jsjavascript
    • pypython
    • ymlyaml

如果需要完整的支持列表,可以参考具体工具的文档(如 Prism.js 支持的语言)。

为博客增加鼠标点击特效-烟花

新建一个./theme/components/confetti.vue文件

TIP

组件代码
vue
<script setup lang="ts">
import { onMounted, onUnmounted } from 'vue';
import confetti from 'canvas-confetti';

// 定义触发烟花效果的函数
const triggerFireworks = (event: MouseEvent) => {
  const x = event.clientX / window.innerWidth; // 鼠标点击的相对 X 坐标
  const y = event.clientY / window.innerHeight; // 鼠标点击的相对 Y 坐标

  // 配置烟花效果
  confetti({
    particleCount: 150, // 粒子数量,增加数量以增强效果
    startVelocity: 5, // 初始速度,降低速度
    spread: 360, // 扩散角度,360 度表示全方位扩散
    origin: { x, y }, // 粒子的起始位置
    gravity: 0.2, // 重力值,使粒子更轻盈
    scalar: 0.8, // 粒子大小
    ticks: 200, // 动画持续时间(帧数)
    shapes: ["circle", "square", "star"], // 粒子形状
    colors: ["#ff00ff", "#00ffff", "#ffff00", "#ff0000", "#00ff00", "#0000ff"], // 粒子颜色
    drift: 0, // 粒子的水平漂移量
    decay: 0.94, // 粒子速度衰减
  });


  // 添加上升的粒子效果
  confetti({
    particleCount: 30,
    startVelocity: 10,
    spread: 360,
    origin: { x, y },
    gravity: -0.2, // 负值使粒子向上飘动
    scalar: 0.6,
    ticks: 120,
    shapes: ["square"],
    colors: ["#ff0000", "#00ff00", "#0000ff"],
  });
};

// 挂载时绑定全局点击事件
onMounted(() => {
  document.addEventListener("click", triggerFireworks);
});

// 组件销毁时移除事件监听
onUnmounted(() => {
  document.removeEventListener("click", triggerFireworks);
});
</script>

:::

然后在index.ts中添加全局定义

Details
ts
import { h } from 'vue'
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import './style.css'
import confetti from "./components/confetti.vue"

export default {
  extends: DefaultTheme,
  Layout: () => {
    return h(DefaultTheme.Layout, null, {
      // https://vitepress.dev/guide/extending-default-theme#layout-slots
    })
  },
  async enhanceApp({ app, router, siteData }) {
      // 注册全局组件transparent
      app.component('confetti' , confetti),
  }
} satisfies Theme

最后在md中调用即可

Details
md
<!-- 爆炸效果 -->
<confetti />

Vitepress插入live2d人物,为你的网页添加一个看板娘

md
.
 docs
 ├─ .vitepress                        ->VitePress的配置目录
 │  └─ config.mts                     ->定义网站的全局配置
 │  └─ theme                          ->自定义主题
 │     └─ index.mts 或者 index.ts     ->定义主题的样式、布局和功能
 ├─ docs                              ->存放文档内容的主目录
 │  ├─ index.md                       ->文档网站的首页文件
 │  └─ public                         ->存放静态资源的目录
 └─ node_modules                      ->Node.js项目中依赖模块的存储目录

在你的VitePress项目中安装oh-my-live2d

sh
npm install oh-my-live2d@latest

然后在.vitepress/theme/index.ts文件中添加以下代码

js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme';

export default {
  ...DefaultTheme,
  async enhanceApp() {
    if (!import.meta.env.SSR) {
      const { loadOml2d } = await import('oh-my-live2d');
      loadOml2d({
        models: [
          {
            path: 'https://cdn.jsdelivr.net/gh/Eikanya/Live2d-model/Live2D/Senko_Normals/senko.model3.json'
          }
        ]
      });
    }
  }
};

path路径中填写你的模型文件.model.json|.model3.json

loadOml2d参数解析

mobileDisplay:移动端人物展示开关(true|false)

models: {

path:本地|在线模型地址

position:人物位置

scale:人物缩放大小

stageStyle:舞台范围(width宽度height高度)

}

ts
loadOml2d({
  mobileDisplay: true,
  models: [
    {
      "path": ['/ariu/ariu.model3.json',],
      "position": [0, 60],
      "scale": 0.08,
      "stageStyle": {
      "height": 500
      }
    },
    {
      "path": ['/豌豆射手/豌豆射手.model3.json',],
      "position": [0, 60],
      "scale": 0.16,
      "stageStyle": {
      "height": 400
      }
    }
  ]
});

小纸条

本地模型文件要放在public文件夹下,支持多级搜索

小纸条

如果出现这个报错可不必理会,正常build就行。

live2d人物来源

以下列出此网站的live2d人物来源

【免费L2D模型】可盐可甜的机能风少女!无料模型大公开~点击领取-哔哩哔哩

【免费模型】这么可爱的小狗免费带回家!-哔哩哔哩

【Live2D免费模型】别让僵尸吃了你的脑子!-哔哩哔哩

【live2d免费模型】⚡️小黑子:过来吧我的辛苦奴隶⚡️-哔哩哔哩

【live2d免费模型】米西米西,花不拉几-哔哩哔哩

网上开源的live2d人物模型库

[人物模型库]-(https://github.com/oh-my-live2d/live2d-models)

[狐狸]-(https://model.oml2d.com/Senko_Normals/senko.model3.json)

[小恶魔]-(https://model.oml2d.com/Pio/model.json)

[学生]-(https://model.oml2d.com/shizuku/shizuku.model.json)

[上班族]-(https://model.oml2d.com/shizuku_pajama/index.json)

[女王]-(https://model.oml2d.com/HK416-1-normal/model.json)

[黑猫]-(https://model.oml2d.com/cat-black/model.json)

创建你的专属空间

在你的./theme/components目录中创建PasswordCheck.vue文件

PasswordCheck.vue
vue
<template>
    <div v-if="!isLocked" class="password-protected">
      <!-- 密码框和解锁按钮 -->
      <div class="unlock-section">
        <input
          type="password"
          v-model="password"
          placeholder="请输入密码"
          class="password-input"
        />
        <button @click="checkPassword" class="check-button">✔️</button>
      </div>
  
      <!-- 提示信息 -->
      <div v-if="showHint" class="hint-message" :class="{ fading: hintFading }">
        前面的区域以后再来探索吧
      </div>
  
      <!-- 文档内容 -->
      <transition name="fade">
        <div v-if="isPasswordCorrect" class="document-content">
          <!-- 这里插入你的 Markdown 内容或其他组件 -->
          <slot></slot>
        </div>
      </transition>
    </div>
  </template>
  
  <script>
  export default {
    data() {
      return {
        password: '',
        isPasswordCorrect: false,
        isLocked: false,
        attempts: 0,
        showHint: false,
        hintFading: false,
      };
    },
    methods: {
      checkPassword() {
        const correctPassword = '123'; // 改成你自己的密码
        if (this.password === correctPassword) {
          this.isPasswordCorrect = true;
        } else {
          this.attempts += 1;
          alert('密码错误,请重试。');
          if (this.attempts >= 1) {
            this.showHint = true; // 显示提示信息
            setTimeout(() => {
              this.hintFading = true; // 开始渐隐
              setTimeout(() => {
                this.startDissolveAnimation(); // 开始分解消散动画
              }, 2000); // 提示信息显示2秒后开始分解消散
            }, 500); // 延迟0.5秒后开始渐隐
          }
        }
      },
      startDissolveAnimation() {
        const dissolveElement = document.querySelector('.password-protected');
        dissolveElement.style.animation = 'dissolve 2s forwards';
        setTimeout(() => {
          this.isLocked = true; // 动画结束后锁定大框
        }, 2000); // 确保动画完成后再设置 isLocked
      },
    },
  };
  </script>
  
  <style scoped>
  .password-protected {
    width: 100%; /* 框宽度与页面相同 */
    margin: 2em auto;
    padding: 1em;
    border: 1px solid #ccc;
    border-radius: 20px;
    box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
    background: linear-gradient(135deg, #ff7e5f, #feb47b); /* 渐变背景 */
    color: white;
    text-align: left; /* 修改为向左对齐 */
    position: relative;
    overflow: hidden;
    transition: opacity 2s ease-out, transform 0.5s ease-out; /* 渐隐和上浮过渡 */
    transform: translateY(0); /* 初始位置 */
  }
  
  @keyframes dissolve {
    0% {
      opacity: 1;
      background: linear-gradient(135deg, #ff7e5f, #feb47b);
    }
    100% {
      opacity: 0;
      background: linear-gradient(135deg, rgba(255, 126, 95, 0), rgba(251, 180, 123, 0));
    }
  }
  
  .password-protected:hover {
    transform: translateY(-10px); /* 鼠标悬停时上浮 */
  }
  
  .unlock-section {
    display: flex; /* 使用 flex 布局 */
    align-items: center; /* 垂直居中 */
    justify-content: flex-start; /* 水平起始对齐 */
  }
  
  .password-input {
    width: calc(100% - 60px); /* 为按钮留出空间 */
    padding: 10px;
    margin-right: 10px; /* 与按钮的间距 */
    border: 1px solid #ccc;
    border-radius: 10px;
    background-color: rgba(255, 255, 255, 0.8); /* 输入框半透明 */
    color: #333;
  }
  
  .check-button {
    width: 40px; /* 设置按钮宽度 */
    height: 40px; /* 设置按钮高度 */
    padding: 0;
    background-color: #05c10f;
    color: white;
    border: none;
    border-radius: 10px; /* 圆角矩形 */
    cursor: pointer;
    transition: background-color 0.3s, transform 0.3s;
    display: flex;
    align-items: center;
    justify-content: center;
    font-size: 1.5em; /* 调整对号大小 */
  }
  
  .check-button:hover {
    background-color: #369f7e;
    transform: scale(1.05); /* 鼠标悬停时轻微放大 */
  }
  
  .document-content {
    margin-top: 2em;
    padding: 1em;
    border: 1px solid #ccc;
    border-radius: 10px;
    background-color: rgba(255, 255, 255, 0.8); /* 内容框半透明 */
    color: #333;
    transition: opacity 0.5s;
    text-align: left; /* 修改为向左对齐 */
  }
  
  .hint-message {
    margin-top: 1em;
    padding: 1em;
    background-color: rgba(255, 255, 255, 0.8); /* 提示框半透明 */
    border: 1px solid #ccc;
    border-radius: 10px;
    text-align: left; /* 修改为向左对齐 */
    transition: opacity 2s ease-out, filter 2s ease-out;
    filter: blur(0); /* 初始无模糊 */
  }
  
  .hint-message.fading {
    opacity: 0;
    filter: blur(5px); /* 渐隐时模糊 */
  }
  
  .fade-enter-active,
  .fade-leave-active {
    transition: opacity 0.5s;
  }
  
  .fade-enter,
  .fade-leave-to {
    opacity: 0;
  }
  </style>

然后,在index.ts中注册全局组件

ts
/* .vitepress/theme/index.ts */
import DefaultTheme from 'vitepress/theme'
import Password from "./components/PasswordCheck.vue"

export default {
  extends: DefaultTheme,
  enhanceApp({app}) { 
    // 注册全局组件
    app.component('Password' , Password)
  }
}

在你想加密的文档中添加这段代码

md
<Password>
markdown写作内容
</Password>

自动获取网站图标

如何使用 Favicon.im 获取图标 使用 Favicon.im 非常简单,只需在网址后加上目标网站的域名即可获取该网站的 favicon 图标。

weibo.com favicon 这段代码将获取 Weibo 的 favicon 图标,并将其显示在页面中。对于需要批量获取网站图标的开发者,Favicon.im 提供了一种高效的解决方案。

利用deepseek为你的博客锦上添花

prompt:

md

写一篇关于{}的技术博客
语言风格为严谨的专业性描述中加一点有趣的解释
公式格式为latex
frontmatter格式为
---
title: 标题
description: 简述
tags: 
  - 标签(可以叠加)
---
通俗解释,使用有趣但不失严谨的比喻

📖FAQS

代码块怎么默认显示行号?

在comfig.mts文件中添加lineNumbers:true,

ts

export default defineConfigWithTheme({
  markdown: {
    lineNumbers:true,
  }
})
为什么我的Vitepress无法加载图床外链?

config.mtsexport default defineConfigWithTheme中添加以下代码

ts

export default defineConfigWithTheme({

  head: [
      /* 解决了Vitepress无法加载图床链接的问题 */
      [
        "meta",
        {
          name:"referrer",
          content:"no-referrer"
        }
      ],
    ],

})
为什么我的Katex总是重复渲染?

没有引入Katex的css文件,同时引入的css文件要对应版本,插件的github页面上有说明

ts

export default defineConfigWithTheme({
  head: [
    ['link', { rel: 'stylesheet', href: 'https://cdnjs.cloudflare.com/ajax/libs/KaTeX/0.5.1/katex.min.css' }],
  ],
  markdown: {
    config: (md) => {
      md.use(markdownItKatex),
    },  
  },
  vue: {
    template: {
      compilerOptions: {
        isCustomElement: (tag) => customElements.includes(tag)
      }
    }
  }
})
Frontmatter是什么?

Frontmatter是md文件中最上方使用两个“---”框起来的YAML数据

md
---
title: 🥯从零开始的Vitepress博客网站搭建?
description: 使用Vitepress搭建个人博客时,需要归档和标签,利用createContentLoader进行生成
layout: doc
tags: 
  - vitepress
  - 前端
  - 闲谈
created: '2024-05-07'
updated: '2024-05-18'
---

在原页面中引用

js
显示文本内容{{ $frontmatter.title }}

在其他页面中引用

js
import { useData } from 'vitepress'
const { frontmatter, page } = useData()

显示文本内容{{ this.$frontmatter.title }}

能用来干嘛?

  1. 设计标签页
  2. 更新时间记录
  3. 全局组件信息输入

📕文渊阁

Playlist
Total 4
  • 星茶会
    灰澈
  • song1
    author1
  • soewrewfg1
    author1
  • PIKASONIC - Blossom
    author1