mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-24 11:08:16 +08:00
118 lines
3.2 KiB
TypeScript
118 lines
3.2 KiB
TypeScript
import { resolveRouteFullPath, usePageLang, useRoute } from 'vuepress/client'
|
|
import { isPlainObject, isString } from 'vuepress/shared'
|
|
import { computed } from 'vue'
|
|
import type { Ref } from 'vue'
|
|
import type { NavItemWithLink, PlumeThemeBlogPostItem, SidebarItem } from '../../shared/index.js'
|
|
import { resolveNavLink } from '../utils/index.js'
|
|
import { useBlogPostData } from './blog-data.js'
|
|
import { useSidebar } from './sidebar.js'
|
|
import { useData } from './data.js'
|
|
|
|
export function usePrevNext() {
|
|
const route = useRoute()
|
|
const { page, frontmatter } = useData()
|
|
const { sidebar } = useSidebar()
|
|
const postList = useBlogPostData() as unknown as Ref<PlumeThemeBlogPostItem[]>
|
|
const locale = usePageLang()
|
|
|
|
const prevNavList = computed(() => {
|
|
const prevConfig = resolveFromFrontmatterConfig(frontmatter.value.prev)
|
|
if (prevConfig !== false)
|
|
return prevConfig
|
|
|
|
if (page.value.isBlogPost) {
|
|
return resolveFromBlogPostData(
|
|
postList.value.filter(item => item.lang === locale.value),
|
|
route.path,
|
|
-1,
|
|
)
|
|
}
|
|
else {
|
|
return resolveFromSidebarItems(flatSidebar(sidebar.value), route.path, -1)
|
|
}
|
|
})
|
|
|
|
const nextNavList = computed(() => {
|
|
const nextConfig = resolveFromFrontmatterConfig(frontmatter.value.next)
|
|
if (nextConfig !== false)
|
|
return nextConfig
|
|
|
|
if (page.value.isBlogPost) {
|
|
return resolveFromBlogPostData(
|
|
postList.value.filter(item => item.lang === locale.value),
|
|
route.path,
|
|
1,
|
|
)
|
|
}
|
|
else {
|
|
return resolveFromSidebarItems(flatSidebar(sidebar.value), route.path, 1)
|
|
}
|
|
})
|
|
|
|
return {
|
|
prev: prevNavList,
|
|
next: nextNavList,
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Resolve `prev` or `next` config from frontmatter
|
|
*/
|
|
function resolveFromFrontmatterConfig(conf: unknown): null | false | NavItemWithLink {
|
|
if (conf === false)
|
|
return null
|
|
|
|
if (isString(conf))
|
|
return resolveNavLink(conf)
|
|
|
|
if (isPlainObject<NavItemWithLink>(conf))
|
|
return conf
|
|
|
|
return false
|
|
}
|
|
|
|
function flatSidebar(sidebar: SidebarItem[], res: NavItemWithLink[] = []): NavItemWithLink[] {
|
|
for (const item of sidebar) {
|
|
if (item.link)
|
|
res.push({ link: item.link, text: item.text || item.dir || '' })
|
|
|
|
if (Array.isArray(item.items) && item.items.length)
|
|
flatSidebar(item.items as SidebarItem[], res)
|
|
}
|
|
|
|
return res
|
|
}
|
|
|
|
/**
|
|
* Resolve `prev` or `next` config from sidebar items
|
|
*/
|
|
function resolveFromSidebarItems(sidebarItems: NavItemWithLink[], currentPath: string, offset: number): null | NavItemWithLink {
|
|
const index = sidebarItems.findIndex(item => resolveRouteFullPath(item.link) === currentPath)
|
|
if (index !== -1) {
|
|
const targetItem = sidebarItems[index + offset]
|
|
if (targetItem?.link) {
|
|
return {
|
|
link: targetItem.link,
|
|
text: targetItem.text,
|
|
}
|
|
}
|
|
}
|
|
|
|
return null
|
|
}
|
|
|
|
function resolveFromBlogPostData(postList: PlumeThemeBlogPostItem[], currentPath: string, offset: number): null | NavItemWithLink {
|
|
const index = postList.findIndex(item => item.path === currentPath)
|
|
if (index !== -1) {
|
|
const targetItem = postList[index + offset]
|
|
if (!targetItem?.path)
|
|
return null
|
|
|
|
return {
|
|
link: targetItem.path,
|
|
text: targetItem.title,
|
|
}
|
|
}
|
|
return null
|
|
}
|