From e605bdfcc2fb4f36bdf2819f2954ba6bb117b44b Mon Sep 17 00:00:00 2001 From: pengzhanbo Date: Wed, 12 Feb 2025 01:08:56 +0800 Subject: [PATCH] refactor(theme): improve theme options --- theme/src/node/autoFrontmatter/generator.ts | 11 ++-- .../src/node/config/extendsBundlerOptions.ts | 6 ++- .../src/node/config/templateBuildRenderer.ts | 4 +- theme/src/node/pages/createPages.ts | 31 ++++++++---- theme/src/node/pages/extendsPage.ts | 5 +- theme/src/node/plugins/getPlugins.ts | 19 ++++--- theme/src/node/prepare/prepareThemeData.ts | 5 +- theme/src/node/theme.ts | 50 ++++++++++++------- theme/src/node/utils/package.ts | 2 +- 9 files changed, 80 insertions(+), 53 deletions(-) diff --git a/theme/src/node/autoFrontmatter/generator.ts b/theme/src/node/autoFrontmatter/generator.ts index 10521d4ae..01c57aa56 100644 --- a/theme/src/node/autoFrontmatter/generator.ts +++ b/theme/src/node/autoFrontmatter/generator.ts @@ -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' @@ -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 }) diff --git a/theme/src/node/config/extendsBundlerOptions.ts b/theme/src/node/config/extendsBundlerOptions.ts index 47a8b2ef9..804a82e40 100644 --- a/theme/src/node/config/extendsBundlerOptions.ts +++ b/theme/src/node/config/extendsBundlerOptions.ts @@ -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, [ diff --git a/theme/src/node/config/templateBuildRenderer.ts b/theme/src/node/config/templateBuildRenderer.ts index bbd3dd7e2..9c9d0caa3 100644 --- a/theme/src/node/config/templateBuildRenderer.ts +++ b/theme/src/node/config/templateBuildRenderer.ts @@ -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 || '') diff --git a/theme/src/node/pages/createPages.ts b/theme/src/node/pages/createPages.ts index e6e6c1f4f..336e7ac3e 100644 --- a/theme/src/node/pages/createPages.ts +++ b/theme/src/node/pages/createPages.ts @@ -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[] = [] - 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)) { @@ -24,7 +35,7 @@ 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' }, })) } @@ -32,7 +43,7 @@ export async function createPages(app: App, localeOption: PlumeThemeLocaleOption 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' }, })) } @@ -40,7 +51,7 @@ export async function createPages(app: App, localeOption: PlumeThemeLocaleOption 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' }, })) } @@ -48,7 +59,7 @@ export async function createPages(app: App, localeOption: PlumeThemeLocaleOption 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' }, })) } } diff --git a/theme/src/node/pages/extendsPage.ts b/theme/src/node/pages/extendsPage.ts index 23bf12830..9560f87d5 100644 --- a/theme/src/node/pages/extendsPage.ts +++ b/theme/src/node/pages/extendsPage.ts @@ -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, - localeOptions: PlumeThemeLocaleOptions, ) { + const { localeOptions } = getThemeConfig() cleanPageData(page) autoCategory(page, localeOptions) enableBulletin(page, localeOptions) diff --git a/theme/src/node/plugins/getPlugins.ts b/theme/src/node/plugins/getPlugins.ts index 2ef0d78d1..460999e7d 100644 --- a/theme/src/node/plugins/getPlugins.ts +++ b/theme/src/node/plugins/getPlugins.ts @@ -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' @@ -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 @@ -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(), diff --git a/theme/src/node/prepare/prepareThemeData.ts b/theme/src/node/prepare/prepareThemeData.ts index 4f61fc2d4..ffa16a4bc 100644 --- a/theme/src/node/prepare/prepareThemeData.ts +++ b/theme/src/node/prepare/prepareThemeData.ts @@ -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 @@ -16,10 +17,10 @@ process.on('exit', () => bulletinFileWatcher?.close()) export async function prepareThemeData( app: App, - localeOptions: PlumeThemeLocaleOptions, pluginOptions: PlumeThemePluginOptions, ): Promise { perfMark('prepare:theme-data') + const { localeOptions } = getThemeConfig() const resolvedThemeData = resolveThemeData(app, localeOptions) await resolveProfileImage(app, resolvedThemeData, pluginOptions) diff --git a/theme/src/node/theme.ts b/theme/src/node/theme.ts index 391a0c60e..259d617eb 100644 --- a/theme/src/node/theme.ts +++ b/theme/src/node/theme.ts @@ -1,9 +1,19 @@ 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' @@ -11,15 +21,18 @@ 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 { @@ -33,17 +46,16 @@ 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 @@ -51,22 +63,22 @@ export function plumeTheme(options: PlumeThemeOptions = {}): Theme { } }, - extendsPage: async (page) => { - extendsPageData(page as Page, getThemeConfig().localeOptions) + extendsPage: (page) => { + extendsPageData(page as Page) }, 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) diff --git a/theme/src/node/utils/package.ts b/theme/src/node/utils/package.ts index 5cf80992c..bf355f3ef 100644 --- a/theme/src/node/utils/package.ts +++ b/theme/src/node/utils/package.ts @@ -16,5 +16,5 @@ export function getPackage() { } export function getThemePackage() { - return readJsonFileAsync(resolve('.../../package.json')) + return readJsonFileAsync(resolve('../../package.json')) }