132 lines
4.3 KiB
TypeScript
132 lines
4.3 KiB
TypeScript
import type { LLMPage, LLMState } from '@vuepress/plugin-llms'
|
|
import type { ThemeSidebarItem } from 'vuepress-theme-plume'
|
|
import { generateTOCLink as rawGenerateTOCLink } from '@vuepress/plugin-llms'
|
|
import { ensureEndingSlash, ensureLeadingSlash } from 'vuepress/shared'
|
|
import { path } from 'vuepress/utils'
|
|
import { enCollections, zhCollections } from './collections/index.js'
|
|
|
|
function normalizePath(prefix: string, path = ''): string {
|
|
if (path.startsWith('/'))
|
|
return path
|
|
|
|
return `${ensureEndingSlash(prefix)}${path}`
|
|
}
|
|
|
|
function withBase(url = '', base = '/'): string {
|
|
if (!url)
|
|
return ''
|
|
if (url.startsWith(base))
|
|
return normalizePath(url)
|
|
return path.join(base, url)
|
|
}
|
|
|
|
function genStarsWith(stars: string | undefined, locale: string) {
|
|
return (url: string): boolean => {
|
|
if (!stars)
|
|
return false
|
|
return url.startsWith(withBase(stars, locale))
|
|
}
|
|
}
|
|
|
|
export function tocGetter(llmPages: LLMPage[], llmState: LLMState): string {
|
|
const { currentLocale } = llmState
|
|
const isZh = currentLocale === '/'
|
|
const collections = isZh ? zhCollections : enCollections
|
|
|
|
let tableOfContent = ''
|
|
const usagePages: LLMPage[] = []
|
|
|
|
collections
|
|
.filter(item => item.type === 'post')
|
|
.forEach(({ title, linkPrefix, link }) => {
|
|
tableOfContent += `### ${title}\n\n`
|
|
const withLinkPrefix = genStarsWith(linkPrefix, currentLocale)
|
|
const withLink = genStarsWith(link, currentLocale)
|
|
const withFallback = genStarsWith('/article/', currentLocale)
|
|
const list: string[] = []
|
|
llmPages.forEach((page) => {
|
|
if (withLinkPrefix(page.path) || withLink(page.path) || withFallback(page.path)) {
|
|
usagePages.push(page)
|
|
list.push(rawGenerateTOCLink(page, llmState))
|
|
}
|
|
})
|
|
tableOfContent += `${list.filter(Boolean).join('')}\n`
|
|
})
|
|
|
|
const generateTOCLink = (path: string): string => {
|
|
const filepath = path.endsWith('/') ? `${path}README.md` : path.endsWith('.md') ? path : `${path || 'README'}.md`
|
|
const link = path.endsWith('/') ? `${path}index.html` : `${path}.html`
|
|
const page = llmPages.find((item) => {
|
|
return ensureLeadingSlash(item.filePathRelative || '') === filepath || link === item.path
|
|
})
|
|
|
|
if (page) {
|
|
usagePages.push(page)
|
|
return rawGenerateTOCLink(page, llmState)
|
|
}
|
|
return ''
|
|
}
|
|
|
|
const processAutoSidebar = (prefix: string): string[] => {
|
|
const list: string[] = []
|
|
llmPages.forEach((page) => {
|
|
if (ensureLeadingSlash(page.filePathRelative || '').startsWith(prefix)) {
|
|
usagePages.push(page)
|
|
list.push(rawGenerateTOCLink(page, llmState))
|
|
}
|
|
})
|
|
return list.filter(Boolean)
|
|
}
|
|
|
|
const processSidebar = (items: (string | ThemeSidebarItem)[], prefix: string): string[] => {
|
|
const result: string[] = []
|
|
items.forEach((item) => {
|
|
if (typeof item === 'string') {
|
|
result.push(generateTOCLink(normalizePath(prefix, item)))
|
|
}
|
|
else {
|
|
if (item.link) {
|
|
result.push(generateTOCLink(normalizePath(prefix, item.link)))
|
|
}
|
|
if (item.items === 'auto') {
|
|
result.push(...processAutoSidebar(normalizePath(prefix, item.prefix)))
|
|
}
|
|
else if (item.items?.length) {
|
|
result.push(...processSidebar(item.items, normalizePath(prefix, item.prefix)))
|
|
}
|
|
}
|
|
})
|
|
return result
|
|
}
|
|
|
|
// Collections
|
|
collections
|
|
.filter(collection => collection.type === 'doc')
|
|
.forEach(({ dir, title, sidebar = [] }) => {
|
|
tableOfContent += `### ${title}\n\n`
|
|
const prefix = normalizePath(ensureLeadingSlash(withBase(dir, currentLocale)))
|
|
if (sidebar === 'auto') {
|
|
tableOfContent += `${processAutoSidebar(prefix).join('')}\n`
|
|
}
|
|
else if (sidebar.length) {
|
|
const home = generateTOCLink(ensureEndingSlash(prefix))
|
|
const list = processSidebar(sidebar, prefix)
|
|
if (home && !list.includes(home)) {
|
|
list.unshift(home)
|
|
}
|
|
tableOfContent += `${list.join('')}\n`
|
|
}
|
|
})
|
|
|
|
// Others
|
|
const unUsagePages = llmPages.filter(page => !usagePages.includes(page))
|
|
if (unUsagePages.length) {
|
|
tableOfContent += '### Others\n\n'
|
|
tableOfContent += unUsagePages
|
|
.map(page => rawGenerateTOCLink(page, llmState))
|
|
.join('')
|
|
}
|
|
|
|
return tableOfContent
|
|
}
|