mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
perf(theme): 优化侧边栏数据自动生成
This commit is contained in:
parent
cfbea845a4
commit
766285e8f8
@ -116,7 +116,7 @@ export const zhNotes = definePlumeNotesConfig({
|
||||
{
|
||||
text: 'plugin-netlify-functions',
|
||||
dir: 'netlify-functions',
|
||||
link: '/plugins/plugin-netlify-functions/',
|
||||
link: 'plugin-netlify-functions/',
|
||||
items: [
|
||||
'介绍',
|
||||
'使用',
|
||||
|
||||
@ -23,6 +23,7 @@ import { isActive, normalizeLink, normalizePrefix, resolveNavLink } from '../uti
|
||||
import type { Sidebar, SidebarItem } from '../../shared/index.js'
|
||||
import type { ResolvedSidebarItem } from '../../shared/resolved/sidebar.js'
|
||||
import { useData } from './data.js'
|
||||
import { useEncrypt } from './encrypt.js'
|
||||
|
||||
export type SidebarData = Record<string, Sidebar>
|
||||
|
||||
@ -229,6 +230,7 @@ export function useSidebar(): UseSidebarReturn {
|
||||
const { theme, frontmatter, page } = useData()
|
||||
const routeLocal = useRouteLocale()
|
||||
const is960 = useMediaQuery('(min-width: 960px)')
|
||||
const { isPageDecrypted } = useEncrypt()
|
||||
|
||||
const isOpen = ref(false)
|
||||
|
||||
@ -257,6 +259,13 @@ export function useSidebar(): UseSidebarReturn {
|
||||
const hasAside = computed(() => {
|
||||
if (frontmatter.value.pageLayout === 'home' || frontmatter.value.home)
|
||||
return false
|
||||
|
||||
if (frontmatter.value.pageLayout === 'friends' || frontmatter.value.friends)
|
||||
return false
|
||||
|
||||
if (!isPageDecrypted.value)
|
||||
return false
|
||||
|
||||
if (frontmatter.value.aside != null)
|
||||
return !!frontmatter.value.aside
|
||||
return theme.value.aside !== false
|
||||
|
||||
@ -101,7 +101,7 @@ export function resolveOptions(
|
||||
const note = findNote(relativePath)
|
||||
if (note?.text)
|
||||
return note.text
|
||||
return getCurrentDirname(note?.dir, relativePath) || ''
|
||||
return getCurrentDirname('', relativePath) || ''
|
||||
},
|
||||
...baseFrontmatter,
|
||||
permalink(permalink: string, { relativePath }, data: any) {
|
||||
|
||||
@ -1,6 +1,17 @@
|
||||
import type { App, Page } from 'vuepress'
|
||||
import { entries, isArray, isPlainObject, removeLeadingSlash } from '@vuepress/helper'
|
||||
import type { PlumeThemeLocaleOptions, PlumeThemePageData, Sidebar, SidebarItem, ThemeIcon } from '../../shared/index.js'
|
||||
import {
|
||||
entries,
|
||||
isArray,
|
||||
isPlainObject,
|
||||
removeLeadingSlash,
|
||||
} from '@vuepress/helper'
|
||||
import type {
|
||||
PlumeThemeLocaleOptions,
|
||||
PlumeThemePageData,
|
||||
Sidebar,
|
||||
SidebarItem,
|
||||
ThemeIcon,
|
||||
} from '../../shared/index.js'
|
||||
import { normalizeLink, resolveContent, writeTemp } from '../utils/index.js'
|
||||
import type { ResolvedSidebarItem } from '../../shared/resolved/sidebar.js'
|
||||
|
||||
@ -53,6 +64,14 @@ function getSidebarData(
|
||||
return resolved
|
||||
}
|
||||
|
||||
const MD_RE = /\.md$/
|
||||
const NUMBER_RE = /^\d+\./
|
||||
function resolveTitle(dirname: string) {
|
||||
return dirname
|
||||
.replace(MD_RE, '')
|
||||
.replace(NUMBER_RE, '')
|
||||
}
|
||||
|
||||
function getAutoDirSidebar(
|
||||
app: App,
|
||||
localePath: string,
|
||||
@ -80,6 +99,7 @@ function getAutoDirSidebar(
|
||||
}
|
||||
|
||||
const RE_INDEX = ['index.md', 'README.md', 'readme.md']
|
||||
|
||||
const result: ResolvedSidebarItem[] = []
|
||||
for (const page of pages) {
|
||||
const { data, title, path, frontmatter } = page
|
||||
@ -90,25 +110,37 @@ function getAutoDirSidebar(
|
||||
let index = 0
|
||||
let dir: string
|
||||
let items = result
|
||||
let parent: ResolvedSidebarItem | undefined
|
||||
// eslint-disable-next-line no-cond-assign
|
||||
while ((dir = paths[index])) {
|
||||
const text = dir.replace(/\.md$/, '').replace(/^\d+\./, '')
|
||||
const text = resolveTitle(dir)
|
||||
const isHome = RE_INDEX.includes(dir)
|
||||
let current = items.find(item => item.text === text)
|
||||
if (!current) {
|
||||
current = { text, link: undefined, items: [] } as ResolvedSidebarItem
|
||||
!RE_INDEX.includes(dir) ? items.push(current) : items.unshift(current)
|
||||
if (!isHome) {
|
||||
items.push(current)
|
||||
}
|
||||
else {
|
||||
!parent && items.unshift(current)
|
||||
}
|
||||
}
|
||||
if (dir.endsWith('.md')) {
|
||||
current.link = path
|
||||
current.text = title
|
||||
if (isHome && parent) {
|
||||
parent.link = path
|
||||
}
|
||||
else {
|
||||
current.link = path
|
||||
current.text = title
|
||||
}
|
||||
}
|
||||
if (frontmatter.icon)
|
||||
if (frontmatter.icon) {
|
||||
current.icon = frontmatter.icon as ThemeIcon
|
||||
|
||||
if (index > 0) {
|
||||
current.collapsed = false
|
||||
}
|
||||
|
||||
if (parent?.items?.length) {
|
||||
parent.collapsed = true
|
||||
}
|
||||
parent = current
|
||||
items = current.items as ResolvedSidebarItem[]
|
||||
index++
|
||||
}
|
||||
|
||||
@ -2,17 +2,19 @@ import {
|
||||
ensureLeadingSlash,
|
||||
getRootLang,
|
||||
getRootLangPath,
|
||||
removeLeadingSlash,
|
||||
} from '@vuepress/helper'
|
||||
import type { App, Page } from 'vuepress/core'
|
||||
import { createPage } from 'vuepress/core'
|
||||
import { createFilter } from 'create-filter'
|
||||
import type {
|
||||
PageCategoryData,
|
||||
PlumeThemeLocaleOptions,
|
||||
PlumeThemePageData,
|
||||
} from '../shared/index.js'
|
||||
import { withBase } from './utils/index.js'
|
||||
import { normalizePath, withBase } from './utils/index.js'
|
||||
import { PRESET_LOCALES } from './locales/index.js'
|
||||
import { resolveNotesLinkList } from './config/index.js'
|
||||
import { resolveNotesLinkList, resolveNotesOptions } from './config/index.js'
|
||||
|
||||
export async function setupPage(
|
||||
app: App,
|
||||
@ -56,6 +58,35 @@ export async function setupPage(
|
||||
app.pages.push(...await Promise.all(pageList))
|
||||
}
|
||||
|
||||
const weakFilter = new WeakMap<PlumeThemeLocaleOptions, (id: string | undefined) => boolean>()
|
||||
|
||||
function createBlogFilter(localeOptions: PlumeThemeLocaleOptions) {
|
||||
if (weakFilter.has(localeOptions))
|
||||
return weakFilter.get(localeOptions)!
|
||||
|
||||
const blog = localeOptions.blog || {}
|
||||
const notesList = resolveNotesOptions(localeOptions)
|
||||
const notesDirList = notesList
|
||||
.map(notes => removeLeadingSlash(normalizePath(`${notes.dir}/**`)))
|
||||
.filter(Boolean)
|
||||
|
||||
const filter = createFilter(
|
||||
blog.include ?? ['**/*.md'],
|
||||
[
|
||||
'**/{README,readme,index}.md',
|
||||
'.vuepress/',
|
||||
'node_modules/',
|
||||
...(blog.exclude ?? []),
|
||||
...notesDirList,
|
||||
].filter(Boolean),
|
||||
{ resolve: false },
|
||||
)
|
||||
|
||||
weakFilter.set(localeOptions, filter)
|
||||
|
||||
return filter
|
||||
}
|
||||
|
||||
export function extendsPageData(
|
||||
page: Page<PlumeThemePageData>,
|
||||
localeOptions: PlumeThemeLocaleOptions,
|
||||
@ -63,6 +94,10 @@ export function extendsPageData(
|
||||
page.data.filePathRelative = page.filePathRelative
|
||||
page.routeMeta.title = page.frontmatter.title || page.title
|
||||
|
||||
if (createBlogFilter(localeOptions)(page.filePathRelative || '')) {
|
||||
page.data.isBlogPost = true
|
||||
}
|
||||
|
||||
if (page.frontmatter.icon) {
|
||||
page.routeMeta.icon = page.frontmatter.icon
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user