diff --git a/theme/src/node/extendsBundlerOptions.ts b/theme/src/node/config/extendsBundlerOptions.ts similarity index 100% rename from theme/src/node/extendsBundlerOptions.ts rename to theme/src/node/config/extendsBundlerOptions.ts diff --git a/theme/src/node/config/index.ts b/theme/src/node/config/index.ts index 99c2e188..4b3f606f 100644 --- a/theme/src/node/config/index.ts +++ b/theme/src/node/config/index.ts @@ -1,5 +1,12 @@ +export * from './resolveThemeOption.js' export * from './resolveLocaleOptions.js' export * from './resolveThemeData.js' +export * from './resolveProvideData.js' +export * from './resolveAlias.js' + +export * from './extendsBundlerOptions.js' +export * from './templateBuildRenderer.js' + export * from './resolveSearchOptions.js' export * from './resolvePageHead.js' export * from './resolveEncrypt.js' diff --git a/theme/src/node/config/resolveAlias.ts b/theme/src/node/config/resolveAlias.ts new file mode 100644 index 00000000..e4b66179 --- /dev/null +++ b/theme/src/node/config/resolveAlias.ts @@ -0,0 +1,18 @@ +import { fs, path } from 'vuepress/utils' +import { resolve } from '../utils.js' + +export function resolveAlias() { + return { + ...Object.fromEntries( + fs.readdirSync( + resolve('client/components'), + { encoding: 'utf-8', recursive: true }, + ) + .filter(file => file.endsWith('.vue')) + .map(file => [ + path.join('@theme', file), + resolve('client/components', file), + ]), + ), + } +} diff --git a/theme/src/node/config/resolveProvideData.ts b/theme/src/node/config/resolveProvideData.ts new file mode 100644 index 00000000..a0bb6b47 --- /dev/null +++ b/theme/src/node/config/resolveProvideData.ts @@ -0,0 +1,28 @@ +import type { App } from 'vuepress' +import { entries, fromEntries, getRootLangPath, isPlainObject } from '@vuepress/helper' +import type { PlumeThemeEncrypt, PlumeThemePluginOptions } from '../../shared/index.js' +import { PRESET_LOCALES } from '../locales/index.js' +import { resolveEncrypt } from './resolveEncrypt.js' + +export function resolveProvideData( + app: App, + plugins: PlumeThemePluginOptions, + encrypt?: PlumeThemeEncrypt, + +): Record { + const root = getRootLangPath(app) + + return { + // 注入 加密配置 + ...resolveEncrypt(encrypt), + // 注入水印配置 + __PLUME_WM_FP__: isPlainObject(plugins.watermark) + ? plugins.watermark.fullPage !== false + : true, + // 注入多语言配置 + __PLUME_PRESET_LOCALE__: fromEntries( + entries(PRESET_LOCALES) + .map(([locale, value]) => [locale === root ? '/' : locale, value]), + ), + } +} diff --git a/theme/src/node/config/resolveSearchOptions.ts b/theme/src/node/config/resolveSearchOptions.ts index 7b07faaf..32d4013d 100644 --- a/theme/src/node/config/resolveSearchOptions.ts +++ b/theme/src/node/config/resolveSearchOptions.ts @@ -4,7 +4,10 @@ import type { DocsearchPluginOptions } from '@vuepress/plugin-docsearch' import type { SearchPluginOptions } from '@vuepress-plume/plugin-search' import { DOCSEARCH_LOCALES, SEARCH_LOCALES } from '../locales/index.js' -export function resolveSearchOptions(app: App, { locales, ...options }: SearchPluginOptions = {}): SearchPluginOptions { +export function resolveSearchOptions( + app: App, + { locales, ...options }: SearchPluginOptions = {}, +): SearchPluginOptions { return { ...options, locales: getLocaleConfig({ @@ -15,7 +18,10 @@ export function resolveSearchOptions(app: App, { locales, ...options }: SearchPl } } -export function resolveDocsearchOptions(app: App, { locales, ...options }: DocsearchPluginOptions = {}): DocsearchPluginOptions { +export function resolveDocsearchOptions( + app: App, + { locales, ...options }: DocsearchPluginOptions = {}, +): DocsearchPluginOptions { return { ...options, locales: getLocaleConfig({ diff --git a/theme/src/node/config/resolveThemeOption.ts b/theme/src/node/config/resolveThemeOption.ts new file mode 100644 index 00000000..39157647 --- /dev/null +++ b/theme/src/node/config/resolveThemeOption.ts @@ -0,0 +1,19 @@ +import type { PlumeThemeOptions } from '../../shared/index.js' +import { logger } from '../utils.js' + +export function resolveThemeOptions({ themePlugins, plugins, encrypt, hostname, ...localeOptions }: PlumeThemeOptions) { + const pluginOptions = plugins ?? themePlugins ?? {} + + if (themePlugins) { + logger.warn( + `The 'themePlugins' option is deprecated. Please use 'plugins' instead.`, + ) + } + + return { + pluginOptions, + encrypt, + hostname, + localeOptions, + } +} diff --git a/theme/src/node/templateBuildRenderer.ts b/theme/src/node/config/templateBuildRenderer.ts similarity index 89% rename from theme/src/node/templateBuildRenderer.ts rename to theme/src/node/config/templateBuildRenderer.ts index fed950ae..a512f14a 100644 --- a/theme/src/node/templateBuildRenderer.ts +++ b/theme/src/node/config/templateBuildRenderer.ts @@ -1,5 +1,5 @@ import { type TemplateRendererContext, templateRenderer } from 'vuepress/utils' -import { getThemePackage } from './utils.js' +import { getThemePackage } from '../utils.js' export function templateBuildRenderer(template: string, context: TemplateRendererContext) { const pkg = getThemePackage() diff --git a/theme/src/node/index.ts b/theme/src/node/index.ts index a89a69bb..c1dd2421 100644 --- a/theme/src/node/index.ts +++ b/theme/src/node/index.ts @@ -5,4 +5,7 @@ export * from '../shared/index.js' export { plumeTheme } +/** + * @deprecated 请使用 具名导出 替代 默认导出 + */ export default plumeTheme diff --git a/theme/src/node/locales/en.ts b/theme/src/node/locales/en.ts index a0da0045..06cf33b5 100644 --- a/theme/src/node/locales/en.ts +++ b/theme/src/node/locales/en.ts @@ -1,6 +1,5 @@ import type { SearchLocaleOptions } from '@vuepress-plume/plugin-search' -import type { PlumeThemeLocaleData } from '../../shared/index.js' -import type { PresetLocale } from '../types.js' +import type { PlumeThemeLocaleData, PresetLocale } from '../../shared/index.js' export const enLocale: PlumeThemeLocaleData = { selectLanguageName: 'English', diff --git a/theme/src/node/locales/index.ts b/theme/src/node/locales/index.ts index 4467b5b0..1faa093b 100644 --- a/theme/src/node/locales/index.ts +++ b/theme/src/node/locales/index.ts @@ -1,7 +1,6 @@ import type { DocsearchLocaleOptions } from '@vuepress/plugin-docsearch' import type { SearchLocaleOptions } from '@vuepress-plume/plugin-search' -import type { PlumeThemeLocaleData } from '../../shared/index.js' -import type { PresetLocale } from '../types.js' +import type { PlumeThemeLocaleData, PresetLocale } from '../../shared/index.js' import { zhDocsearchLocale, zhLocale, zhPresetLocale, zhSearchLocale } from './zh.js' import { enLocale, enPresetLocale, enSearchLocale } from './en.js' diff --git a/theme/src/node/locales/zh.ts b/theme/src/node/locales/zh.ts index df0d53dc..c77c8049 100644 --- a/theme/src/node/locales/zh.ts +++ b/theme/src/node/locales/zh.ts @@ -1,7 +1,6 @@ import type { DocsearchLocaleOptions } from '@vuepress/plugin-docsearch' import type { SearchLocaleOptions } from '@vuepress-plume/plugin-search' -import type { PlumeThemeLocaleData } from '../../shared/index.js' -import type { PresetLocale } from '../types.js' +import type { PlumeThemeLocaleData, PresetLocale } from '../../shared/index.js' export const zhLocale: PlumeThemeLocaleData = { selectLanguageName: '简体中文', diff --git a/theme/src/node/theme.ts b/theme/src/node/theme.ts index 2e1bbbf7..251cdffa 100644 --- a/theme/src/node/theme.ts +++ b/theme/src/node/theme.ts @@ -1,62 +1,40 @@ import type { Page, Theme } from 'vuepress/core' -import { fs, path } from 'vuepress/utils' -import { isPlainObject } from '@vuepress/helper' import type { PlumeThemeOptions, PlumeThemePageData } from '../shared/index.js' import { getPlugins } from './plugins/index.js' import { extendsPageData, setupPage } from './setupPages.js' -import { THEME_NAME, logger, resolve, templates } from './utils.js' -import { resolveEncrypt, resolveLocaleOptions, resolvePageHead } from './config/index.js' -import { extendsBundlerOptions } from './extendsBundlerOptions.js' -import { templateBuildRenderer } from './templateBuildRenderer.js' +import { THEME_NAME, resolve, templates } from './utils.js' +import { + extendsBundlerOptions, + resolveAlias, + resolveLocaleOptions, + resolvePageHead, + resolveProvideData, + resolveThemeOptions, + templateBuildRenderer, +} from './config/index.js' import { setupPrepare, watchPrepare } from './prepare/index.js' -export function plumeTheme({ - themePlugins, - plugins, - encrypt, - hostname, - ...localeOptions -}: PlumeThemeOptions = {}): Theme { - const pluginOptions = plugins ?? themePlugins ?? {} - - const watermarkFullPage = isPlainObject(pluginOptions.watermark) - ? pluginOptions.watermark.fullPage !== false - : true - - if (themePlugins) { - logger.warn( - `The 'themePlugins' option is deprecated. Please use 'plugins' instead.`, - ) - } +export function plumeTheme(options: PlumeThemeOptions = {}): Theme { + const { + localeOptions: rawLocaleOptions, + pluginOptions, + hostname, + encrypt, + } = resolveThemeOptions(options) return (app) => { - localeOptions = resolveLocaleOptions(app, localeOptions) + const localeOptions = resolveLocaleOptions(app, rawLocaleOptions) return { name: THEME_NAME, - define: { - ...resolveEncrypt(encrypt), - __PLUME_WM_FP__: watermarkFullPage, - }, + define: resolveProvideData(app, pluginOptions, encrypt), templateBuild: templates('build.html'), clientConfigFile: resolve('client/config.js'), - alias: { - ...Object.fromEntries( - fs.readdirSync( - resolve('client/components'), - { encoding: 'utf-8', recursive: true }, - ) - .filter(file => file.endsWith('.vue')) - .map(file => [ - path.join('@theme', file), - resolve('client/components', file), - ]), - ), - }, + alias: resolveAlias(), plugins: getPlugins({ app, pluginOptions, localeOptions, encrypt, hostname }), diff --git a/theme/src/node/types.ts b/theme/src/node/types.ts deleted file mode 100644 index d461eb5f..00000000 --- a/theme/src/node/types.ts +++ /dev/null @@ -1,6 +0,0 @@ -export interface PresetLocale { - home: string - blog: string - tag: string - archive: string -} diff --git a/theme/src/shared/base.ts b/theme/src/shared/base.ts index 3a361c8e..b7e185ad 100644 --- a/theme/src/shared/base.ts +++ b/theme/src/shared/base.ts @@ -38,3 +38,10 @@ export type SocialLinkIconUnion = | 'xbox' export type SocialLinkIcon = SocialLinkIconUnion | { svg: string } + +export interface PresetLocale { + home: string + blog: string + tag: string + archive: string +} diff --git a/theme/src/shared/options/locale.ts b/theme/src/shared/options/locale.ts index 17f0a522..99081b7f 100644 --- a/theme/src/shared/options/locale.ts +++ b/theme/src/shared/options/locale.ts @@ -48,9 +48,9 @@ export interface PlumeThemeLocaleData extends LocaleData { social?: SocialLink[] /** - * Navbar config + * 导航栏配置 * - * Set to `false` to disable navbar in current locale + * 设置为 `false` 将会禁用导航栏 */ navbar?: false | NavItem[] @@ -75,114 +75,119 @@ export interface PlumeThemeLocaleData extends LocaleData { /** * 笔记配置, 笔记中的文章默认不会出现在首页文章列表 * - * 注:你也可以将notes配置到navbar中,默认自动生成在右侧栏目中 + * 注:也可以将notes配置到navbar中 */ notes?: false | NotesDataOptions + /** + * 要显示的标题级别。 + * + * 单个数字表示只显示该级别的标题。 + * + * 如果传递的是一个元组,第一个数字是最小级别,第二个数字是最大级别。 + * + * 'deep' 与 [2, 6] 相同,将显示从

的所有标题。 + * + * @default [2, 3] + */ outline?: ThemeOutline /** * 是否显示侧边栏 * + * - `false` 表示禁用 右侧边栏 + * - `true` 表示启用 右侧边栏 + * - `'left` 表示将有侧边栏移动到文章内容左侧,sidebar 右侧 + * * @default true */ aside?: boolean | 'left' /** - * language text + * 选择语言菜单 的文本。 */ selectLanguageText?: string /** - * language aria label + * 选择语言菜单 的 `aria-label` 属性。 */ selectLanguageAriaLabel?: string /** - * language name + * 语言名称 + * + * 仅能在主题配置的 locales 的内部生效 。它将被用作 locale 的语言名称,展示在 选择语言菜单 内。 */ selectLanguageName?: string /** - * Page meta - edit link config * - * Whether to show "Edit this page" or not + * + * 是否显示 "编辑此页" */ editLink?: boolean /** - * Page meta - edit link config + * "编辑此页" 的文本 * - * The text to replace the default "Edit this page" + * @default "Edit this page" */ editLinkText?: string /** - * Page meta - edit link config - * - * Pattern of edit link + * "编辑此页" 的链接匹配模式 * * @example ':repo/edit/:branch/:path' */ editLinkPattern?: string /** - * Page meta - edit link config - * - * Use `repo` config by default - * - * Set this config if your docs is placed in a different repo + * 文档仓库配置, 用于生成 Edit this page 链接 */ docsRepo?: string /** - * Page meta - edit link config - * - * Set this config if the branch of your docs is not 'main' + * 文档仓库分支配置,用于生成 `Edit this page` 链接。 */ docsBranch?: string /** - * Page meta - edit link config - * - * Set this config if your docs is placed in sub dir of your `docsRepo` + * 文档仓库目录配置,用于生成 `Edit this page` 链接。 */ docsDir?: string /** - * Page meta - last updated config + * 最后更新时间 * - * Whether to show "Last Updated" or not + * @default { text: 'Last Updated', formatOptions: { dateStyle: 'short', timeStyle: 'short' } } */ lastUpdated?: false | LastUpdatedOptions /** - * @deprecated Use `lastUpdated.text` instead. + * @deprecated 使用 `lastUpdated.text` 代替. * - * Set custom last updated text. + * "最后更新时间" 的文本 * * @default 'Last updated' */ lastUpdatedText?: string /** - * Page meta - contributors config - * - * Whether to show "Contributors" or not + * 是否显示贡献者 */ contributors?: boolean /** - * Page meta - contributors config - * - * The text to replace the default "Contributors" + * 贡献者的文本 */ contributorsText?: string - // backToHome?: string - /** - * sidebar menu label + * 移动设备下的导航栏中 菜单选项的文字。 + * + * @default 'Menu' */ sidebarMenuLabel?: string /** - * return to top label + * 移动设备下的导航栏中返回顶部的文字。 + * + * @default 'return to top' */ returnToTopLabel?: string @@ -193,15 +198,30 @@ export interface PlumeThemeLocaleData extends LocaleData { */ outlineLabel?: string + /** + * 上一页的文本 + * + * @default 'Previous Page' + */ prevPageLabel?: string + /** + * 下一页的文本 + * + * @default 'Next Page' + */ nextPageLabel?: string /** * 是否显示外部链接图标 + * + * @default true */ externalLinkIcon?: string + /** + * 页脚配置。 + */ footer?: | false | { @@ -210,7 +230,7 @@ export interface PlumeThemeLocaleData extends LocaleData { } /** - * 404 page options + * 404 页面配置 */ notFound?: { code?: string | number