feat(theme): add @vuepress/plugin-cache

This commit is contained in:
pengzhanbo 2024-07-21 00:52:03 +08:00
parent 688c96452e
commit 62ac0b3371
12 changed files with 97 additions and 166 deletions

10
.vscode/launch.json vendored
View File

@ -5,13 +5,19 @@
"name": "dev", "name": "dev",
"request": "launch", "request": "launch",
"type": "node-terminal", "type": "node-terminal",
"command": "pnpm run dev" "command": "pnpm dev"
},
{
"name": "build",
"request": "launch",
"type": "node-terminal",
"command": "pnpm build"
}, },
{ {
"name": "docs:dev", "name": "docs:dev",
"type": "node-terminal", "type": "node-terminal",
"request": "launch", "request": "launch",
"command": "pnpm run docs:dev" "command": "pnpm docs:dev"
}, },
{ {
"name": "docs:build", "name": "docs:build",

View File

@ -161,6 +161,26 @@ interface BlogOptions {
} }
``` ```
### cache
- 类型: `false | 'memory' | 'filesystem'`
- 默认值: `filesystem`
- 详情:
是否启用 编译缓存,或配置缓存方式
此配置项用于解决 VuePress 启动速度慢的问题,在首次启动服务时,对编译结果进行缓存,二次启动时
直接读取缓存,跳过编译,从而加快启动速度。
- `false`:禁用 缓存
- `'memory'`:使用内存缓存,此方式可获得更快的启动速度,但随着项目文件数量增加,内存占用会增加,
适合文章数量较少的项目使用
- `'filesystem'`:使用文件系统缓存,此方式可获得相对快且稳定的启动速度,更适合内容多的项目使用
::: warning
该字段不支持在 [主题配置文件 `plume.config.js`](./配置说明.md#主题配置文件) 中进行配置。
:::
### locales ### locales
- 类型: `Record<string, PlumeThemeLocaleConfig>` - 类型: `Record<string, PlumeThemeLocaleConfig>`

View File

@ -19,11 +19,10 @@ import {
transformerRenderWhitespace, transformerRenderWhitespace,
} from '@shikijs/transformers' } from '@shikijs/transformers'
import type { HighlighterOptions, ThemeOptions } from './types.js' import type { HighlighterOptions, ThemeOptions } from './types.js'
import { LRUCache, attrsToLines, resolveLanguage } from './utils/index.js' import { attrsToLines, resolveLanguage } from './utils/index.js'
import { defaultHoverInfoProcessor, transformerTwoslash } from './twoslash/rendererTransformer.js' import { defaultHoverInfoProcessor, transformerTwoslash } from './twoslash/rendererTransformer.js'
const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10) const nanoid = customAlphabet('abcdefghijklmnopqrstuvwxyz', 10)
const cache = new LRUCache<string, string>(64)
const vueRE = /-vue$/ const vueRE = /-vue$/
const mustacheRE = /\{\{.*?\}\}/g const mustacheRE = /\{\{.*?\}\}/g
@ -32,7 +31,6 @@ const decorationsRE = /^\/\/ @decorations:(.*)\n/
export async function highlight( export async function highlight(
theme: ThemeOptions, theme: ThemeOptions,
options: HighlighterOptions, options: HighlighterOptions,
isDev: boolean,
): Promise<(str: string, lang: string, attrs: string) => string> { ): Promise<(str: string, lang: string, attrs: string) => string> {
const { const {
defaultHighlightLang: defaultLang = '', defaultHighlightLang: defaultLang = '',
@ -95,14 +93,6 @@ export async function highlight(
let lang = resolveLanguage(language) || defaultLang let lang = resolveLanguage(language) || defaultLang
const vPre = vueRE.test(lang) ? '' : 'v-pre' const vPre = vueRE.test(lang) ? '' : 'v-pre'
const key = str + language + attrs
if (isDev) {
const rendered = cache.get(key)
if (rendered)
return rendered
}
if (lang) { if (lang) {
const langLoaded = loadedLanguages.includes(lang as any) const langLoaded = loadedLanguages.includes(lang as any)
if (!langLoaded && !isPlainLang(lang) && !isSpecialLang(lang)) { if (!langLoaded && !isPlainLang(lang) && !isSpecialLang(lang)) {
@ -183,9 +173,6 @@ export async function highlight(
const rendered = restoreMustache(highlighted) const rendered = restoreMustache(highlighted)
if (isDev)
cache.set(key, rendered)
return rendered return rendered
} }
catch (e) { catch (e) {

View File

@ -51,7 +51,7 @@ export function shikiPlugin({
extendsMarkdown: async (md, app) => { extendsMarkdown: async (md, app) => {
const theme = options.theme ?? { light: 'github-light', dark: 'github-dark' } const theme = options.theme ?? { light: 'github-light', dark: 'github-dark' }
md.options.highlight = await highlight(theme, options, app.env.isDev) md.options.highlight = await highlight(theme, options)
md.use(highlightLinesPlugin) md.use(highlightLinesPlugin)
md.use<PreWrapperOptions>(preWrapperPlugin, { md.use<PreWrapperOptions>(preWrapperPlugin, {

35
pnpm-lock.yaml generated
View File

@ -259,6 +259,9 @@ importers:
theme: theme:
dependencies: dependencies:
'@iconify/vue':
specifier: ^4.1.2
version: 4.1.2(vue@3.4.33(typescript@5.5.3))
'@pengzhanbo/utils': '@pengzhanbo/utils':
specifier: ^1.1.2 specifier: ^1.1.2
version: 1.1.2 version: 1.1.2
@ -283,6 +286,9 @@ importers:
'@vuepress/plugin-active-header-links': '@vuepress/plugin-active-header-links':
specifier: 2.0.0-rc.39 specifier: 2.0.0-rc.39
version: 2.0.0-rc.39(typescript@5.5.3)(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3))) version: 2.0.0-rc.39(typescript@5.5.3)(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3)))
'@vuepress/plugin-cache':
specifier: 2.0.0-rc.39
version: 2.0.0-rc.39(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3)))
'@vuepress/plugin-comment': '@vuepress/plugin-comment':
specifier: 2.0.0-rc.39 specifier: 2.0.0-rc.39
version: 2.0.0-rc.39(typescript@5.5.3)(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3))) version: 2.0.0-rc.39(typescript@5.5.3)(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3)))
@ -361,6 +367,10 @@ importers:
vuepress-plugin-md-power: vuepress-plugin-md-power:
specifier: workspace:* specifier: workspace:*
version: link:../plugins/plugin-md-power version: link:../plugins/plugin-md-power
devDependencies:
'@iconify/json':
specifier: ^2.2.229
version: 2.2.229
packages: packages:
@ -1934,6 +1944,11 @@ packages:
peerDependencies: peerDependencies:
vuepress: 2.0.0-rc.14 vuepress: 2.0.0-rc.14
'@vuepress/plugin-cache@2.0.0-rc.39':
resolution: {integrity: sha512-PVsC797lGMuu8L7jtW9vv2hYM+d5qq5fbWwBJuSyRXEdpcwryhAjGWnz9F19dYe5KWLYG6EbCoANTQObmiyBag==}
peerDependencies:
vuepress: 2.0.0-rc.14
'@vuepress/plugin-comment@2.0.0-rc.39': '@vuepress/plugin-comment@2.0.0-rc.39':
resolution: {integrity: sha512-/oCS+0wH/MtE4c1HUKlqH/tj70oXSz/tfR1hsHj8F8wiZ+IVJxexvtzMKk0vdRmYnH4nqeZh6dg5ggSJjrLEZQ==} resolution: {integrity: sha512-/oCS+0wH/MtE4c1HUKlqH/tj70oXSz/tfR1hsHj8F8wiZ+IVJxexvtzMKk0vdRmYnH4nqeZh6dg5ggSJjrLEZQ==}
peerDependencies: peerDependencies:
@ -3981,14 +3996,13 @@ packages:
resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==} resolution: {integrity: sha512-Ajzxb8CM6WAnFjgiloPsI3bF+WCxcvhdIG3KNA2KN962+tdBsHcuQ4k4qX/EcS/2CRkcc0iAkR956Nib6aXU/Q==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
lru-cache@10.0.1:
resolution: {integrity: sha512-IJ4uwUTi2qCccrioU6g9g/5rvvVl13bsdczUUcqbciD9iLr095yj8DQKdObriEvuNSx325N1rV1O0sJFszx75g==}
engines: {node: 14 || >=16.14}
lru-cache@10.0.2: lru-cache@10.0.2:
resolution: {integrity: sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==} resolution: {integrity: sha512-Yj9mA8fPiVgOUpByoTZO5pNrcl5Yk37FcSHsUINpAsaBIEZIuqcCclDZJCVxqQShDsmYX8QG63svJiTbOATZwg==}
engines: {node: 14 || >=16.14} engines: {node: 14 || >=16.14}
lru-cache@10.4.3:
resolution: {integrity: sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==}
lru-cache@11.0.0: lru-cache@11.0.0:
resolution: {integrity: sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==} resolution: {integrity: sha512-Qv32eSV1RSCfhY3fpPE2GNZ8jgM9X7rdAfemLWqTUxwiyIC4jJ6Sy0fZ8H+oLWevO6i4/bizg7c8d8i6bxrzbA==}
engines: {node: 20 || >=22} engines: {node: 20 || >=22}
@ -7269,6 +7283,11 @@ snapshots:
- '@vue/composition-api' - '@vue/composition-api'
- typescript - typescript
'@vuepress/plugin-cache@2.0.0-rc.39(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3)))':
dependencies:
lru-cache: 10.4.3
vuepress: 2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3))
'@vuepress/plugin-comment@2.0.0-rc.39(typescript@5.5.3)(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3)))': '@vuepress/plugin-comment@2.0.0-rc.39(typescript@5.5.3)(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3)))':
dependencies: dependencies:
'@vuepress/helper': 2.0.0-rc.39(typescript@5.5.3)(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3))) '@vuepress/helper': 2.0.0-rc.39(typescript@5.5.3)(vuepress@2.0.0-rc.14(@vuepress/bundler-vite@2.0.0-rc.14(@types/node@20.12.10)(jiti@1.21.6)(tsx@4.16.0)(typescript@5.5.3)(yaml@2.4.2))(typescript@5.5.3)(vue@3.4.33(typescript@5.5.3)))
@ -9534,11 +9553,11 @@ snapshots:
longest@2.0.1: {} longest@2.0.1: {}
lru-cache@10.0.1: {}
lru-cache@10.0.2: lru-cache@10.0.2:
dependencies: dependencies:
semver: 7.6.0 semver: 7.6.3
lru-cache@10.4.3: {}
lru-cache@11.0.0: {} lru-cache@11.0.0: {}
@ -10331,7 +10350,7 @@ snapshots:
path-scurry@1.10.1: path-scurry@1.10.1:
dependencies: dependencies:
lru-cache: 10.0.1 lru-cache: 10.0.2
minipass: 5.0.0 minipass: 5.0.0
path-scurry@2.0.0: path-scurry@2.0.0:

View File

@ -59,9 +59,16 @@
"tsup:watch": "tsup --config tsup.config.ts --watch" "tsup:watch": "tsup --config tsup.config.ts --watch"
}, },
"peerDependencies": { "peerDependencies": {
"@iconify/json": "^2",
"vuepress": "2.0.0-rc.14" "vuepress": "2.0.0-rc.14"
}, },
"peerDependenciesMeta": {
"@iconify/json": {
"optional": true
}
},
"dependencies": { "dependencies": {
"@iconify/vue": "^4.1.2",
"@pengzhanbo/utils": "^1.1.2", "@pengzhanbo/utils": "^1.1.2",
"@vuepress-plume/plugin-content-update": "workspace:*", "@vuepress-plume/plugin-content-update": "workspace:*",
"@vuepress-plume/plugin-fonts": "workspace:*", "@vuepress-plume/plugin-fonts": "workspace:*",
@ -70,6 +77,7 @@
"@vuepress-plume/plugin-shikiji": "workspace:*", "@vuepress-plume/plugin-shikiji": "workspace:*",
"@vuepress/helper": "2.0.0-rc.39", "@vuepress/helper": "2.0.0-rc.39",
"@vuepress/plugin-active-header-links": "2.0.0-rc.39", "@vuepress/plugin-active-header-links": "2.0.0-rc.39",
"@vuepress/plugin-cache": "2.0.0-rc.39",
"@vuepress/plugin-comment": "2.0.0-rc.39", "@vuepress/plugin-comment": "2.0.0-rc.39",
"@vuepress/plugin-docsearch": "2.0.0-rc.39", "@vuepress/plugin-docsearch": "2.0.0-rc.39",
"@vuepress/plugin-git": "2.0.0-rc.38", "@vuepress/plugin-git": "2.0.0-rc.38",
@ -95,5 +103,8 @@
"vue-router": "^4.4.0", "vue-router": "^4.4.0",
"vuepress-plugin-md-enhance": "2.0.0-rc.52", "vuepress-plugin-md-enhance": "2.0.0-rc.52",
"vuepress-plugin-md-power": "workspace:*" "vuepress-plugin-md-power": "workspace:*"
},
"devDependencies": {
"@iconify/json": "^2.2.229"
} }
} }

View File

@ -6,6 +6,7 @@ export function resolveThemeOptions({
plugins, plugins,
hostname, hostname,
configFile, configFile,
cache,
...localeOptions ...localeOptions
}: PlumeThemeOptions) { }: PlumeThemeOptions) {
const pluginOptions = plugins ?? themePlugins ?? {} const pluginOptions = plugins ?? themePlugins ?? {}
@ -17,6 +18,7 @@ export function resolveThemeOptions({
} }
return { return {
cache,
configFile, configFile,
pluginOptions, pluginOptions,
hostname, hostname,

View File

@ -1,134 +0,0 @@
/**
* 使 shiki + twoslash markdown
* markdown render
* markdown render content hash
*
*
* vuepress/ecosystem
* vuepress/core
*
*
* 使 13s 1.2s
* vuepress shiki 0.5s
*/
import process from 'node:process'
import { fs, path } from 'vuepress/utils'
import type { App } from 'vuepress'
import type { Markdown, MarkdownEnv } from 'vuepress/markdown'
import { hash } from './utils/index.js'
export interface CacheData {
content: string
env: MarkdownEnv
}
// { [filepath]: CacheDta }
export type Cache = Record<string, CacheData>
// { [filepath]: hash }
export type Metadata = Record<string, string>
const CACHE_DIR = 'markdown/rendered'
const META_FILE = '_metadata.json'
export async function extendsMarkdown(md: Markdown, app: App): Promise<void> {
if (app.env.isBuild && !fs.existsSync(app.dir.cache(CACHE_DIR))) {
return
}
const basename = app.dir.cache(CACHE_DIR)
await fs.ensureDir(basename)
const speed = checkIOSpeed(basename)
const metaFilepath = `${basename}/${META_FILE}`
const metadata = (await readFile<Metadata>(metaFilepath)) || {}
let timer: ReturnType<typeof setTimeout> | null = null
const update = (filepath: string, data: CacheData): void => {
writeFile(`${basename}/${filepath}`, data)
if (timer) {
clearTimeout(timer)
}
timer = setTimeout(async () => writeFile(metaFilepath, metadata), 200)
}
const rawRender = md.render
md.render = (input, env: MarkdownEnv) => {
const filepath = env.filePathRelative
if (!filepath) {
return rawRender(input, env)
}
const key = hash(input)
const filename = normalizeFilename(filepath)
if (metadata[filepath] === key) {
const cached = readFileSync<CacheData>(`${basename}/${filename}`)
if (cached) {
Object.assign(env, cached.env)
return cached.content
}
else {
metadata[filepath] = ''
}
}
const start = performance.now()
const content = rawRender(input, env)
/**
* High-frequency I/O is also a time-consuming operation,
* therefore, for render operations with low overhead, caching is not performed.
*/
if (performance.now() - start > speed) {
metadata[filepath] = key
update(filename, { content, env })
}
return content
}
}
function normalizeFilename(filename: string): string {
return hash(filename).slice(0, 10)
}
async function readFile<T = any>(filepath: string): Promise<T | null> {
try {
const content = await fs.readFile(filepath, 'utf-8')
return JSON.parse(content) as T
}
catch {
return null
}
}
function readFileSync<T = any>(filepath: string): T | null {
try {
const content = fs.readFileSync(filepath, 'utf-8')
return JSON.parse(content) as T
}
catch {
return null
}
}
async function writeFile<T = any>(filepath: string, data: T): Promise<void> {
return await fs.writeFile(filepath, JSON.stringify(data), 'utf-8')
}
export function checkIOSpeed(cwd = process.cwd()): number {
try {
const tmp = path.join(cwd, 'tmp')
fs.writeFileSync(tmp, '{}', 'utf-8')
const start = performance.now()
readFileSync(tmp)
const end = performance.now()
fs.unlinkSync(tmp)
return end - start
}
catch {
return 0.15
}
}

View File

@ -1,5 +1,6 @@
import type { App, PluginConfig } from 'vuepress/core' import type { App, PluginConfig } from 'vuepress/core'
import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links' import { activeHeaderLinksPlugin } from '@vuepress/plugin-active-header-links'
import { cachePlugin } from '@vuepress/plugin-cache'
import { docsearchPlugin } from '@vuepress/plugin-docsearch' import { docsearchPlugin } from '@vuepress/plugin-docsearch'
import { gitPlugin } from '@vuepress/plugin-git' import { gitPlugin } from '@vuepress/plugin-git'
import { photoSwipePlugin } from '@vuepress/plugin-photo-swipe' import { photoSwipePlugin } from '@vuepress/plugin-photo-swipe'
@ -27,12 +28,14 @@ export interface SetupPluginOptions {
app: App app: App
pluginOptions: PlumeThemePluginOptions pluginOptions: PlumeThemePluginOptions
hostname?: string hostname?: string
cache?: false | 'memory' | 'filesystem'
} }
export function getPlugins({ export function getPlugins({
app, app,
pluginOptions, pluginOptions,
hostname, hostname,
cache,
}: SetupPluginOptions): PluginConfig { }: SetupPluginOptions): PluginConfig {
const isProd = !app.env.isDev const isProd = !app.env.isDev
@ -156,5 +159,9 @@ export function getPlugins({
plugins.push(seoPlugin({ hostname })) plugins.push(seoPlugin({ hostname }))
} }
if (cache !== false) {
plugins.push(cachePlugin({ type: cache || 'filesystem' }))
}
return plugins return plugins
} }

View File

@ -26,7 +26,6 @@ import {
} from './autoFrontmatter/index.js' } from './autoFrontmatter/index.js'
import { prepareData, watchPrepare } from './prepare/index.js' import { prepareData, watchPrepare } from './prepare/index.js'
import { prepareThemeData } from './prepare/prepareThemeData.js' import { prepareThemeData } from './prepare/prepareThemeData.js'
import { extendsMarkdown } from './extendsMarkdown.js'
export function plumeTheme(options: PlumeThemeOptions = {}): Theme { export function plumeTheme(options: PlumeThemeOptions = {}): Theme {
const { const {
@ -34,6 +33,7 @@ export function plumeTheme(options: PlumeThemeOptions = {}): Theme {
pluginOptions, pluginOptions,
hostname, hostname,
configFile, configFile,
cache,
} = resolveThemeOptions(options) } = resolveThemeOptions(options)
return (app) => { return (app) => {
@ -65,7 +65,7 @@ export function plumeTheme(options: PlumeThemeOptions = {}): Theme {
alias: resolveAlias(), alias: resolveAlias(),
plugins: getPlugins({ app, pluginOptions, hostname }), plugins: getPlugins({ app, pluginOptions, hostname, cache }),
onInitialized: async (app) => { onInitialized: async (app) => {
const { localeOptions } = await waitForConfigLoaded() const { localeOptions } = await waitForConfigLoaded()
@ -90,14 +90,14 @@ export function plumeTheme(options: PlumeThemeOptions = {}): Theme {
}, },
extendsPage: async (page) => { extendsPage: async (page) => {
const { localeOptions } = await waitForConfigLoaded() const { localeOptions, autoFrontmatter } = await waitForConfigLoaded()
await waitForAutoFrontmatter() if ((autoFrontmatter ?? pluginOptions.frontmatter) !== false) {
await waitForAutoFrontmatter()
}
extendsPageData(page as Page<PlumeThemePageData>, localeOptions) extendsPageData(page as Page<PlumeThemePageData>, localeOptions)
resolvePageHead(page, localeOptions) resolvePageHead(page, localeOptions)
}, },
extendsMarkdown,
extendsBundlerOptions, extendsBundlerOptions,
templateBuildRenderer, templateBuildRenderer,

View File

@ -23,6 +23,13 @@ export interface PlumeThemeOptions extends PlumeThemeLocaleOptions {
*/ */
hostname?: string hostname?: string
/**
*
*
* @default 'filesystem'
*/
cache?: false | 'memory' | 'filesystem'
/** /**
* *
*/ */
@ -33,6 +40,9 @@ export interface PlumeThemeOptions extends PlumeThemeLocaleOptions {
*/ */
configFile?: string configFile?: string
/**
* frontmatter
*/
autoFrontmatter?: false | Omit<AutoFrontmatter, 'frontmatter'> autoFrontmatter?: false | Omit<AutoFrontmatter, 'frontmatter'>
} }

View File

@ -60,13 +60,16 @@ export interface PlumeThemePluginOptions {
* @deprecated * @deprecated
* 使 [@vuepress/plugin-baidu-analytics](https://ecosystem.vuejs.press/zh/plugins/analytics/baidu-analytics.html) 代替 * 使 [@vuepress/plugin-baidu-analytics](https://ecosystem.vuejs.press/zh/plugins/analytics/baidu-analytics.html) 代替
*/ */
baiduTongji?: never baiduTongji?: false | { key: string }
/** /**
* @deprecated 使 `autoFrontmatter` * @deprecated 使 `autoFrontmatter`
*/ */
frontmatter?: Omit<AutoFrontmatter, 'frontmatter'> frontmatter?: Omit<AutoFrontmatter, 'frontmatter'>
/**
*
*/
readingTime?: false | ReadingTimePluginOptions readingTime?: false | ReadingTimePluginOptions
/** /**