Skip to content

Commit

Permalink
refactor(theme): improve theme options (#463)
Browse files Browse the repository at this point in the history
  • Loading branch information
pengzhanbo authored Feb 16, 2025
1 parent 6442ffa commit b7ced3b
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 53 deletions.
11 changes: 5 additions & 6 deletions theme/src/node/autoFrontmatter/generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@ import type {
AutoFrontmatterArray,
AutoFrontmatterMarkdownFile,
AutoFrontmatterObject,
AutoFrontmatterOptions,
PlumeThemeLocaleOptions,
} from '../../shared/index.js'
import { isArray, isEmptyObject, promiseParallel, toArray } from '@pengzhanbo/utils'
import chokidar from 'chokidar'
Expand Down Expand Up @@ -34,10 +32,11 @@ export interface Generate {

let generate: Generate | null = null

export function initAutoFrontmatter(
localeOptions: PlumeThemeLocaleOptions,
autoFrontmatter: AutoFrontmatterOptions = {},
) {
export function initAutoFrontmatter() {
const { localeOptions, autoFrontmatter = {} } = getThemeConfig()
if (autoFrontmatter === false)
return

const { include, exclude, frontmatter = {} } = resolveOptions(localeOptions, autoFrontmatter)

const globFilter = createFilter(include, exclude, { resolve: false })
Expand Down
6 changes: 5 additions & 1 deletion theme/src/node/config/extendsBundlerOptions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,11 @@ export function extendsBundlerOptions(bundlerOptions: any, app: App): void {
},
})

addViteOptimizeDepsInclude(bundlerOptions, app, '@vueuse/core', true)
addViteOptimizeDepsInclude(
bundlerOptions,
app,
['@vueuse/core', 'bcrypt-ts/browser', '@vuepress/helper/client', '@iconify/vue', '@iconify/vue/offline'],
)
addViteOptimizeDepsExclude(bundlerOptions, app, '@theme')

addViteSsrNoExternal(bundlerOptions, app, [
Expand Down
4 changes: 2 additions & 2 deletions theme/src/node/config/templateBuildRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
import type { TemplateRendererContext } from 'vuepress/utils'
import type { PlumeThemeLocaleOptions } from '../../shared/index.js'
import { templateRenderer } from 'vuepress/utils'
import { getThemeConfig } from '../loadConfig/index.js'
import { getThemePackage } from '../utils/index.js'

export function templateBuildRenderer(
template: string,
context: TemplateRendererContext,
options: PlumeThemeLocaleOptions,
) {
const { localeOptions: options } = getThemeConfig()
const pkg = getThemePackage()
template = template
.replace('{{ themeVersion }}', pkg.version || '')
Expand Down
31 changes: 21 additions & 10 deletions theme/src/node/pages/createPages.ts
Original file line number Diff line number Diff line change
@@ -1,19 +1,30 @@
import type { App, Page } from 'vuepress/core'
import type { PlumeThemeLocaleOptions } from '../../shared/index.js'
import { getRootLang } from '@vuepress/helper'
import { createPage } from 'vuepress/core'
import { getThemeConfig } from '../loadConfig/index.js'
import { perfLog, perfMark, withBase } from '../utils/index.js'

export async function createPages(app: App, localeOption: PlumeThemeLocaleOptions) {
if (localeOption.blog === false)
function getRootLang(app: App): string {
// infer from siteLocale
const siteLocales = app.siteData.locales

if (siteLocales['/']?.lang)
return siteLocales['/'].lang

return app.siteData.lang
}

export async function createPages(app: App) {
const { localeOptions } = getThemeConfig()

if (localeOptions.blog === false)
return

perfMark('create:blog-pages')
const pageList: Promise<Page>[] = []
const locales = localeOption.locales || {}
const locales = localeOptions.locales || {}
const rootLang = getRootLang(app)

const blog = localeOption.blog || {}
const blog = localeOptions.blog || {}
const link = blog.link || '/blog/'

for (const localePath of Object.keys(locales)) {
Expand All @@ -24,31 +35,31 @@ export async function createPages(app: App, localeOption: PlumeThemeLocaleOption
if (blog.postList !== false) {
pageList.push(createPage(app, {
path: withBase(link, localePath),
frontmatter: { lang, _pageLayout: 'blog', title: opt.blogText || localeOption.blogText || 'Blog' },
frontmatter: { lang, _pageLayout: 'blog', title: opt.blogText || localeOptions.blogText || 'Blog' },
}))
}

// 添加 标签页
if (blog.tags !== false) {
pageList.push(createPage(app, {
path: withBase(blog.tagsLink || `${link}/tags/`, localePath),
frontmatter: { lang, _pageLayout: 'blog-tags', title: opt.tagText || localeOption.tagText || 'Tags' },
frontmatter: { lang, _pageLayout: 'blog-tags', title: opt.tagText || localeOptions.tagText || 'Tags' },
}))
}

// 添加归档页
if (blog.archives !== false) {
pageList.push(createPage(app, {
path: withBase(blog.archivesLink || `${link}/archives/`, localePath),
frontmatter: { lang, _pageLayout: 'blog-archives', title: opt.archiveText || localeOption.archiveText || 'Archives' },
frontmatter: { lang, _pageLayout: 'blog-archives', title: opt.archiveText || localeOptions.archiveText || 'Archives' },
}))
}

// 添加分类页
if (blog.categories !== false) {
pageList.push(createPage(app, {
path: withBase(blog.categoriesLink || `${link}/categories/`, localePath),
frontmatter: { lang, _pageLayout: 'blog-categories', title: opt.categoryText || localeOption.categoryText || 'Categories' },
frontmatter: { lang, _pageLayout: 'blog-categories', title: opt.categoryText || localeOptions.categoryText || 'Categories' },
}))
}
}
Expand Down
5 changes: 3 additions & 2 deletions theme/src/node/pages/extendsPage.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { Page } from 'vuepress/core'
import type { PlumeThemeLocaleOptions, PlumeThemePageData } from '../../shared/index.js'
import type { PlumeThemePageData } from '../../shared/index.js'
import { getThemeConfig } from '../loadConfig/index.js'
import { autoCategory } from './autoCategory.js'
import { enableBulletin } from './pageBulletin.js'

export function extendsPageData(
page: Page<PlumeThemePageData>,
localeOptions: PlumeThemeLocaleOptions,
) {
const { localeOptions } = getThemeConfig()
cleanPageData(page)
autoCategory(page, localeOptions)
enableBulletin(page, localeOptions)
Expand Down
19 changes: 9 additions & 10 deletions theme/src/node/plugins/getPlugins.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { SeoPluginOptions } from '@vuepress/plugin-seo'
import type { SitemapPluginOptions } from '@vuepress/plugin-sitemap'
import type { App, PluginConfig } from 'vuepress/core'
import type { PlumeThemeLocaleOptions, PlumeThemePluginOptions } from '../../shared/index.js'
import type { PlumeThemePluginOptions } from '../../shared/index.js'
import { contentUpdatePlugin } from '@vuepress-plume/plugin-content-update'
import { fontsPlugin } from '@vuepress-plume/plugin-fonts'
import { searchPlugin } from '@vuepress-plume/plugin-search'
Expand All @@ -23,6 +23,7 @@ import { sitemapPlugin } from '@vuepress/plugin-sitemap'
import { watermarkPlugin } from '@vuepress/plugin-watermark'
import { mdEnhancePlugin } from 'vuepress-plugin-md-enhance'
import { markdownPowerPlugin } from 'vuepress-plugin-md-power'
import { getThemeConfig } from '../loadConfig/index.js'

export interface SetupPluginOptions {
app: App
Expand All @@ -31,16 +32,14 @@ export interface SetupPluginOptions {
cache?: false | 'memory' | 'filesystem'
}

export function getPlugins(
options: PlumeThemeLocaleOptions,
{
app,
pluginOptions,
hostname,
cache,
}: SetupPluginOptions,
): PluginConfig {
export function getPlugins({
app,
pluginOptions,
hostname,
cache,
}: SetupPluginOptions): PluginConfig {
const isProd = app.env.isBuild
const { localeOptions: options } = getThemeConfig()

const plugins: PluginConfig = [
fontsPlugin(),
Expand Down
5 changes: 3 additions & 2 deletions theme/src/node/prepare/prepareThemeData.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import type { FSWatcher } from 'chokidar'
import type { App } from 'vuepress'
import type { PlumeThemeData, PlumeThemeLocaleOptions, PlumeThemePluginOptions } from '../../shared/index.js'
import type { PlumeThemeData, PlumeThemePluginOptions } from '../../shared/index.js'
import fs from 'node:fs/promises'
import process from 'node:process'
import { watch } from 'chokidar'
import { resolveImageSize } from 'vuepress-plugin-md-power'
import { hash } from 'vuepress/utils'
import { resolveThemeData } from '../config/resolveThemeData.js'
import { getThemeConfig } from '../loadConfig/index.js'
import { perfLog, perfMark, resolveContent, writeTemp } from '../utils/index.js'

let bulletinFileWatcher: FSWatcher | null = null
Expand All @@ -16,10 +17,10 @@ process.on('exit', () => bulletinFileWatcher?.close())

export async function prepareThemeData(
app: App,
localeOptions: PlumeThemeLocaleOptions,
pluginOptions: PlumeThemePluginOptions,
): Promise<void> {
perfMark('prepare:theme-data')
const { localeOptions } = getThemeConfig()
const resolvedThemeData = resolveThemeData(app, localeOptions)

await resolveProfileImage(app, resolvedThemeData, pluginOptions)
Expand Down
50 changes: 31 additions & 19 deletions theme/src/node/theme.ts
Original file line number Diff line number Diff line change
@@ -1,25 +1,38 @@
import type { Page, Theme } from 'vuepress/core'
import type { PlumeThemeOptions, PlumeThemePageData } from '../shared/index.js'
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 {
generateAutoFrontmatter,
initAutoFrontmatter,
watchAutoFrontmatter,
} from './autoFrontmatter/index.js'
import {
extendsBundlerOptions,
resolveAlias,
resolveProvideData,
resolveThemeOptions,
templateBuildRenderer,
} from './config/index.js'
import { 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 { resolve, templates, THEME_NAME } from './utils/index.js'

export function plumeTheme(options: PlumeThemeOptions = {}): Theme {
const { localeOptions, pluginOptions, hostname, configFile, cache } = resolveThemeOptions(options)
const {
localeOptions,
pluginOptions,
hostname,
configFile,
cache,
} = resolveThemeOptions(options)

return (app) => {
initConfigLoader(app, localeOptions, {
configFile,
onChange: ({ localeOptions, autoFrontmatter }) => {
if (autoFrontmatter !== false)
initAutoFrontmatter(localeOptions, autoFrontmatter)
},
onChange: initAutoFrontmatter,
})

return {
Expand All @@ -33,40 +46,39 @@ export function plumeTheme(options: PlumeThemeOptions = {}): Theme {

alias: resolveAlias(),

plugins: getPlugins(getThemeConfig().localeOptions, { app, pluginOptions, hostname, cache }),
plugins: getPlugins({ app, pluginOptions, hostname, cache }),

extendsBundlerOptions,

templateBuildRenderer: (template, context) =>
templateBuildRenderer(template, context, getThemeConfig().localeOptions),
templateBuildRenderer,

extendsMarkdown: async (_, app) => {
const { autoFrontmatter, localeOptions } = await waitForConfigLoaded()
const { autoFrontmatter } = await waitForConfigLoaded()
if (autoFrontmatter !== false) {
initAutoFrontmatter(localeOptions, autoFrontmatter)
initAutoFrontmatter()
await generateAutoFrontmatter(app)
// wait for autoFrontmatter generated
// i/o performance
await sleep(100)
}
},

extendsPage: async (page) => {
extendsPageData(page as Page<PlumeThemePageData>, getThemeConfig().localeOptions)
extendsPage: (page) => {
extendsPageData(page as Page<PlumeThemePageData>)
},

onInitialized: async (app) => {
await createPages(app, getThemeConfig().localeOptions)
await createPages(app)
},

onPrepared: async (app) => {
await prepareThemeData(app, getThemeConfig().localeOptions, pluginOptions)
await prepareThemeData(app, pluginOptions)
await prepareData(app)
},

onWatched: (app, watchers) => {
watchConfigFile(app, watchers, async ({ localeOptions }) => {
await prepareThemeData(app, localeOptions, pluginOptions)
watchConfigFile(app, watchers, async () => {
await prepareThemeData(app, pluginOptions)
await prepareData(app)
})
watchAutoFrontmatter(app, watchers)
Expand Down
2 changes: 1 addition & 1 deletion theme/src/node/utils/package.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@ export function getPackage() {
}

export function getThemePackage() {
return readJsonFileAsync(resolve('.../../package.json'))
return readJsonFileAsync(resolve('../../package.json'))
}

0 comments on commit b7ced3b

Please sign in to comment.