refactor: move config to seperate folder & use defu merge

This commit is contained in:
YunYouJun 2024-01-16 06:37:09 +08:00
parent ed3b9b57d4
commit fe089ed70a
36 changed files with 1715 additions and 1914 deletions

View File

@ -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": [

44
demo/yun/theme.config.ts Normal file
View File

@ -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,
},
},
})

View File

@ -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,

View File

@ -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"

View File

@ -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)
```

View File

@ -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"
}
}

View File

@ -0,0 +1 @@
export * from './node'

View File

@ -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
/**

View File

@ -0,0 +1 @@
export * from './node'

View File

@ -2,3 +2,4 @@ export * from '../types/index.d'
export * from './config'
export * from './unocss'
export * from './theme'

View File

@ -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: {

View File

@ -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

View File

@ -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": {

View File

@ -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 *;

View File

@ -0,0 +1,3 @@
import { defaultThemeConfig, defineThemeConfig } from './node'
export default defineThemeConfig(defaultThemeConfig)

View File

@ -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 {

View File

@ -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, {

View File

@ -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)

View File

@ -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')

View File

@ -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
}

View File

@ -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
}

View File

@ -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

View File

@ -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 {

View File

@ -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

View File

@ -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,

View File

@ -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
}

View File

@ -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

View File

@ -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()

View File

@ -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))})`
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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"

View File

@ -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

View File

@ -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'}`,

View File

@ -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

File diff suppressed because it is too large Load Diff