mirror of
https://github.com/pengzhanbo/vuepress-theme-plume.git
synced 2026-04-23 10:58:13 +08:00
feat(theme): add fs cache for encrypt and icons (#248)
This commit is contained in:
parent
a6079d69ae
commit
2a355705ff
@ -3,7 +3,7 @@ import type { Page } from 'vuepress/core'
|
||||
import type { PlumeThemeEncrypt, PlumeThemePageData } from '../../shared/index.js'
|
||||
import { isNumber, isString, random, toArray } from '@pengzhanbo/utils'
|
||||
import { genSaltSync, hashSync } from 'bcrypt-ts'
|
||||
import { hash, logger, resolveContent, writeTemp } from '../utils/index.js'
|
||||
import { createFsCache, type FsCache, hash, logger, resolveContent, writeTemp } from '../utils/index.js'
|
||||
|
||||
export type EncryptConfig = readonly [
|
||||
boolean, // global
|
||||
@ -16,19 +16,30 @@ export type EncryptConfig = readonly [
|
||||
const isStringLike = (value: unknown): boolean => isString(value) || isNumber(value)
|
||||
const separator = ':'
|
||||
let contentHash = ''
|
||||
let fsCache: FsCache<[string, EncryptConfig]> | null = null
|
||||
|
||||
export async function prepareEncrypt(app: App, encrypt?: PlumeThemeEncrypt) {
|
||||
const start = performance.now()
|
||||
|
||||
if (!fsCache && app.env.isDev) {
|
||||
fsCache = createFsCache(app, 'encrypt')
|
||||
await fsCache.read()
|
||||
}
|
||||
contentHash = fsCache?.data?.[0] ?? ''
|
||||
let resolvedEncrypt = fsCache?.data?.[1]
|
||||
const currentHash = encrypt ? hash(JSON.stringify(encrypt)) : ''
|
||||
|
||||
if (!contentHash || contentHash !== currentHash) {
|
||||
if (!contentHash || contentHash !== currentHash || !resolvedEncrypt) {
|
||||
contentHash = currentHash
|
||||
const content = resolveContent(app, {
|
||||
name: 'encrypt',
|
||||
content: resolveEncrypt(encrypt),
|
||||
})
|
||||
await writeTemp(app, 'internal/encrypt.js', content)
|
||||
resolvedEncrypt = resolveEncrypt(encrypt)
|
||||
}
|
||||
await writeTemp(app, 'internal/encrypt.js', resolveContent(app, {
|
||||
name: 'encrypt',
|
||||
content: resolvedEncrypt,
|
||||
}))
|
||||
|
||||
fsCache?.write([currentHash, resolvedEncrypt])
|
||||
|
||||
if (app.env.isDebug) {
|
||||
logger.info(`Generate encrypt: ${(performance.now() - start).toFixed(2)}ms`)
|
||||
}
|
||||
|
||||
@ -5,7 +5,7 @@ import { isArray, uniq } from '@pengzhanbo/utils'
|
||||
import { entries, isLinkAbsolute, isLinkHttp, isPlainObject } from '@vuepress/helper'
|
||||
import { isPackageExists } from 'local-pkg'
|
||||
import { fs } from 'vuepress/utils'
|
||||
import { interopDefault, logger, nanoid, resolveContent, writeTemp } from '../utils/index.js'
|
||||
import { createFsCache, type FsCache, interopDefault, logger, nanoid, resolveContent, writeTemp } from '../utils/index.js'
|
||||
|
||||
interface IconData {
|
||||
className: string
|
||||
@ -26,6 +26,7 @@ const CSS_FILENAME = 'internal/iconify.css'
|
||||
const isInstalled = isPackageExists('@iconify/json')
|
||||
let locate!: ((name: string) => any)
|
||||
|
||||
let fsCache: FsCache<IconDataMap> | null = null
|
||||
// { iconName: { className, content } }
|
||||
const cache: IconDataMap = {}
|
||||
|
||||
@ -41,13 +42,21 @@ export async function prepareIcons(app: App, localeOptions: PlumeThemeLocaleOpti
|
||||
await writeTemp(app, JS_FILENAME, resolveContent(app, { name: 'icons', content: '{}' }))
|
||||
return
|
||||
}
|
||||
if (!fsCache && app.env.isDev) {
|
||||
fsCache = createFsCache(app, 'iconify')
|
||||
await fsCache.read()
|
||||
}
|
||||
|
||||
const iconList: string[] = []
|
||||
app.pages.forEach(page => iconList.push(...getIconsWithPage(page)))
|
||||
iconList.push(...getIconWithThemeConfig(localeOptions))
|
||||
|
||||
const collectMap: CollectMap = {}
|
||||
uniq(iconList).filter(icon => !cache[icon]).forEach((iconName) => {
|
||||
uniq(iconList).filter((icon) => {
|
||||
if (fsCache?.data?.[icon] && !cache[icon])
|
||||
cache[icon] = fsCache.data[icon]
|
||||
return !cache[icon]
|
||||
}).forEach((iconName) => {
|
||||
const [collect, name] = iconName.split(':')
|
||||
if (!collectMap[collect])
|
||||
collectMap[collect] = []
|
||||
@ -94,6 +103,7 @@ export async function prepareIcons(app: App, localeOptions: PlumeThemeLocaleOpti
|
||||
})),
|
||||
])
|
||||
|
||||
fsCache?.write(cache)
|
||||
if (app.env.isDebug) {
|
||||
logger.info(`Generate icons total time: ${(performance.now() - start).toFixed(2)}ms`)
|
||||
}
|
||||
|
||||
65
theme/src/node/utils/createFsCache.ts
Normal file
65
theme/src/node/utils/createFsCache.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import type { App } from 'vuepress'
|
||||
import fs from 'node:fs/promises'
|
||||
import path from 'node:path'
|
||||
import { hash } from 'vuepress/utils'
|
||||
|
||||
interface CacheData<T = any> {
|
||||
hash: string
|
||||
data: T | null
|
||||
}
|
||||
|
||||
export interface FsCache<T> {
|
||||
hash: string
|
||||
data: T | null
|
||||
read: () => Promise<T | null>
|
||||
write: (data: T) => Promise<void>
|
||||
}
|
||||
|
||||
const CACHE_BASE = 'markdown'
|
||||
|
||||
export function createFsCache<T = any>(app: App, name: string): FsCache<T> {
|
||||
const filepath = app.dir.cache(`${CACHE_BASE}/${name}.json`)
|
||||
const cache: CacheData<T> = { hash: '', data: null }
|
||||
|
||||
const read = async (): Promise<T | null> => {
|
||||
if (!cache.data) {
|
||||
try {
|
||||
const content = await fs.readFile(filepath, 'utf-8')
|
||||
if (content) {
|
||||
const res = JSON.parse(content) as CacheData<T>
|
||||
cache.data = res.data ?? null
|
||||
cache.hash = hash(res.hash || '')
|
||||
}
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
return cache.data
|
||||
}
|
||||
|
||||
let timer: NodeJS.Timeout | null = null
|
||||
const write = async (data: T) => {
|
||||
const currentHash = hash(data)
|
||||
if (cache.hash && currentHash === cache.hash)
|
||||
return
|
||||
|
||||
cache.data = data
|
||||
cache.hash = currentHash
|
||||
|
||||
timer && clearTimeout(timer)
|
||||
timer = setTimeout(async () => {
|
||||
await fs.mkdir(path.dirname(filepath), { recursive: true })
|
||||
await fs.writeFile(filepath, JSON.stringify(cache), 'utf-8')
|
||||
}, 300)
|
||||
}
|
||||
|
||||
return {
|
||||
get hash() {
|
||||
return cache.hash
|
||||
},
|
||||
get data() {
|
||||
return cache.data
|
||||
},
|
||||
read,
|
||||
write,
|
||||
}
|
||||
}
|
||||
@ -4,6 +4,7 @@ export const THEME_NAME = 'vuepress-theme-plume'
|
||||
|
||||
export const logger = new Logger(THEME_NAME)
|
||||
|
||||
export * from './createFsCache.js'
|
||||
export * from './deleteAttrs.js'
|
||||
export * from './hash.js'
|
||||
export * from './interopDefault.js'
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user