179 lines
4.4 KiB
TypeScript
179 lines
4.4 KiB
TypeScript
import type { App, Page } from '@vuepress/core'
|
|
import { path } from '@vuepress/utils'
|
|
import * as chokidar from 'chokidar'
|
|
import type {
|
|
PlumeThemeLocaleOptions,
|
|
PlumeThemeNotesItem,
|
|
PlumeThemeNotesOptions,
|
|
PlumeThemePageData,
|
|
PlumeThemeSidebarConfigOptions,
|
|
SidebarItem,
|
|
SidebarOptions,
|
|
} from '../../shared'
|
|
|
|
const HMR_CODE = `
|
|
if (import.meta.webpackHot) {
|
|
import.meta.webpackHot.accept()
|
|
if (__VUE_HMR_RUNTIME__.updateSidebarIndex) {
|
|
__VUE_HMR_RUNTIME__.updatePostIndex(sidebarIndex)
|
|
}
|
|
}
|
|
|
|
if (import.meta.hot) {
|
|
import.meta.hot.accept(({ sidebarIndex }) => {
|
|
__VUE_HMR_RUNTIME__.updateSidebarIndex(sidebarIndex)
|
|
})
|
|
}
|
|
`
|
|
|
|
interface NotePage {
|
|
relativePath: string[]
|
|
title: string
|
|
link: string
|
|
}
|
|
|
|
export const preparedSidebarIndex = (
|
|
app: App,
|
|
{ notes }: PlumeThemeLocaleOptions
|
|
): void => {
|
|
const pages = app.pages as Page<PlumeThemePageData>[]
|
|
if (notes === false) return
|
|
const {
|
|
notes: noteList,
|
|
dir: rootDir,
|
|
link: rootLink,
|
|
} = notes as PlumeThemeNotesOptions
|
|
const notePageList: NotePage[] = pages
|
|
.filter((page) => page.filePathRelative?.startsWith(rootDir as string))
|
|
.map((page) => {
|
|
return {
|
|
relativePath: page.filePathRelative?.split('/').slice(1) || [],
|
|
title: page.title,
|
|
link: page.path,
|
|
}
|
|
})
|
|
|
|
const sidebarMap: Record<string, SidebarOptions> = {}
|
|
noteList.forEach((note) => {
|
|
sidebarMap[path.join('/', rootLink, note.link)] = noteSidebar(
|
|
note,
|
|
notePageList.filter(
|
|
(page) =>
|
|
page.relativePath?.[0] === note.dir.trim().replace(/^\/|\/$/g, '')
|
|
)
|
|
)
|
|
})
|
|
|
|
let content = `
|
|
export const sidebarIndex = ${JSON.stringify(sidebarMap, null, 2)}
|
|
`
|
|
if (app.env.isDev) {
|
|
content += HMR_CODE
|
|
}
|
|
|
|
app.writeTemp('internal/sidebarIndex.js', content)
|
|
}
|
|
|
|
function noteSidebar(
|
|
note: PlumeThemeNotesItem,
|
|
notePageList: NotePage[]
|
|
): SidebarOptions {
|
|
if (note.sidebar === undefined) return []
|
|
if (note.sidebar === 'auto') {
|
|
return autoSidebar(note, notePageList)
|
|
}
|
|
return sidebarByConfig(
|
|
note.text,
|
|
note.link,
|
|
note.dir,
|
|
note.sidebar,
|
|
notePageList
|
|
)
|
|
}
|
|
|
|
function autoSidebar(
|
|
note: PlumeThemeNotesItem,
|
|
notePageList: NotePage[]
|
|
): SidebarOptions {
|
|
return []
|
|
}
|
|
|
|
function sidebarByConfig(
|
|
text: string,
|
|
link: string | undefined,
|
|
dir: string,
|
|
sidebarConfig: PlumeThemeSidebarConfigOptions,
|
|
notePageList: NotePage[]
|
|
): SidebarOptions {
|
|
return sidebarConfig.map((sidebar) => {
|
|
if (typeof sidebar === 'string') {
|
|
const current = findNotePage(sidebar, dir, notePageList)
|
|
return {
|
|
text: current ? current.title : text,
|
|
link: current ? current.link : '',
|
|
children: [],
|
|
} as SidebarItem
|
|
} else {
|
|
dir = path.join(dir, sidebar.dir || '')
|
|
link = path.join(link, sidebar.link)
|
|
const current = sidebar.link
|
|
? findNotePage(sidebar.link, dir, notePageList)
|
|
: undefined
|
|
return {
|
|
text: sidebar.text || sidebar.dir || '',
|
|
link: current?.link || link,
|
|
children: sidebarByConfig(
|
|
sidebar.text,
|
|
sidebar.link,
|
|
dir,
|
|
sidebar.children,
|
|
notePageList
|
|
),
|
|
}
|
|
}
|
|
})
|
|
}
|
|
|
|
function findNotePage(
|
|
sidebar: string,
|
|
dir: string,
|
|
notePageList: NotePage[]
|
|
): NotePage | undefined {
|
|
if (sidebar === '' || sidebar === 'README.md' || sidebar === 'index.md') {
|
|
return notePageList.find((page) => {
|
|
const relative = page.relativePath.join('/')
|
|
return (
|
|
relative === path.join(dir, 'README.md') ||
|
|
relative === path.join(dir, 'index.md')
|
|
)
|
|
})
|
|
} else {
|
|
return notePageList.find((page) => {
|
|
const relative = page.relativePath.join('/')
|
|
return (
|
|
relative === path.join(dir, sidebar) ||
|
|
relative === path.join(dir, sidebar + '.md') ||
|
|
page.link === sidebar
|
|
)
|
|
})
|
|
}
|
|
}
|
|
|
|
export const watchSidebarIndex = (
|
|
app: App,
|
|
watchers: any[],
|
|
localeOption: PlumeThemeLocaleOptions
|
|
): void => {
|
|
if (!localeOption.notes || !localeOption.notes.dir) return
|
|
const dir = path.join('pages', localeOption.notes.dir, '**/*')
|
|
const watcher = chokidar.watch(dir, {
|
|
cwd: app.dir.temp(),
|
|
ignoreInitial: true,
|
|
})
|
|
|
|
watcher.on('add', () => preparedSidebarIndex(app, localeOption))
|
|
watcher.on('change', () => preparedSidebarIndex(app, localeOption))
|
|
watcher.on('unlink', () => preparedSidebarIndex(app, localeOption))
|
|
watchers.push(watcher)
|
|
}
|