diff --git a/plugins/plugin-notes-data/package.json b/plugins/plugin-notes-data/package.json index de7cc676..b110de47 100644 --- a/plugins/plugin-notes-data/package.json +++ b/plugins/plugin-notes-data/package.json @@ -2,6 +2,7 @@ "name": "@vuepress-plume/plugin-notes-data", "type": "module", "version": "1.0.0-rc.72", + "private": "true", "description": "The Plugin for VuePress 2 - notes data", "author": "pengzhanbo ", "license": "MIT", diff --git a/plugins/plugin-notes-data/src/client/clientConfig.ts b/plugins/plugin-notes-data/src/client/clientConfig.ts index 69e26d18..4cd6b0e1 100644 --- a/plugins/plugin-notes-data/src/client/clientConfig.ts +++ b/plugins/plugin-notes-data/src/client/clientConfig.ts @@ -30,7 +30,7 @@ export default defineClientConfig({ id: PLUGIN_ID, label: PLUGIN_LABEL, packageName: '@vuepress-plume/plugin-notes-data', - homepage: 'https://pengzhanbo.cn', + homepage: 'https://theme-plume.vuejs.press/', logo: 'https://v2.vuepress.vuejs.org/images/hero.png', componentStateTypes: ['VuePress'], }, diff --git a/theme/package.json b/theme/package.json index 011fb16a..bd1f37c4 100644 --- a/theme/package.json +++ b/theme/package.json @@ -5,7 +5,7 @@ "description": "A Blog&Document Theme for VuePress 2.0", "author": "pengzhanbo (https://github.com/pengzhanbo/)", "license": "MIT", - "homepage": "https://pengzhanbo.cn/note/vuepress-theme-plume", + "homepage": "https://theme-plume.vuejs.press/", "repository": { "type": "git", "url": "git+https://github.com/pengzhanbo/vuepress-theme-plume.git" @@ -67,13 +67,11 @@ }, "dependencies": { "@pengzhanbo/utils": "^1.1.2", - "@vuepress-plume/plugin-auto-frontmatter": "workspace:*", + "@vue/devtools-api": "6.6.3", "@vuepress-plume/plugin-baidu-tongji": "workspace:*", - "@vuepress-plume/plugin-blog-data": "workspace:*", "@vuepress-plume/plugin-content-update": "workspace:*", "@vuepress-plume/plugin-fonts": "workspace:*", "@vuepress-plume/plugin-iconify": "workspace:*", - "@vuepress-plume/plugin-notes-data": "workspace:*", "@vuepress-plume/plugin-search": "workspace:*", "@vuepress-plume/plugin-shikiji": "workspace:*", "@vuepress/helper": "2.0.0-rc.37", @@ -87,14 +85,17 @@ "@vuepress/plugin-reading-time": "2.0.0-rc.37", "@vuepress/plugin-seo": "2.0.0-rc.37", "@vuepress/plugin-sitemap": "2.0.0-rc.37", - "@vuepress/plugin-theme-data": "2.0.0-rc.37", "@vuepress/plugin-watermark": "2.0.0-rc.37", "@vueuse/core": "^10.11.0", "bcrypt-ts": "^5.0.2", "chokidar": "^3.6.0", + "create-filter": "^1.1.0", "date-fns": "^3.6.0", + "esbuild": "~0.21.5", + "fast-glob": "^3.3.2", + "gray-matter": "^4.0.3", + "json2yaml": "^1.1.0", "katex": "^0.16.10", - "lodash.merge": "^4.6.2", "nanoid": "^5.0.7", "vue": "^3.4.31", "vue-router": "^4.4.0", diff --git a/theme/src/node/defineConfig.ts b/theme/src/node/defineConfig.ts index 5376b6b2..8380861a 100644 --- a/theme/src/node/defineConfig.ts +++ b/theme/src/node/defineConfig.ts @@ -3,6 +3,7 @@ import type { NotesItemOptions, } from '@vuepress-plume/plugin-notes-data' import type { NavItem } from '../shared/index.js' +import type { ThemeConfig } from '../shared/theme-data.js' export function definePlumeNotesConfig(notes: NotesDataOptions): NotesDataOptions { return notes @@ -28,3 +29,10 @@ export type { NotesItemOptions, NotesItemOptions as NotesItem, } + +/** + * 主题配置,在单独的 `plume.config.ts` 中使用的类型帮助函数 + */ +export function defineThemeConfig(config: ThemeConfig): ThemeConfig { + return config +} diff --git a/theme/src/node/setupPages.ts b/theme/src/node/setupPages.ts index cfcb8c88..f4427d7f 100644 --- a/theme/src/node/setupPages.ts +++ b/theme/src/node/setupPages.ts @@ -10,7 +10,7 @@ import type { PlumeThemeLocaleOptions, PlumeThemePageData, } from '../shared/index.js' -import { withBase } from './utils.js' +import { withBase } from './utils/index.js' import { PRESET_LOCALES } from './locales/index.js' import { resolveNotesLinkList } from './config/index.js' @@ -63,6 +63,10 @@ export function extendsPageData( 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 diff --git a/theme/src/node/theme.ts b/theme/src/node/theme.ts index c47bafe6..8986e8f4 100644 --- a/theme/src/node/theme.ts +++ b/theme/src/node/theme.ts @@ -2,34 +2,59 @@ import type { Page, Theme } from 'vuepress/core' import type { PlumeThemeOptions, PlumeThemePageData } from '../shared/index.js' import { getPlugins } from './plugins/index.js' import { extendsPageData, setupPage } from './setupPages.js' -import { THEME_NAME, resolve, templates } from './utils.js' +import { THEME_NAME, resolve, templates } from './utils/index.js' import { extendsBundlerOptions, resolveAlias, - resolveLocaleOptions, resolvePageHead, resolveProvideData, resolveThemeOptions, templateBuildRenderer, } from './config/index.js' -import { setupPrepare, watchPrepare } from './prepare/index.js' +import { + getResolvedThemeConfig, + initConfigLoader, + onConfigChange, + waitForConfigLoaded, + watchConfigFile, +} from './loadConfig/index.js' +import { + generateAFrontmatter, + initAutoFrontmatter, + watchAutoFrontmatter, +} from './autoFrontmatter/index.js' +import { prepareData, watchPrepare } from './prepare/index.js' +import { prepareThemeData } from './prepare/prepareThemeData.js' import { extendsMarkdown } from './extendsMarkdown.js' export function plumeTheme(options: PlumeThemeOptions = {}): Theme { const { - localeOptions: rawLocaleOptions, + localeOptions, pluginOptions, hostname, - encrypt, + configFile, } = resolveThemeOptions(options) return (app) => { - const localeOptions = resolveLocaleOptions(app, rawLocaleOptions) + initConfigLoader(app, localeOptions, { + configFile, + onChange: ({ localeOptions, autoFrontmatter }) => { + autoFrontmatter ??= pluginOptions.frontmatter + autoFrontmatter !== false && initAutoFrontmatter(localeOptions, autoFrontmatter) + }, + }) + + waitForConfigLoaded().then(({ autoFrontmatter }) => { + autoFrontmatter ??= pluginOptions.frontmatter + if (autoFrontmatter !== false) { + generateAFrontmatter(app) + } + }) return { name: THEME_NAME, - define: resolveProvideData(app, pluginOptions, encrypt), + define: resolveProvideData(app, pluginOptions), templateBuild: templates('build.html'), @@ -37,21 +62,31 @@ export function plumeTheme(options: PlumeThemeOptions = {}): Theme { alias: resolveAlias(), - plugins: getPlugins({ app, pluginOptions, localeOptions, encrypt, hostname }), + plugins: getPlugins({ app, pluginOptions, hostname }), onInitialized: async (app) => { + const { localeOptions } = await waitForConfigLoaded() await setupPage(app, localeOptions) }, - onPrepared: async (app) => { - await setupPrepare(app) + onPrepared: (app) => { + onConfigChange(({ localeOptions }) => { + prepareThemeData(app, localeOptions) + prepareData(app) + }) }, onWatched: (app, watchers) => { + watchConfigFile(app, watchers) watchPrepare(app, watchers) + const autoFrontmatter = getResolvedThemeConfig().autoFrontmatter ?? pluginOptions.frontmatter + if (autoFrontmatter !== false) { + watchAutoFrontmatter(app, watchers) + } }, - extendsPage: (page) => { + extendsPage: async (page) => { + const { localeOptions } = await waitForConfigLoaded() extendsPageData(page as Page, localeOptions) resolvePageHead(page, localeOptions) },