perf: 优化代码结构

This commit is contained in:
pengzhanbo 2023-12-28 15:30:56 +08:00
parent 0dc441a0e6
commit 7ab06863e7
7 changed files with 192 additions and 186 deletions

View File

@ -1,11 +1,3 @@
## scripts/autoInstall
检查各个 workspace package 中的 vuepress 相关依赖,并更新到最新版本。
``` sh
pnpm autoUpdate
```
## scripts/create ## scripts/create
`packages/` 目录下生成一个新的 插件包 `packages/` 目录下生成一个新的 插件包

View File

@ -11,7 +11,6 @@ import NotFound from './layouts/NotFound.vue'
export default defineClientConfig({ export default defineClientConfig({
enhance({ app, router }) { enhance({ app, router }) {
// global component // global component
app.component('Badge', Badge) app.component('Badge', Badge)
app.component('ExternalLinkIcon', ExternalLinkIcon) app.component('ExternalLinkIcon', ExternalLinkIcon)

View File

@ -1,6 +1,4 @@
import fs from 'node:fs'
import path from 'node:path' import path from 'node:path'
import process from 'node:process'
import type { App } from '@vuepress/core' import type { App } from '@vuepress/core'
import { resolveLocalePath } from '@vuepress/shared' import { resolveLocalePath } from '@vuepress/shared'
import type { import type {
@ -8,28 +6,13 @@ import type {
FrontmatterArray, FrontmatterArray,
FrontmatterObject, FrontmatterObject,
} from '@vuepress-plume/plugin-auto-frontmatter' } from '@vuepress-plume/plugin-auto-frontmatter'
import type { NotesItem } from '@vuepress-plume/plugin-notes-data'
import { format } from 'date-fns' import { format } from 'date-fns'
import { customAlphabet } from 'nanoid' import { uniq } from '@pengzhanbo/utils'
import type { import type {
PlumeThemeLocaleOptions, PlumeThemeLocaleOptions,
PlumeThemePluginOptions, PlumeThemePluginOptions,
} from '../shared/index.js' } from '../shared/index.js'
import { getCurrentDirname, getPackage, nanoid, pathJoin } from './utils.js'
const nanoid = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 8)
function getPackage() {
let pkg = {} as any
try {
const content = fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8')
pkg = JSON.parse(content)
}
catch {}
return pkg
}
function normalizePath(dir: string) {
return dir.replace(/\\+/g, '/')
}
export default function autoFrontmatter( export default function autoFrontmatter(
app: App, app: App,
@ -38,17 +21,17 @@ export default function autoFrontmatter(
): AutoFrontmatterOptions { ): AutoFrontmatterOptions {
const sourceDir = app.dir.source() const sourceDir = app.dir.source()
const pkg = getPackage() const pkg = getPackage()
const articlePrefix = localeOption.article || '/article/' const { locales = {}, avatar, article: articlePrefix = '/article/' } = localeOption
const { frontmatter } = options
const locales = (app.siteData.locales || {}) as PlumeThemeLocaleOptions const localesNotesDirs = Object.keys(app.siteData.locales || {})
const localesNotesDirs = Object.keys(locales)
.map((locale) => { .map((locale) => {
// fixed: #15 // fixed: #15
const notes = localeOption.locales?.[locale]?.notes const notes = locales[locale]?.notes
if (!notes) if (!notes)
return '' return ''
const dir = notes.dir
return dir ? normalizePath(path.join(locale, dir)).replace(/^\//, '') : '' return notes.dir ? pathJoin(locale, notes.dir).replace(/^\//, '') : ''
}) })
.filter(Boolean) .filter(Boolean)
@ -58,7 +41,7 @@ export default function autoFrontmatter(
return author return author
if (data.friends) if (data.friends)
return return
return localeOption.avatar?.name || pkg.author || '' return avatar?.name || pkg.author || ''
}, },
createTime(formatTime: string, { createTime }, data: any) { createTime(formatTime: string, { createTime }, data: any) {
if (formatTime) if (formatTime)
@ -70,20 +53,20 @@ export default function autoFrontmatter(
} }
const resolveLocale = (filepath: string) => { const resolveLocale = (filepath: string) => {
const file = normalizePath( const file = pathJoin('/', path.relative(sourceDir, filepath))
path.join('/', path.relative(sourceDir, filepath)),
)
return resolveLocalePath(localeOption.locales!, file) return resolveLocalePath(localeOption.locales!, file)
} }
const notesByLocale = (locale: string) => { const notesByLocale = (locale: string) => {
const notes = localeOption.locales![locale]?.notes || localeOption.notes const notes = locales[locale]?.notes || localeOption.notes
if (notes === false) if (notes === false)
return undefined return undefined
return notes return notes
} }
const findNote = (filepath: string) => { const findNote = (filepath: string) => {
const file = path.join('/', path.relative(sourceDir, filepath)) const file = pathJoin('/', path.relative(sourceDir, filepath))
const locale = resolveLocalePath(localeOption.locales!, normalizePath(file)) const locale = resolveLocalePath(locales, file)
const notes = notesByLocale(locale) const notes = notesByLocale(locale)
if (!notes) if (!notes)
return undefined return undefined
@ -94,22 +77,15 @@ export default function autoFrontmatter(
) )
} }
const getCurrentDirname = (note: NotesItem | undefined, filepath: string) => {
const dirList = normalizePath(note?.dir || path.dirname(filepath))
.replace(/^\/|\/$/g, '')
.split('/')
return dirList.length > 0 ? dirList[dirList.length - 1] : ''
}
return { return {
include: options.frontmatter?.include ?? ['**/*.md'], include: frontmatter?.include ?? ['**/*.md'],
exclude: options.frontmatter?.exclude ?? ['.vuepress/**/*', 'node_modules'], exclude: uniq(['.vuepress/**/*', 'node_modules', ...(frontmatter?.exclude ?? [])]),
frontmatter: options.frontmatter?.frontmatter ?? [
frontmatter: [
localesNotesDirs.length localesNotesDirs.length
? { ? {
// note 首页链接 // note 首页链接
include: localesNotesDirs.map(dir => include: localesNotesDirs.map(dir => pathJoin(dir, '**/{readme,README,index}.md')),
normalizePath(path.join(dir, '**/{readme,README,index}.md')),
),
frontmatter: { frontmatter: {
title(title: string, { filepath }) { title(title: string, { filepath }) {
if (title) if (title)
@ -117,7 +93,7 @@ export default function autoFrontmatter(
const note = findNote(filepath) const note = findNote(filepath)
if (note?.text) if (note?.text)
return note.text return note.text
return getCurrentDirname(note, filepath) || '' return getCurrentDirname(note?.dir, filepath) || ''
}, },
...baseFrontmatter, ...baseFrontmatter,
permalink(permalink: string, { filepath }, data: any) { permalink(permalink: string, { filepath }, data: any) {
@ -128,13 +104,11 @@ export default function autoFrontmatter(
const locale = resolveLocale(filepath) const locale = resolveLocale(filepath)
const notes = notesByLocale(locale) const notes = notesByLocale(locale)
const note = findNote(filepath) const note = findNote(filepath)
return normalizePath( return pathJoin(
path.join(
locale, locale,
notes?.link || '', notes?.link || '',
note?.link || getCurrentDirname(note, filepath), note?.link || getCurrentDirname(note?.dir, filepath),
'/', '/',
),
) )
}, },
}, },
@ -142,9 +116,7 @@ export default function autoFrontmatter(
: '', : '',
localesNotesDirs.length localesNotesDirs.length
? { ? {
include: localesNotesDirs.map(dir => include: localesNotesDirs.map(dir => pathJoin(dir, '**/**.md')),
normalizePath(path.join(dir, '**/**.md')),
),
frontmatter: { frontmatter: {
title(title: string, { filepath }) { title(title: string, { filepath }) {
if (title) if (title)
@ -161,14 +133,12 @@ export default function autoFrontmatter(
const locale = resolveLocale(filepath) const locale = resolveLocale(filepath)
const note = findNote(filepath) const note = findNote(filepath)
const notes = notesByLocale(locale) const notes = notesByLocale(locale)
return normalizePath( return pathJoin(
path.join(
locale, locale,
notes?.link || '', notes?.link || '',
note?.link || getCurrentDirname(note, filepath), note?.link || getCurrentDirname(note?.dir, filepath),
nanoid(), nanoid(),
'/', '/',
),
) )
}, },
}, },
@ -192,9 +162,7 @@ export default function autoFrontmatter(
if (permalink) if (permalink)
return permalink return permalink
const locale = resolveLocale(filepath) const locale = resolveLocale(filepath)
return normalizePath( return pathJoin(locale, articlePrefix, nanoid(), '/')
path.join(locale, articlePrefix, nanoid(), '/'),
)
}, },
}, },
}, },

View File

@ -18,8 +18,8 @@ import { iconifyPlugin } from '@vuepress-plume/plugin-iconify'
import { notesDataPlugin } from '@vuepress-plume/plugin-notes-data' import { notesDataPlugin } from '@vuepress-plume/plugin-notes-data'
import { shikijiPlugin } from '@vuepress-plume/plugin-shikiji' import { shikijiPlugin } from '@vuepress-plume/plugin-shikiji'
import { commentPlugin } from 'vuepress-plugin-comment2' import { commentPlugin } from 'vuepress-plugin-comment2'
import { mdEnhancePlugin } from 'vuepress-plugin-md-enhance' import { type MarkdownEnhanceOptions, mdEnhancePlugin } from 'vuepress-plugin-md-enhance'
import { useReadingTimePlugin } from 'vuepress-plugin-reading-time2' import { readingTimePlugin } from 'vuepress-plugin-reading-time2'
import { seoPlugin } from 'vuepress-plugin-seo2' import { seoPlugin } from 'vuepress-plugin-seo2'
import { sitemapPlugin } from 'vuepress-plugin-sitemap2' import { sitemapPlugin } from 'vuepress-plugin-sitemap2'
import type { import type {
@ -41,10 +41,7 @@ export function setupPlugins(app: App, options: PlumeThemePluginOptions, localeO
}) })
.filter(Boolean) .filter(Boolean)
if (options.readingTime !== false) const plugins: PluginConfig = [
useReadingTimePlugin(app, options.readingTime || {}, true)
return [
palettePlugin({ preset: 'sass' }), palettePlugin({ preset: 'sass' }),
themeDataPlugin({ themeDataPlugin({
@ -55,6 +52,7 @@ export function setupPlugins(app: App, options: PlumeThemePluginOptions, localeO
: undefined, : undefined,
} as any, } as any,
}), }),
autoFrontmatterPlugin(autoFrontmatter(app, options, localeOptions)), autoFrontmatterPlugin(autoFrontmatter(app, options, localeOptions)),
blogDataPlugin({ blogDataPlugin({
@ -85,8 +83,6 @@ export function setupPlugins(app: App, options: PlumeThemePluginOptions, localeO
}, },
}), }),
localeOptions.notes ? notesDataPlugin(localeOptions.notes) : [],
iconifyPlugin(), iconifyPlugin(),
activeHeaderLinksPlugin({ activeHeaderLinksPlugin({
@ -95,37 +91,45 @@ export function setupPlugins(app: App, options: PlumeThemePluginOptions, localeO
delay: 200, delay: 200,
offset: 20, offset: 20,
}), }),
]
options.nprogress !== false ? nprogressPlugin() : [], if (options.readingTime !== false)
plugins.push(readingTimePlugin(options.readingTime || {}))
options.git !== false if (localeOptions.notes)
? gitPlugin({ plugins.push(notesDataPlugin(localeOptions.notes))
if (options.nprogress !== false)
plugins.push(nprogressPlugin())
if (options.git !== false) {
plugins.push(gitPlugin({
createdTime: false, createdTime: false,
updatedTime: localeOptions.lastUpdated !== false, updatedTime: localeOptions.lastUpdated !== false,
contributors: localeOptions.contributors !== false, contributors: localeOptions.contributors !== false,
}) }))
: [], }
options.mediumZoom !== false if (options.mediumZoom !== false) {
? mediumZoomPlugin({ plugins.push(mediumZoomPlugin({
selector: '.plume-content > img, .plume-content :not(a) > img', selector: '.plume-content > img, .plume-content :not(a) > img',
zoomOptions: { zoomOptions: {
background: 'var(--vp-c-bg)', background: 'var(--vp-c-bg)',
}, },
delay: 300, delay: 300,
}) }))
: [], }
options.caniuse !== false if (options.caniuse !== false) {
? caniusePlugin( plugins.push(caniusePlugin(
options.caniuse || { options.caniuse || {
mode: 'embed', mode: 'embed',
}, },
) ))
: [], }
options.externalLinkIcon !== false if (options.externalLinkIcon !== false) {
? externalLinkIconPlugin({ plugins.push(externalLinkIconPlugin({
locales: Object.entries(localeOptions.locales || {}).reduce( locales: Object.entries(localeOptions.locales || {}).reduce(
(result: Record<string, any>, [key, value]) => { (result: Record<string, any>, [key, value]) => {
result[key] = { result[key] = {
@ -136,33 +140,42 @@ export function setupPlugins(app: App, options: PlumeThemePluginOptions, localeO
}, },
{}, {},
), ),
}) }))
: [], }
options.search !== false ? searchPlugin(options.search) : [], if (options.search !== false)
options.docsearch !== false && !options.search plugins.push(searchPlugin(options.search))
? docsearchPlugin(options.docsearch!)
: [],
options.shikiji !== false if (options.docsearch !== false && !options.search) {
? shikijiPlugin({ if (options.docsearch?.appId && options.docsearch?.apiKey) {
plugins.push(docsearchPlugin(options.docsearch))
}
else {
console.error(
'docsearch plugin: appId and apiKey are both required',
)
}
}
if (options.shikiji !== false) {
plugins.push(shikijiPlugin({
theme: { light: 'vitesse-light', dark: 'vitesse-dark' }, theme: { light: 'vitesse-light', dark: 'vitesse-dark' },
...(options.shikiji ?? {}), ...(options.shikiji ?? {}),
}) }))
: [], }
options.copyCode !== false if (options.copyCode !== false) {
? copyCodePlugin({ plugins.push(copyCodePlugin({
selector: '.plume-content div[class*="language-"] pre', selector: '.plume-content div[class*="language-"] pre',
...options.copyCode, ...options.copyCode,
}) }))
: [], }
options.markdownEnhance !== false if (options.markdownEnhance !== false) {
? mdEnhancePlugin( plugins.push(mdEnhancePlugin(
Object.assign( Object.assign(
{ {
hint: true, // info note tip warning danger details d hint: true, // info note tip warning danger details
codetabs: true, codetabs: true,
tabs: true, tabs: true,
align: true, align: true,
@ -170,28 +183,32 @@ export function setupPlugins(app: App, options: PlumeThemePluginOptions, localeO
tasklist: true, tasklist: true,
demo: true, demo: true,
attrs: true, attrs: true,
}, sup: true,
sub: true,
} as MarkdownEnhanceOptions,
options.markdownEnhance || {}, options.markdownEnhance || {},
), ),
) ))
: [], }
options.comment !== false ? commentPlugin(options.comment || {}) : [], if (options.comment !== false)
plugins.push(commentPlugin(options.comment || {}))
options.baiduTongji !== false && options.baiduTongji?.key if (options.baiduTongji !== false && options.baiduTongji?.key)
? baiduTongjiPlugin(options.baiduTongji) plugins.push(baiduTongjiPlugin(options.baiduTongji))
: [],
options.sitemap !== false && localeOptions.hostname && isProd if (options.sitemap !== false && localeOptions.hostname && isProd) {
? sitemapPlugin({ plugins.push(sitemapPlugin({
hostname: localeOptions.hostname, hostname: localeOptions.hostname,
}) }))
: [], }
options.seo !== false && localeOptions.hostname && isProd
? seoPlugin({ if (options.seo !== false && localeOptions.hostname && isProd) {
plugins.push(seoPlugin({
hostname: localeOptions.hostname || '', hostname: localeOptions.hostname || '',
author: localeOptions.avatar?.name, author: localeOptions.avatar?.name,
}) }))
: [], }
]
return plugins
} }

View File

@ -6,10 +6,7 @@ import type {
PlumeThemeLocaleOptions, PlumeThemeLocaleOptions,
PlumeThemePageData, PlumeThemePageData,
} from '../shared/index.js' } from '../shared/index.js'
import { normalizePath } from './utils.js'
function normalizePath(dir: string) {
return dir.replace(/\\+/g, '/')
}
export async function setupPage( export async function setupPage(
app: App, app: App,

33
theme/src/node/utils.ts Normal file
View File

@ -0,0 +1,33 @@
import fs from 'node:fs'
import path from 'node:path'
import process from 'node:process'
import { customAlphabet } from 'nanoid'
export const nanoid = customAlphabet('0123456789abcdefghijklmnopqrstuvwxyz', 8)
export function getPackage() {
let pkg = {} as any
try {
const content = fs.readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8')
pkg = JSON.parse(content)
}
catch { }
return pkg
}
const RE_SLASH = /\\+/g
export function normalizePath(dir: string) {
return dir.replace(RE_SLASH, '/')
}
export function pathJoin(...args: string[]) {
return normalizePath(path.join(...args))
}
const RE_START_END_SLASH = /^\/|\/$/g
export function getCurrentDirname(basePath: string | undefined, filepath: string) {
const dirList = normalizePath(basePath || path.dirname(filepath))
.replace(RE_START_END_SLASH, '')
.split('/')
return dirList.length > 0 ? dirList[dirList.length - 1] : ''
}

View File

@ -50,7 +50,7 @@ export interface PlumeThemePluginOptions {
baiduTongji?: false | BaiduTongjiOptions baiduTongji?: false | BaiduTongjiOptions
frontmatter?: AutoFrontmatterOptions frontmatter?: Omit<AutoFrontmatterOptions, 'frontmatter'>
readingTime?: false | ReadingTimeOptions readingTime?: false | ReadingTimeOptions
} }