更新任务

This commit is contained in:
jimmy committed 2025-01-18 00:48:37 +08:00
1 parent 120a57ad57
commit 6118a80ac4
279 files changed
+9682 -2362

No files matched your search

@@ -0,0 +1,57 @@
<template>
<div class="comments" v-if="!frontmatter.isNoComment">
<!-- params generate in https://giscus.app/zh-CN -->
<Giscus
v-if="showComment"
repo="duyl328/duyl328.github.io"
repo-id="R_kgDONmELAA"
category="Announcements"
category-id="DIC_kwDONmELAM4ClzgV"
mapping="specific"
:term="term"
strict="1"
reactions-enabled="1"
emit-metadata="0"
input-position="top"
:theme="theme"
:lang="lang"
loading="lazy"
crossorigin="anonymous"
/>
</div>
</template>
<script lang="ts" setup>
import { ref, watch, nextTick, computed } from 'vue'
import { useData, useRoute } from 'vitepress'
import Giscus from '@giscus/vue'
const route = useRoute()
const { isDark, frontmatter } = useData()
// 保证中英文路径显示同一个评论
const term = computed(() => route.path)
const theme = computed(() => (isDark.value ? 'noborder_dark' : 'noborder_light'))
const lang = computed(() => 'zh-Hans')
// language 变化不会触发重新加载,这里 v-if 强制刷新
const showComment = ref(true)
watch(
() => route.path,
() => {
showComment.value = false
nextTick(() => {
showComment.value = true
})
},
{
immediate: true,
},
)
</script>
<style lang="scss" scoped>
.comments {
margin-top: 80px;
}
</style>
@@ -0,0 +1,55 @@
<template>
<t-button
v-if="isPosts && !frontmatter.isNoBackBtn"
theme="default"
variant="dashed"
style="margin-bottom: 10px"
@click="goBack"
>
<template #icon>
<RollbackIcon/>
</template>
{{ '返回上一页' }}
</t-button>
</template>
<script setup lang="ts">
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { useRoute, useData } from 'vitepress'
import { RollbackIcon } from 'tdesign-icons-vue-next'
const route = useRoute()
const isPosts = computed(() => route.path.startsWith('/posts'))
const { frontmatter } = useData()
function goBack () {
if (window.history.length <= 1) {
location.href = '/'
} else {
window.history.go(hashChangeCount.value)
hashChangeCount.value = -1
}
}
const hashChangeCount = ref(-1)
onMounted(() => {
window.onhashchange = () => {
hashChangeCount.value--
}
})
onUnmounted(() => {
window.onhashchange = null
})
</script>
<style scoped>
.img-container {
height: 105px;
width: 100px;
}
img {
height: 100px;
border-radius: 5px;
margin-top: 5px;
}
</style>
@@ -0,0 +1,92 @@
<template>
<div class="image-viewer">
<t-config-provider :global-config="globalConfig">
<t-image-viewer
v-model:visible="show"
:images="previewImageInfo.list"
:default-index="previewImageInfo.idx"
:key="previewImageInfo.idx"
@close="show = false"
>
</t-image-viewer>
<TDesignDark/>
</t-config-provider>
</div>
</template>
<script setup lang="ts">
import { onMounted, onUnmounted, reactive, ref, watch } from 'vue'
import { useRoute } from 'vitepress'
// import enConfig from 'tdesign-vue-next/es/locale/en_US'
import zhConfig from 'tdesign-vue-next/es/locale/zh_CN'
import TDesignDark from './TDesignDark.vue'
// 处理 TDesign 的国际化
const route = useRoute()
const globalConfig = ref<typeof zhConfig >(zhConfig)
watch(
() => route.path,
() => {
globalConfig.value = zhConfig
},
{
immediate: true,
},
)
// 处理图片预览
const show = ref(false)
const previewImageInfo = reactive<{ url: string; list: string[]; idx: number }>(
{
url: '',
list: [],
idx: 0,
},
)
function previewImage (e: Event) {
const target = e.target as HTMLElement
const currentTarget = e.currentTarget as HTMLElement
if (target.tagName.toLowerCase() === 'img') {
const imgs = currentTarget.querySelectorAll<HTMLImageElement>(
'.content-container .main img',
)
const idx = Array.from(imgs).findIndex((el) => el === target)
const urls = Array.from(imgs).map((el) => el.src)
const url = target.getAttribute('src')
previewImageInfo.url = url!
previewImageInfo.list = urls
previewImageInfo.idx = idx
// 兼容点击 main 之外的图片
if (idx === -1 && url) {
previewImageInfo.list.push(url)
previewImageInfo.idx = previewImageInfo.list.length - 1
}
show.value = true
}
}
onMounted(() => {
if (typeof document !== 'undefined') {
// 使用document的代码
const docDomContainer = document.querySelector('#VPContent')
docDomContainer?.addEventListener('click', previewImage)
}
})
onUnmounted(() => {
if (typeof document !== 'undefined') {
// 使用document的代码
const docDomContainer = document.querySelector('#VPContent')
docDomContainer?.removeEventListener('click', previewImage)
}
})
</script>
<style>
/* 不提供下载功能,隐藏下载按钮,tdesign 下载有问题 */
.t-image-viewer__modal-icon:nth-child(7) {
display: none !important;
}
</style>
@@ -0,0 +1,17 @@
<template>
</template>
<script setup lang="ts">
import { useRouter } from 'vitepress'
import { createSideBarZH } from '../utils/createSideBar'
const router = useRouter()
const sideBar = createSideBarZH()
const prefix = '/notes/'
const firstItemLink = sideBar[prefix][0].items[0].link
router.go(firstItemLink)
</script>
<style scoped></style>
@@ -0,0 +1,25 @@
<template></template>
<script setup lang="ts">
import { useData } from 'vitepress'
import { watch } from 'vue'
const { isDark } = useData()
// tdesign 暗色切换 https://tdesign.tencent.com/vue-next/dark-mode
watch(
isDark,
() => {
if (typeof document !== 'undefined') {
// 使用document的代码
if (isDark.value) {
document.documentElement.setAttribute('theme-mode', 'dark')
} else {
document.documentElement.removeAttribute('theme-mode')
}
}
},
{
immediate: true,
},
)
</script>
+23
View File
@@ -0,0 +1,23 @@
// https://vitepress.dev/guide/custom-theme
import { h } from 'vue'
import Theme from 'vitepress/theme-without-fonts' // https://vitepress.dev/zh/guide/extending-default-theme#using-different-fonts
// 引入组件库的少量全局样式变量
import 'tdesign-vue-next/es/style/index.css'
import './style.css'
import Comment from './components/Comment.vue'
import ImageViewer from './components/ImageViewer.vue'
import GoBack from './components/GoBack.vue'
export default {
...Theme,
Layout: () => {
return h(Theme.Layout, null, {
// https://vitepress.dev/guide/extending-default-theme#layout-slots
'doc-after': () => h(Comment),
'doc-bottom': () => h(ImageViewer),
'aside-top': () => h(GoBack),
})
},
}
+57
View File
@@ -0,0 +1,57 @@
import { createContentLoader } from 'vitepress'
interface Post {
title: string
url: string
date: {
time: number
string: string
year: string
monthDay: string
}
tags: string[]
excerpt: string | undefined
}
export declare const data: Post[]
export default createContentLoader('posts/**/*.md', {
excerpt: excerptFn,
transform (raw): Post[] {
return raw.map(({ url, frontmatter, excerpt }) => ({
title: frontmatter.title,
url,
excerpt,
date: formatDate(frontmatter.date),
tags: frontmatter.tags,
})).sort((a, b) => b.date.time - a.date.time)
},
})
function excerptFn (file: {
data: { [key: string]: any };
content: string;
excerpt?: string
}, options?: any) {
file.excerpt = file.content.split('<!-- DESC SEP -->')[1]
}
function formatDate (raw: string): Post['date'] {
const date = new Date(raw)
date.setUTCHours(12)
return {
time: +date,
string: date.toLocaleDateString('zh-Hans', {
year: 'numeric',
month: '2-digit',
day: '2-digit',
}),
year: date.toLocaleDateString('zh-Hans', {
year: 'numeric',
}),
monthDay: date.toLocaleDateString('zh-Hans', {
month: '2-digit',
day: '2-digit',
}),
}
}
+190
View File
@@ -0,0 +1,190 @@
/** 代码字体 */
@font-face {
font-family: "FiraCode";
src: url("/assets/fonts/FiraCode-VF.woff2");
}
/** 正文字体 */
@font-face {
font-family: "SourceHanSerifCN";
src: local("SourceHanSerifCN"), url("/assets/fonts/SourceHanSerifCN-VF.woff2");
}
/** logo 字体 */
@font-face {
font-family: "Niconne";
src: local("Niconne"), url("/assets/fonts/Niconne-Regular.ttf");
}
/* 参考 https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css */
/**
* Colors Base
*
* These are the pure base color presets. Most of the time, you should not be
* using these colors directly in the theme but rather use "Colors Theme"
* instead because those are "Theme (light or dark)" dependant.
* -------------------------------------------------------------------------- */
:root {
--vp-c-blue-1: #2949a4;
--vp-c-blue-2: #0749ff;
--vp-c-blue-3: #7494ec;
--vp-c-blue-soft: rgba(110, 156, 190, 0.14);
--vp-c-yellow-1: #aa9100;
--vp-c-yellow-2: #d5b811;
--vp-c-yellow-3: #ecce23;
--vp-c-yellow-soft: rgba(186, 186, 186, 0.14);
}
/**
* Colors Theme
* -------------------------------------------------------------------------- */
:root {
--vp-c-brand-1: var(--vp-c-blue-1);
--vp-c-brand-2: var(--vp-c-blue-2);
--vp-c-brand-3: var(--vp-c-blue-3);
--vp-c-brand-soft: var(--vp-c-blue-soft);
}
.dark {
--vp-c-brand-1: var(--vp-c-yellow-1);
--vp-c-brand-2: var(--vp-c-yellow-2);
--vp-c-brand-3: var(--vp-c-yellow-3);
--vp-c-brand-soft: var(--vp-c-yellow-soft);
}
/**
* Typography
* -------------------------------------------------------------------------- */
:root {
--vp-font-family-base: "SourceHanSerifCN";
--vp-font-family-mono: "FiraCode";
}
:root {
--td-border-level-2-color: var(--vp-c-brand-soft) !important;
--td-brand-color: var(--vp-c-brand-1) !important;
--td-brand-color-light: var(--vp-c-brand-soft) !important;
--td-brand-color-hover: var(--vp-c-brand-1) !important;
--td-brand-color-active: var(--vp-c-brand-2) !important;
/* 字体 family token */
--td-font-family: SourceHanSerifCN, PingFang SC, Microsoft YaHei,
Arial Regular;
--td-font-family-medium: SourceHanSerifCN, PingFang SC, Microsoft YaHei,
Arial Medium;
}
/**
* 特殊配置
* -------------------------------------------------------------------------- */
/* logo 字体设置 */
.VPNavBarTitle .title {
font-family: "Niconne", "SourceHanSerifCN";
font-size: 24px !important;
}
/* 侧边栏标题隐藏单行文本溢出 */
.VPSidebar .items p {
display: inline-block;
width: calc(var(--vp-sidebar-width) - 100px);
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
/** 总体类 */
::selection {
background: var(--vp-c-brand-1);
color: var(--vp-c-bg);
}
::-moz-selection {
background: var(--vp-c-brand-1);
color: var(--vp-c-bg);
}
::-webkit-selection {
background: var(--vp-c-brand-1);
color: var(--vp-c-bg);
}
/** 链接样式 */
.VPDoc a {
text-decoration: none !important;
}
.VPDoc a:hover {
text-decoration: underline !important;
}
.VPDoc img {
border-radius: 4px;
cursor: zoom-in;
}
/* jupyter 输出代码不换行显示 */
main > div > div > pre > code {
white-space: normal;
}
#app {
/* 取消移动端点击 div 默认高亮效果 */
-webkit-tap-highlight-color: rgba(0, 0, 0, 0);
}
/** 磨砂玻璃效果设置 */
.VPNavBar {
background-color: transparent !important;
}
.VPNav .content .content-body {
backdrop-filter: blur(36px);
background-color: linear-gradient(
to bottom,
rgba(var(--vp-nav-bg-color), 0.98),
rgba(var(--vp-nav-bg-color), 0.6)
) !important;
}
.VPLocalNav,
.VPLocalNav .container {
backdrop-filter: blur(36px);
background-color: linear-gradient(
to bottom,
rgba(var(--vp-nav-bg-color), 0.6),
rgba(var(--vp-nav-bg-color), 0.4)
) !important;
}
.VPLocalNav,
.has-aside .container {
backdrop-filter: none;
background-color: none !important;
}
/** i18n 选项不显示下拉图标 */
.vpi-chevron-down,
.text-icon {
display: none;
}
/** 主题切换按钮样式 */
.VPSwitchAppearance {
width: 22px !important;
}
.VPSwitchAppearance .check {
transform: none !important;
}
/** 滚动条 */
* {
/* scrollbar-color: rgba(0, 0, 0, 0.12) transparent; */
scrollbar-width: thin;
}
@@ -0,0 +1,213 @@
export function createSideBarZH() {
return {
"/notes/": [
{
text: "Python基础",
collapsed: false,
items: [
{ text: "01python数据模型", link: "/notes/Python基础/01python数据模型" },
{ text: "02序列构成的数组", link: "/notes/Python基础/02序列构成的数组" },
{ text: "03字典与集合", link: "/notes/Python基础/03字典与集合" },
{ text: "04文本与字节序列", link: "/notes/Python基础/04文本与字节序列" },
{ text: "05一等函数", link: "/notes/Python基础/05一等函数" },
{ text: "06使用一等函数实现设计模式", link: "/notes/Python基础/06使用一等函数实现设计模式" },
{ text: "07函数装饰器与闭包", link: "/notes/Python基础/07函数装饰器与闭包" },
{ text: "08对象引用、可变性和垃圾回收", link: "/notes/Python基础/08对象引用、可变性和垃圾回收" },
{ text: "09符合python风格的对象", link: "/notes/Python基础/09符合python风格的对象" },
{ text: "10序列的修改、散列和切片", link: "/notes/Python基础/10序列的修改、散列和切片" },
{ text: "11接口:从协议到抽象基类", link: "/notes/Python基础/11接口:从协议到抽象基类" },
{ text: "12继承的优缺点", link: "/notes/Python基础/12继承的优缺点" },
{ text: "13正确重载运算符", link: "/notes/Python基础/13正确重载运算符" },
{ text: "14可迭代的对象、迭代器和生成器", link: "/notes/Python基础/14可迭代的对象、迭代器和生成器" },
{ text: "15上下文管理和else块", link: "/notes/Python基础/15上下文管理和else块" },
{ text: "16协程", link: "/notes/Python基础/16协程" },
{ text: "17使用future处理并发", link: "/notes/Python基础/17使用future处理并发" },
{ text: "18使用asyncio包处理并发", link: "/notes/Python基础/18使用asyncio包处理并发" },
{ text: "19元编程", link: "/notes/Python基础/19元编程" },
],
},
{
text: "threejs入门",
collapsed: false,
items: [
{ text: "01起步", link: "/notes/threejs入门/01起步" },
{ text: "02一个基本的threejs应用", link: "/notes/threejs入门/02一个基本的threejs应用" },
{ text: "03基于物理的渲染和照明", link: "/notes/threejs入门/03基于物理的渲染和照明" },
{ text: "04变换、坐标系和场景图", link: "/notes/threejs入门/04变换、坐标系和场景图" },
{ text: "05动画循环", link: "/notes/threejs入门/05动画循环" },
{ text: "06纹理映射", link: "/notes/threejs入门/06纹理映射" },
{ text: "07插件", link: "/notes/threejs入门/07插件" },
{ text: "08环境光", link: "/notes/threejs入门/08环境光" },
{ text: "09组织你的场景", link: "/notes/threejs入门/09组织你的场景" },
{ text: "10内置几何体", link: "/notes/threejs入门/10内置几何体" },
{ text: "11以gLTF格式加载3D模型", link: "/notes/threejs入门/11以gLTF格式加载3D模型" },
{ text: "12threejs动画系统", link: "/notes/threejs入门/12threejs动画系统" },
],
},
{
text: "Rust基础学习",
collapsed: false,
items: [
{ text: "01认识Cargo", link: "/notes/Rust基础学习/01认识Cargo" },
{ text: "02变量绑定与解构", link: "/notes/Rust基础学习/02变量绑定与解构" },
{ text: "03基本类型", link: "/notes/Rust基础学习/03基本类型" },
{ text: "04所有权与借用", link: "/notes/Rust基础学习/04所有权与借用" },
{ text: "05复合类型", link: "/notes/Rust基础学习/05复合类型" },
{ text: "06流程控制", link: "/notes/Rust基础学习/06流程控制" },
{ text: "07模式匹配", link: "/notes/Rust基础学习/07模式匹配" },
{ text: "08方法Method", link: "/notes/Rust基础学习/08方法Method" },
{ text: "09泛型", link: "/notes/Rust基础学习/09泛型" },
{ text: "10特征", link: "/notes/Rust基础学习/10特征" },
{ text: "11特征对象", link: "/notes/Rust基础学习/11特征对象" },
{ text: "12深入特征", link: "/notes/Rust基础学习/12深入特征" },
{ text: "13动态数组Vector", link: "/notes/Rust基础学习/13动态数组Vector" },
{ text: "14KV存储HashMap", link: "/notes/Rust基础学习/14KV存储HashMap" },
{ text: "15认识生命周期", link: "/notes/Rust基础学习/15认识生命周期" },
{ text: "16返回值和错误处理", link: "/notes/Rust基础学习/16返回值和错误处理" },
{ text: "17包和模块", link: "/notes/Rust基础学习/17包和模块" },
{ text: "18注释和文档", link: "/notes/Rust基础学习/18注释和文档" },
{ text: "19格式化输出", link: "/notes/Rust基础学习/19格式化输出" },
{ text: "20实战-文件搜索工具", link: "/notes/Rust基础学习/20实战-文件搜索工具" },
],
},
{
text: "微前端设计与实现笔记",
collapsed: false,
items: [
{ text: "01前端概览", link: "/notes/微前端设计与实现/01前端概览" },
{ text: "02微前端原则", link: "/notes/微前端设计与实现/02微前端原则" },
{ text: "03微前端的架构和挑战", link: "/notes/微前端设计与实现/03微前端的架构和挑战" },
{ text: "04探索微前端架构", link: "/notes/微前端设计与实现/04探索微前端架构" },
{ text: "05其他", link: "/notes/微前端设计与实现/05其他" },
],
},
{
text: "ChatGPT提示学习笔记",
collapsed: false,
items: [
{ text: "1_2引言—指示", link: "/notes/ChatGPT提示学习/ChatGPT提示学习笔记1_2" },
{ text: "3迭代", link: "/notes/ChatGPT提示学习/ChatGPT提示学习笔记3" },
{ text: "4摘要", link: "/notes/ChatGPT提示学习/ChatGPT提示学习笔记4" },
{ text: "5推理", link: "/notes/ChatGPT提示学习/ChatGPT提示学习笔记5" },
{ text: "6转换", link: "/notes/ChatGPT提示学习/ChatGPT提示学习笔记6" },
{ text: "7扩展", link: "/notes/ChatGPT提示学习/ChatGPT提示学习笔记7" },
{ text: "8聊天机器人", link: "/notes/ChatGPT提示学习/ChatGPT提示学习笔记8" },
],
},
{
text: "算法与数据结构",
collapsed: false,
items: [
{ text: "基础概念", link: "/notes/算法与数据结构/01基础概念" },
{ text: "线性表", link: "/notes/算法与数据结构/02线性表" },
{ text: "栈和队列", link: "/notes/算法与数据结构/03栈和队列" },
{ text: "数组", link: "/notes/算法与数据结构/04数组" },
{ text: "树", link: "/notes/算法与数据结构/05树" },
{ text: "图", link: "/notes/算法与数据结构/06图" },
{ text: "查找", link: "/notes/算法与数据结构/07查找" },
{ text: "排序", link: "/notes/算法与数据结构/08排序" },
{ text: "算法概述", link: "/notes/算法与数据结构/10算法概述" },
{ text: "递归与分治", link: "/notes/算法与数据结构/11递归与分治" },
{ text: "动态规划", link: "/notes/算法与数据结构/12动态规划" },
{ text: "贪心算法", link: "/notes/算法与数据结构/13贪心算法" },
{ text: "回溯与分支极限", link: "/notes/算法与数据结构/14回溯与分支界限" },
{ text: "经典算法实现", link: "/notes/算法与数据结构/15经典算法实现" },
{ text: "剑指Offer", link: "/notes/算法与数据结构/16剑指Offer" },
],
},
{
text: "计算机基础知识",
collapsed: false,
items: [{ text: "操作系统基础", link: "/notes/计算机基础知识/01操作系统基础" }],
},
{
text: "数据库一期",
collapsed: false,
items: [
{ text: "数据库系统概述", link: "/notes/数据库01/01数据库系统概述" },
{ text: "关系数据库", link: "/notes/数据库01/02关系数据库" },
{ text: "SQL(重点)", link: "/notes/数据库01/03SQL(重点)" },
{ text: "数据库管理与维护(重点)", link: "/notes/数据库01/05数据库管理与维护(重点)" },
{ text: "关系数据理论(重点)", link: "/notes/数据库01/06关系数据理论(重点)" },
{ text: "数据库设计", link: "/notes/数据库01/07数据库设计" },
],
},
{
text: "JavaScript[待更新]",
collapsed: false,
items: [{ text: "JS常见手写面试题", link: "/notes/JavaScript/01JS常见手写面试题" }],
},
{
text: "CSS相关[待更新]",
collapsed: false,
items: [],
},
{
text: "Vue相关",
collapsed: false,
items: [
{ text: "Vue3是如何运行的", link: "/notes/Vue相关/01Vue3是如何运行的" },
{ text: "Vue3编译器", link: "/notes/Vue相关/02Vue3编译器" },
{ text: "虚拟DOM", link: "/notes/Vue相关/03虚拟DOM" },
{ text: "Vue3-Reactivity", link: "/notes/Vue相关/04Vue3-Reactivity" },
{ text: "Mini-Vue", link: "/notes/Vue相关/05Mini-Vue" },
{ text: "Vue3其他", link: "/notes/Vue相关/06Vue3其他" },
],
},
{
text: "NestJS",
collapsed: false,
items: [
{ text: "controller", link: "/notes/NestJS/01controller" },
{ text: "service", link: "/notes/NestJS/02service" },
{ text: "module", link: "/notes/NestJS/03module" },
{ text: "DTO", link: "/notes/NestJS/04DTO" },
{ text: "postgreSQL", link: "/notes/NestJS/05postgreSQL" },
{ text: "原理细节", link: "/notes/NestJS/06原理细节" },
{ text: "应用配置", link: "/notes/NestJS/07应用配置" },
{ text: "更多模块", link: "/notes/NestJS/08更多模块" },
{ text: "openAPI", link: "/notes/NestJS/09openAPI" },
{ text: "测试", link: "/notes/NestJS/10测试" },
],
},
{
text: "前端八股文",
collapsed: false,
items: [
{ text: "HTML", link: "/notes/前端八股文/01HTML" },
{ text: "CSS", link: "/notes/前端八股文/02CSS" },
{ text: "JavaScript", link: "/notes/前端八股文/03JavaScript" },
{ text: "Vue", link: "/notes/前端八股文/04Vue" },
{ text: "计算机网络", link: "/notes/前端八股文/05计算机网络" },
{ text: "浏览器原理", link: "/notes/前端八股文/06浏览器原理" },
{ text: "性能优化", link: "/notes/前端八股文/07性能优化" },
],
},
{
text: "后端储备",
collapsed: false,
items: [
{ text: "Django进阶学习笔记", link: "/notes/后端储备/01Django进阶学习笔记" },
{ text: "DRF学习笔记", link: "/notes/后端储备/02DRF学习笔记" },
{ text: "Redis学习笔记", link: "/notes/后端储备/03Redis学习笔记" },
],
},
{
text: "Web3.0",
collapsed: false,
items: [
{ text: "Solidity8新特性", link: "/notes/Web3.0/00Solidity8新特性" },
{ text: "Solidity8基本语法", link: "/notes/Web3.0/01Solidity8基本语法" },
{ text: "Solidity8高级", link: "/notes/Web3.0/02Solidity8高级" },
{ text: "Solidity8进阶", link: "/notes/Web3.0/03Solidity8进阶" },
],
},
{
text: "AI相关[待更新]",
collapsed: false,
items: [],
},
].map((item, i) => (!i ? item : { ...item, collapsed: true })),
}
}
@@ -0,0 +1,41 @@
import { type HeadConfig, type TransformContext } from 'vitepress'
// 处理每个页面的元数据
export function handleHeadMeta (context: TransformContext) {
// 预加载字体
const preloadHead: HeadConfig[] = handleFontsPreload(context)
return [ ...preloadHead]
}
export function addBase (relativePath: string) {
const host = 'https://duyl328.github.io'
if (relativePath.startsWith('/')) {
return host + relativePath
} else {
return host + '/' + relativePath
}
}
export function handleFontsPreload ({ assets }: TransformContext) {
// 只预加载正文字体,代码字体不预加载,因为可能不会使用或者很少使用
const SourceHanSerifCN = assets.find(
file => /SourceHanSerifCN-VF\.\w+\.woff2/)
if (SourceHanSerifCN) {
return [
[
'link',
{
rel: 'preload',
href: SourceHanSerifCN,
as: 'font',
type: 'font/woff2',
crossorigin: '',
},
],
] as HeadConfig[]
}
return []
}
+9
View File
@@ -0,0 +1,9 @@
import { inBrowser } from 'vitepress'
// 判断当前页面是否为移动端
export function isMobile() {
if (inBrowser) {
return /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
}
return false;
}