feat: optimize blog build and deployment
This commit is contained in:
@@ -1,5 +1,13 @@
|
|||||||
node_modules
|
node_modules
|
||||||
dist
|
dist
|
||||||
src/.vuepress/dist
|
src/.vuepress/dist
|
||||||
|
src/.vuepress/.cache
|
||||||
|
src/.vuepress/.temp
|
||||||
|
.cache
|
||||||
|
.temp
|
||||||
|
.npm
|
||||||
|
.env
|
||||||
.git
|
.git
|
||||||
|
.gitignore
|
||||||
*.log
|
*.log
|
||||||
|
coverage
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
ENCRYPT_PASSWORD=local-dev-password
|
||||||
@@ -3,7 +3,6 @@ node_modules/
|
|||||||
npm-debug.log*
|
npm-debug.log*
|
||||||
yarn-debug.log*
|
yarn-debug.log*
|
||||||
yarn-error.log*
|
yarn-error.log*
|
||||||
package-lock.json
|
|
||||||
|
|
||||||
# VuePress
|
# VuePress
|
||||||
src/.vuepress/.cache/
|
src/.vuepress/.cache/
|
||||||
|
|||||||
@@ -0,0 +1,7 @@
|
|||||||
|
node_modules
|
||||||
|
src/.vuepress/.cache
|
||||||
|
src/.vuepress/.temp
|
||||||
|
src/.vuepress/dist
|
||||||
|
package-lock.json
|
||||||
|
*.md
|
||||||
|
src/**/*.md
|
||||||
+16
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"printWidth": 100,
|
||||||
|
"tabWidth": 2,
|
||||||
|
"useTabs": false,
|
||||||
|
"semi": true,
|
||||||
|
"singleQuote": true,
|
||||||
|
"trailingComma": "all",
|
||||||
|
"overrides": [
|
||||||
|
{
|
||||||
|
"files": "*.md",
|
||||||
|
"options": {
|
||||||
|
"proseWrap": "preserve"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
+9
-2
@@ -2,12 +2,19 @@ FROM node:20-alpine AS build
|
|||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
ARG ENCRYPT_PASSWORD
|
||||||
|
ENV ENCRYPT_PASSWORD=$ENCRYPT_PASSWORD
|
||||||
|
|
||||||
COPY package.json package-lock.json ./
|
COPY package.json package-lock.json ./
|
||||||
RUN npm ci
|
RUN --mount=type=cache,target=/root/.npm npm install --include=optional
|
||||||
|
|
||||||
COPY . .
|
COPY . .
|
||||||
RUN npm run docs:build
|
RUN npm run docs:build
|
||||||
|
|
||||||
FROM nginx:1.25-alpine
|
FROM nginx:1.27-alpine
|
||||||
|
|
||||||
COPY --from=build /app/src/.vuepress/dist /usr/share/nginx/html
|
COPY --from=build /app/src/.vuepress/dist /usr/share/nginx/html
|
||||||
|
COPY nginx.conf /etc/nginx/conf.d/default.conf
|
||||||
|
|
||||||
|
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
|
||||||
|
CMD wget -qO- http://127.0.0.1/ >/dev/null 2>&1 || exit 1
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
.PHONY: up down
|
.PHONY: up down ensure-env
|
||||||
|
|
||||||
up:
|
ensure-env:
|
||||||
docker compose up -d --build
|
@if [ ! -f .env ]; then \
|
||||||
|
cp .env.example .env; \
|
||||||
|
echo "Created .env from .env.example. Edit ENCRYPT_PASSWORD in .env for deployment."; \
|
||||||
|
fi
|
||||||
|
|
||||||
|
up: ensure-env
|
||||||
|
docker compose --env-file .env up -d --build
|
||||||
|
|
||||||
down:
|
down:
|
||||||
docker compose down
|
docker compose --env-file .env down
|
||||||
|
|||||||
@@ -3,6 +3,34 @@ services:
|
|||||||
image: myblog:latest
|
image: myblog:latest
|
||||||
build:
|
build:
|
||||||
context: .
|
context: .
|
||||||
|
args:
|
||||||
|
ENCRYPT_PASSWORD: ${ENCRYPT_PASSWORD:?Set ENCRYPT_PASSWORD in .env or shell before building}
|
||||||
|
environment:
|
||||||
|
ENCRYPT_PASSWORD: ${ENCRYPT_PASSWORD:?Set ENCRYPT_PASSWORD in .env or shell before starting}
|
||||||
ports:
|
ports:
|
||||||
- '51888:80'
|
- '51888:80'
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
healthcheck:
|
||||||
|
test: ['CMD', 'wget', '-qO-', 'http://127.0.0.1/']
|
||||||
|
interval: 30s
|
||||||
|
timeout: 3s
|
||||||
|
retries: 3
|
||||||
|
start_period: 10s
|
||||||
|
logging:
|
||||||
|
driver: json-file
|
||||||
|
options:
|
||||||
|
max-size: '10m'
|
||||||
|
max-file: '3'
|
||||||
|
deploy:
|
||||||
|
resources:
|
||||||
|
limits:
|
||||||
|
cpus: '1.00'
|
||||||
|
memory: 256M
|
||||||
|
reservations:
|
||||||
|
memory: 64M
|
||||||
|
networks:
|
||||||
|
- myblog-net
|
||||||
|
|
||||||
|
networks:
|
||||||
|
myblog-net:
|
||||||
|
driver: bridge
|
||||||
|
|||||||
@@ -0,0 +1,46 @@
|
|||||||
|
import js from '@eslint/js';
|
||||||
|
import vue from 'eslint-plugin-vue';
|
||||||
|
import tseslint from 'typescript-eslint';
|
||||||
|
|
||||||
|
export default [
|
||||||
|
{
|
||||||
|
ignores: [
|
||||||
|
'node_modules/**',
|
||||||
|
'src/.vuepress/.cache/**',
|
||||||
|
'src/.vuepress/.temp/**',
|
||||||
|
'src/.vuepress/dist/**',
|
||||||
|
],
|
||||||
|
},
|
||||||
|
js.configs.recommended,
|
||||||
|
...tseslint.configs.recommended,
|
||||||
|
...vue.configs['flat/recommended'],
|
||||||
|
{
|
||||||
|
files: ['**/*.{ts,vue}'],
|
||||||
|
languageOptions: {
|
||||||
|
globals: {
|
||||||
|
clearTimeout: 'readonly',
|
||||||
|
console: 'readonly',
|
||||||
|
document: 'readonly',
|
||||||
|
fetch: 'readonly',
|
||||||
|
setTimeout: 'readonly',
|
||||||
|
window: 'readonly',
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
parser: tseslint.parser,
|
||||||
|
extraFileExtensions: ['.vue'],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
rules: {
|
||||||
|
'vue/multi-word-component-names': 'off',
|
||||||
|
'vue/html-indent': ['error', 2],
|
||||||
|
'vue/max-attributes-per-line': 'off',
|
||||||
|
'vue/singleline-html-element-content-newline': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['src/.vuepress/**/*.ts'],
|
||||||
|
rules: {
|
||||||
|
'no-console': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
+45
@@ -0,0 +1,45 @@
|
|||||||
|
server {
|
||||||
|
listen 80;
|
||||||
|
server_name _;
|
||||||
|
|
||||||
|
root /usr/share/nginx/html;
|
||||||
|
index index.html;
|
||||||
|
|
||||||
|
gzip on;
|
||||||
|
gzip_vary on;
|
||||||
|
gzip_min_length 1024;
|
||||||
|
gzip_types
|
||||||
|
application/javascript
|
||||||
|
application/json
|
||||||
|
application/xml
|
||||||
|
image/svg+xml
|
||||||
|
text/css
|
||||||
|
text/plain
|
||||||
|
text/xml;
|
||||||
|
|
||||||
|
location ~* \.(?:css|js|mjs|woff2?|ttf|otf|eot|ico|png|jpg|jpeg|gif|webp|avif|svg)$ {
|
||||||
|
try_files $uri =404;
|
||||||
|
access_log off;
|
||||||
|
add_header Cache-Control "public, max-age=31536000, immutable";
|
||||||
|
}
|
||||||
|
|
||||||
|
location ~* \.html$ {
|
||||||
|
try_files $uri =404;
|
||||||
|
add_header Cache-Control "no-cache";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /robots.txt {
|
||||||
|
try_files $uri =404;
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
}
|
||||||
|
|
||||||
|
location = /sitemap.xml {
|
||||||
|
try_files $uri =404;
|
||||||
|
add_header Cache-Control "public, max-age=3600";
|
||||||
|
}
|
||||||
|
|
||||||
|
location / {
|
||||||
|
try_files $uri $uri/ /index.html;
|
||||||
|
add_header Cache-Control "no-cache";
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+9211
File diff suppressed because it is too large
Load Diff
+14
-6
@@ -9,15 +9,23 @@
|
|||||||
"docs:clean-dev": "vuepress-vite dev src --clean-cache",
|
"docs:clean-dev": "vuepress-vite dev src --clean-cache",
|
||||||
"docs:dev": "vuepress-vite dev src",
|
"docs:dev": "vuepress-vite dev src",
|
||||||
"docs:update-package": "npx vp-update",
|
"docs:update-package": "npx vp-update",
|
||||||
|
"format": "prettier \"*.{js,json,yml}\" \"src/.vuepress/**/*.{ts,vue,scss}\" --write",
|
||||||
|
"format:check": "prettier \"*.{js,json,yml}\" \"src/.vuepress/**/*.{ts,vue,scss}\" --check",
|
||||||
|
"lint": "eslint \"src/.vuepress/**/*.{ts,vue}\" eslint.config.js",
|
||||||
"update:browsers": "npx update-browserslist-db@latest"
|
"update:browsers": "npx update-browserslist-db@latest"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@vuepress/bundler-vite": "2.0.0-rc.22",
|
"@eslint/js": "^9.39.1",
|
||||||
"@vuepress/plugin-git": "2.0.0-rc.99",
|
"@vuepress/bundler-vite": "^2.0.0-rc.28",
|
||||||
"@vuepress/plugin-search": "2.0.0-rc.99",
|
"@vuepress/plugin-git": "^2.0.0-rc.128",
|
||||||
"sass-embedded": "^1.87.0",
|
"@vuepress/plugin-search": "^2.0.0-rc.128",
|
||||||
|
"eslint": "^9.39.1",
|
||||||
|
"eslint-plugin-vue": "^10.6.1",
|
||||||
|
"prettier": "^3.6.2",
|
||||||
|
"sass-embedded": "^1.99.0",
|
||||||
|
"typescript-eslint": "^8.46.4",
|
||||||
"vue": "^3.5.13",
|
"vue": "^3.5.13",
|
||||||
"vuepress": "2.0.0-rc.22",
|
"vuepress": "^2.0.0-rc.28",
|
||||||
"vuepress-theme-hope": "2.0.0-rc.85"
|
"vuepress-theme-hope": "^2.0.0-rc.106"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,12 +1,148 @@
|
|||||||
<script setup lang="ts">
|
<script setup lang="ts">
|
||||||
import BlogHero from "vuepress-theme-hope/blog/components/BlogHero.js";
|
import { computed } from 'vue';
|
||||||
import HitokotoBlogHero from "vuepress-theme-hope/presets/HitokotoBlogHero.js";
|
import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
|
||||||
|
import { usePageFrontmatter, withBase } from 'vuepress/client';
|
||||||
|
|
||||||
|
import HeroSlideDownButton from 'vuepress-theme-hope/components/home/HeroSlideDownButton';
|
||||||
|
import 'vuepress-theme-hope/styles/blog/blog-hero.scss';
|
||||||
|
import 'vuepress-theme-hope/presets/hitokoto-blog-hero.scss';
|
||||||
|
|
||||||
|
interface BlogHomeFrontmatter {
|
||||||
|
bgImage?: string | false;
|
||||||
|
bgImageDark?: string | false;
|
||||||
|
bgImageStyle?: string | Record<string, string>;
|
||||||
|
hero?: boolean;
|
||||||
|
heroFullScreen?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface HitokotoResult {
|
||||||
|
hitokoto: string;
|
||||||
|
from?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fallbackText = '山高路远,看世界,也找自己。';
|
||||||
|
const fallbackAuthor = '氓氓小栈';
|
||||||
|
const defaultHero = '//theme-hope-assets.vuejs.press/hero/default.jpg';
|
||||||
|
const frontmatter = usePageFrontmatter<BlogHomeFrontmatter>();
|
||||||
|
|
||||||
|
const resolveImage = (image: string): string =>
|
||||||
|
image.startsWith('//') || /^https?:\/\//.test(image) ? image : withBase(image);
|
||||||
|
|
||||||
|
const background = computed(() => ({
|
||||||
|
image:
|
||||||
|
typeof frontmatter.value.bgImage === 'string'
|
||||||
|
? resolveImage(frontmatter.value.bgImage)
|
||||||
|
: frontmatter.value.bgImage === false
|
||||||
|
? null
|
||||||
|
: defaultHero,
|
||||||
|
imageDark:
|
||||||
|
typeof frontmatter.value.bgImageDark === 'string'
|
||||||
|
? resolveImage(frontmatter.value.bgImageDark)
|
||||||
|
: null,
|
||||||
|
style: frontmatter.value.bgImageStyle ?? null,
|
||||||
|
}));
|
||||||
|
|
||||||
|
const scrollDown = (): void => {
|
||||||
|
window.scrollTo({
|
||||||
|
top: window.innerHeight - (document.querySelector('[vp-navbar]')?.clientHeight ?? 0),
|
||||||
|
behavior: 'smooth',
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
const text = ref(fallbackText);
|
||||||
|
const display = ref(fallbackText);
|
||||||
|
const author = ref(fallbackAuthor);
|
||||||
|
|
||||||
|
let isMounted = false;
|
||||||
|
let timer: ReturnType<typeof setTimeout> | undefined;
|
||||||
|
|
||||||
|
const clearRenderTimer = (): void => {
|
||||||
|
if (timer) {
|
||||||
|
clearTimeout(timer);
|
||||||
|
timer = undefined;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const renderText = async (): Promise<void> => {
|
||||||
|
clearRenderTimer();
|
||||||
|
display.value = '';
|
||||||
|
|
||||||
|
let index = 0;
|
||||||
|
|
||||||
|
const renderNextWord = async (): Promise<void> => {
|
||||||
|
display.value += text.value[index] ?? '';
|
||||||
|
index += 1;
|
||||||
|
|
||||||
|
await nextTick();
|
||||||
|
|
||||||
|
if (isMounted && index < text.value.length) {
|
||||||
|
timer = setTimeout(() => {
|
||||||
|
void renderNextWord();
|
||||||
|
}, 120);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
await renderNextWord();
|
||||||
|
};
|
||||||
|
|
||||||
|
const getHitokoto = async (): Promise<void> => {
|
||||||
|
try {
|
||||||
|
const response = await fetch('https://v1.hitokoto.cn');
|
||||||
|
const result = (await response.json()) as HitokotoResult;
|
||||||
|
|
||||||
|
if (result.hitokoto) {
|
||||||
|
text.value = result.hitokoto;
|
||||||
|
author.value = result.from ?? fallbackAuthor;
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to fetch hitokoto:', error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
watch(text, () => {
|
||||||
|
void renderText();
|
||||||
|
});
|
||||||
|
|
||||||
|
onMounted(() => {
|
||||||
|
isMounted = true;
|
||||||
|
void getHitokoto();
|
||||||
|
});
|
||||||
|
|
||||||
|
onUnmounted(() => {
|
||||||
|
isMounted = false;
|
||||||
|
clearRenderTimer();
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<BlogHero>
|
<div
|
||||||
<template #info="info">
|
v-if="frontmatter.hero !== false"
|
||||||
<HitokotoBlogHero v-bind="info" />
|
class="vp-blog-hero"
|
||||||
</template>
|
:class="{
|
||||||
</BlogHero>
|
'hero-fullscreen': frontmatter.heroFullScreen,
|
||||||
|
'no-bg': !background.image,
|
||||||
|
}"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
v-if="background.image"
|
||||||
|
class="vp-blog-mask"
|
||||||
|
:class="{ light: background.imageDark }"
|
||||||
|
:style="[{ background: `url(${background.image}) center/cover no-repeat` }, background.style]"
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
v-if="background.imageDark"
|
||||||
|
class="vp-blog-mask dark"
|
||||||
|
:style="[
|
||||||
|
{ background: `url(${background.imageDark}) center/cover no-repeat` },
|
||||||
|
background.style,
|
||||||
|
]"
|
||||||
|
/>
|
||||||
|
<div class="hitokoto">
|
||||||
|
<p class="hitokoto-text">
|
||||||
|
<span>{{ display }}</span>
|
||||||
|
</p>
|
||||||
|
<p class="hitokoto-author">——「{{ author }}」</p>
|
||||||
|
</div>
|
||||||
|
<HeroSlideDownButton v-if="frontmatter.heroFullScreen" @click="scrollDown" />
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
+13
-14
@@ -1,17 +1,16 @@
|
|||||||
import {defineUserConfig} from "vuepress";
|
import { defineUserConfig } from 'vuepress';
|
||||||
import {viteBundler} from "@vuepress/bundler-vite";
|
import { viteBundler } from '@vuepress/bundler-vite';
|
||||||
import {getDirname, path} from "vuepress/utils";
|
import { getDirname, path } from 'vuepress/utils';
|
||||||
import theme from "./theme.js";
|
import theme from './theme.js';
|
||||||
|
|
||||||
|
|
||||||
const __dirname = getDirname(import.meta.url);
|
const __dirname = getDirname(import.meta.url);
|
||||||
|
|
||||||
export default defineUserConfig({
|
export default defineUserConfig({
|
||||||
base: "/",
|
base: '/',
|
||||||
|
|
||||||
lang: "zh-CN",
|
lang: 'zh-CN',
|
||||||
title: "氓氓小栈",
|
title: '氓氓小栈',
|
||||||
description: "氓氓小栈",
|
description: '氓氓小栈',
|
||||||
theme,
|
theme,
|
||||||
bundler: viteBundler({
|
bundler: viteBundler({
|
||||||
viteOptions: {
|
viteOptions: {
|
||||||
@@ -19,20 +18,20 @@ export default defineUserConfig({
|
|||||||
preprocessorOptions: {
|
preprocessorOptions: {
|
||||||
scss: {
|
scss: {
|
||||||
quietDeps: true,
|
quietDeps: true,
|
||||||
silenceDeprecations: ["if-function"],
|
silenceDeprecations: ['if-function'],
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}),
|
}),
|
||||||
alias: {
|
alias: {
|
||||||
"@theme-hope/modules/blog/components/BlogHero": path.resolve(
|
'@theme-hope/components/blog/BlogHero': path.resolve(__dirname, './components/BlogHero.vue'),
|
||||||
|
'@theme-hope/modules/blog/components/BlogHero': path.resolve(
|
||||||
__dirname,
|
__dirname,
|
||||||
"./components/BlogHero.vue",
|
'./components/BlogHero.vue',
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
// 和 PWA 一起启用
|
// 和 PWA 一起启用
|
||||||
// shouldPrefetch: false,
|
// VuePress 默认会预取页面资源;如后续启用 PWA,可按需显式调整。
|
||||||
});
|
});
|
||||||
|
|||||||
+17
-17
@@ -1,30 +1,30 @@
|
|||||||
import {navbar} from "vuepress-theme-hope";
|
import { navbar } from 'vuepress-theme-hope';
|
||||||
|
|
||||||
export default navbar([
|
export default navbar([
|
||||||
"/",
|
'/',
|
||||||
{
|
{
|
||||||
text: "编程",
|
text: '编程',
|
||||||
icon: "mdi:code-tags",
|
icon: 'mdi:code-tags',
|
||||||
link: "/programming/",
|
link: '/programming/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "工作",
|
text: '工作',
|
||||||
icon: "mdi:briefcase",
|
icon: 'mdi:briefcase',
|
||||||
link: "/work/",
|
link: '/work/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "应用",
|
text: '应用',
|
||||||
icon: "mdi:application",
|
icon: 'mdi:application',
|
||||||
link: "/apps/",
|
link: '/apps/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "工具箱",
|
text: '工具箱',
|
||||||
icon: "mdi:toolbox",
|
icon: 'mdi:toolbox',
|
||||||
link: "/tools/",
|
link: '/tools/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "AI",
|
text: 'AI',
|
||||||
icon: "mdi:robot-outline",
|
icon: 'mdi:robot-outline',
|
||||||
link: "/ai/",
|
link: '/ai/',
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
|||||||
+178
-209
@@ -1,347 +1,316 @@
|
|||||||
import {sidebar} from "vuepress-theme-hope";
|
import { sidebar } from 'vuepress-theme-hope';
|
||||||
|
|
||||||
export default sidebar({
|
export default sidebar({
|
||||||
"/programming/": [
|
'/programming/': [
|
||||||
{
|
{
|
||||||
text: "前端",
|
text: '前端',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
icon: "mdi:vuejs",
|
icon: 'mdi:vuejs',
|
||||||
prefix: "frontend/",
|
prefix: 'frontend/',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "Vue",
|
text: 'Vue',
|
||||||
icon: "mdi:vuejs",
|
icon: 'mdi:vuejs',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "vue/",
|
prefix: 'vue/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "CSS",
|
text: 'CSS',
|
||||||
icon: "mdi:language-css3",
|
icon: 'mdi:language-css3',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "css/",
|
prefix: 'css/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "HTML",
|
text: 'HTML',
|
||||||
icon: "mdi:language-html5",
|
icon: 'mdi:language-html5',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "html/",
|
prefix: 'html/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "开发工具",
|
text: '开发工具',
|
||||||
icon: "mdi:tools",
|
icon: 'mdi:tools',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "tools/",
|
prefix: 'tools/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "后端",
|
text: '后端',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
icon: "mdi:code-tags",
|
icon: 'mdi:code-tags',
|
||||||
prefix: "backend/",
|
prefix: 'backend/',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "Java",
|
text: 'Java',
|
||||||
icon: "mdi:language-java",
|
icon: 'mdi:language-java',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "java/",
|
prefix: 'java/',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "框架",
|
text: '框架',
|
||||||
icon: "mdi:code-braces",
|
icon: 'mdi:code-braces',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "框架/",
|
prefix: '框架/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "功能整理",
|
text: '功能整理',
|
||||||
icon: "mdi:puzzle",
|
icon: 'mdi:puzzle',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "功能整理/",
|
prefix: '功能整理/',
|
||||||
children: [
|
children: 'structure',
|
||||||
"01XJar.md",
|
},
|
||||||
"02Maven.md",
|
{
|
||||||
"03WebSocket和HTTP关系.md",
|
text: '试题',
|
||||||
"05防止表单和参数重复提交.md",
|
icon: 'mdi:comment-question',
|
||||||
"06Spring Boot JAR 瘦身与加密.md",
|
collapsible: true,
|
||||||
"SDKMAN-Java-Maven版本管理.md",
|
prefix: 'AI试题/',
|
||||||
"Windows-Jabba-Java版本管理.md",
|
children: 'structure',
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "试题",
|
text: 'Go',
|
||||||
icon: "mdi:comment-question",
|
icon: 'mdi:language-go',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "AI试题/",
|
prefix: 'go/',
|
||||||
children: "structure",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Go",
|
|
||||||
icon: "mdi:language-go",
|
|
||||||
collapsible: true,
|
|
||||||
prefix: "go/",
|
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "Go基础语法",
|
text: 'Go基础语法',
|
||||||
icon: "mdi:book-open-outline",
|
icon: 'mdi:book-open-outline',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "Go基础语法/",
|
prefix: 'Go基础语法/',
|
||||||
|
children: 'structure',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Go并发模型',
|
||||||
|
icon: 'mdi:run-fast',
|
||||||
|
collapsible: true,
|
||||||
|
prefix: 'Go并发模型/',
|
||||||
|
children: 'structure',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
text: 'Web开发数据库',
|
||||||
|
icon: 'mdi:database-outline',
|
||||||
|
collapsible: true,
|
||||||
|
prefix: 'Web开发数据库/',
|
||||||
children: [
|
children: [
|
||||||
"01Hello World.md",
|
'README.md',
|
||||||
"02变量与类型.md",
|
'15Gin基础入门.md',
|
||||||
"03slice和map.md",
|
'16Gin中间件.md',
|
||||||
"04Struct、方法与接收者类型详解.md",
|
'17GORM数据库.md',
|
||||||
"05接口.md",
|
'18GORM事务关联.md',
|
||||||
"06错误机制.md",
|
'19Viper配置管理.md',
|
||||||
"07从零实现 Mini 日志库.md",
|
'20Zap日志.md',
|
||||||
|
'21综合实战项目.md',
|
||||||
|
],
|
||||||
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Go并发模型",
|
text: 'C++',
|
||||||
icon: "mdi:run-fast",
|
icon: 'mdi:language-cpp',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "Go并发模型/",
|
prefix: 'c++/',
|
||||||
children: [
|
children: 'structure',
|
||||||
"08Goroutine与GPM调度模型.md",
|
},
|
||||||
"09Channel与单向Channel.md",
|
|
||||||
"10select与超时控制.md",
|
|
||||||
"11context取消与超时.md",
|
|
||||||
"12Mutex与WaitGroup.md",
|
|
||||||
"13atomic原子操作.md",
|
|
||||||
"14并发爬虫实战.md",
|
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Web开发数据库",
|
text: 'Linux',
|
||||||
icon: "mdi:database-outline",
|
|
||||||
collapsible: true,
|
|
||||||
prefix: "Web开发数据库/",
|
|
||||||
children: [
|
|
||||||
"README.md",
|
|
||||||
"15Gin基础入门.md",
|
|
||||||
"16Gin中间件.md",
|
|
||||||
"17GORM数据库.md",
|
|
||||||
"18GORM事务关联.md",
|
|
||||||
"19Viper配置管理.md",
|
|
||||||
"20Zap日志.md",
|
|
||||||
"21综合实战项目.md",
|
|
||||||
],
|
|
||||||
}
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "C++",
|
|
||||||
icon: "mdi:language-cpp",
|
|
||||||
collapsible: true,
|
|
||||||
prefix: "c++/",
|
|
||||||
children: "structure",
|
|
||||||
},
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
text: "Linux",
|
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
icon: "mdi:linux",
|
icon: 'mdi:linux',
|
||||||
prefix: "linux/",
|
prefix: 'linux/',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "基础",
|
text: '基础',
|
||||||
icon: "mdi:console",
|
icon: 'mdi:console',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "基础/",
|
prefix: '基础/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Linux_Mint",
|
text: 'Linux_Mint',
|
||||||
icon: "simple-icons:linuxmint",
|
icon: 'simple-icons:linuxmint',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "Linux_Mint/",
|
prefix: 'Linux_Mint/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "凝思",
|
text: '凝思',
|
||||||
icon: "mdi:server",
|
icon: 'mdi:server',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "凝思/",
|
prefix: '凝思/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
]
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Docker",
|
text: 'Docker',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
icon: "mdi:docker",
|
icon: 'mdi:docker',
|
||||||
prefix: "docker/",
|
prefix: 'docker/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"/work/": [
|
'/work/': [
|
||||||
{
|
{
|
||||||
text: "工作日志",
|
text: '工作日志',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
icon: "mdi:file-document-outline",
|
icon: 'mdi:file-document-outline',
|
||||||
prefix: "log/",
|
prefix: 'log/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "项目总结",
|
text: '项目总结',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
icon: "mdi:book-open-page-variant",
|
icon: 'mdi:book-open-page-variant',
|
||||||
prefix: "project-summary/",
|
prefix: 'project-summary/',
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "常用记录",
|
text: '常用记录',
|
||||||
icon: "mdi:star",
|
icon: 'mdi:star',
|
||||||
link: "/work/常用.md",
|
link: '/work/常用.md',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "待办事项",
|
text: '待办事项',
|
||||||
icon: "fa6-solid:list-check",
|
icon: 'fa6-solid:list-check',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "待办首页",
|
text: '待办首页',
|
||||||
icon: "mdi:home-outline",
|
icon: 'mdi:home-outline',
|
||||||
link: "/work/todo/",
|
link: '/work/todo/',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "4月待办",
|
text: '4月待办',
|
||||||
icon: "mdi:calendar-month",
|
icon: 'mdi:calendar-month',
|
||||||
link: "/work/todo/2026-04.md",
|
link: '/work/todo/2026-04.md',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "3月待办",
|
text: '3月待办',
|
||||||
icon: "mdi:calendar-month",
|
icon: 'mdi:calendar-month',
|
||||||
link: "/work/todo/2026-03.md",
|
link: '/work/todo/2026-03.md',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
}
|
},
|
||||||
],
|
],
|
||||||
"/apps/": [
|
'/apps/': [
|
||||||
{
|
{
|
||||||
text: "自建应用",
|
text: '自建应用',
|
||||||
icon: "mdi:apps",
|
icon: 'mdi:apps',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
children: "structure",
|
children: 'structure',
|
||||||
}
|
|
||||||
],
|
|
||||||
"/tools/": [
|
|
||||||
{
|
|
||||||
text: "工具箱",
|
|
||||||
icon: "mdi:toolbox",
|
|
||||||
collapsible: true,
|
|
||||||
children: [
|
|
||||||
"01gkd.md",
|
|
||||||
"02WSL2.md",
|
|
||||||
"03Scoop.md",
|
|
||||||
"04gitee-ssh.md",
|
|
||||||
"05Google.md",
|
|
||||||
"06MobaXterm.md"
|
|
||||||
],
|
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"/ai/": [
|
'/tools/': [
|
||||||
{
|
{
|
||||||
text: "OpenCode",
|
text: '工具箱',
|
||||||
icon: "fa6-solid:code",
|
icon: 'mdi:toolbox',
|
||||||
|
collapsible: true,
|
||||||
|
children: 'structure',
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'/ai/': [
|
||||||
|
{
|
||||||
|
text: 'OpenCode',
|
||||||
|
icon: 'fa6-solid:code',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "opencode-cli",
|
text: 'opencode-cli',
|
||||||
icon: "fa6-solid:terminal",
|
icon: 'fa6-solid:terminal',
|
||||||
link: "opencode.md",
|
link: 'opencode.md',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "opencode-tui",
|
text: 'opencode-tui',
|
||||||
icon: "fa6-solid:desktop",
|
icon: 'fa6-solid:desktop',
|
||||||
link: "opencode-tui.md",
|
link: 'opencode-tui.md',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Superpowers",
|
text: 'Superpowers',
|
||||||
icon: "fa6-solid:rocket",
|
icon: 'fa6-solid:rocket',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
prefix: "superpowers/",
|
prefix: 'superpowers/',
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "superpowers-总览",
|
text: 'superpowers-总览',
|
||||||
icon: "fa6-solid:eye",
|
icon: 'fa6-solid:eye',
|
||||||
link: "opencode-superpowers-overview.md",
|
link: 'opencode-superpowers-overview.md',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "superpowers",
|
text: 'superpowers',
|
||||||
icon: "fa6-solid:bolt",
|
icon: 'fa6-solid:bolt',
|
||||||
link: "opencode-superpowers.md",
|
link: 'opencode-superpowers.md',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "skills-使用方案汇总",
|
text: 'skills-使用方案汇总',
|
||||||
icon: "fa6-solid:book",
|
icon: 'fa6-solid:book',
|
||||||
link: "opencode-skills-playbook.md",
|
link: 'opencode-skills-playbook.md',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "Claude Code",
|
text: 'Claude Code',
|
||||||
icon: "fa6-solid:code-branch",
|
icon: 'fa6-solid:code-branch',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "多分支工作流实战总结(2026)",
|
text: '多分支工作流实战总结(2026)',
|
||||||
icon: "fa6-solid:code-merge",
|
icon: 'fa6-solid:code-merge',
|
||||||
link: "claude-code-branch-workflow-2026.md",
|
link: 'claude-code-branch-workflow-2026.md',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "ChatGPT",
|
text: 'ChatGPT',
|
||||||
icon: "fa6-solid:comments",
|
icon: 'fa6-solid:comments',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "chatgpt-使用记录与实践",
|
text: 'chatgpt-使用记录与实践',
|
||||||
icon: "fa6-solid:message",
|
icon: 'fa6-solid:message',
|
||||||
link: "chatgpt.md",
|
link: 'chatgpt.md',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "OpenClaw",
|
text: 'OpenClaw',
|
||||||
icon: "fa6-solid:robot",
|
icon: 'fa6-solid:robot',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "openclaw-24h在线部署实战",
|
text: 'openclaw-24h在线部署实战',
|
||||||
icon: "fa6-solid:server",
|
icon: 'fa6-solid:server',
|
||||||
link: "openclaw.md",
|
link: 'openclaw.md',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
text: "iFlow",
|
text: 'iFlow',
|
||||||
icon: "fa6-solid:diagram-project",
|
icon: 'fa6-solid:diagram-project',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
children: [
|
children: [
|
||||||
{
|
{
|
||||||
text: "iflow-流程编排实践记录",
|
text: 'iflow-流程编排实践记录',
|
||||||
icon: "fa6-solid:flow-chart",
|
icon: 'fa6-solid:flow-chart',
|
||||||
link: "iflow.md",
|
link: 'iflow.md',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
"/": false,
|
'/': false,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
// you can change config here
|
// you can change config here
|
||||||
$theme-color: #DC143C;
|
$theme-color: #dc143c;
|
||||||
|
|||||||
@@ -4,11 +4,11 @@
|
|||||||
/* .vuepress/styles/index.scss */
|
/* .vuepress/styles/index.scss */
|
||||||
|
|
||||||
.hitokoto-text {
|
.hitokoto-text {
|
||||||
color: #DC143C !important; // 替换为你想要的颜色
|
color: #dc143c !important; // 替换为你想要的颜色
|
||||||
}
|
}
|
||||||
|
|
||||||
.hitokoto-author {
|
.hitokoto-author {
|
||||||
color: #DC143C!important; // 可选:也可自定义作者名颜色
|
color: #dc143c !important; // 可选:也可自定义作者名颜色
|
||||||
}
|
}
|
||||||
|
|
||||||
.vp-navbar .auto-link {
|
.vp-navbar .auto-link {
|
||||||
|
|||||||
+35
-25
@@ -1,27 +1,36 @@
|
|||||||
import {hopeTheme} from "vuepress-theme-hope";
|
import { hopeTheme } from 'vuepress-theme-hope';
|
||||||
|
|
||||||
|
import navbar from './navbar.js';
|
||||||
|
import sidebar from './sidebar.js';
|
||||||
|
|
||||||
|
const encryptPassword = process.env.ENCRYPT_PASSWORD;
|
||||||
|
|
||||||
|
if (process.env.NODE_ENV === 'production' && !encryptPassword) {
|
||||||
|
throw new Error('Missing ENCRYPT_PASSWORD. Set it before running a production build.');
|
||||||
|
}
|
||||||
|
|
||||||
|
const accountsPassword = encryptPassword ?? 'local-dev-password';
|
||||||
|
|
||||||
import navbar from "./navbar.js";
|
|
||||||
import sidebar from "./sidebar.js";
|
|
||||||
//VuePress Theme Hope主题的博客
|
//VuePress Theme Hope主题的博客
|
||||||
export default hopeTheme(
|
export default hopeTheme(
|
||||||
{
|
{
|
||||||
// 网站域名配置(用于SEO和RSS等功能)
|
// 网站域名配置(用于SEO和RSS等功能)
|
||||||
hostname: "https://mangmang.fun/",
|
hostname: 'https://mangmang.fun/',
|
||||||
|
|
||||||
// 加密配置
|
// 加密配置
|
||||||
encrypt: {
|
encrypt: {
|
||||||
config: {
|
config: {
|
||||||
"/accounts/": "362165265", // 账号密码页面访问密码
|
'/accounts/': accountsPassword, // 账号密码页面访问密码
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
||||||
// 作者信息
|
// 作者信息
|
||||||
author: {
|
author: {
|
||||||
name: "LiuMangMang",
|
name: 'LiuMangMang',
|
||||||
},
|
},
|
||||||
|
|
||||||
// 网站许可证
|
// 网站许可证
|
||||||
license: "CC 4.0",
|
license: 'CC 4.0',
|
||||||
|
|
||||||
// 导航栏配置(从 navbar.js 文件导入)
|
// 导航栏配置(从 navbar.js 文件导入)
|
||||||
navbar,
|
navbar,
|
||||||
@@ -30,36 +39,37 @@ export default hopeTheme(
|
|||||||
sidebar,
|
sidebar,
|
||||||
|
|
||||||
// 网站logo设置
|
// 网站logo设置
|
||||||
logo: "logo/transparentLogo.png", // 亮色模式下的logo
|
logo: 'logo/transparentLogo.png', // 亮色模式下的logo
|
||||||
logoDark: "logo/transparentLogo.png", // 暗色模式下的logo
|
logoDark: 'logo/transparentLogo.png', // 暗色模式下的logo
|
||||||
|
|
||||||
// 支持简写仓库名称,会解析到 GitHub 上,同时也可以是一个完整的 URL
|
// 支持简写仓库名称,会解析到 GitHub 上,同时也可以是一个完整的 URL
|
||||||
// repo: "https://gitea.mangmang.fun/mangmang/blog",
|
// repo: "https://gitea.mangmang.fun/mangmang/blog",
|
||||||
// 默认从 `repo` 内容中推断为以下之一:
|
// 默认从 `repo` 内容中推断为以下之一:
|
||||||
// "GitHub" / "GitLab" / "Gitee" / "Bitbucket" / "Source"
|
// "GitHub" / "GitLab" / "Gitee" / "Bitbucket" / "Source"
|
||||||
repoLabel: "Gitea",
|
repoLabel: 'Gitea',
|
||||||
repoDisplay: true,
|
repoDisplay: true,
|
||||||
|
|
||||||
// 是否显示编辑链接
|
// 是否显示编辑链接
|
||||||
editLink: true,
|
editLink: true,
|
||||||
|
|
||||||
// 文档源码目录
|
// 文档源码目录
|
||||||
docsDir: "src",
|
docsDir: 'src',
|
||||||
|
|
||||||
// 页脚配置
|
// 页脚配置
|
||||||
footer: "<a href='https://beian.miit.gov.cn/' target='_blank'>蜀ICP备2025176018号-1</a> | Powered by VuePress | Theme by Hope",
|
footer:
|
||||||
|
"<a href='https://beian.miit.gov.cn/' target='_blank'>蜀ICP备2025176018号-1</a> | Powered by VuePress | Theme by Hope",
|
||||||
displayFooter: true,
|
displayFooter: true,
|
||||||
|
|
||||||
// 是否显示最后更新时间
|
// 是否显示最后更新时间
|
||||||
lastUpdated: false,
|
lastUpdated: true,
|
||||||
|
|
||||||
// 深色模式配置(toggle表示用户可以切换)
|
// 深色模式配置(toggle表示用户可以切换)
|
||||||
darkmode: "toggle",
|
darkmode: 'toggle',
|
||||||
|
|
||||||
// 博客相关配置
|
// 博客相关配置
|
||||||
blog: {
|
blog: {
|
||||||
description: "一个后端开发者",
|
description: '一个后端开发者',
|
||||||
intro: "/intro.html"
|
intro: '/intro.html',
|
||||||
},
|
},
|
||||||
|
|
||||||
// Markdown增强功能配置
|
// Markdown增强功能配置
|
||||||
@@ -81,13 +91,13 @@ export default hopeTheme(
|
|||||||
// 文本样式化配置
|
// 文本样式化配置
|
||||||
stylize: [
|
stylize: [
|
||||||
{
|
{
|
||||||
matcher: "Recommended",
|
matcher: 'Recommended',
|
||||||
replacer: ({ tag }) => {
|
replacer: ({ tag }) => {
|
||||||
if (tag === "em")
|
if (tag === 'em')
|
||||||
return {
|
return {
|
||||||
tag: "Badge",
|
tag: 'Badge',
|
||||||
attrs: {type: "tip"},
|
attrs: { type: 'tip' },
|
||||||
content: "Recommended",
|
content: 'Recommended',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -110,17 +120,17 @@ export default hopeTheme(
|
|||||||
|
|
||||||
// 组件配置
|
// 组件配置
|
||||||
components: {
|
components: {
|
||||||
components: ["Badge", "VPCard"],
|
components: ['Badge', 'VPCard'],
|
||||||
},
|
},
|
||||||
|
|
||||||
// 图标配置
|
// 图标配置
|
||||||
icon: {
|
icon: {
|
||||||
prefix: "fa6-solid:",
|
prefix: 'fa6-solid:',
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// 自定义主题配置
|
// 自定义主题配置
|
||||||
custom: true
|
custom: true,
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
---
|
---
|
||||||
home: true
|
home: true
|
||||||
layout: BlogHome
|
layout: Blog
|
||||||
hero: true
|
hero: true
|
||||||
title: 博客主页
|
title: 博客主页
|
||||||
heroText: ''
|
heroText: ''
|
||||||
|
|||||||
+3
-7
@@ -2,13 +2,9 @@
|
|||||||
"compilerOptions": {
|
"compilerOptions": {
|
||||||
"module": "NodeNext",
|
"module": "NodeNext",
|
||||||
"moduleResolution": "NodeNext",
|
"moduleResolution": "NodeNext",
|
||||||
|
"skipLibCheck": true,
|
||||||
"target": "ES2022"
|
"target": "ES2022"
|
||||||
},
|
},
|
||||||
"include": [
|
"include": ["src/.vuepress/**/*.ts", "src/.vuepress/**/*.vue"],
|
||||||
"src/.vuepress/**/*.ts",
|
"exclude": ["node_modules"]
|
||||||
"src/.vuepress/**/*.vue"
|
|
||||||
],
|
|
||||||
"exclude": [
|
|
||||||
"node_modules"
|
|
||||||
]
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user