feat(theme): add support for blog category expand depth, close #271 (#275)

This commit is contained in:
pengzhanbo 2024-10-13 15:23:50 +08:00 committed by GitHub
parent c32dd3eb93
commit c6907dfe74
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 82 additions and 21 deletions

View File

@ -96,18 +96,47 @@ interface BlogOptions {
* @default true
*/
tags?: boolean
/**
* 自定义标签页链接
*
* @default '/blog/tags/'
*/
tagsLink?: string
/**
* 是否启用归档页
* @default true
*/
archives?: boolean
/**
* 自定义归档页链接
*
* @default '/blog/archives/'
*/
archivesLink?: string
/**
* 是否启用分类页
* @default true
*/
categories?: boolean
/**
* 自定义分类页链接
*
* @default '/blog/categories/'
*/
categoriesLink?: string
/**
* 分类页展开深度
*
* @default 'deep'
*/
categoriesExpand?: number | 'deep'
/**
* 博客文章封面图
*

View File

@ -18,7 +18,7 @@ const { categories } = useBlogCategory()
<slot name="blog-categories-content-before" />
<div class="content">
<VPCategories :items="categories" />
<VPCategories :items="categories" :depth="0" />
</div>
<slot name="blog-categories-after" />

View File

@ -3,9 +3,12 @@ import type { BlogCategoryItem, BlogCategoryItemWithPost } from '../../composabl
import VPCategoriesGroup from '@theme/Blog/VPCategoriesGroup.vue'
import VPLink from '@theme/VPLink.vue'
defineProps<{
withDefaults(defineProps<{
items: (BlogCategoryItem | BlogCategoryItemWithPost)[]
}>()
depth?: number
}>(), {
depth: 0,
})
</script>
<template>
@ -19,7 +22,7 @@ defineProps<{
<span class="vpi-post" />
<VPLink :href="item.path" :text="item.title" />
</p>
<VPCategoriesGroup v-else :item="item" />
<VPCategoriesGroup v-else :item="item" :depth="depth + 1" />
</li>
</ul>
</template>

View File

@ -1,53 +1,68 @@
<script setup lang="ts">
import type { BlogCategoryItem } from '../../composables/index.js'
import VPCategories from '@theme/Blog/VPCategories.vue'
import { onMounted, ref, watch } from 'vue'
import { computed, onMounted, ref, watch } from 'vue'
import { useRoute } from 'vuepress/client'
import { useData } from '../../composables/index.js'
const props = defineProps<{
const props = withDefaults(defineProps<{
item: BlogCategoryItem
}>()
depth?: number
}>(), {
depth: 0,
})
const { theme } = useData()
const route = useRoute()
const el = ref<HTMLDivElement | null>(null)
const active = ref(true)
const isActive = ref(false)
const expand = ref(true)
const isExpand = ref(false)
const expandDepth = computed(() => {
const blog = typeof theme.value.blog === 'boolean' ? {} : theme.value.blog
const depth = blog?.categoriesExpand ?? 'deep'
if (depth === 'deep')
return Infinity
const d = Number(depth)
if (Number.isNaN(d))
return Infinity
return d
})
watch(
() => [route.query, props.item],
() => [route.query, props.item, expandDepth.value],
() => {
const id = route.query.id as string
if (!id) {
active.value = true
expand.value = props.depth <= expandDepth.value
}
else {
active.value = hasActive(props.item, id)
expand.value = hasExpand(props.item, id)
}
isActive.value = id ? props.item.id === id : false
isExpand.value = id ? props.item.id === id : false
},
{ immediate: true },
)
function hasActive(item: BlogCategoryItem, id: string) {
function hasExpand(item: BlogCategoryItem, id: string) {
return item.id === id
|| item.items.filter(item => item.type === 'category').some(item => hasActive(item, id))
|| item.items.filter(item => item.type === 'category').some(item => hasExpand(item, id))
}
function toggle() {
active.value = !active.value
expand.value = !expand.value
}
onMounted(() => {
if (el.value && isActive.value) {
if (el.value && isExpand.value) {
el.value.scrollIntoView({ block: 'center' })
}
})
</script>
<template>
<div ref="el" class="vp-category-group" :class="{ active }">
<div ref="el" class="vp-category-group" :class="{ expand }">
<p class="folder" @click="toggle">
<span class="icon" :class="[active ? 'vpi-folder-open' : 'vpi-folder']" />
<span class="icon" :class="[expand ? 'vpi-folder-open' : 'vpi-folder']" />
<span>{{ item.title }}</span>
</p>
@ -55,6 +70,7 @@ onMounted(() => {
v-if="item.items.length"
class="group"
:items="item.items"
:depth="depth"
/>
</div>
</template>
@ -113,7 +129,7 @@ onMounted(() => {
}
}
.vp-category-group.active > .group {
.vp-category-group.expand > .group {
display: block;
}
</style>

View File

@ -64,6 +64,12 @@ function sortCategory(items: BlogCategory): BlogCategory {
if (a.type === 'category' && b.type === 'category') {
return a.sort < b.sort ? -1 : 1
}
if (a.type === 'category' && b.type === 'post') {
return -1
}
if (a.type === 'post' && b.type === 'category') {
return 1
}
return 0
})
}

View File

@ -100,6 +100,13 @@ export interface PlumeThemeBlog {
*/
categoriesLink?: string
/**
*
*
* @default 'deep'
*/
categoriesExpand?: number | 'deep'
/**
*
*