Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(theme): improve theme options #463

Merged
merged 1 commit into from
Feb 16, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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'))
}
Loading