mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
perf(theme): optimize the startup time of auto-frontmatter (#185)
This commit is contained in:
parent
4907bf4b29
commit
5b5409d2ef
21
theme/src/node/autoFrontmatter/baseFrontmatter.ts
Normal file
21
theme/src/node/autoFrontmatter/baseFrontmatter.ts
Normal file
@ -0,0 +1,21 @@
|
||||
import { format } from 'date-fns'
|
||||
import type {
|
||||
AutoFrontmatter,
|
||||
AutoFrontmatterObject,
|
||||
} from '../../shared/index.js'
|
||||
|
||||
export function createBaseFrontmatter(options: AutoFrontmatter): AutoFrontmatterObject {
|
||||
const res: AutoFrontmatterObject = {}
|
||||
|
||||
if (options.createTime !== false) {
|
||||
res.createTime = (formatTime: string, { createTime }, data) => {
|
||||
if (formatTime)
|
||||
return formatTime
|
||||
if (data.friends || data.pageLayout === 'friends')
|
||||
return
|
||||
return format(new Date(createTime), 'yyyy/MM/dd HH:mm:ss')
|
||||
}
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
@ -3,7 +3,7 @@ import chokidar from 'chokidar'
|
||||
import { createFilter } from 'create-filter'
|
||||
import grayMatter from 'gray-matter'
|
||||
import jsonToYaml from 'json2yaml'
|
||||
import { fs, hash } from 'vuepress/utils'
|
||||
import { fs, hash, path } from 'vuepress/utils'
|
||||
import type { App } from 'vuepress'
|
||||
import { getThemeConfig } from '../loadConfig/index.js'
|
||||
import { readMarkdown, readMarkdownList } from './readFile.js'
|
||||
@ -16,6 +16,8 @@ import type {
|
||||
PlumeThemeLocaleOptions,
|
||||
} from '../../shared/index.js'
|
||||
|
||||
const CACHE_FILE = 'markdown/auto-frontmatter.json'
|
||||
|
||||
export interface Generate {
|
||||
globFilter: (id?: string) => boolean
|
||||
global: AutoFrontmatterObject
|
||||
@ -24,6 +26,9 @@ export interface Generate {
|
||||
filter: (id?: string) => boolean
|
||||
frontmatter: AutoFrontmatterObject
|
||||
}[]
|
||||
cache: Record<string, string>
|
||||
checkCache: (id: string) => boolean
|
||||
updateCache: (app: App) => Promise<void>
|
||||
}
|
||||
|
||||
let generate: Generate | null = null
|
||||
@ -53,21 +58,46 @@ export function initAutoFrontmatter(
|
||||
}
|
||||
})
|
||||
|
||||
const cache: Record<string, string> = {}
|
||||
|
||||
function checkCache(filepath: string): boolean {
|
||||
const stats = fs.statSync(filepath)
|
||||
|
||||
if (cache[filepath] && cache[filepath] === stats.mtimeMs.toString())
|
||||
return false
|
||||
cache[filepath] = stats.mtimeMs.toString()
|
||||
return true
|
||||
}
|
||||
|
||||
async function updateCache(app: App): Promise<void> {
|
||||
await fs.writeFile(app.dir.cache(CACHE_FILE), JSON.stringify(cache), 'utf-8')
|
||||
}
|
||||
|
||||
generate = {
|
||||
globFilter,
|
||||
global: globalConfig,
|
||||
rules,
|
||||
cache,
|
||||
checkCache,
|
||||
updateCache,
|
||||
}
|
||||
}
|
||||
|
||||
export async function generateAutoFrontmatter(app: App) {
|
||||
if (!generate)
|
||||
return
|
||||
const markdownList = await readMarkdownList(app.dir.source(), generate.globFilter)
|
||||
|
||||
const cachePath = app.dir.cache(CACHE_FILE)
|
||||
if (fs.existsSync(cachePath)) {
|
||||
generate.cache = JSON.parse(await fs.readFile(cachePath, 'utf-8'))
|
||||
}
|
||||
const markdownList = await readMarkdownList(app, generate)
|
||||
await promiseParallel(
|
||||
markdownList.map(file => () => generator(file)),
|
||||
64,
|
||||
)
|
||||
|
||||
await generate.updateCache(app)
|
||||
}
|
||||
|
||||
export async function watchAutoFrontmatter(app: App, watchers: any[]) {
|
||||
@ -88,6 +118,14 @@ export async function watchAutoFrontmatter(app: App, watchers: any[]) {
|
||||
await generator(file)
|
||||
})
|
||||
|
||||
watcher.on('change', async (relativePath) => {
|
||||
const enabled = getThemeConfig().autoFrontmatter !== false
|
||||
if (!generate!.globFilter(relativePath) || !enabled)
|
||||
return
|
||||
if (generate!.checkCache(path.join(app.dir.source(), relativePath)))
|
||||
await generate!.updateCache(app)
|
||||
})
|
||||
|
||||
watchers.push(watcher)
|
||||
}
|
||||
|
||||
@ -103,8 +141,11 @@ async function generator(file: AutoFrontmatterMarkdownFile): Promise<void> {
|
||||
const beforeHash = hash(data)
|
||||
|
||||
for (const key in formatter) {
|
||||
const value = await formatter[key](data[key], file, data)
|
||||
data[key] = value ?? data[key]
|
||||
const value = (await formatter[key](data[key], file, data)) ?? data[key]
|
||||
if (typeof value !== 'undefined')
|
||||
data[key] = value
|
||||
else
|
||||
delete data[key]
|
||||
}
|
||||
|
||||
if (beforeHash === hash(data))
|
||||
@ -121,6 +162,7 @@ async function generator(file: AutoFrontmatterMarkdownFile): Promise<void> {
|
||||
const newContent = yaml ? `${yaml}---\n${content}` : content
|
||||
|
||||
await fs.promises.writeFile(filepath, newContent, 'utf-8')
|
||||
generate.checkCache(filepath)
|
||||
}
|
||||
catch (e) {
|
||||
console.error(e)
|
||||
|
||||
@ -1,20 +1,27 @@
|
||||
import fg from 'fast-glob'
|
||||
import { fs, path } from 'vuepress/utils'
|
||||
import type { App } from 'vuepress'
|
||||
import type { AutoFrontmatterMarkdownFile } from '../../shared/index.js'
|
||||
import type { Generate } from './generator.js'
|
||||
|
||||
export async function readMarkdownList(
|
||||
sourceDir: string,
|
||||
filter: (id: string) => boolean,
|
||||
app: App,
|
||||
{ globFilter, checkCache }: Generate,
|
||||
): Promise<AutoFrontmatterMarkdownFile[]> {
|
||||
const source = app.dir.source()
|
||||
const files: string[] = await fg(['**/*.md'], {
|
||||
cwd: sourceDir,
|
||||
cwd: source,
|
||||
ignore: ['node_modules', '.vuepress'],
|
||||
})
|
||||
|
||||
return await Promise.all(
|
||||
files
|
||||
.filter(filter)
|
||||
.map(file => readMarkdown(sourceDir, file)),
|
||||
.filter((id) => {
|
||||
if (!globFilter(id))
|
||||
return false
|
||||
return checkCache(path.join(source, id))
|
||||
})
|
||||
.map(file => readMarkdown(source, file)),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
51
theme/src/node/autoFrontmatter/resolveLinkBySidebar.ts
Normal file
51
theme/src/node/autoFrontmatter/resolveLinkBySidebar.ts
Normal file
@ -0,0 +1,51 @@
|
||||
import { pathJoin } from '../utils/index.js'
|
||||
import type { SidebarItem } from '../../shared/index.js'
|
||||
|
||||
export function resolveLinkBySidebar(
|
||||
sidebar: 'auto' | (string | SidebarItem)[],
|
||||
_prefix: string,
|
||||
) {
|
||||
const res: Record<string, string> = {}
|
||||
|
||||
if (sidebar === 'auto') {
|
||||
return res
|
||||
}
|
||||
|
||||
for (const item of sidebar) {
|
||||
if (typeof item !== 'string') {
|
||||
const { prefix, dir = '', link = '/', items, text = '' } = item
|
||||
getSidebarLink(items, link, text, pathJoin(_prefix, prefix || dir), res)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function getSidebarLink(items: 'auto' | (string | SidebarItem)[] | undefined, link: string, text: string, dir = '', res: Record<string, string> = {}) {
|
||||
if (items === 'auto')
|
||||
return
|
||||
|
||||
if (!items) {
|
||||
res[pathJoin(dir, `${text}.md`)] = link
|
||||
return
|
||||
}
|
||||
|
||||
for (const item of items) {
|
||||
if (typeof item === 'string') {
|
||||
if (!link)
|
||||
continue
|
||||
if (item) {
|
||||
res[pathJoin(dir, `${item}.md`)] = link
|
||||
}
|
||||
else {
|
||||
res[pathJoin(dir, 'README.md')] = link
|
||||
res[pathJoin(dir, 'index.md')] = link
|
||||
res[pathJoin(dir, 'readme.md')] = link
|
||||
}
|
||||
res[dir] = link
|
||||
}
|
||||
else {
|
||||
const { prefix, dir: subDir = '', link: subLink = '/', items: subItems, text: subText = '' } = item
|
||||
getSidebarLink(subItems, pathJoin(link, subLink), subText, pathJoin(prefix || dir, subDir), res)
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1,65 +1,35 @@
|
||||
import { uniq } from '@pengzhanbo/utils'
|
||||
import { ensureLeadingSlash } from '@vuepress/helper'
|
||||
import { format } from 'date-fns'
|
||||
import { removeLeadingSlash, resolveLocalePath } from 'vuepress/shared'
|
||||
import { resolveLocalePath } from 'vuepress/shared'
|
||||
import { path } from 'vuepress/utils'
|
||||
import { resolveNotesOptions } from '../config/index.js'
|
||||
import {
|
||||
getCurrentDirname,
|
||||
nanoid,
|
||||
normalizePath,
|
||||
pathJoin,
|
||||
withBase,
|
||||
} from '../utils/index.js'
|
||||
import { resolveNotesDirs } from '../config/index.js'
|
||||
import { getCurrentDirname, nanoid, normalizePath, pathJoin, withBase } from '../utils/index.js'
|
||||
import { createBaseFrontmatter } from './baseFrontmatter.js'
|
||||
import { resolveLinkBySidebar } from './resolveLinkBySidebar.js'
|
||||
import type {
|
||||
AutoFrontmatter,
|
||||
AutoFrontmatterArray,
|
||||
AutoFrontmatterObject,
|
||||
NoteItem,
|
||||
NotesOptions,
|
||||
PlumeThemeLocaleOptions,
|
||||
SidebarItem,
|
||||
} from '../../shared/index.js'
|
||||
|
||||
export function resolveOptions(
|
||||
localeOptions: PlumeThemeLocaleOptions,
|
||||
options: AutoFrontmatter,
|
||||
): AutoFrontmatter {
|
||||
const { article: articlePrefix = '/article/' } = localeOptions
|
||||
const resolveLocale = (relativeFilepath: string): string =>
|
||||
resolveLocalePath(localeOptions.locales!, ensureLeadingSlash(relativeFilepath))
|
||||
|
||||
const resolveLocale = (relativeFilepath: string) => {
|
||||
const file = ensureLeadingSlash(relativeFilepath)
|
||||
|
||||
return resolveLocalePath(localeOptions.locales!, file)
|
||||
}
|
||||
|
||||
const notesList = resolveNotesOptions(localeOptions)
|
||||
const localesNotesDirs = uniq(notesList
|
||||
.flatMap(({ notes, dir }) =>
|
||||
notes.map(note => removeLeadingSlash(normalizePath(`${dir}/${note.dir || ''}/`))),
|
||||
))
|
||||
|
||||
const baseFrontmatter: AutoFrontmatterObject = {}
|
||||
|
||||
if (options.createTime !== false) {
|
||||
baseFrontmatter.createTime = (formatTime: string, { createTime }, data) => {
|
||||
if (formatTime)
|
||||
return formatTime
|
||||
if (data.friends || data.pageLayout === 'friends')
|
||||
return
|
||||
return format(new Date(createTime), 'yyyy/MM/dd HH:mm:ss')
|
||||
}
|
||||
}
|
||||
|
||||
const notesByLocale = (locale: string) => {
|
||||
const findNotesByLocale = (locale: string): NotesOptions | undefined => {
|
||||
const notes = localeOptions.locales?.[locale]?.notes
|
||||
if (notes === false)
|
||||
return undefined
|
||||
return notes
|
||||
return notes === false ? undefined : notes
|
||||
}
|
||||
|
||||
const findNote = (relativeFilepath: string) => {
|
||||
const findNote = (relativeFilepath: string): NoteItem | undefined => {
|
||||
const locale = resolveLocale(relativeFilepath)
|
||||
const filepath = ensureLeadingSlash(relativeFilepath)
|
||||
const notes = notesByLocale(locale)
|
||||
const notes = findNotesByLocale(locale)
|
||||
if (!notes)
|
||||
return undefined
|
||||
const notesList = notes?.notes || []
|
||||
@ -69,217 +39,145 @@ export function resolveOptions(
|
||||
)
|
||||
}
|
||||
|
||||
const baseFrontmatter = createBaseFrontmatter(options)
|
||||
const localesNotesDirs = resolveNotesDirs(localeOptions)
|
||||
const configs: AutoFrontmatterArray = []
|
||||
|
||||
if (localesNotesDirs.length) {
|
||||
// note 首页
|
||||
configs.push({
|
||||
include: localesNotesDirs.map(dir => pathJoin(dir, '/{readme,README,index}.md')),
|
||||
frontmatter: {
|
||||
title(title: string, { relativePath }) {
|
||||
if (title)
|
||||
return title
|
||||
if (options.title === false)
|
||||
return
|
||||
return findNote(relativePath)?.text || getCurrentDirname('', relativePath)
|
||||
},
|
||||
...baseFrontmatter,
|
||||
permalink(permalink: string, { relativePath }, data: any) {
|
||||
if (permalink)
|
||||
return permalink
|
||||
if (options.permalink === false || data.friends || data.pageLayout === 'friends')
|
||||
return
|
||||
|
||||
const locale = resolveLocale(relativePath)
|
||||
const prefix = findNotesByLocale(locale)?.link || ''
|
||||
const note = findNote(relativePath)
|
||||
return pathJoin(
|
||||
prefix.startsWith(locale) ? '/' : locale,
|
||||
prefix,
|
||||
note?.link || getCurrentDirname(note?.dir, relativePath),
|
||||
'/',
|
||||
)
|
||||
},
|
||||
},
|
||||
})
|
||||
// note page
|
||||
configs.push({
|
||||
include: localesNotesDirs.map(dir => `${dir}**/**.md`),
|
||||
frontmatter: {
|
||||
title(title: string, { relativePath }) {
|
||||
if (title)
|
||||
return title
|
||||
if (options.title === false)
|
||||
return
|
||||
return path.basename(relativePath, '.md').replace(/^\d+\./, '')
|
||||
},
|
||||
...baseFrontmatter,
|
||||
permalink(permalink: string, { relativePath }, data) {
|
||||
if (permalink)
|
||||
return permalink
|
||||
if (options.permalink === false)
|
||||
return
|
||||
if (data.friends || data.pageLayout === 'friends')
|
||||
return
|
||||
const locale = resolveLocale(relativePath)
|
||||
const notes = findNotesByLocale(locale)
|
||||
const note = findNote(relativePath)
|
||||
const prefix = notes?.link || ''
|
||||
const args: string[] = [
|
||||
prefix.startsWith(locale) ? '/' : locale,
|
||||
prefix,
|
||||
note?.link || '',
|
||||
]
|
||||
const sidebar = note?.sidebar
|
||||
|
||||
if (note && sidebar && sidebar !== 'auto') {
|
||||
const res = resolveLinkBySidebar(sidebar, pathJoin(notes?.dir || '', note.dir || ''))
|
||||
const file = ensureLeadingSlash(relativePath)
|
||||
if (res[file]) {
|
||||
args.push(res[file])
|
||||
}
|
||||
else if (res[path.dirname(file)]) {
|
||||
args.push(res[path.dirname(file)])
|
||||
}
|
||||
}
|
||||
|
||||
return pathJoin(...args, nanoid(), '/')
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
// 未知 readme 不处理
|
||||
configs.push({
|
||||
include: '**/{readme,README,index}.md',
|
||||
frontmatter: {},
|
||||
})
|
||||
|
||||
if (localeOptions.blog !== false) {
|
||||
// 博客文章
|
||||
configs.push({
|
||||
include: localeOptions.blog?.include ?? ['**/*.md'],
|
||||
frontmatter: {
|
||||
title(title: string, { relativePath }) {
|
||||
if (title)
|
||||
return title
|
||||
if (options.title === false)
|
||||
return
|
||||
return path.basename(relativePath || '', '.md')
|
||||
},
|
||||
...baseFrontmatter,
|
||||
permalink(permalink: string, { relativePath }) {
|
||||
if (permalink)
|
||||
return permalink
|
||||
if (options.permalink === false)
|
||||
return
|
||||
const locale = resolveLocale(relativePath)
|
||||
const prefix = withBase(localeOptions.article || '/article/', locale)
|
||||
|
||||
return normalizePath(`${prefix}/${nanoid()}/`)
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
// 其他
|
||||
configs.push({
|
||||
include: '*',
|
||||
frontmatter: {
|
||||
title(title: string, { relativePath }) {
|
||||
if (title)
|
||||
return title
|
||||
if (options.title === false)
|
||||
return
|
||||
return path.basename(relativePath || '', '.md')
|
||||
},
|
||||
...baseFrontmatter,
|
||||
permalink(permalink: string, { relativePath }) {
|
||||
if (permalink)
|
||||
return permalink
|
||||
if (options.permalink === false)
|
||||
return
|
||||
return ensureLeadingSlash(normalizePath(relativePath.replace(/\.md$/, '/')))
|
||||
},
|
||||
},
|
||||
})
|
||||
|
||||
return {
|
||||
include: options?.include ?? ['**/*.md'],
|
||||
exclude: uniq(['.vuepress/**/*', 'node_modules', ...(options?.exclude ?? [])]),
|
||||
|
||||
frontmatter: [
|
||||
localesNotesDirs.length
|
||||
? {
|
||||
// note 首页链接
|
||||
include: localesNotesDirs.map(dir => pathJoin(dir, '/{readme,README,index}.md')),
|
||||
frontmatter: {
|
||||
...options.title !== false
|
||||
? {
|
||||
title(title: string, { relativePath }) {
|
||||
if (title)
|
||||
return title
|
||||
const note = findNote(relativePath)
|
||||
if (note?.text)
|
||||
return note.text
|
||||
return getCurrentDirname('', relativePath) || ''
|
||||
},
|
||||
} as AutoFrontmatterObject
|
||||
: undefined,
|
||||
...baseFrontmatter,
|
||||
...options.permalink !== false
|
||||
? {
|
||||
permalink(permalink: string, { relativePath }, data: any) {
|
||||
if (permalink)
|
||||
return permalink
|
||||
if (data.friends)
|
||||
return
|
||||
const locale = resolveLocale(relativePath)
|
||||
|
||||
const prefix = notesByLocale(locale)?.link || ''
|
||||
const note = findNote(relativePath)
|
||||
return pathJoin(
|
||||
prefix.startsWith(locale) ? '/' : locale,
|
||||
prefix,
|
||||
note?.link || getCurrentDirname(note?.dir, relativePath),
|
||||
'/',
|
||||
)
|
||||
},
|
||||
} as AutoFrontmatterObject
|
||||
: undefined,
|
||||
},
|
||||
}
|
||||
: '',
|
||||
localesNotesDirs.length
|
||||
? {
|
||||
include: localesNotesDirs.map(dir => `${dir}**/**.md`),
|
||||
frontmatter: {
|
||||
...options.title !== false
|
||||
? {
|
||||
title(title: string, { relativePath }) {
|
||||
if (title)
|
||||
return title
|
||||
|
||||
const note = findNote(relativePath)
|
||||
let basename = path.basename(relativePath, '.md')
|
||||
if (note?.sidebar === 'auto')
|
||||
basename = basename.replace(/^\d+\./, '')
|
||||
|
||||
return basename
|
||||
},
|
||||
} as AutoFrontmatterObject
|
||||
: undefined,
|
||||
...baseFrontmatter,
|
||||
...options.permalink !== false
|
||||
? {
|
||||
permalink(permalink: string, { relativePath }, data: any) {
|
||||
if (permalink)
|
||||
return permalink
|
||||
if (data.friends)
|
||||
return
|
||||
const locale = resolveLocale(relativePath)
|
||||
const notes = notesByLocale(locale)
|
||||
const note = findNote(relativePath)
|
||||
const prefix = notes?.link || ''
|
||||
const args: string[] = [
|
||||
prefix.startsWith(locale) ? '/' : locale,
|
||||
prefix,
|
||||
note?.link || '',
|
||||
]
|
||||
const sidebar = note?.sidebar
|
||||
|
||||
if (note && sidebar && sidebar !== 'auto') {
|
||||
const res = resolveLinkBySidebar(sidebar, pathJoin(notes?.dir || '', note.dir || ''))
|
||||
const file = ensureLeadingSlash(relativePath)
|
||||
if (res[file]) {
|
||||
args.push(res[file])
|
||||
}
|
||||
else if (res[path.dirname(file)]) {
|
||||
args.push(res[path.dirname(file)])
|
||||
}
|
||||
}
|
||||
|
||||
return pathJoin(...args, nanoid(), '/')
|
||||
},
|
||||
} as AutoFrontmatterObject
|
||||
: undefined,
|
||||
},
|
||||
}
|
||||
: '',
|
||||
{
|
||||
include: '**/{readme,README,index}.md',
|
||||
frontmatter: {},
|
||||
},
|
||||
localeOptions.blog !== false
|
||||
? {
|
||||
include: localeOptions.blog?.include ?? ['**/*.md'],
|
||||
frontmatter: {
|
||||
...options.title !== false
|
||||
? {
|
||||
title(title: string, { relativePath }) {
|
||||
if (title)
|
||||
return title
|
||||
const basename = path.basename(relativePath || '', '.md')
|
||||
return basename
|
||||
},
|
||||
} as AutoFrontmatterObject
|
||||
: undefined,
|
||||
...baseFrontmatter,
|
||||
...options.permalink !== false
|
||||
? {
|
||||
permalink(permalink: string, { relativePath }) {
|
||||
if (permalink)
|
||||
return permalink
|
||||
const locale = resolveLocale(relativePath)
|
||||
const prefix = withBase(articlePrefix, locale)
|
||||
|
||||
return normalizePath(`${prefix}/${nanoid()}/`)
|
||||
},
|
||||
} as AutoFrontmatterObject
|
||||
: undefined,
|
||||
},
|
||||
}
|
||||
: '',
|
||||
|
||||
{
|
||||
include: '*',
|
||||
frontmatter: {
|
||||
...options.title !== false
|
||||
? {
|
||||
title(title: string, { relativePath }) {
|
||||
if (title)
|
||||
return title
|
||||
const basename = path.basename(relativePath || '', '.md')
|
||||
return basename
|
||||
},
|
||||
} as AutoFrontmatterObject
|
||||
: undefined,
|
||||
...baseFrontmatter,
|
||||
...options.permalink !== false
|
||||
? {
|
||||
permalink(permalink: string, { relativePath }) {
|
||||
if (permalink)
|
||||
return permalink
|
||||
return ensureLeadingSlash(normalizePath(relativePath.replace(/\.md$/, '/')))
|
||||
},
|
||||
} as AutoFrontmatterObject
|
||||
: undefined,
|
||||
},
|
||||
},
|
||||
].filter(Boolean) as AutoFrontmatterArray,
|
||||
}
|
||||
}
|
||||
|
||||
function resolveLinkBySidebar(
|
||||
sidebar: 'auto' | (string | SidebarItem)[],
|
||||
_prefix: string,
|
||||
) {
|
||||
const res: Record<string, string> = {}
|
||||
|
||||
if (sidebar === 'auto') {
|
||||
return res
|
||||
}
|
||||
|
||||
for (const item of sidebar) {
|
||||
if (typeof item !== 'string') {
|
||||
const { prefix, dir = '', link = '/', items, text = '' } = item
|
||||
getSidebarLink(items, link, text, pathJoin(_prefix, prefix || dir), res)
|
||||
}
|
||||
}
|
||||
return res
|
||||
}
|
||||
|
||||
function getSidebarLink(items: 'auto' | (string | SidebarItem)[] | undefined, link: string, text: string, dir = '', res: Record<string, string> = {}) {
|
||||
if (items === 'auto')
|
||||
return
|
||||
|
||||
if (!items) {
|
||||
res[pathJoin(dir, `${text}.md`)] = link
|
||||
return
|
||||
}
|
||||
|
||||
for (const item of items) {
|
||||
if (typeof item === 'string') {
|
||||
if (!link)
|
||||
continue
|
||||
if (item) {
|
||||
res[pathJoin(dir, `${item}.md`)] = link
|
||||
}
|
||||
else {
|
||||
res[pathJoin(dir, 'README.md')] = link
|
||||
res[pathJoin(dir, 'index.md')] = link
|
||||
res[pathJoin(dir, 'readme.md')] = link
|
||||
}
|
||||
res[dir] = link
|
||||
}
|
||||
else {
|
||||
const { prefix, dir: subDir = '', link: subLink = '/', items: subItems, text: subText = '' } = item
|
||||
getSidebarLink(subItems, pathJoin(link, subLink), subText, pathJoin(prefix || dir, subDir), res)
|
||||
}
|
||||
frontmatter: configs,
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
import { uniq } from '@pengzhanbo/utils'
|
||||
import { entries } from '@vuepress/helper'
|
||||
import { withBase } from '../utils/index.js'
|
||||
import { entries, removeLeadingSlash } from '@vuepress/helper'
|
||||
import { normalizePath, withBase } from '../utils/index.js'
|
||||
import type { NotesOptions, PlumeThemeLocaleOptions } from '../../shared/index.js'
|
||||
|
||||
export function resolveNotesLinkList(localeOptions: PlumeThemeLocaleOptions) {
|
||||
@ -34,3 +34,11 @@ export function resolveNotesOptions(localeOptions: PlumeThemeLocaleOptions): Not
|
||||
|
||||
return notesOptionsList
|
||||
}
|
||||
|
||||
export function resolveNotesDirs(localeOptions: PlumeThemeLocaleOptions): string[] {
|
||||
const notesList = resolveNotesOptions(localeOptions)
|
||||
return uniq(notesList
|
||||
.flatMap(({ notes, dir }) =>
|
||||
notes.map(note => removeLeadingSlash(normalizePath(`${dir}/${note.dir || ''}/`))),
|
||||
))
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user