mirror of https://github.com/YunYouJun/valaxy
refactor: move config to seperate folder & use defu merge
This commit is contained in:
parent
ed3b9b57d4
commit
fe089ed70a
|
@ -25,8 +25,8 @@
|
|||
|
||||
"stylelint.validate": ["css", "scss", "vue"],
|
||||
"[scss]": {
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "stylelint.vscode-stylelint"
|
||||
"editor.formatOnSave": true
|
||||
// "editor.defaultFormatter": "stylelint.vscode-stylelint"
|
||||
},
|
||||
|
||||
"cSpell.words": [
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
import { defineThemeConfig } from 'valaxy-theme-yun'
|
||||
|
||||
export default defineThemeConfig({
|
||||
// colors: {
|
||||
// primary: 'red',
|
||||
// },
|
||||
// bg_image: {},
|
||||
|
||||
banner: {
|
||||
enable: true,
|
||||
title: '云游君的小站',
|
||||
},
|
||||
|
||||
notice: {
|
||||
enable: true,
|
||||
content: '公告测试',
|
||||
},
|
||||
|
||||
pages: [
|
||||
{
|
||||
name: '我的小伙伴们',
|
||||
url: '/links/',
|
||||
icon: 'i-ri-genderless-line',
|
||||
color: 'dodgerblue',
|
||||
},
|
||||
{
|
||||
name: '喜欢的女孩子',
|
||||
url: '/girls/',
|
||||
icon: 'i-ri-women-line',
|
||||
color: 'hotpink',
|
||||
},
|
||||
],
|
||||
|
||||
footer: {
|
||||
since: 2016,
|
||||
beian: {
|
||||
enable: true,
|
||||
icp: '苏ICP备17038157号',
|
||||
},
|
||||
icon: {
|
||||
animated: true,
|
||||
},
|
||||
},
|
||||
})
|
|
@ -20,48 +20,8 @@ export default defineValaxyConfig<ThemeConfig>({
|
|||
// siteConfig: {},
|
||||
|
||||
theme: 'yun',
|
||||
themeConfig: {
|
||||
// colors: {
|
||||
// primary: 'red',
|
||||
// },
|
||||
// bg_image: {},
|
||||
|
||||
banner: {
|
||||
enable: true,
|
||||
title: '云游君的小站',
|
||||
},
|
||||
|
||||
notice: {
|
||||
enable: true,
|
||||
content: '公告测试',
|
||||
},
|
||||
|
||||
pages: [
|
||||
{
|
||||
name: '我的小伙伴们',
|
||||
url: '/links/',
|
||||
icon: 'i-ri-genderless-line',
|
||||
color: 'dodgerblue',
|
||||
},
|
||||
{
|
||||
name: '喜欢的女孩子',
|
||||
url: '/girls/',
|
||||
icon: 'i-ri-women-line',
|
||||
color: 'hotpink',
|
||||
},
|
||||
],
|
||||
|
||||
footer: {
|
||||
since: 2016,
|
||||
beian: {
|
||||
enable: true,
|
||||
icp: '苏ICP备17038157号',
|
||||
},
|
||||
icon: {
|
||||
animated: true,
|
||||
},
|
||||
},
|
||||
},
|
||||
// see theme.config.ts or write in themeConfig
|
||||
// themeConfig: {},
|
||||
|
||||
unocss: {
|
||||
safelist,
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
"valaxy-theme-press": "link:../packages/valaxy-theme-press"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@iconify-json/simple-icons": "^1.1.87",
|
||||
"@iconify-json/simple-icons": "^1.1.88",
|
||||
"nodemon": "^3.0.2",
|
||||
"vite": "^5.0.11",
|
||||
"vitepress": "1.0.0-rc.36"
|
||||
|
|
|
@ -29,3 +29,26 @@ pnpm test:space
|
|||
改为使用 `::before` 伪元素实现。
|
||||
|
||||
</details>
|
||||
|
||||
## 合并
|
||||
|
||||
使用 `defu`。
|
||||
|
||||
但实测 defu faster than `@fastify/deepmerge`。
|
||||
|
||||
合并单个配置:
|
||||
|
||||
- `defu`: 0.06ms
|
||||
- `@fastify/deepmerge`: 0.256ms
|
||||
|
||||
- [`@fastify/deepmerge`](https://github.com/fastify/deepmerge)。
|
||||
|
||||
```bash
|
||||
# benchmark
|
||||
@fastify/deepmerge x 605,343 ops/sec ±0.87% (96 runs sampled)
|
||||
deepmerge x 20,312 ops/sec ±1.06% (92 runs sampled)
|
||||
merge-deep x 83,167 ops/sec ±1.30% (94 runs sampled)
|
||||
ts-deepmerge x 175,977 ops/sec ±0.57% (96 runs sampled)
|
||||
deepmerge-ts x 174,973 ops/sec ±0.44% (93 runs sampled)
|
||||
lodash.merge x 89,213 ops/sec ±0.70% (98 runs sampled)
|
||||
```
|
||||
|
|
|
@ -54,13 +54,13 @@
|
|||
"devDependencies": {
|
||||
"@antfu/eslint-config": "2.6.2",
|
||||
"@iconify-json/logos": "^1.1.42",
|
||||
"@iconify-json/vscode-icons": "^1.1.32",
|
||||
"@iconify-json/vscode-icons": "^1.1.33",
|
||||
"@microsoft/api-extractor": "^7.39.1",
|
||||
"@types/debug": "^4.1.12",
|
||||
"@types/markdown-it-attrs": "^4.1.3",
|
||||
"@types/markdown-it-container": "^2.0.9",
|
||||
"@types/markdown-it-emoji": "^2.0.4",
|
||||
"@types/node": "^20.11.0",
|
||||
"@types/node": "^20.11.2",
|
||||
"@types/prompts": "^2.4.9",
|
||||
"@types/resolve": "^1.20.6",
|
||||
"bumpp": "^9.2.1",
|
||||
|
@ -108,5 +108,8 @@
|
|||
"{packages,demo,scripts}/**/*.{js,ts,vue,json,yml}": [
|
||||
"eslint --fix"
|
||||
]
|
||||
},
|
||||
"dependencies": {
|
||||
"c12": "^1.6.1"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from './node'
|
|
@ -1,6 +1,6 @@
|
|||
<script lang="ts" setup>
|
||||
import { computed, onMounted, ref } from 'vue'
|
||||
import type { Category, Post } from 'valaxy'
|
||||
import type { CategoryList, Post } from 'valaxy'
|
||||
import { isCategoryList, useInvisibleElement } from 'valaxy'
|
||||
import { useI18n } from 'vue-i18n'
|
||||
import { useRoute, useRouter } from 'vue-router'
|
||||
|
@ -8,7 +8,7 @@ import { useRoute, useRouter } from 'vue-router'
|
|||
const props = withDefaults(defineProps<{
|
||||
parentKey: string
|
||||
// to eliminate the warning
|
||||
category: Category
|
||||
category: Post | CategoryList
|
||||
level?: number
|
||||
|
||||
/**
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
export * from './node'
|
|
@ -2,3 +2,4 @@ export * from '../types/index.d'
|
|||
|
||||
export * from './config'
|
||||
export * from './unocss'
|
||||
export * from './theme'
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import type { ResolvedValaxyOptions } from 'valaxy'
|
||||
import { defineValaxyTheme } from 'valaxy'
|
||||
import type { Plugin } from 'vite'
|
||||
import type { ThemeConfig } from './types'
|
||||
import { defaultThemeConfig, generateSafelist } from './node'
|
||||
import { defineTheme } from 'valaxy'
|
||||
import type { ThemeConfig } from '../types'
|
||||
import { defaultThemeConfig, generateSafelist } from './index'
|
||||
|
||||
function ThemeVitePlugin(options: ResolvedValaxyOptions<ThemeConfig>): Plugin {
|
||||
const themeConfig = options.config.themeConfig || {}
|
||||
const themeConfig = options?.config.themeConfig || {}
|
||||
return {
|
||||
name: 'valaxy-theme-yun',
|
||||
enforce: 'pre',
|
||||
|
@ -27,7 +27,7 @@ function ThemeVitePlugin(options: ResolvedValaxyOptions<ThemeConfig>): Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
export default defineValaxyTheme<ThemeConfig>((options) => {
|
||||
export default defineTheme<ThemeConfig>((options) => {
|
||||
return {
|
||||
themeConfig: defaultThemeConfig,
|
||||
vite: {
|
|
@ -5,7 +5,7 @@ import type { UserThemeConfig } from '../types'
|
|||
* generateSafelist by config
|
||||
*/
|
||||
export function generateSafelist(options: ResolvedValaxyOptions<UserThemeConfig>) {
|
||||
const themeConfig = options.config.themeConfig || {}
|
||||
const themeConfig = options?.config.themeConfig || {}
|
||||
const safelist = []
|
||||
|
||||
const types = themeConfig.types
|
||||
|
|
|
@ -12,14 +12,15 @@
|
|||
"url": "https://github.com/YunYouJun/valaxy/tree/main/packages/valaxy-theme-yun"
|
||||
},
|
||||
"exports": {
|
||||
"./theme": "./types/index.d.ts",
|
||||
"./*": "./*"
|
||||
},
|
||||
"main": "node/index.ts",
|
||||
"types": "types/index.d.ts",
|
||||
"main": "index.ts",
|
||||
"module": "index.ts",
|
||||
"dependencies": {
|
||||
"@explosions/fireworks": "^0.0.2",
|
||||
"@iconify-json/ant-design": "^1.1.13",
|
||||
"@iconify-json/simple-icons": "^1.1.87",
|
||||
"@iconify-json/simple-icons": "^1.1.88",
|
||||
"animejs": "^3.2.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
|
|
@ -1,3 +1,5 @@
|
|||
$c-primary: #0078e7 !default;
|
||||
|
||||
@use "./layout" as *;
|
||||
@forward "star-markdown-css/src/scss/theme/yun.scss" with (
|
||||
$colors: (
|
||||
|
@ -8,6 +10,5 @@
|
|||
// override the default style of star-markdown-css
|
||||
@use "./common/button.scss" as *;
|
||||
@use "./common/markdown.scss" as *;
|
||||
|
||||
@use 'valaxy/client/styles/components/code-group.scss' as *;
|
||||
@use 'valaxy/client/styles/components/custom-block.scss' as *;
|
||||
|
|
|
@ -0,0 +1,3 @@
|
|||
import { defaultThemeConfig, defineThemeConfig } from './node'
|
||||
|
||||
export default defineThemeConfig(defaultThemeConfig)
|
|
@ -1,6 +1,6 @@
|
|||
import type { MaybeRef } from '@vueuse/core'
|
||||
import { computed, unref } from 'vue'
|
||||
import type { Post } from '../..'
|
||||
import type { Post } from '../../types'
|
||||
import { useSiteStore } from '../stores'
|
||||
|
||||
export interface BaseCategory {
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
import { computed } from 'vue'
|
||||
import type { Post } from '../..'
|
||||
import type { Post } from '../../types'
|
||||
import { useSiteStore } from '../stores'
|
||||
|
||||
export type Tags = Map<string, {
|
||||
|
|
|
@ -2,7 +2,7 @@ import dayjs from 'dayjs'
|
|||
import utc from 'dayjs/plugin/utc'
|
||||
import timezone from 'dayjs/plugin/timezone'
|
||||
|
||||
import type { Post } from '../..'
|
||||
import type { Post } from '../../types'
|
||||
|
||||
dayjs.extend(utc)
|
||||
dayjs.extend(timezone)
|
||||
|
|
|
@ -74,7 +74,7 @@ export function registerBuildCommand(cli: yargs.Argv) {
|
|||
outDir: path.resolve(options.userRoot, output),
|
||||
},
|
||||
logLevel: log as LogLevel,
|
||||
},
|
||||
} as InlineConfig,
|
||||
)
|
||||
// init config
|
||||
await valaxyApp.hooks.callHook('config:init')
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
import type { DefaultTheme, ValaxyAddon } from '../../types'
|
||||
import path from 'node:path'
|
||||
import fs from 'fs-extra'
|
||||
import type { ValaxyAddon } from '../../types'
|
||||
import type { ResolvedValaxyOptions } from '../options'
|
||||
import type { ValaxyAddonResolver, ValaxyNodeConfig } from '../types'
|
||||
import { mergeValaxyConfig, resolveValaxyConfigFromRoot } from './valaxy'
|
||||
|
||||
export function defineValaxyAddon<AddonOptions = object>(
|
||||
addonFunc: (addonOptions?: AddonOptions, valaxyOptions?: ResolvedValaxyOptions) => ValaxyAddon & {
|
||||
|
@ -11,13 +14,20 @@ export function defineValaxyAddon<AddonOptions = object>(
|
|||
}
|
||||
export const defineAddon = defineValaxyAddon
|
||||
|
||||
export type ValaxyConfigExtendKey = 'vite' | 'vue' | 'unocss' | 'unocssPresets' | 'markdown' | 'extendMd' | 'addons'
|
||||
export type ValaxyPickConfig = Pick<ValaxyNodeConfig, ValaxyConfigExtendKey>
|
||||
export type ValaxyTheme<ThemeConfig = DefaultTheme.Config> = ValaxyPickConfig & { themeConfig?: ThemeConfig }
|
||||
export function defineValaxyTheme<ThemeConfig = DefaultTheme.Config>(
|
||||
theme: ValaxyTheme<ThemeConfig> | ((options: ResolvedValaxyOptions<ThemeConfig>) => ValaxyTheme<ThemeConfig>),
|
||||
) {
|
||||
return theme
|
||||
}
|
||||
export async function resolveAddonConfig(addons: ValaxyAddonResolver[], _options?: ResolvedValaxyOptions) {
|
||||
let valaxyConfig: ValaxyNodeConfig = {} as ValaxyNodeConfig
|
||||
for (const addon of addons) {
|
||||
// unconfig get node_modules/valaxy-addon-xxx/valaxy.config.ts(not exist) but get userRoot/valaxy.config.ts
|
||||
// so we need to check if valaxy.config.ts exist
|
||||
if (!fs.existsSync(path.resolve(addon.root, 'valaxy.config.ts')))
|
||||
continue
|
||||
|
||||
export const defineTheme = defineValaxyTheme
|
||||
const { config, configFile } = await resolveValaxyConfigFromRoot(addon.root)
|
||||
if (!config)
|
||||
continue
|
||||
|
||||
addon.configFile = configFile
|
||||
valaxyConfig = mergeValaxyConfig(config, valaxyConfig)
|
||||
}
|
||||
return valaxyConfig
|
||||
}
|
||||
|
|
|
@ -1,161 +1,17 @@
|
|||
import { webcrypto } from 'node:crypto'
|
||||
import type { VitePluginConfig as UnoCssConfig } from 'unocss/vite'
|
||||
import type { Awaitable } from '@antfu/utils'
|
||||
import type { SiteConfig, UserSiteConfig } from '../../types'
|
||||
import type { UserValaxyNodeConfig, ValaxyNodeConfig } from '../types'
|
||||
|
||||
// export * from './merge'
|
||||
export * from './utils'
|
||||
|
||||
export * from './valaxy'
|
||||
export * from './addon'
|
||||
export * from './site'
|
||||
export * from './theme'
|
||||
|
||||
/**
|
||||
* Type helper for site.config.ts
|
||||
* @param config
|
||||
*/
|
||||
export function defineSiteConfig(config: UserSiteConfig) {
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* Type helper for valaxy.config.ts
|
||||
*/
|
||||
export function defineValaxyConfig<ThemeConfig>(config: UserValaxyNodeConfig<ThemeConfig>) {
|
||||
return config
|
||||
}
|
||||
export const defineConfig = defineValaxyConfig
|
||||
|
||||
export const defaultSiteConfig: SiteConfig = {
|
||||
mode: 'auto',
|
||||
url: '/',
|
||||
lang: 'en',
|
||||
languages: ['en', 'zh-CN'],
|
||||
timezone: '',
|
||||
title: 'Valaxy Blog',
|
||||
description: 'A blog generated by Valaxy.',
|
||||
subtitle: 'Next Generation Static Blog Framework.',
|
||||
author: {
|
||||
avatar: 'https://valaxy.site/valaxy-logo.png',
|
||||
email: 'i@valaxy.site',
|
||||
link: 'https://valaxy.site',
|
||||
name: 'VALAXY Developer',
|
||||
status: {
|
||||
emoji: '🌌',
|
||||
message: 'The moonlight is beautiful.',
|
||||
},
|
||||
},
|
||||
favicon: '/favicon.svg',
|
||||
feed: {
|
||||
name: '',
|
||||
favicon: '/favicon.svg',
|
||||
},
|
||||
social: [],
|
||||
|
||||
lastUpdated: true,
|
||||
|
||||
license: {
|
||||
enabled: true,
|
||||
language: '',
|
||||
type: 'by-nc-sa',
|
||||
},
|
||||
|
||||
sponsor: {
|
||||
enable: true,
|
||||
description: '这是关于赞助的一些描述',
|
||||
methods: [],
|
||||
},
|
||||
|
||||
search: {
|
||||
enable: false,
|
||||
type: 'fuse',
|
||||
},
|
||||
fuse: {
|
||||
dataPath: 'valaxy-fuse-list.json',
|
||||
options: {
|
||||
keys: [],
|
||||
},
|
||||
},
|
||||
|
||||
comment: {
|
||||
enable: false,
|
||||
},
|
||||
|
||||
frontmatter: {
|
||||
time_warning: 180 * 24 * 60 * 60 * 1000,
|
||||
},
|
||||
|
||||
cdn: {
|
||||
prefix: 'https://unpkg.com/',
|
||||
},
|
||||
|
||||
mediumZoom: {
|
||||
enable: false,
|
||||
selector: '',
|
||||
options: {},
|
||||
},
|
||||
|
||||
vanillaLazyload: {
|
||||
enable: false,
|
||||
options: {},
|
||||
},
|
||||
|
||||
statistics: {
|
||||
enable: false,
|
||||
readTime: {
|
||||
speed: {
|
||||
cn: 300,
|
||||
en: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
pageSize: 7,
|
||||
|
||||
encrypt: {
|
||||
enable: false,
|
||||
algorithm: 'AES-CBC',
|
||||
salt: webcrypto.getRandomValues(new Uint8Array(16)),
|
||||
iv: webcrypto.getRandomValues(new Uint8Array(16)),
|
||||
},
|
||||
}
|
||||
|
||||
export const defaultValaxyConfig: ValaxyNodeConfig = {
|
||||
ignoreDeadLinks: true,
|
||||
|
||||
siteConfig: defaultSiteConfig,
|
||||
theme: 'yun',
|
||||
themeConfig: {
|
||||
pkg: {
|
||||
name: '',
|
||||
version: '',
|
||||
},
|
||||
},
|
||||
|
||||
// markdown: {
|
||||
// excerpt: '<!-- more -->',
|
||||
// },
|
||||
runtimeConfig: { addons: {} },
|
||||
|
||||
modules: {
|
||||
rss: {
|
||||
enable: true,
|
||||
},
|
||||
},
|
||||
|
||||
features: {
|
||||
katex: true,
|
||||
},
|
||||
|
||||
vite: {
|
||||
build: {
|
||||
rollupOptions: {
|
||||
external: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
devtools: true,
|
||||
}
|
||||
|
||||
// other configs
|
||||
// unocss
|
||||
export type UnoSetup = () => Awaitable<Partial<UnoCssConfig> | undefined>
|
||||
|
||||
export function defineUnoSetup(fn: UnoSetup) {
|
||||
return fn
|
||||
}
|
||||
|
|
|
@ -0,0 +1,16 @@
|
|||
// import defu, { createDefu } from 'defu'
|
||||
|
||||
// function replaceByClonedSource(options: any) {
|
||||
// const clone = options.clone
|
||||
// return function (target: object, source: object) {
|
||||
// return clone(source)
|
||||
// }
|
||||
// }
|
||||
|
||||
// override array merge
|
||||
// export const replaceArrMerge = createDefu(({ obj, key, value }) => {
|
||||
// console.log(value)
|
||||
|
||||
// return value
|
||||
// })
|
||||
// export const replaceArrMerge = defu
|
|
@ -1,13 +1,117 @@
|
|||
import { webcrypto } from 'node:crypto'
|
||||
import type { UserSiteConfig } from 'valaxy'
|
||||
import { cyan, dim } from 'kolorist'
|
||||
import consola from 'consola'
|
||||
import type { SiteConfig } from '../../types'
|
||||
import { loadConfigFromFile } from './utils'
|
||||
|
||||
export const defaultSiteConfig: SiteConfig = {
|
||||
mode: 'auto',
|
||||
url: '/',
|
||||
lang: 'en',
|
||||
languages: ['en', 'zh-CN'],
|
||||
timezone: '',
|
||||
title: 'Valaxy Blog',
|
||||
description: 'A blog generated by Valaxy.',
|
||||
subtitle: 'Next Generation Static Blog Framework.',
|
||||
author: {
|
||||
avatar: 'https://valaxy.site/valaxy-logo.png',
|
||||
email: 'i@valaxy.site',
|
||||
link: 'https://valaxy.site',
|
||||
name: 'VALAXY Developer',
|
||||
status: {
|
||||
emoji: '🌌',
|
||||
message: 'The moonlight is beautiful.',
|
||||
},
|
||||
},
|
||||
favicon: '/favicon.svg',
|
||||
feed: {
|
||||
name: '',
|
||||
favicon: '/favicon.svg',
|
||||
},
|
||||
social: [],
|
||||
|
||||
lastUpdated: true,
|
||||
|
||||
license: {
|
||||
enabled: true,
|
||||
language: '',
|
||||
type: 'by-nc-sa',
|
||||
},
|
||||
|
||||
sponsor: {
|
||||
enable: true,
|
||||
description: '这是关于赞助的一些描述',
|
||||
methods: [],
|
||||
},
|
||||
|
||||
search: {
|
||||
enable: false,
|
||||
type: 'fuse',
|
||||
},
|
||||
fuse: {
|
||||
dataPath: 'valaxy-fuse-list.json',
|
||||
options: {
|
||||
keys: [],
|
||||
},
|
||||
},
|
||||
|
||||
comment: {
|
||||
enable: false,
|
||||
},
|
||||
|
||||
frontmatter: {
|
||||
time_warning: 180 * 24 * 60 * 60 * 1000,
|
||||
},
|
||||
|
||||
cdn: {
|
||||
prefix: 'https://unpkg.com/',
|
||||
},
|
||||
|
||||
mediumZoom: {
|
||||
enable: false,
|
||||
selector: '',
|
||||
options: {},
|
||||
},
|
||||
|
||||
vanillaLazyload: {
|
||||
enable: false,
|
||||
options: {},
|
||||
},
|
||||
|
||||
statistics: {
|
||||
enable: false,
|
||||
readTime: {
|
||||
speed: {
|
||||
cn: 300,
|
||||
en: 100,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
pageSize: 7,
|
||||
|
||||
encrypt: {
|
||||
enable: false,
|
||||
algorithm: 'AES-CBC',
|
||||
salt: webcrypto.getRandomValues(new Uint8Array(16)),
|
||||
iv: webcrypto.getRandomValues(new Uint8Array(16)),
|
||||
},
|
||||
}
|
||||
|
||||
/**
|
||||
* Type helper for site.config.ts
|
||||
* @param config
|
||||
*/
|
||||
export function defineSiteConfig(config: UserSiteConfig) {
|
||||
return config
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve valaxy config from special root
|
||||
*/
|
||||
export async function resolveSiteConfigFromRoot(root: string) {
|
||||
return loadConfigFromFile<UserSiteConfig>('site.config', {
|
||||
return loadConfigFromFile<UserSiteConfig>('site', {
|
||||
cwd: root,
|
||||
})
|
||||
}
|
||||
|
@ -18,7 +122,8 @@ export async function resolveSiteConfigFromRoot(root: string) {
|
|||
*/
|
||||
export async function resolveSiteConfig(root: string) {
|
||||
const { config: userSiteConfig, configFile: siteConfigFile } = await resolveSiteConfigFromRoot(root)
|
||||
if (userSiteConfig)
|
||||
|
||||
if (userSiteConfig && siteConfigFile)
|
||||
consola.success(`Resolve ${cyan('siteConfig')} from ${dim(siteConfigFile)}`)
|
||||
|
||||
return {
|
||||
|
|
|
@ -1,13 +1,16 @@
|
|||
import type { UserSiteConfig } from 'valaxy'
|
||||
import type { DefaultTheme } from 'valaxy'
|
||||
import { cyan, dim } from 'kolorist'
|
||||
import defu from 'defu'
|
||||
import { logger } from '../logger'
|
||||
import type { ResolvedValaxyOptions } from '../options'
|
||||
import type { ValaxyNodeConfig } from '../types'
|
||||
import { loadConfigFromFile } from './utils'
|
||||
|
||||
/**
|
||||
* resolve theme config from special root
|
||||
*/
|
||||
export async function resolveThemeConfigFromRoot(root: string) {
|
||||
return loadConfigFromFile<UserSiteConfig>('theme.config', {
|
||||
return loadConfigFromFile<DefaultTheme.Config>('theme', {
|
||||
cwd: root,
|
||||
})
|
||||
}
|
||||
|
@ -15,14 +18,32 @@ export async function resolveThemeConfigFromRoot(root: string) {
|
|||
/**
|
||||
* resolve theme.config.ts and merge with default
|
||||
*/
|
||||
export async function resolveThemeConfig(root: string) {
|
||||
const { config: userThemeConfig, configFile: themeConfigFile } = await resolveThemeConfigFromRoot(root)
|
||||
export async function resolveUserThemeConfig(options: ResolvedValaxyOptions) {
|
||||
let { config: userThemeConfig, configFile: themeConfigFile } = await resolveThemeConfigFromRoot(options.userRoot)
|
||||
|
||||
if (userThemeConfig)
|
||||
if (userThemeConfig && themeConfigFile)
|
||||
logger.info(`Resolve ${cyan('themeConfig')} from ${dim(themeConfigFile)}`)
|
||||
|
||||
if (options?.themeRoot) {
|
||||
// todo mount defaultThemeConfig
|
||||
const { config: defaultThemeConfig } = await resolveThemeConfigFromRoot(options.themeRoot)
|
||||
userThemeConfig = defu(userThemeConfig || {}, defaultThemeConfig)
|
||||
}
|
||||
|
||||
return {
|
||||
themeConfig: userThemeConfig,
|
||||
themeConfigFile,
|
||||
}
|
||||
}
|
||||
|
||||
export type ValaxyConfigExtendKey = 'vite' | 'vue' | 'unocss' | 'unocssPresets' | 'markdown' | 'extendMd' | 'addons'
|
||||
export type ValaxyPickConfig = Pick<ValaxyNodeConfig, ValaxyConfigExtendKey>
|
||||
export type ValaxyTheme<ThemeConfig = DefaultTheme.Config> = ValaxyPickConfig & { themeConfig?: ThemeConfig }
|
||||
|
||||
export function defineValaxyTheme<ThemeConfig = DefaultTheme.Config>(
|
||||
theme: ValaxyTheme<ThemeConfig> | ((options: ResolvedValaxyOptions<ThemeConfig>) => ValaxyTheme<ThemeConfig>),
|
||||
) {
|
||||
return theme
|
||||
}
|
||||
|
||||
export const defineTheme = defineValaxyTheme
|
||||
|
|
|
@ -1,22 +1,40 @@
|
|||
import process from 'node:process'
|
||||
import type { LoadConfigSource } from 'unconfig'
|
||||
import { loadConfig } from 'unconfig'
|
||||
import { normalizePath } from 'vite'
|
||||
|
||||
// https://github.com/unjs/c12
|
||||
// use c12 instead of unconfig, because c12 faster a lot
|
||||
// unconfig load config need 2-3s, c12 only need 0.2s
|
||||
|
||||
// import type { LoadConfigSource } from 'unconfig'
|
||||
// import { loadConfig } from 'unconfig'
|
||||
|
||||
// import { normalizePath } from 'vite'
|
||||
import type { UserInputConfig } from 'c12'
|
||||
import { loadConfig } from 'c12'
|
||||
|
||||
export interface LoadConfigFromFileOptions {
|
||||
cwd?: string
|
||||
rewrite?: LoadConfigSource['rewrite']
|
||||
// rewrite?: LoadConfigSource['rewrite']
|
||||
}
|
||||
|
||||
export async function loadConfigFromFile<T>(
|
||||
export async function loadConfigFromFile<T extends UserInputConfig>(
|
||||
file: string,
|
||||
options: LoadConfigFromFileOptions = {},
|
||||
) {
|
||||
const { config: userValaxyConfig, sources } = await loadConfig<T>({
|
||||
sources: { files: file, rewrite: options.rewrite },
|
||||
const { config: userValaxyConfig, configFile } = await loadConfig<T, any>({
|
||||
name: file,
|
||||
|
||||
// sources: {
|
||||
// files: file,
|
||||
// // less for speed
|
||||
// extensions: ['ts', 'js'],
|
||||
// // rewrite: options.rewrite,
|
||||
// },
|
||||
cwd: options.cwd || process.cwd(),
|
||||
})
|
||||
const configFile = normalizePath(sources[0] || '')
|
||||
// const configFile = normalizePath(sources[0] || '')
|
||||
|
||||
// if (file.startsWith('valaxy'))
|
||||
// console.log(userValaxyConfig, configFile)
|
||||
|
||||
return {
|
||||
config: userValaxyConfig,
|
||||
|
|
|
@ -1,15 +1,73 @@
|
|||
import { existsSync } from 'node:fs'
|
||||
import { resolve } from 'node:path'
|
||||
import process from 'node:process'
|
||||
import { mergeConfig as mergeViteConfig } from 'vite'
|
||||
|
||||
import { createDefu } from 'defu'
|
||||
import { mergeConfig as mergeViteConfig } from 'vite'
|
||||
import { isFunction } from '@antfu/utils'
|
||||
import { cyan, dim } from 'kolorist'
|
||||
|
||||
import consola from 'consola'
|
||||
import type { UserValaxyNodeConfig, ValaxyNodeConfig } from '../types'
|
||||
import type { ResolvedValaxyOptions, ValaxyEntryOptions } from '../options'
|
||||
import type { ValaxyAddonFn, ValaxyAddonResolver, ValaxyConfigFn, ValaxyNodeConfig } from '../types'
|
||||
import { loadConfigFromFile } from '../config/utils'
|
||||
import { loadConfigFromFile } from './utils'
|
||||
import { defaultSiteConfig } from './site'
|
||||
|
||||
export const defaultValaxyConfig: ValaxyNodeConfig = {
|
||||
ignoreDeadLinks: true,
|
||||
|
||||
siteConfig: defaultSiteConfig,
|
||||
theme: 'yun',
|
||||
themeConfig: {
|
||||
pkg: {
|
||||
name: '',
|
||||
version: '',
|
||||
},
|
||||
},
|
||||
|
||||
// markdown: {
|
||||
// excerpt: '<!-- more -->',
|
||||
// },
|
||||
runtimeConfig: { addons: {} },
|
||||
|
||||
modules: {
|
||||
rss: {
|
||||
enable: true,
|
||||
},
|
||||
},
|
||||
|
||||
features: {
|
||||
katex: true,
|
||||
},
|
||||
|
||||
vite: {
|
||||
build: {
|
||||
rollupOptions: {
|
||||
external: [],
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
devtools: true,
|
||||
}
|
||||
|
||||
/**
|
||||
* Type helper for valaxy.config.ts
|
||||
*/
|
||||
export function defineValaxyConfig<ThemeConfig>(config: UserValaxyNodeConfig<ThemeConfig>) {
|
||||
return config
|
||||
}
|
||||
export const defineConfig = defineValaxyConfig
|
||||
|
||||
/*
|
||||
* resolve valaxy config from special root
|
||||
*/
|
||||
export async function resolveValaxyConfigFromRoot(root: string, _options?: ResolvedValaxyOptions) {
|
||||
const c = await loadConfigFromFile<ValaxyNodeConfig>('valaxy', {
|
||||
// rewrite<F = ValaxyNodeConfig | ValaxyConfigFn>(c: F) {
|
||||
// return (typeof c === 'function' ? c(options || {} as ResolvedValaxyOptions) : c)
|
||||
// },
|
||||
cwd: root,
|
||||
})
|
||||
return c
|
||||
}
|
||||
|
||||
/**
|
||||
* merge valaxy.config
|
||||
|
@ -29,18 +87,6 @@ export const mergeValaxyConfig = createDefu((obj: any, key, value) => {
|
|||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* resolve valaxy config from special root
|
||||
*/
|
||||
export async function resolveValaxyConfigFromRoot(root: string, options?: ResolvedValaxyOptions) {
|
||||
return loadConfigFromFile<ValaxyNodeConfig>('valaxy.config', {
|
||||
rewrite<F = ValaxyNodeConfig | ValaxyConfigFn>(c: F) {
|
||||
return (typeof c === 'function' ? c(options || {} as ResolvedValaxyOptions) : c)
|
||||
},
|
||||
cwd: root,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve user valaxy config
|
||||
* options only have userRoot
|
||||
|
@ -50,7 +96,8 @@ export async function resolveValaxyConfig(options: ValaxyEntryOptions) {
|
|||
const configRoot = options.userRoot || process.cwd()
|
||||
|
||||
const { config: userValaxyConfig, configFile } = await resolveValaxyConfigFromRoot(configRoot)
|
||||
if (userValaxyConfig)
|
||||
|
||||
if (userValaxyConfig && configFile)
|
||||
consola.success(`Resolve ${cyan('userValaxyConfig')} from ${dim(configFile)}`)
|
||||
|
||||
const theme = options.theme || userValaxyConfig?.theme || 'yun'
|
||||
|
@ -61,27 +108,3 @@ export async function resolveValaxyConfig(options: ValaxyEntryOptions) {
|
|||
theme,
|
||||
}
|
||||
}
|
||||
|
||||
export async function resolveAddonConfig(addons: ValaxyAddonResolver[], options?: ResolvedValaxyOptions) {
|
||||
let valaxyConfig: ValaxyNodeConfig = {} as ValaxyNodeConfig
|
||||
for (const addon of addons) {
|
||||
// unconfig get node_modules/valaxy-addon-xxx/valaxy.config.ts(not exist) but get userRoot/valaxy.config.ts
|
||||
// so we need to check if valaxy.config.ts exist
|
||||
if (!existsSync(resolve(addon.root, 'valaxy.config.ts')))
|
||||
continue
|
||||
|
||||
const { config, configFile } = await loadConfigFromFile('valaxy.config', {
|
||||
rewrite<F = ValaxyNodeConfig | ValaxyAddonFn>(obj: F, _filepath: string) {
|
||||
return (typeof obj === 'function' ? obj(addon, options!) : obj)
|
||||
},
|
||||
cwd: addon.root,
|
||||
})
|
||||
|
||||
if (!config)
|
||||
continue
|
||||
|
||||
addon.configFile = configFile
|
||||
valaxyConfig = mergeValaxyConfig(config, valaxyConfig)
|
||||
}
|
||||
return valaxyConfig
|
||||
}
|
|
@ -9,13 +9,18 @@ import { cyan, magenta, yellow } from 'kolorist'
|
|||
import consola from 'consola'
|
||||
import type { DefaultTheme, RuntimeConfig } from '../types'
|
||||
import { resolveImportPath, slash } from './utils'
|
||||
import { mergeValaxyConfig, resolveAddonConfig, resolveValaxyConfig, resolveValaxyConfigFromRoot } from './utils/config'
|
||||
import {
|
||||
defaultValaxyConfig,
|
||||
mergeValaxyConfig,
|
||||
resolveAddonConfig,
|
||||
resolveThemeConfigFromRoot,
|
||||
resolveValaxyConfig,
|
||||
resolveValaxyConfigFromRoot,
|
||||
} from './config'
|
||||
import type { ValaxyAddonResolver, ValaxyNodeConfig } from './types'
|
||||
import { defaultValaxyConfig } from './config'
|
||||
import { parseAddons } from './utils/addons'
|
||||
import { getThemeRoot } from './utils/theme'
|
||||
import { resolveSiteConfig } from './config/site'
|
||||
import { resolveThemeConfig } from './config/theme'
|
||||
|
||||
// for cli entry
|
||||
export interface ValaxyEntryOptions {
|
||||
|
@ -161,22 +166,28 @@ export async function resolveOptions(
|
|||
const [resolvedValaxy, resolvedSite, resolvedTheme, pages] = await Promise.all([
|
||||
resolveValaxyConfig(options),
|
||||
resolveSiteConfig(options.userRoot),
|
||||
resolveThemeConfig(options.userRoot),
|
||||
// resolveThemeConfig(options),
|
||||
resolveThemeConfigFromRoot(options.userRoot),
|
||||
|
||||
fg(['**.md'], {
|
||||
cwd: resolve(userRoot, 'pages'),
|
||||
ignore: ['**/node_modules'],
|
||||
}),
|
||||
])
|
||||
let { config: userValaxyConfig, configFile, theme } = resolvedValaxy
|
||||
const { siteConfig, siteConfigFile } = resolvedSite
|
||||
const { themeConfig, themeConfigFile } = resolvedTheme
|
||||
|
||||
// merge with valaxy
|
||||
userValaxyConfig = defu<ValaxyNodeConfig, any>({ siteConfig }, { themeConfig }, userValaxyConfig)
|
||||
let { config: userValaxyConfig, configFile, theme } = resolvedValaxy
|
||||
|
||||
const themeRoot = getThemeRoot(theme, options.userRoot)
|
||||
|
||||
const { siteConfig, siteConfigFile } = resolvedSite
|
||||
|
||||
const { config: themeConfig, configFile: themeConfigFile } = resolvedTheme
|
||||
const { config: defaultThemeConfig } = await resolveThemeConfigFromRoot(themeRoot)
|
||||
const userThemeConfig = defu(themeConfig, defaultThemeConfig)
|
||||
|
||||
// merge with valaxy
|
||||
userValaxyConfig = defu<ValaxyNodeConfig, any>({ siteConfig }, { themeConfig: userThemeConfig }, userValaxyConfig)
|
||||
|
||||
// pages
|
||||
// Important: fast-glob doesn't guarantee order of the returned files.
|
||||
// We must sort the pages so the input list to rollup is stable across
|
||||
|
|
|
@ -8,16 +8,14 @@ import fs from 'fs-extra'
|
|||
import type { Plugin, ResolvedConfig } from 'vite'
|
||||
import { defu } from 'defu'
|
||||
import pascalCase from 'pascalcase'
|
||||
import { defaultSiteConfig } from '../config'
|
||||
import { defaultSiteConfig, mergeValaxyConfig, resolveSiteConfig, resolveUserThemeConfig } from '../config'
|
||||
import type { ResolvedValaxyOptions, ValaxyServerOptions } from '../options'
|
||||
import { processValaxyOptions, resolveOptions, resolveThemeValaxyConfig } from '../options'
|
||||
import { mergeValaxyConfig, resolveImportPath, slash, toAtFS } from '../utils'
|
||||
import { resolveImportPath, slash, toAtFS } from '../utils'
|
||||
import { createMarkdownToVueRenderFn } from '../markdown/markdownToVue'
|
||||
import type { PageDataPayload, SiteConfig } from '../../types'
|
||||
import type { DefaultTheme, PageDataPayload, Pkg, SiteConfig } from '../../types'
|
||||
import type { ValaxyNodeConfig } from '../types'
|
||||
import { checkMd } from '../markdown/check'
|
||||
import { resolveSiteConfig } from '../config/site'
|
||||
import { resolveThemeConfig } from '../config/theme'
|
||||
|
||||
/**
|
||||
* for /@valaxyjs/styles
|
||||
|
@ -264,20 +262,18 @@ export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions
|
|||
|
||||
// themeConfig
|
||||
if (file === options.themeConfigFile) {
|
||||
const { themeConfig } = await resolveThemeConfig(options.userRoot)
|
||||
valaxyConfig.themeConfig = defu(themeConfig, valaxyConfig.themeConfig)
|
||||
const { themeConfig } = await resolveUserThemeConfig(options)
|
||||
valaxyConfig.themeConfig = themeConfig as (DefaultTheme.Config & { pkg: Pkg })
|
||||
return reloadConfigAndEntries(valaxyConfig)
|
||||
}
|
||||
|
||||
if (file === resolve(options.themeRoot, 'valaxy.config.ts')) {
|
||||
const themeValaxyConfig = resolveThemeValaxyConfig(options)
|
||||
const themeValaxyConfig = await resolveThemeValaxyConfig(options)
|
||||
const valaxyConfig = mergeValaxyConfig(options.config, themeValaxyConfig)
|
||||
const { config } = await processValaxyOptions(options, valaxyConfig)
|
||||
return reloadConfigAndEntries(config)
|
||||
}
|
||||
|
||||
// if (file === options.siteConfigFile) {}
|
||||
|
||||
// send headers
|
||||
if (file.endsWith('.md')) {
|
||||
const content = await read()
|
||||
|
|
|
@ -29,3 +29,11 @@ export function toAtFS(path: string) {
|
|||
export function isPath(name: string) {
|
||||
return name.startsWith('/') || /^\.\.?[\/\\]/.test(name)
|
||||
}
|
||||
|
||||
/**
|
||||
* transform obj for vite code
|
||||
* @param obj
|
||||
*/
|
||||
export function transformObject(obj: any) {
|
||||
return `JSON.parse(${JSON.stringify(JSON.stringify(obj))})`
|
||||
}
|
||||
|
|
|
@ -1,48 +1,3 @@
|
|||
import { join } from 'node:path'
|
||||
import isInstalledGlobally from 'is-installed-globally'
|
||||
import globalDirs from 'global-directory'
|
||||
import type resolve from 'resolve'
|
||||
import { sync as resolveSync } from 'resolve'
|
||||
import consola from 'consola'
|
||||
|
||||
export * from './getGitTimestamp'
|
||||
export * from './resolve'
|
||||
export * from './helper'
|
||||
export * from './config'
|
||||
|
||||
/**
|
||||
* transform obj for vite code
|
||||
* @param obj
|
||||
*/
|
||||
export function transformObject(obj: any) {
|
||||
return `JSON.parse(${JSON.stringify(JSON.stringify(obj))})`
|
||||
}
|
||||
|
||||
export function resolveImportPath(importName: string, ensure?: true): string
|
||||
export function resolveImportPath(importName: string, ensure = false, resolveOptions: resolve.SyncOpts = {
|
||||
preserveSymlinks: false,
|
||||
}) {
|
||||
try {
|
||||
return resolveSync(importName, resolveOptions)
|
||||
}
|
||||
catch (error) {
|
||||
consola.log(error)
|
||||
}
|
||||
|
||||
if (isInstalledGlobally) {
|
||||
try {
|
||||
return require.resolve(join(globalDirs.yarn.packages, importName))
|
||||
}
|
||||
catch {}
|
||||
|
||||
try {
|
||||
return require.resolve(join(globalDirs.npm.packages, importName))
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
|
||||
if (ensure)
|
||||
throw new Error(`Failed to resolve package ${importName}`)
|
||||
|
||||
consola.error(`Failed to resolve package ${importName}`)
|
||||
return undefined
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
import { join } from 'node:path'
|
||||
import isInstalledGlobally from 'is-installed-globally'
|
||||
import globalDirs from 'global-directory'
|
||||
import type resolve from 'resolve'
|
||||
import { sync as resolveSync } from 'resolve'
|
||||
import consola from 'consola'
|
||||
|
||||
export function resolveImportPath(importName: string, ensure?: true): string
|
||||
export function resolveImportPath(importName: string, ensure = false, resolveOptions: resolve.SyncOpts = {
|
||||
preserveSymlinks: false,
|
||||
}) {
|
||||
try {
|
||||
return resolveSync(importName, resolveOptions)
|
||||
}
|
||||
catch (error) {
|
||||
consola.log(error)
|
||||
}
|
||||
|
||||
if (isInstalledGlobally) {
|
||||
try {
|
||||
return require.resolve(join(globalDirs.yarn.packages, importName))
|
||||
}
|
||||
catch {}
|
||||
|
||||
try {
|
||||
return require.resolve(join(globalDirs.npm.packages, importName))
|
||||
}
|
||||
catch {}
|
||||
}
|
||||
|
||||
if (ensure)
|
||||
throw new Error(`Failed to resolve package ${importName}`)
|
||||
|
||||
consola.error(`Failed to resolve package ${importName}`)
|
||||
return undefined
|
||||
}
|
|
@ -23,7 +23,8 @@
|
|||
".": {
|
||||
"types": "./index.d.ts",
|
||||
"import": "./dist/node/index.mjs",
|
||||
"require": "./dist/node/index.cjs"
|
||||
"require": "./dist/node/index.cjs",
|
||||
"default": "./dist/node/index.mjs"
|
||||
},
|
||||
"./client/*": "./client/*",
|
||||
"./client": "./client/index.ts",
|
||||
|
@ -49,6 +50,7 @@
|
|||
"client",
|
||||
"dist",
|
||||
"index.d.ts",
|
||||
"shims.d.ts",
|
||||
"types"
|
||||
],
|
||||
"engines": {
|
||||
|
@ -63,8 +65,9 @@
|
|||
"dependencies": {
|
||||
"@antfu/utils": "^0.7.7",
|
||||
"@ctrl/tinycolor": "^4.0.2",
|
||||
"@fastify/deepmerge": "^1.3.0",
|
||||
"@iconify-json/carbon": "^1.1.27",
|
||||
"@iconify-json/ri": "^1.1.18",
|
||||
"@iconify-json/ri": "^1.1.19",
|
||||
"@intlify/unplugin-vue-i18n": "^2.0.0",
|
||||
"@types/body-scroll-lock": "^3.1.2",
|
||||
"@types/katex": "^0.16.7",
|
||||
|
@ -122,7 +125,7 @@
|
|||
"vite-plugin-vue-layouts": "0.11.0",
|
||||
"vite-ssg": "0.23.6",
|
||||
"vite-ssg-sitemap": "0.6.1",
|
||||
"vue": "^3.4.13",
|
||||
"vue": "^3.4.14",
|
||||
"vue-i18n": "^9.9.0",
|
||||
"vue-router": "^4.2.5",
|
||||
"yargs": "^17.7.2"
|
||||
|
|
|
@ -5,6 +5,12 @@ import './client/typed-router'
|
|||
import type { Post } from './types'
|
||||
import type { Header } from './node/markdown'
|
||||
|
||||
declare module 'valaxy-addon-*'
|
||||
declare module '@docsearch/js' {
|
||||
function docsearch<T = any>(props: T): void
|
||||
export default docsearch
|
||||
}
|
||||
|
||||
declare interface Window {
|
||||
// algolia
|
||||
instantsearch: any
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
import { defineConfig } from 'tsup'
|
||||
import pkg from './package.json'
|
||||
|
||||
export default defineConfig((options) => {
|
||||
return {
|
||||
|
@ -18,8 +19,10 @@ export default defineConfig((options) => {
|
|||
external: [
|
||||
'/@valaxyjs/config',
|
||||
'/@valaxyjs/context',
|
||||
'open',
|
||||
|
||||
...Object.keys(pkg.dependencies || {}),
|
||||
],
|
||||
|
||||
outExtension({ format }) {
|
||||
return {
|
||||
js: `.${format === 'esm' ? 'mjs' : 'cjs'}`,
|
||||
|
|
|
@ -337,6 +337,13 @@ export interface RuntimeConfig {
|
|||
addons: Record<string, ValaxyAddon>
|
||||
}
|
||||
|
||||
export interface Pkg {
|
||||
name: string
|
||||
version: string
|
||||
homepage?: string
|
||||
[key: string]: any
|
||||
}
|
||||
|
||||
export interface ValaxyConfig<ThemeConfig = DefaultTheme.Config> {
|
||||
siteConfig: SiteConfig
|
||||
/**
|
||||
|
@ -349,12 +356,7 @@ export interface ValaxyConfig<ThemeConfig = DefaultTheme.Config> {
|
|||
* @description 主题配置
|
||||
*/
|
||||
themeConfig: ThemeConfig & {
|
||||
pkg: {
|
||||
name: string
|
||||
version: string
|
||||
homepage?: string
|
||||
[key: string]: any
|
||||
}
|
||||
pkg: Pkg
|
||||
}
|
||||
/**
|
||||
* generated by runtime
|
||||
|
|
2806
pnpm-lock.yaml
2806
pnpm-lock.yaml
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue