refactor(theme): improve node extends page
This commit is contained in:
parent
e74130c19d
commit
960b2ca65a
@ -2,7 +2,6 @@ export * from '../shared/index.js'
|
||||
|
||||
export { default as VPBadge } from './components/global/VPBadge.vue'
|
||||
export { default as VPCard } from './components/global/VPCard.vue'
|
||||
|
||||
export { default as VPCardGrid } from './components/global/VPCardGrid.vue'
|
||||
export { default as VPHomeBanner } from './components/Home/VPHomeBanner.vue'
|
||||
export { default as VPHomeBox } from './components/Home/VPHomeBox.vue'
|
||||
@ -10,7 +9,6 @@ export { default as VPHomeCustom } from './components/Home/VPHomeCustom.vue'
|
||||
export { default as VPHomeFeatures } from './components/Home/VPHomeFeatures.vue'
|
||||
export { default as VPHomeHero } from './components/Home/VPHomeHero.vue'
|
||||
export { default as VPHomeProfile } from './components/Home/VPHomeProfile.vue'
|
||||
|
||||
export { default as VPHomeTextImage } from './components/Home/VPHomeTextImage.vue'
|
||||
export { default as VPButton } from './components/VPButton.vue'
|
||||
export { default as VPImage } from './components/VPImage.vue'
|
||||
|
||||
48
theme/src/node/pages/autoCategory.ts
Normal file
48
theme/src/node/pages/autoCategory.ts
Normal file
@ -0,0 +1,48 @@
|
||||
import type { Page } from 'vuepress/core'
|
||||
import type { PageCategoryData, PlumeThemeLocaleOptions, PlumeThemePageData } from '../../shared/index.js'
|
||||
import { ensureLeadingSlash } from '@vuepress/helper'
|
||||
import { resolveNotesLinkList } from '../config/index.js'
|
||||
import { hash } from '../utils/index.js'
|
||||
|
||||
let uuid = 10000
|
||||
const cache: Record<string, number> = {}
|
||||
|
||||
const RE_CATEGORY = /^(?:(\d+)\.)?([\s\S]+)$/
|
||||
let LOCALE_RE: RegExp
|
||||
|
||||
export function autoCategory(
|
||||
page: Page<PlumeThemePageData>,
|
||||
options: PlumeThemeLocaleOptions,
|
||||
) {
|
||||
const pagePath = page.filePathRelative
|
||||
|
||||
if (page.data.type || !pagePath)
|
||||
return
|
||||
const notesLinks = resolveNotesLinkList(options)
|
||||
|
||||
if (notesLinks.some(link => page.path.startsWith(link)))
|
||||
return
|
||||
|
||||
LOCALE_RE ??= new RegExp(
|
||||
`^(${Object.keys(options.locales || {}).filter(l => l !== '/').join('|')})`,
|
||||
)
|
||||
const list = ensureLeadingSlash(pagePath)
|
||||
.replace(LOCALE_RE, '')
|
||||
.replace(/^\//, '')
|
||||
.split('/')
|
||||
.slice(0, -1)
|
||||
|
||||
const categoryList: PageCategoryData[] = list
|
||||
.map((category, index) => {
|
||||
const match = category.match(RE_CATEGORY) || []
|
||||
if (!cache[match[2]] && !match[1]) {
|
||||
cache[match[2]] = uuid++
|
||||
}
|
||||
return {
|
||||
id: hash(list.slice(0, index + 1).join('-')).slice(0, 6),
|
||||
sort: Number(match[1] || cache[match[2]]),
|
||||
name: match[2],
|
||||
}
|
||||
})
|
||||
page.data.categoryList = categoryList
|
||||
}
|
||||
63
theme/src/node/pages/createPages.ts
Normal file
63
theme/src/node/pages/createPages.ts
Normal file
@ -0,0 +1,63 @@
|
||||
import type { App, Page } from 'vuepress/core'
|
||||
import type { PlumeThemeLocaleOptions } from '../../shared/index.js'
|
||||
import { getRootLang, getRootLangPath } from '@vuepress/helper'
|
||||
import { createPage } from 'vuepress/core'
|
||||
import { PRESET_LOCALES } from '../locales/index.js'
|
||||
import { withBase } from '../utils/index.js'
|
||||
|
||||
export async function createPages(app: App, localeOption: PlumeThemeLocaleOptions) {
|
||||
if (localeOption.blog === false)
|
||||
return
|
||||
|
||||
const pageList: Promise<Page>[] = []
|
||||
const locales = localeOption.locales || {}
|
||||
const rootPath = getRootLangPath(app)
|
||||
const rootLang = getRootLang(app)
|
||||
|
||||
const blog = localeOption.blog || {}
|
||||
const link = blog.link || '/blog/'
|
||||
|
||||
const getTitle = (locale: string, key: string) => {
|
||||
const opt = PRESET_LOCALES[locale] || PRESET_LOCALES[rootPath] || {}
|
||||
return opt[key] || ''
|
||||
}
|
||||
|
||||
for (const localePath of Object.keys(locales)) {
|
||||
const lang = app.siteData.locales?.[localePath]?.lang || rootLang
|
||||
const locale = localePath === '/' ? rootPath : localePath
|
||||
|
||||
// 添加 博客页面
|
||||
if (blog.postList !== false) {
|
||||
pageList.push(createPage(app, {
|
||||
path: withBase(link, localePath),
|
||||
frontmatter: { lang, _pageLayout: 'blog', title: getTitle(locale, 'blog') },
|
||||
}))
|
||||
}
|
||||
|
||||
// 添加 标签页
|
||||
if (blog.tags !== false) {
|
||||
pageList.push(createPage(app, {
|
||||
path: withBase(blog.tagsLink || `${link}/tags/`, localePath),
|
||||
frontmatter: { lang, _pageLayout: 'blog-tags', title: getTitle(locale, 'tag') },
|
||||
}))
|
||||
}
|
||||
|
||||
// 添加归档页
|
||||
if (blog.archives !== false) {
|
||||
pageList.push(createPage(app, {
|
||||
path: withBase(blog.archivesLink || `${link}/archives/`, localePath),
|
||||
frontmatter: { lang, _pageLayout: 'blog-archives', title: getTitle(locale, 'archive') },
|
||||
}))
|
||||
}
|
||||
|
||||
// 添加分类页
|
||||
if (blog.categories !== false) {
|
||||
pageList.push(createPage(app, {
|
||||
path: withBase(blog.categoriesLink || `${link}/categories/`, localePath),
|
||||
frontmatter: { lang, _pageLayout: 'blog-categories', title: getTitle(locale, 'category') },
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
app.pages.push(...await Promise.all(pageList))
|
||||
}
|
||||
57
theme/src/node/pages/extendsPage.ts
Normal file
57
theme/src/node/pages/extendsPage.ts
Normal file
@ -0,0 +1,57 @@
|
||||
import type { Page } from 'vuepress/core'
|
||||
import type { PlumeThemeLocaleOptions, PlumeThemePageData } from '../../shared/index.js'
|
||||
import { autoCategory } from './autoCategory.js'
|
||||
import { enableBulletin } from './pageBulletin.js'
|
||||
|
||||
export function extendsPageData(
|
||||
page: Page<PlumeThemePageData>,
|
||||
localeOptions: PlumeThemeLocaleOptions,
|
||||
) {
|
||||
cleanPageData(page)
|
||||
autoCategory(page, localeOptions)
|
||||
enableBulletin(page, localeOptions)
|
||||
}
|
||||
|
||||
function cleanPageData(page: Page<PlumeThemePageData>) {
|
||||
page.data.filePathRelative = page.filePathRelative
|
||||
page.routeMeta.title = page.frontmatter.title || page.title
|
||||
|
||||
if (page.frontmatter.icon) {
|
||||
page.routeMeta.icon = page.frontmatter.icon
|
||||
}
|
||||
|
||||
if (page.frontmatter.home) {
|
||||
page.frontmatter.pageLayout = 'home'
|
||||
delete page.frontmatter.home
|
||||
}
|
||||
|
||||
if (page.frontmatter.article === false) {
|
||||
page.frontmatter.draft = true
|
||||
}
|
||||
delete page.frontmatter.article
|
||||
|
||||
if (page.frontmatter.friends) {
|
||||
page.frontmatter.draft = true
|
||||
page.data.type = 'friends'
|
||||
page.permalink = page.permalink ?? '/friends/'
|
||||
page.frontmatter.pageLayout = 'friends'
|
||||
delete page.frontmatter.friends
|
||||
}
|
||||
|
||||
const pageType = page.frontmatter._pageLayout as string
|
||||
if (pageType) {
|
||||
page.frontmatter.draft = true
|
||||
page.data.type = pageType as any
|
||||
delete page.frontmatter._pageLayout
|
||||
}
|
||||
|
||||
if (page.frontmatter.pageLayout === 'blog') {
|
||||
page.frontmatter.draft = true
|
||||
page.data.type = 'blog'
|
||||
}
|
||||
|
||||
if ('externalLink' in page.frontmatter) {
|
||||
page.frontmatter.externalLinkIcon = page.frontmatter.externalLink
|
||||
delete page.frontmatter.externalLink
|
||||
}
|
||||
}
|
||||
2
theme/src/node/pages/index.ts
Normal file
2
theme/src/node/pages/index.ts
Normal file
@ -0,0 +1,2 @@
|
||||
export * from './createPages.js'
|
||||
export * from './extendsPage.js'
|
||||
29
theme/src/node/pages/pageBulletin.ts
Normal file
29
theme/src/node/pages/pageBulletin.ts
Normal file
@ -0,0 +1,29 @@
|
||||
import type { Page } from 'vuepress/core'
|
||||
import type { BulletinOptions, PlumeThemeLocaleOptions, PlumeThemePageData } from '../../shared/index.js'
|
||||
import { isPlainObject } from '@vuepress/helper'
|
||||
|
||||
export function enableBulletin(
|
||||
page: Page<PlumeThemePageData>,
|
||||
options: PlumeThemeLocaleOptions,
|
||||
) {
|
||||
let enablePage: BulletinOptions['enablePage']
|
||||
if (isPlainObject(options.bulletin) && options.bulletin.enablePage) {
|
||||
enablePage = options.bulletin.enablePage
|
||||
}
|
||||
else if (options.locales) {
|
||||
for (const locale of Object.keys(options.locales)) {
|
||||
if (isPlainObject(options.locales[locale].bulletin) && options.locales[locale].bulletin.enablePage) {
|
||||
enablePage = options.locales[locale].bulletin.enablePage
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof enablePage === 'function') {
|
||||
page.data.bulletin = enablePage(page) ?? true
|
||||
}
|
||||
|
||||
else {
|
||||
page.data.bulletin = enablePage ?? !!options.bulletin
|
||||
}
|
||||
}
|
||||
@ -1,196 +0,0 @@
|
||||
import type { App, Page } from 'vuepress/core'
|
||||
import type {
|
||||
BulletinOptions,
|
||||
PageCategoryData,
|
||||
PlumeThemeLocaleOptions,
|
||||
PlumeThemePageData,
|
||||
} from '../shared/index.js'
|
||||
import {
|
||||
ensureLeadingSlash,
|
||||
getRootLang,
|
||||
getRootLangPath,
|
||||
isPlainObject,
|
||||
} from '@vuepress/helper'
|
||||
import { createPage } from 'vuepress/core'
|
||||
import { resolveNotesLinkList } from './config/index.js'
|
||||
import { PRESET_LOCALES } from './locales/index.js'
|
||||
import { hash, withBase } from './utils/index.js'
|
||||
|
||||
export async function setupPage(
|
||||
app: App,
|
||||
localeOption: PlumeThemeLocaleOptions,
|
||||
) {
|
||||
if (localeOption.blog === false)
|
||||
return
|
||||
|
||||
const pageList: Promise<Page>[] = []
|
||||
const locales = localeOption.locales || {}
|
||||
const rootPath = getRootLangPath(app)
|
||||
const rootLang = getRootLang(app)
|
||||
|
||||
const blog = localeOption.blog || {}
|
||||
const link = blog.link || '/blog/'
|
||||
|
||||
const getTitle = (locale: string, key: string) => {
|
||||
const opt = PRESET_LOCALES[locale] || PRESET_LOCALES[rootPath] || {}
|
||||
return opt[key] || ''
|
||||
}
|
||||
|
||||
for (const localePath of Object.keys(locales)) {
|
||||
const lang = app.siteData.locales?.[localePath]?.lang || rootLang
|
||||
const locale = localePath === '/' ? rootPath : localePath
|
||||
|
||||
// 添加 博客页面
|
||||
if (blog.postList !== false) {
|
||||
pageList.push(createPage(app, {
|
||||
path: withBase(link, localePath),
|
||||
frontmatter: { lang, _pageLayout: 'blog', title: getTitle(locale, 'blog') },
|
||||
}))
|
||||
}
|
||||
|
||||
// 添加 标签页
|
||||
if (blog.tags !== false) {
|
||||
pageList.push(createPage(app, {
|
||||
path: withBase(blog.tagsLink || `${link}/tags/`, localePath),
|
||||
frontmatter: { lang, _pageLayout: 'blog-tags', title: getTitle(locale, 'tag') },
|
||||
}))
|
||||
}
|
||||
|
||||
// 添加归档页
|
||||
if (blog.archives !== false) {
|
||||
pageList.push(createPage(app, {
|
||||
path: withBase(blog.archivesLink || `${link}/archives/`, localePath),
|
||||
frontmatter: { lang, _pageLayout: 'blog-archives', title: getTitle(locale, 'archive') },
|
||||
}))
|
||||
}
|
||||
|
||||
// 添加分类页
|
||||
if (blog.categories !== false) {
|
||||
pageList.push(createPage(app, {
|
||||
path: withBase(blog.categoriesLink || `${link}/categories/`, localePath),
|
||||
frontmatter: { lang, _pageLayout: 'blog-categories', title: getTitle(locale, 'category') },
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
app.pages.push(...await Promise.all(pageList))
|
||||
}
|
||||
|
||||
export function extendsPageData(
|
||||
page: Page<PlumeThemePageData>,
|
||||
localeOptions: PlumeThemeLocaleOptions,
|
||||
) {
|
||||
page.data.filePathRelative = page.filePathRelative
|
||||
page.routeMeta.title = page.frontmatter.title || page.title
|
||||
|
||||
if (page.frontmatter.icon) {
|
||||
page.routeMeta.icon = page.frontmatter.icon
|
||||
}
|
||||
|
||||
if (page.frontmatter.home) {
|
||||
page.frontmatter.pageLayout = 'home'
|
||||
delete page.frontmatter.home
|
||||
}
|
||||
|
||||
if (page.frontmatter.article === false) {
|
||||
page.frontmatter.draft = true
|
||||
}
|
||||
delete page.frontmatter.article
|
||||
|
||||
if (page.frontmatter.friends) {
|
||||
page.frontmatter.draft = true
|
||||
page.data.type = 'friends'
|
||||
page.permalink = page.permalink ?? '/friends/'
|
||||
page.frontmatter.pageLayout = 'friends'
|
||||
delete page.frontmatter.friends
|
||||
}
|
||||
|
||||
const pageType = page.frontmatter._pageLayout as string
|
||||
if (pageType) {
|
||||
page.frontmatter.draft = true
|
||||
page.data.type = pageType as any
|
||||
delete page.frontmatter._pageLayout
|
||||
}
|
||||
|
||||
if (page.frontmatter.pageLayout === 'blog') {
|
||||
page.frontmatter.draft = true
|
||||
page.data.type = 'blog'
|
||||
}
|
||||
|
||||
if ('externalLink' in page.frontmatter) {
|
||||
page.frontmatter.externalLinkIcon = page.frontmatter.externalLink
|
||||
delete page.frontmatter.externalLink
|
||||
}
|
||||
|
||||
autoCategory(page, localeOptions)
|
||||
enableBulletin(page, localeOptions)
|
||||
}
|
||||
|
||||
let uuid = 10000
|
||||
const cache: Record<string, number> = {}
|
||||
|
||||
const RE_CATEGORY = /^(?:(\d+)\.)?([\s\S]+)$/
|
||||
let LOCALE_RE: RegExp
|
||||
|
||||
export function autoCategory(
|
||||
page: Page<PlumeThemePageData>,
|
||||
options: PlumeThemeLocaleOptions,
|
||||
) {
|
||||
const pagePath = page.filePathRelative
|
||||
|
||||
if (page.data.type || !pagePath)
|
||||
return
|
||||
const notesLinks = resolveNotesLinkList(options)
|
||||
|
||||
if (notesLinks.some(link => page.path.startsWith(link)))
|
||||
return
|
||||
|
||||
LOCALE_RE ??= new RegExp(
|
||||
`^(${Object.keys(options.locales || {}).filter(l => l !== '/').join('|')})`,
|
||||
)
|
||||
const list = ensureLeadingSlash(pagePath)
|
||||
.replace(LOCALE_RE, '')
|
||||
.replace(/^\//, '')
|
||||
.split('/')
|
||||
.slice(0, -1)
|
||||
|
||||
const categoryList: PageCategoryData[] = list
|
||||
.map((category, index) => {
|
||||
const match = category.match(RE_CATEGORY) || []
|
||||
if (!cache[match[2]] && !match[1]) {
|
||||
cache[match[2]] = uuid++
|
||||
}
|
||||
return {
|
||||
id: hash(list.slice(0, index + 1).join('-')).slice(0, 6),
|
||||
sort: Number(match[1] || cache[match[2]]),
|
||||
name: match[2],
|
||||
}
|
||||
})
|
||||
page.data.categoryList = categoryList
|
||||
}
|
||||
|
||||
function enableBulletin(
|
||||
page: Page<PlumeThemePageData>,
|
||||
options: PlumeThemeLocaleOptions,
|
||||
) {
|
||||
let enablePage: BulletinOptions['enablePage']
|
||||
if (isPlainObject(options.bulletin) && options.bulletin.enablePage) {
|
||||
enablePage = options.bulletin.enablePage
|
||||
}
|
||||
else if (options.locales) {
|
||||
for (const locale of Object.keys(options.locales)) {
|
||||
if (isPlainObject(options.locales[locale].bulletin) && options.locales[locale].bulletin.enablePage) {
|
||||
enablePage = options.locales[locale].bulletin.enablePage
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof enablePage === 'function') {
|
||||
page.data.bulletin = enablePage(page) ?? true
|
||||
}
|
||||
|
||||
else {
|
||||
page.data.bulletin = enablePage ?? !!options.bulletin
|
||||
}
|
||||
}
|
||||
@ -4,10 +4,10 @@ import { sleep } from '@pengzhanbo/utils'
|
||||
import { generateAutoFrontmatter, initAutoFrontmatter, watchAutoFrontmatter } from './autoFrontmatter/index.js'
|
||||
import { extendsBundlerOptions, resolveAlias, resolveProvideData, resolveThemeOptions, templateBuildRenderer } from './config/index.js'
|
||||
import { getThemeConfig, initConfigLoader, waitForConfigLoaded, watchConfigFile } from './loadConfig/index.js'
|
||||
import { createPages, extendsPageData } from './pages/index.js'
|
||||
import { getPlugins } from './plugins/index.js'
|
||||
import { prepareData, watchPrepare } from './prepare/index.js'
|
||||
import { prepareThemeData } from './prepare/prepareThemeData.js'
|
||||
import { extendsPageData, setupPage } from './setupPages.js'
|
||||
import { resolve, templates, THEME_NAME } from './utils/index.js'
|
||||
|
||||
export function plumeTheme(options: PlumeThemeOptions = {}): Theme {
|
||||
@ -52,18 +52,15 @@ export function plumeTheme(options: PlumeThemeOptions = {}): Theme {
|
||||
},
|
||||
|
||||
extendsPage: async (page) => {
|
||||
const { localeOptions } = getThemeConfig()
|
||||
extendsPageData(page as Page<PlumeThemePageData>, localeOptions)
|
||||
extendsPageData(page as Page<PlumeThemePageData>, getThemeConfig().localeOptions)
|
||||
},
|
||||
|
||||
onInitialized: async (app) => {
|
||||
const { localeOptions } = getThemeConfig()
|
||||
await setupPage(app, localeOptions)
|
||||
await createPages(app, getThemeConfig().localeOptions)
|
||||
},
|
||||
|
||||
onPrepared: async (app) => {
|
||||
const { localeOptions } = getThemeConfig()
|
||||
await prepareThemeData(app, localeOptions, pluginOptions)
|
||||
await prepareThemeData(app, getThemeConfig().localeOptions, pluginOptions)
|
||||
await prepareData(app)
|
||||
},
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user