refactor: extract site common configs to siteConfig & support site.config.ts

This commit is contained in:
YunYouJun 2023-01-23 05:06:12 +08:00
parent 79afaefbe6
commit 11f0e86236
52 changed files with 677 additions and 511 deletions

View File

@ -30,7 +30,7 @@ More info see [valaxy.site](https://valaxy.site).
* User Config
* do not use export const, because c12 will set as child property
*/
const config: UserConfig<ThemeUserConfig> = {
const config: UserConfig<UserThemeConfig> = {
theme: 'yun',
themeConfig: {

125
demo/yun/site.config.ts Normal file
View File

@ -0,0 +1,125 @@
import { defineSiteConfig } from 'valaxy'
export default defineSiteConfig({
lang: 'zh-CN',
title: 'Valaxy Theme Yun',
url: 'https://valaxy.yyj.moe/',
author: {
avatar: 'https://www.yunyoujun.cn/images/avatar.jpg',
name: '云游君',
},
description: 'Valaxy Theme Yun Preview.',
social: [
{
name: 'RSS',
link: '/atom.xml',
icon: 'i-ri-rss-line',
color: 'orange',
},
{
name: 'QQ 群 1050458482',
link: 'https://qm.qq.com/cgi-bin/qm/qr?k=kZJzggTTCf4SpvEQ8lXWoi5ZjhAx0ILZ&jump_from=webapi',
icon: 'i-ri-qq-line',
color: '#12B7F5',
},
{
name: 'GitHub',
link: 'https://github.com/YunYouJun',
icon: 'i-ri-github-line',
color: '#6e5494',
},
{
name: '微博',
link: 'https://weibo.com/jizhideyunyoujun',
icon: 'i-ri-weibo-line',
color: '#E6162D',
},
{
name: '豆瓣',
link: 'https://www.douban.com/people/yunyoujun/',
icon: 'i-ri-douban-line',
color: '#007722',
},
{
name: '网易云音乐',
link: 'https://music.163.com/#/user/home?id=247102977',
icon: 'i-ri-netease-cloud-music-line',
color: '#C20C0C',
},
{
name: '知乎',
link: 'https://www.zhihu.com/people/yunyoujun/',
icon: 'i-ri-zhihu-line',
color: '#0084FF',
},
{
name: '哔哩哔哩',
link: 'https://space.bilibili.com/1579790',
icon: 'i-ri-bilibili-line',
color: '#FF8EB3',
},
{
name: '微信公众号',
link: 'https://cdn.yunyoujun.cn/img/about/white-qrcode-and-search.jpg',
icon: 'i-ri-wechat-2-line',
color: '#1AAD19',
},
{
name: 'Twitter',
link: 'https://twitter.com/YunYouJun',
icon: 'i-ri-twitter-line',
color: '#1da1f2',
},
{
name: 'Telegram Channel',
link: 'https://t.me/elpsycn',
icon: 'i-ri-telegram-line',
color: '#0088CC',
},
{
name: 'E-Mail',
link: 'mailto:me@yunyoujun.cn',
icon: 'i-ri-mail-line',
color: '#8E71C1',
},
{
name: 'Travelling',
link: 'https://www.travellings.cn/go.html',
icon: 'i-ri-train-line',
color: 'var(--va-c-text)',
},
],
search: {
enable: true,
type: 'algolia',
},
comment: {
enable: true,
},
sponsor: {
enable: true,
methods: [
{
name: '支付宝',
url: 'https://cdn.yunyoujun.cn/img/donate/alipay-qrcode.jpg',
color: '#00A3EE',
icon: 'i-ri-alipay-line',
},
{
name: 'QQ 支付',
url: 'https://cdn.yunyoujun.cn/img/donate/qqpay-qrcode.png',
color: '#12B7F5',
icon: 'i-ri-qq-line',
},
{
name: '微信支付',
url: 'https://cdn.yunyoujun.cn/img/donate/wechatpay-qrcode.jpg',
color: '#2DC100',
icon: 'i-ri-wechat-pay-line',
},
],
},
})

View File

@ -1,141 +1,19 @@
import { defineConfig } from 'valaxy'
import { defineValaxyConfig } from 'valaxy'
import type { ThemeConfig } from 'valaxy-theme-yun'
// import { VitePWA } from 'vite-plugin-pwa'
import Inspect from 'vite-plugin-inspect'
import { addonAlgolia } from 'valaxy-addon-algolia'
import { addonWaline } from 'valaxy-addon-waline'
import { addonComponents } from 'valaxy-addon-components'
// import site from './site.config'
const safelist = [
'i-ri-home-line',
]
export default defineConfig<ThemeConfig>({
lang: 'zh-CN',
title: 'Valaxy Theme Yun',
url: 'https://valaxy.yyj.moe/',
author: {
avatar: 'https://www.yunyoujun.cn/images/avatar.jpg',
name: '云游君',
},
description: 'Valaxy Theme Yun Preview.',
social: [
{
name: 'RSS',
link: '/atom.xml',
icon: 'i-ri-rss-line',
color: 'orange',
},
{
name: 'QQ 群 1050458482',
link: 'https://qm.qq.com/cgi-bin/qm/qr?k=kZJzggTTCf4SpvEQ8lXWoi5ZjhAx0ILZ&jump_from=webapi',
icon: 'i-ri-qq-line',
color: '#12B7F5',
},
{
name: 'GitHub',
link: 'https://github.com/YunYouJun',
icon: 'i-ri-github-line',
color: '#6e5494',
},
{
name: '微博',
link: 'https://weibo.com/jizhideyunyoujun',
icon: 'i-ri-weibo-line',
color: '#E6162D',
},
{
name: '豆瓣',
link: 'https://www.douban.com/people/yunyoujun/',
icon: 'i-ri-douban-line',
color: '#007722',
},
{
name: '网易云音乐',
link: 'https://music.163.com/#/user/home?id=247102977',
icon: 'i-ri-netease-cloud-music-line',
color: '#C20C0C',
},
{
name: '知乎',
link: 'https://www.zhihu.com/people/yunyoujun/',
icon: 'i-ri-zhihu-line',
color: '#0084FF',
},
{
name: '哔哩哔哩',
link: 'https://space.bilibili.com/1579790',
icon: 'i-ri-bilibili-line',
color: '#FF8EB3',
},
{
name: '微信公众号',
link: 'https://cdn.yunyoujun.cn/img/about/white-qrcode-and-search.jpg',
icon: 'i-ri-wechat-2-line',
color: '#1AAD19',
},
{
name: 'Twitter',
link: 'https://twitter.com/YunYouJun',
icon: 'i-ri-twitter-line',
color: '#1da1f2',
},
{
name: 'Telegram Channel',
link: 'https://t.me/elpsycn',
icon: 'i-ri-telegram-line',
color: '#0088CC',
},
{
name: 'E-Mail',
link: 'mailto:me@yunyoujun.cn',
icon: 'i-ri-mail-line',
color: '#8E71C1',
},
{
name: 'Travelling',
link: 'https://www.travellings.cn/go.html',
icon: 'i-ri-train-line',
color: 'var(--va-c-text)',
},
],
search: {
enable: true,
type: 'algolia',
},
comment: {
enable: true,
},
sponsor: {
enable: true,
methods: [
{
name: '支付宝',
url: 'https://cdn.yunyoujun.cn/img/donate/alipay-qrcode.jpg',
color: '#00A3EE',
icon: 'i-ri-alipay-line',
},
{
name: 'QQ 支付',
url: 'https://cdn.yunyoujun.cn/img/donate/qqpay-qrcode.png',
color: '#12B7F5',
icon: 'i-ri-qq-line',
},
{
name: '微信支付',
url: 'https://cdn.yunyoujun.cn/img/donate/wechatpay-qrcode.jpg',
color: '#2DC100',
icon: 'i-ri-wechat-pay-line',
},
],
},
export default defineValaxyConfig<ThemeConfig>({
// site config see site.config.ts
theme: 'yun',
themeConfig: {
// colors: {
// primary: 'red',

View File

@ -54,13 +54,13 @@ I will compare Valaxy with the existing Hexo (popular static blog framework) and
```ts
import type { UserConfig } from 'valaxy'
import type { ThemeUserConfig } from 'valaxy-theme-yun'
import type { UserThemeConfig } from 'valaxy-theme-yun'
/**
* User Config
* do not use export const, because c12 will set as child property
*/
const config: UserConfig<ThemeUserConfig> = {
const config: UserConfig<UserThemeConfig> = {
theme: 'yun',
themeConfig: {

View File

@ -0,0 +1,120 @@
import { defineSiteConfig } from 'valaxy'
export default defineSiteConfig({
url: 'https://valaxy.site/',
lang: 'zh-CN',
title: 'Valaxy Theme Yun',
author: {
name: '云游君',
},
description: 'Valaxy Theme Yun Preview.',
social: [
{
name: 'RSS',
link: '/atom.xml',
icon: 'i-ri-rss-line',
color: 'orange',
},
{
name: 'QQ 群 1050458482',
link: 'https://qm.qq.com/cgi-bin/qm/qr?k=kZJzggTTCf4SpvEQ8lXWoi5ZjhAx0ILZ&jump_from=webapi',
icon: 'i-ri-qq-line',
color: '#12B7F5',
},
{
name: 'GitHub',
link: 'https://github.com/YunYouJun',
icon: 'i-ri-github-line',
color: '#6e5494',
},
{
name: '微博',
link: 'https://weibo.com/jizhideyunyoujun',
icon: 'i-ri-weibo-line',
color: '#E6162D',
},
{
name: '豆瓣',
link: 'https://www.douban.com/people/yunyoujun/',
icon: 'i-ri-douban-line',
color: '#007722',
},
{
name: '网易云音乐',
link: 'https://music.163.com/#/user/home?id=247102977',
icon: 'i-ri-netease-cloud-music-line',
color: '#C20C0C',
},
{
name: '知乎',
link: 'https://www.zhihu.com/people/yunyoujun/',
icon: 'i-ri-zhihu-line',
color: '#0084FF',
},
{
name: '哔哩哔哩',
link: 'https://space.bilibili.com/1579790',
icon: 'i-ri-bilibili-line',
color: '#FF8EB3',
},
{
name: '微信公众号',
link: 'https://cdn.yunyoujun.cn/img/about/white-qrcode-and-search.jpg',
icon: 'i-ri-wechat-2-line',
color: '#1AAD19',
},
{
name: 'Twitter',
link: 'https://twitter.com/YunYouJun',
icon: 'i-ri-twitter-line',
color: '#1da1f2',
},
{
name: 'Telegram Channel',
link: 'https://t.me/elpsycn',
icon: 'i-ri-telegram-line',
color: '#0088CC',
},
{
name: 'E-Mail',
link: 'mailto:me@yunyoujun.cn',
icon: 'i-ri-mail-line',
color: '#8E71C1',
},
{
name: 'Travelling',
link: 'https://www.travellings.cn/go.html',
icon: 'i-ri-train-line',
color: 'var(--va-c-text)',
},
],
search: {
enable: false,
},
sponsor: {
enable: true,
title: '我很可爱,请给我钱!',
methods: [
{
name: '支付宝',
url: 'https://cdn.yunyoujun.cn/img/donate/alipay-qrcode.jpg',
color: '#00A3EE',
icon: 'i-ri-alipay-line',
},
{
name: 'QQ 支付',
url: 'https://cdn.yunyoujun.cn/img/donate/qqpay-qrcode.png',
color: '#12B7F5',
icon: 'i-ri-qq-line',
},
{
name: '微信支付',
url: 'https://cdn.yunyoujun.cn/img/donate/wechatpay-qrcode.jpg',
color: '#2DC100',
icon: 'i-ri-wechat-pay-line',
},
],
},
})

View File

@ -1,5 +1,5 @@
import { defineConfig } from 'valaxy'
import type { ThemeConfig } from 'valaxy-theme-yun'
import { defineValaxyConfig } from 'valaxy'
import type { UserThemeConfig } from 'valaxy-theme-yun'
// add icons what you will need
const safelist = [
@ -9,123 +9,8 @@ const safelist = [
/**
* User Config
*/
export default defineConfig<ThemeConfig>({
url: 'https://valaxy.site/',
lang: 'zh-CN',
title: 'Valaxy Theme Yun',
author: {
name: '云游君',
},
description: 'Valaxy Theme Yun Preview.',
social: [
{
name: 'RSS',
link: '/atom.xml',
icon: 'i-ri-rss-line',
color: 'orange',
},
{
name: 'QQ 群 1050458482',
link: 'https://qm.qq.com/cgi-bin/qm/qr?k=kZJzggTTCf4SpvEQ8lXWoi5ZjhAx0ILZ&jump_from=webapi',
icon: 'i-ri-qq-line',
color: '#12B7F5',
},
{
name: 'GitHub',
link: 'https://github.com/YunYouJun',
icon: 'i-ri-github-line',
color: '#6e5494',
},
{
name: '微博',
link: 'https://weibo.com/jizhideyunyoujun',
icon: 'i-ri-weibo-line',
color: '#E6162D',
},
{
name: '豆瓣',
link: 'https://www.douban.com/people/yunyoujun/',
icon: 'i-ri-douban-line',
color: '#007722',
},
{
name: '网易云音乐',
link: 'https://music.163.com/#/user/home?id=247102977',
icon: 'i-ri-netease-cloud-music-line',
color: '#C20C0C',
},
{
name: '知乎',
link: 'https://www.zhihu.com/people/yunyoujun/',
icon: 'i-ri-zhihu-line',
color: '#0084FF',
},
{
name: '哔哩哔哩',
link: 'https://space.bilibili.com/1579790',
icon: 'i-ri-bilibili-line',
color: '#FF8EB3',
},
{
name: '微信公众号',
link: 'https://cdn.yunyoujun.cn/img/about/white-qrcode-and-search.jpg',
icon: 'i-ri-wechat-2-line',
color: '#1AAD19',
},
{
name: 'Twitter',
link: 'https://twitter.com/YunYouJun',
icon: 'i-ri-twitter-line',
color: '#1da1f2',
},
{
name: 'Telegram Channel',
link: 'https://t.me/elpsycn',
icon: 'i-ri-telegram-line',
color: '#0088CC',
},
{
name: 'E-Mail',
link: 'mailto:me@yunyoujun.cn',
icon: 'i-ri-mail-line',
color: '#8E71C1',
},
{
name: 'Travelling',
link: 'https://www.travellings.cn/go.html',
icon: 'i-ri-train-line',
color: 'var(--va-c-text)',
},
],
search: {
enable: false,
},
sponsor: {
enable: true,
title: '我很可爱,请给我钱!',
methods: [
{
name: '支付宝',
url: 'https://cdn.yunyoujun.cn/img/donate/alipay-qrcode.jpg',
color: '#00A3EE',
icon: 'i-ri-alipay-line',
},
{
name: 'QQ 支付',
url: 'https://cdn.yunyoujun.cn/img/donate/qqpay-qrcode.png',
color: '#12B7F5',
icon: 'i-ri-qq-line',
},
{
name: '微信支付',
url: 'https://cdn.yunyoujun.cn/img/donate/wechatpay-qrcode.jpg',
color: '#2DC100',
icon: 'i-ri-wechat-pay-line',
},
],
},
export default defineValaxyConfig<UserThemeConfig>({
// site config see site.config.ts
theme: 'yun',
@ -134,7 +19,7 @@ export default defineConfig<ThemeConfig>({
enable: true,
title: '云游君的小站',
cloud: {
enable: 'true',
enable: true,
},
},

View File

@ -1,6 +1,6 @@
import { computed } from 'vue'
import type { ValaxyAddon } from 'valaxy'
import { useConfig } from 'valaxy'
import { useRuntimeConfig } from 'valaxy'
import type { AlgoliaSearchOptions } from '../types'
import pkg from '../package.json'
@ -9,6 +9,6 @@ import pkg from '../package.json'
* @returns
*/
export function useAddonAlgolia() {
const config = useConfig()
return computed(() => config.value.runtime.addons[pkg.name] as ValaxyAddon<AlgoliaSearchOptions>)
const runtimeConfig = useRuntimeConfig()
return computed(() => runtimeConfig.value.addons[pkg.name] as ValaxyAddon<AlgoliaSearchOptions>)
}

View File

@ -1,6 +1,6 @@
import { computed } from 'vue'
import type { ValaxyAddon } from 'valaxy'
import { useConfig } from 'valaxy'
import { useRuntimeConfig } from 'valaxy'
import type { WalineOptions } from '../types'
/**
@ -8,6 +8,6 @@ import type { WalineOptions } from '../types'
* @returns
*/
export function useAddonWaline() {
const config = useConfig()
return computed(() => config.value.runtime.addons['valaxy-addon-waline'] as ValaxyAddon<WalineOptions>)
const runtimeConfig = useRuntimeConfig()
return computed(() => runtimeConfig.value.addons['valaxy-addon-waline'] as ValaxyAddon<WalineOptions>)
}

View File

@ -1,13 +1,13 @@
<script lang="ts" setup>
import type { PageData, Post } from 'valaxy'
import { useConfig, useFrontmatter, useLayout, useSidebar } from 'valaxy'
import { useFrontmatter, useLayout, useSidebar, useSiteConfig } from 'valaxy'
defineProps<{
frontmatter: Post
data?: PageData
}>()
const config = useConfig()
const siteConfig = useSiteConfig()
const frontmatter = useFrontmatter()
const { hasSidebar } = useSidebar()
@ -52,7 +52,7 @@ const isHome = useLayout('home')
<slot name="main-nav-after" />
<slot v-if="config.comment.enable && frontmatter.comment !== false" name="comment" />
<slot v-if="siteConfig.comment.enable && frontmatter.comment !== false" name="comment" />
<slot name="footer" />
</slot>

View File

@ -1,5 +1,5 @@
<script lang="ts" setup>
import { useConfig, useSidebar } from 'valaxy'
import { useSidebar, useSiteConfig } from 'valaxy'
import { useThemeConfig } from '../../composables'
defineProps<{
@ -12,15 +12,15 @@ defineEmits<{
const { hasSidebar } = useSidebar()
const config = useConfig()
const siteConfig = useSiteConfig()
const themeConfig = useThemeConfig()
</script>
<template>
<div class="pr-navbar flex justify-between items-center pl-4 pr-2" :class="{ 'has-sidebar': hasSidebar }">
<router-link class="text-xl flex justify-center items-center" to="/" :aria-label="config.title">
<router-link class="text-xl flex justify-center items-center" to="/" :aria-label="siteConfig.title">
<img v-if="themeConfig.logo" class="logo" :src="themeConfig.logo" alt="LOGO">
<span class="inline-flex">{{ config.title }}</span>
<span class="inline-flex">{{ siteConfig.title }}</span>
</router-link>
<div class="self-stretch flex justify-center items-center text-sm leading-5">
<PressNavBarMenu p="x-2" />

View File

@ -84,4 +84,4 @@ export type NavItem = NavItemLink | NavItemGroup
* Theme Config
*/
export type ThemeConfig = PressTheme.Config
export type ThemeUserConfig = Partial<ThemeConfig>
export type UserThemeConfig = Partial<ThemeConfig>

View File

@ -1,6 +1,7 @@
<script lang="ts" setup>
import { useHead } from '@vueuse/head'
import { useConfig } from 'valaxy'
import { useSiteConfig } from 'valaxy'
import { useThemeConfig } from './composables'
useHead({
link: [
@ -11,12 +12,13 @@ useHead({
],
})
const config = useConfig()
const siteConfig = useSiteConfig()
const themeConfig = useThemeConfig()
</script>
<template>
<slot name="bg">
<YunBg v-if="config.themeConfig.bg_image.enable" />
<YunBg v-if="themeConfig.bg_image.enable" />
</slot>
<YunSearch v-if="config.search.enable" />
<YunSearch v-if="siteConfig.search.enable" />
</template>

View File

@ -1,6 +1,6 @@
<script lang="ts" setup>
import type { PageData, Post } from 'valaxy'
import { useConfig, usePostTitle } from 'valaxy'
import { usePostTitle, useRuntimeConfig, useSiteConfig } from 'valaxy'
import { StyleValue, computed, defineAsyncComponent } from 'vue'
import { usePostProperty } from '../composables'
@ -8,7 +8,9 @@ const props = defineProps<{
frontmatter: Post
data?: PageData
}>()
const config = useConfig()
const runtimeConfig = useRuntimeConfig()
const siteConfig = useSiteConfig()
const { styles, icon, color } = usePostProperty(props.frontmatter.type)
const title = usePostTitle(computed(() => props.frontmatter))
@ -16,7 +18,7 @@ const title = usePostTitle(computed(() => props.frontmatter))
const aside = computed(() => props.frontmatter.aside !== false)
// not import from 'valaxy-addon-waline' to judge
const YunWaline = config.value.runtime.addons['valaxy-addon-waline']
const YunWaline = runtimeConfig.value.addons['valaxy-addon-waline']
? defineAsyncComponent(() => import('./YunWaline.vue'))
: () => null
@ -57,7 +59,7 @@ const YunWaline = config.value.runtime.addons['valaxy-addon-waline']
<slot name="main-nav-after" />
<slot v-if="config.comment.enable && frontmatter.comment !== false" name="comment">
<slot v-if="siteConfig.comment.enable && frontmatter.comment !== false" name="comment">
<YunCard w="full" p="4" class="comment sm:p-6 lg:px-12 xl:px-16" :class="frontmatter.nav === false ? 'mt-4' : 0">
<YunWaline />
<!-- <YunTwikoo /> -->

View File

@ -1,12 +1,13 @@
<script lang="ts" setup>
import { capitalize, computed } from 'vue'
import { useConfig } from 'valaxy'
import { useSiteConfig, useValaxyConfig } from 'valaxy'
import { useI18n } from 'vue-i18n'
import pkg from 'valaxy/package.json'
import { useThemeConfig } from '../composables'
const { t } = useI18n()
const config = useConfig()
const config = useValaxyConfig()
const siteConfig = useSiteConfig()
const themeConfig = useThemeConfig()
const year = new Date().getFullYear()
@ -42,7 +43,7 @@ const footerIcon = computed(() => themeConfig.value.footer.icon || {
<a v-if="themeConfig.footer.icon?.enable" class="inline-flex animate-pulse" :href="footerIcon.url" target="_blank" :title="footerIcon.title">
<div :class="footerIcon.name" />
</a>
<span>{{ config.author.name }}</span>
<span>{{ siteConfig.author.name }}</span>
</div>
<div v-if="themeConfig.footer.powered" class="powered" m="2">

View File

@ -1,8 +1,8 @@
<script lang="ts" setup>
import { useConfig } from 'valaxy'
import { useSiteConfig } from 'valaxy'
import { useRouter } from 'vue-router'
const config = useConfig()
const siteConfig = useSiteConfig()
const router = useRouter()
</script>
@ -10,23 +10,23 @@ const router = useRouter()
<div class="sidebar-panel">
<div class="site-info" m="t-6">
<router-link class="site-author-avatar" to="/about">
<img class="rounded-full" :src="config.author.avatar" alt="avatar">
<span class="site-author-status">{{ config.author.status.emoji }}</span>
<img class="rounded-full" :src="siteConfig.author.avatar" alt="avatar">
<span class="site-author-status">{{ siteConfig.author.status.emoji }}</span>
</router-link>
<div class="site-author-name">
<router-link to="/about">
{{ config.author.name }}
{{ siteConfig.author.name }}
</router-link>
</div>
<router-link v-if="router.hasRoute('about-site')" to="/about/site" class="site-name">
{{ config.title }}
{{ siteConfig.title }}
</router-link>
<span v-else class="site-name">{{ config.title }}</span>
<h4 v-if="config.subtitle" class="site-subtitle block" text="xs">
{{ config.subtitle }}
<span v-else class="site-name">{{ siteConfig.title }}</span>
<h4 v-if="siteConfig.subtitle" class="site-subtitle block" text="xs">
{{ siteConfig.subtitle }}
</h4>
<div v-if="config.description" class="site-description my-1">
{{ config.description }}
<div v-if="siteConfig.description" class="site-description my-1">
{{ siteConfig.description }}
</div>
</div>

View File

@ -1,10 +1,10 @@
<script lang="ts" setup>
import { computed } from '@vue/reactivity'
import { useConfig } from 'valaxy'
import { useSiteConfig } from 'valaxy'
import { onMounted, onUnmounted, ref } from 'vue'
import { useI18n } from 'vue-i18n'
const config = useConfig()
const siteConfig = useSiteConfig()
const { t } = useI18n()
// to avoid loading the docsearch js upfront (which is more than 1/3 of the
@ -17,7 +17,7 @@ function load() {
loaded.value = true
}
const isAlgolia = computed(() => config.value.search.type === 'algolia')
const isAlgolia = computed(() => siteConfig.value.search.type === 'algolia')
onMounted(() => {
if (!isAlgolia.value)

View File

@ -1,12 +1,12 @@
<script lang="ts" setup>
import { useConfig } from 'valaxy'
import { useSiteConfig } from 'valaxy'
const config = useConfig()
const siteConfig = useSiteConfig()
</script>
<template>
<div class="links-of-author">
<a v-for="item, i in config.social" :key="i" class="links-of-author-item yun-icon-btn" rel="noopener" :href="item.link" :title="item.name" target="_blank" :style="`color:${item.color}`">
<a v-for="item, i in siteConfig.social" :key="i" class="links-of-author-item yun-icon-btn" rel="noopener" :href="item.link" :title="item.name" target="_blank" :style="`color:${item.color}`">
<div class="icon" :class="item.icon" />
</a>
</div>

View File

@ -1,10 +1,10 @@
<script lang="ts" setup>
import { useConfig } from 'valaxy'
import { useSiteConfig } from 'valaxy'
import { ref } from 'vue'
import { useI18n } from 'vue-i18n'
const { t } = useI18n()
const config = useConfig()
const siteConfig = useSiteConfig()
const showQr = ref(false)
</script>
@ -17,7 +17,7 @@ const showQr = ref(false)
<div class="qrcode-container qrcode flex justify-around" m="y-4" :class="showQr && 'show'">
<a
v-for="method, i in config.sponsor.methods" :key="i"
v-for="method, i in siteConfig.sponsor.methods" :key="i"
class="flex flex-col justify-center items-center animate-iteration-1"
:class="showQr && 'animate-fade-in'"
:href="method.url" target="_blank"

View File

@ -1,7 +1,7 @@
<script lang="ts" setup>
// import { useConfig, useTwikoo } from 'valaxy'
// import { useSiteConfig, useTwikoo } from 'valaxy'
// const config = useConfig()
// const siteConfig = useSiteConfig()
// useTwikoo(config.value.comment.twikoo)
</script>

View File

@ -1,14 +1,14 @@
<script lang="ts" setup>
import { useConfig } from 'valaxy'
import { useRuntimeConfig } from 'valaxy'
import { computed } from 'vue'
import { useRoute } from 'vue-router'
import { useI18n } from 'vue-i18n'
const route = useRoute()
const config = useConfig()
const runtimeConfig = useRuntimeConfig()
const addonWaline = computed(() => config.value.runtime.addons['valaxy-addon-waline'])
const addonWaline = computed(() => runtimeConfig.value.addons['valaxy-addon-waline'])
const { t } = useI18n()
</script>

View File

@ -1,5 +1,5 @@
import { computed } from 'vue'
import { useConfig } from 'valaxy'
import { useValaxyConfig } from 'valaxy'
import type { YunTheme } from '../types'
/**
@ -7,6 +7,6 @@ import type { YunTheme } from '../types'
* @returns
*/
export function useThemeConfig<ThemeConfig = YunTheme.Config>() {
const config = useConfig<ThemeConfig>()
const config = useValaxyConfig<ThemeConfig>()
return computed(() => config!.value.themeConfig)
}

View File

@ -1,8 +1,8 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useConfig, useFrontmatter, useFullUrl } from 'valaxy'
import { useFrontmatter, useFullUrl, useSiteConfig } from 'valaxy'
const config = useConfig()
const siteConfig = useSiteConfig()
const frontmatter = useFrontmatter()
const url = useFullUrl()
@ -10,7 +10,7 @@ const showSponsor = computed(() => {
if (typeof frontmatter.value.sponsor === 'boolean')
return frontmatter.value.sponsor
return config.value.sponsor.enable
return siteConfig.value.sponsor.enable
})
</script>
@ -24,7 +24,7 @@ const showSponsor = computed(() => {
<template #main-content-after>
<YunSponsor v-if="showSponsor" m="t-6" />
<ValaxyCopyright v-if="frontmatter.copyright || config.license.enabled" :url="url" m="y-4" />
<ValaxyCopyright v-if="frontmatter.copyright || siteConfig.license.enabled" :url="url" m="y-4" />
</template>
<template #aside-custom>

View File

@ -1,12 +1,12 @@
import type { ResolvedValaxyOptions } from 'valaxy'
import type { ThemeUserConfig } from '../types'
import type { UserThemeConfig } from '../types'
/**
* generateSafelist by config
* @param themeConfig
* @returns
*/
export function generateSafelist(options: ResolvedValaxyOptions<ThemeUserConfig>) {
export function generateSafelist(options: ResolvedValaxyOptions<UserThemeConfig>) {
const themeConfig = options.config.themeConfig || {}
const safelist = []

View File

@ -145,4 +145,4 @@ export interface ThemeConfig {
}
}
export type ThemeUserConfig = Partial<ThemeConfig>
export type UserThemeConfig = Partial<ThemeConfig>

View File

@ -13,12 +13,12 @@ import { isDark, useFrontmatter } from './composables'
// https://github.com/vueuse/head
// you can use this to manipulate the document head in any components,
// they will be rendered correctly in the html results with vite-ssg
import { useConfig } from './config'
import { useSiteConfig } from './config'
// <link rel="apple-touch-icon" href="/pwa-192x192.png">
// <link rel="mask-icon" href="/safari-pinned-tab.svg" color="#00aba9">
const config = useConfig()
const siteConfig = useSiteConfig()
// todo, allow user config
const themeColor = computed(() => isDark.value ? '#000' : '#ffffff')
const fm = useFrontmatter()
@ -27,16 +27,16 @@ const { locale } = useI18n()
useHead({
title: computed(() => fm.value[`title_${locale.value}`] || fm.value.title),
titleTemplate: computed(() => fm.value.titleTemplate || ((title: string) => title ? `${title} - ${config.value.title}` : config.value.title)),
titleTemplate: computed(() => fm.value.titleTemplate || ((title: string) => title ? `${title} - ${siteConfig.value.title}` : siteConfig.value.title)),
link: [
{
rel: 'icon',
href: config.value.favicon,
type: config.value.favicon?.endsWith('svg') ? 'image/svg+xml' : 'image/png',
href: siteConfig.value.favicon,
type: siteConfig.value.favicon?.endsWith('svg') ? 'image/svg+xml' : 'image/png',
},
],
meta: [
{ name: 'description', content: computed(() => config.value.description) },
{ name: 'description', content: computed(() => siteConfig.value.description) },
{
name: 'theme-color',
content: themeColor,
@ -55,13 +55,13 @@ useHead({
// seo
// todo: get first image url from markdown
useSeoMeta({
description: computed(() => fm.value.excerpt || config.value.description),
ogDescription: computed(() => fm.value.excerpt || config.value.description),
ogLocale: computed(() => fm.value.lang || config.value.lang),
ogSiteName: computed(() => config.value.title),
ogTitle: computed(() => fm.value.title || config.value.title),
ogImage: computed(() => config.value.favicon),
ogUrl: computed(() => fm.value.url || config.value.url),
description: computed(() => fm.value.excerpt || siteConfig.value.description),
ogDescription: computed(() => fm.value.excerpt || siteConfig.value.description),
ogLocale: computed(() => fm.value.lang || siteConfig.value.lang),
ogSiteName: computed(() => siteConfig.value.title),
ogTitle: computed(() => fm.value.title || siteConfig.value.title),
ogImage: computed(() => siteConfig.value.favicon),
ogUrl: computed(() => fm.value.url || siteConfig.value.url),
})
const onContentUpdated = ref()

View File

@ -1,7 +1,7 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useConfig } from '../config'
import { useSiteConfig } from '../config'
withDefaults(defineProps<{
url?: string
@ -11,17 +11,17 @@ withDefaults(defineProps<{
const { t, locale } = useI18n()
const config = useConfig()
const siteConfig = useSiteConfig()
const ccVersion = (config.value.license.type === 'zero') ? '1.0' : '4.0'
const ccPrefix = (config.value.license.type === 'zero') ? 'publicdomain' : 'licenses'
const ccVersion = (siteConfig.value.license.type === 'zero') ? '1.0' : '4.0'
const ccPrefix = (siteConfig.value.license.type === 'zero') ? 'publicdomain' : 'licenses'
const ccURL = computed(() => {
const ccLang = config.value.license.language ? config.value.license.language : (locale.value === 'zh-CN') ? 'zh' : 'en'
return `https://creativecommons.org/${ccPrefix}/${config.value.license.type}/${ccVersion}/deed.${ccLang}`
const ccLang = siteConfig.value.license.language ? siteConfig.value.license.language : (locale.value === 'zh-CN') ? 'zh' : 'en'
return `https://creativecommons.org/${ccPrefix}/${siteConfig.value.license.type}/${ccVersion}/deed.${ccLang}`
})
const licenseHtml = computed(() => {
return t('post.copyright.license_content', [`<a href="${ccURL.value}" target="_blank" rel="noopener" title="CC ${`${config.value.license.type.toUpperCase()} ${ccVersion}`} ">CC ${config.value.license.type.toUpperCase()}</a>`])
return t('post.copyright.license_content', [`<a href="${ccURL.value}" target="_blank" rel="noopener" title="CC ${`${siteConfig.value.license.type.toUpperCase()} ${ccVersion}`} ">CC ${siteConfig.value.license.type.toUpperCase()}</a>`])
})
</script>
@ -31,7 +31,7 @@ const licenseHtml = computed(() => {
<strong>
{{ t('post.copyright.author') + t('symbol.colon') }}
</strong>
<span>{{ config.author.name }}</span>
<span>{{ siteConfig.author.name }}</span>
</li>
<li v-if="url" class="post-copyright-link">
<strong>

View File

@ -2,7 +2,7 @@ import { isClient, useScriptTag } from '@vueuse/core'
import { computed } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute } from 'vue-router'
import { useConfig } from '../..'
import { useSiteConfig } from '../..'
declare global {
interface Window {
@ -24,8 +24,8 @@ declare global {
* @param options
*/
export function useTwikoo(options: {} = {}) {
const config = useConfig()
const cdnPrefix = computed(() => config.value.cdn.prefix)
const siteConfig = useSiteConfig()
const cdnPrefix = computed(() => siteConfig.value.cdn.prefix)
const route = useRoute()
const { locale } = useI18n()

View File

@ -3,7 +3,7 @@ import { computed, inject } from 'vue'
import { isClient } from '@vueuse/core'
import type { PageData, Post } from '../../types'
import { useConfig } from '../config'
import { useSiteConfig } from '../config'
export function useFrontmatter() {
const route = useRoute()
@ -25,10 +25,10 @@ export function useData(): PageData {
* get full url
*/
export function useFullUrl() {
const config = useConfig()
const siteConfig = useSiteConfig()
const route = useRoute()
const url = computed(() => {
const siteUrl = config.value.url.endsWith('/') ? config.value.url.slice(0, -1) : config.value.url
const siteUrl = siteConfig.value.url.endsWith('/') ? siteConfig.value.url.slice(0, -1) : siteConfig.value.url
const origin = siteUrl || (isClient && window.location.origin)
return origin + route.path
})

View File

@ -1,7 +1,7 @@
import { useScriptTag } from '@vueuse/core'
import { useHead } from '@vueuse/head'
import { computed } from 'vue'
import { useConfig } from '../..'
import { useSiteConfig } from '../..'
/**
* use MetingJS and Aplayer
@ -9,8 +9,8 @@ import { useConfig } from '../..'
* @see https://github.com/metowolf/MetingJS
*/
export function useAplayer() {
const config = useConfig()
const cdnPrefix = computed(() => config.value.cdn.prefix)
const siteConfig = useSiteConfig()
const cdnPrefix = computed(() => siteConfig.value.cdn.prefix)
useHead({
link: [

View File

@ -1,5 +1,5 @@
// @ts-expect-error virtual module @valaxyjs/config
import valaxySiteConfig from '/@valaxyjs/site'
import valaxyConfig from '/@valaxyjs/config'
// @ts-expect-error virtual module @valaxyjs/context
import valaxyContext from '/@valaxyjs/context'
import type { ComputedRef, InjectionKey } from 'vue'
@ -8,7 +8,7 @@ import { computed, inject, readonly, shallowRef } from 'vue'
// fix build caused by pnpm
// This is likely not portable. A type annotation is necessary.
// https://github.com/microsoft/TypeScript/issues/42873
import type { DefaultThemeConfig, SiteConfig as ValaxySiteConfig } from 'valaxy/types'
import type { DefaultThemeConfig, ValaxyConfig } from 'valaxy/types'
/**
* parse valaxy config
@ -24,16 +24,16 @@ interface ValaxyContext {
userRoot: string
}
export const valaxySiteConfigSymbol: InjectionKey<ComputedRef<ValaxySiteConfig>> = Symbol('valaxy:site')
export const valaxySiteConfigRef = shallowRef<ValaxySiteConfig>(parse<ValaxySiteConfig>(valaxySiteConfig))
export const valaxyConfigSymbol: InjectionKey<ComputedRef<ValaxyConfig>> = Symbol('valaxy:config')
export const valaxyConfigRef = shallowRef<ValaxyConfig>(parse<ValaxyConfig>(valaxyConfig))
export const valaxyContextRef = shallowRef<ValaxyContext>(parse<ValaxyContext>(valaxyContext))
// hmr
if (import.meta.hot) {
// /@valaxyjs/site must be static string
import.meta.hot.accept('/@valaxyjs/site', (m) => {
valaxySiteConfigRef.value = parse<ValaxySiteConfig>(m?.default)
// /@valaxyjs/config must be static string
import.meta.hot.accept('/@valaxyjs/config', (m) => {
valaxyConfigRef.value = parse<ValaxyConfig>(m?.default)
})
// context
@ -42,8 +42,8 @@ if (import.meta.hot) {
})
}
export function initSite() {
return computed(() => valaxySiteConfigRef.value)
export function initValaxyConfig() {
return computed(() => valaxyConfigRef.value)
}
export function initContext() {
@ -55,8 +55,8 @@ export function initContext() {
* @public
* @returns
*/
export function useSite<ThemeConfig = DefaultThemeConfig>() {
const config = inject<ComputedRef<ValaxySiteConfig<ThemeConfig>>>(valaxySiteConfigSymbol)
export function useValaxyConfig<ThemeConfig = DefaultThemeConfig>() {
const config = inject<ComputedRef<ValaxyConfig<ThemeConfig>>>(valaxyConfigSymbol)
if (!config)
throw new Error('[Valaxy] site config not properly injected in app')
return config!
@ -68,7 +68,17 @@ export function useSite<ThemeConfig = DefaultThemeConfig>() {
* @returns
*/
export function useConfig<ThemeConfig = DefaultThemeConfig>() {
return useSite<ThemeConfig>()
return useValaxyConfig<ThemeConfig>()
}
/**
* get valaxy config
* @public
* @returns
*/
export function useSiteConfig<ThemeConfig = DefaultThemeConfig>() {
const config = useValaxyConfig<ThemeConfig>()
return computed(() => config!.value.siteConfig)
}
/**
@ -79,6 +89,11 @@ export function useConfig<ThemeConfig = DefaultThemeConfig>() {
* @returns
*/
export function useThemeConfig<ThemeConfig = DefaultThemeConfig>() {
const config = useSite<ThemeConfig>()
const config = useValaxyConfig<ThemeConfig>()
return computed(() => config!.value.themeConfig)
}
export function useRuntimeConfig() {
const config = useValaxyConfig()
return computed(() => config!.value.runtimeConfig)
}

View File

@ -12,7 +12,7 @@ import { useStorage } from '@vueuse/core'
import type { Router } from 'vue-router'
import type { PageDataPayload } from '../../types'
import { initSite, valaxySiteConfigSymbol } from '../config'
import { initValaxyConfig, valaxyConfigSymbol } from '../config'
import { ensureSuffix } from '@antfu/utils'
import type { UserModule } from 'valaxy/client/types'
@ -45,10 +45,10 @@ function shouldHotReload(payload: PageDataPayload): boolean {
export const install: UserModule = ({ app, router }) => {
// inject valaxy config before modules
const config = initSite()
app.provide(valaxySiteConfigSymbol, config)
const config = initValaxyConfig()
app.provide(valaxyConfigSymbol, config)
const locale = useStorage('valaxy-locale', config.value.lang || 'en')
const locale = useStorage('valaxy-locale', config.value.siteConfig.lang || 'en')
// init i18n, by valaxy config
const i18n = createI18n({

View File

@ -35,7 +35,7 @@ export async function ssgBuild(
onFinished() {
generateSitemap(
{
hostname: options.config.url,
hostname: options.config.siteConfig.url,
},
)
},

View File

@ -52,7 +52,7 @@ export async function getIndexHtml({ clientRoot, themeRoot, userRoot, config }:
const roots = [userRoot, themeRoot]
if (config.mode === 'auto') {
if (config.siteConfig.mode === 'auto') {
head += `
<script>
(function () {
@ -65,11 +65,11 @@ export async function getIndexHtml({ clientRoot, themeRoot, userRoot, config }:
`
}
if (config.lang) {
if (config.siteConfig.lang) {
head += `
<script>
(function () {
const locale = localStorage.getItem('valaxy-locale') || '${config.lang}'
const locale = localStorage.getItem('valaxy-locale') || '${config.siteConfig.lang}'
document.documentElement.setAttribute('lang', locale)
})()
</script>

View File

@ -1,6 +1,6 @@
import type { DefaultThemeConfig, ValaxyAddon } from '../../types'
import type { ResolvedValaxyOptions } from '../options'
import type { ValaxyConfig } from '../types'
import type { ValaxyNodeConfig } from '../types'
export function defineValaxyAddon<AddonOptions = {}>(
addonFunc: (addonOptions?: AddonOptions, valaxyOptions?: ResolvedValaxyOptions) => ValaxyAddon,
@ -10,7 +10,7 @@ export function defineValaxyAddon<AddonOptions = {}>(
export const defineAddon = defineValaxyAddon
export type ValaxyConfigExtendKey = 'vite' | 'vue' | 'unocss' | 'unocssPresets' | 'markdown' | 'extendMd' | 'addons'
export type ValaxyPickConfig = Pick<ValaxyConfig, ValaxyConfigExtendKey>
export type ValaxyPickConfig = Pick<ValaxyNodeConfig, ValaxyConfigExtendKey>
export type ValaxyTheme<ThemeConfig = DefaultThemeConfig> = ValaxyPickConfig & { themeConfig?: ThemeConfig }
export function defineTheme<ThemeConfig = DefaultThemeConfig>(
theme: ValaxyTheme<ThemeConfig> | ((options: ResolvedValaxyOptions<ThemeConfig>) => ValaxyTheme<ThemeConfig>),

View File

@ -1,30 +1,23 @@
import type { VitePluginConfig as UnoCssConfig } from 'unocss/vite'
import type { Awaitable } from '@antfu/utils'
import type { SiteConfig, UserSiteConfig } from '../../types'
import type { UserConfig } from '../types'
import type { UserValaxyNodeConfig } from '../types'
export * from './addon'
/**
* Type site helper
* Type helper for site.config.ts
* @param config
* @returns
*/
export function defineSite<ThemeConfig>(config: UserSiteConfig<ThemeConfig>) {
export function defineSiteConfig(config: UserSiteConfig) {
return config
}
/**
* Type site helper for custom theme site
* Type helper for valaxy.config.ts
*/
export function defineSiteWithTheme<ThemeConfig>(
config: UserSiteConfig<ThemeConfig>,
) {
return config
}
/**
* Type valaxy config helper
*/
export function defineValaxyConfig<ThemeConfig>(config: UserConfig<ThemeConfig>) {
export function defineValaxyConfig<ThemeConfig>(config: UserValaxyNodeConfig<ThemeConfig>) {
return config
}
export const defineConfig = defineValaxyConfig
@ -58,7 +51,6 @@ export const defaultSiteConfig: SiteConfig = {
format: '',
},
lastUpdated: true,
ignoreDeadLinks: true,
license: {
enabled: true,
@ -88,6 +80,10 @@ export const defaultSiteConfig: SiteConfig = {
features: {
katex: true,
},
}
export const defaultValaxyConfig = {
ignoreDeadLinks: true,
theme: 'yun',
themeConfig: {
@ -100,7 +96,7 @@ export const defaultSiteConfig: SiteConfig = {
// markdown: {
// excerpt: '<!-- more -->',
// },
runtime: { addons: {} },
runtimeConfig: { addons: {} },
}
export type UnoSetup = () => Awaitable<Partial<UnoCssConfig> | undefined>

View File

@ -0,0 +1,32 @@
import type { UserSiteConfig } from 'valaxy'
import consola from 'consola'
import { cyan } from 'kolorist'
import { defu } from 'defu'
import { defaultSiteConfig } from '..'
import { loadConfigFromFile } from './utils'
/**
* resolve valaxy config from special root
* @param options
* @returns
*/
export async function resolveSiteConfigFromRoot(root: string) {
consola.info(`Resolve ${cyan('site.config.ts')}`)
return loadConfigFromFile<UserSiteConfig>('site.config', {
cwd: root,
})
}
/**
* resolve site.config.ts and merge with default
* @param root
* @returns
*/
export async function resolveSiteConfig(root: string) {
const { config: userSiteConfig, configFile: siteConfigFile } = await resolveSiteConfigFromRoot(root)
return {
siteConfig: defu(userSiteConfig, defaultSiteConfig),
siteConfigFile,
}
}

View File

@ -0,0 +1,24 @@
import type { LoadConfigSource } from 'unconfig'
import { loadConfig } from 'unconfig'
import { normalizePath } from 'vite'
export interface LoadConfigFromFileOptions {
cwd?: string
rewrite?: LoadConfigSource['rewrite']
}
export async function loadConfigFromFile<T>(
file: string,
options: LoadConfigFromFileOptions = {},
) {
const { config: userValaxyConfig, sources } = await await loadConfig<T>({
sources: { files: file, rewrite: options.rewrite },
cwd: options.cwd || process.cwd(),
})
const configFile = normalizePath(sources[0] || '')
return {
config: userValaxyConfig,
configFile,
}
}

View File

@ -4,13 +4,14 @@ import _debug from 'debug'
import fg from 'fast-glob'
import { ensureSuffix, uniq } from '@antfu/utils'
import defu from 'defu'
import type { DefaultThemeConfig, ValaxyAddon } from '../types'
import type { DefaultThemeConfig, RuntimeConfig } from '../types'
import { resolveImportPath } from './utils'
import { mergeValaxyConfig, resolveAddonConfig, resolveValaxyConfig, resolveValaxyConfigFromRoot } from './utils/config'
import type { ValaxyAddonResolver, ValaxyConfig } from './types'
import { defaultSiteConfig } 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'
// for cli entry
export interface ValaxyEntryOptions {
@ -18,7 +19,7 @@ export interface ValaxyEntryOptions {
* theme name
*/
theme?: string
userRoot?: string
userRoot: string
}
export interface ResolvedValaxyOptions<ThemeConfig = DefaultThemeConfig> {
@ -53,16 +54,17 @@ export interface ResolvedValaxyOptions<ThemeConfig = DefaultThemeConfig> {
/**
* Valaxy Config
*/
config: ValaxyConfig<ThemeConfig> & {
config: ValaxyNodeConfig<ThemeConfig> & {
/**
* Generated Runtime Config
*/
runtime: { addons: Record<string, ValaxyAddon> }
runtimeConfig: RuntimeConfig
}
/**
* config file path
*/
configFile: string
siteConfigFile: string
pages: string[]
/**
* all addons
@ -72,18 +74,25 @@ export interface ResolvedValaxyOptions<ThemeConfig = DefaultThemeConfig> {
}
export interface ValaxyServerOptions {
onConfigReload?: (newConfig: ValaxyConfig, config: ValaxyConfig, force?: boolean) => void
onConfigReload?: (newConfig: ValaxyNodeConfig, config: ValaxyNodeConfig, force?: boolean) => void
}
const debug = _debug('valaxy:options')
// for cli options
export async function resolveOptions(options: ValaxyEntryOptions, mode: ResolvedValaxyOptions['mode'] = 'dev') {
export async function resolveOptions(
options: ValaxyEntryOptions = { userRoot: process.cwd() },
mode: ResolvedValaxyOptions['mode'] = 'dev',
) {
const pkgRoot = dirname(resolveImportPath('valaxy/package.json', true))
const clientRoot = resolve(pkgRoot, 'client')
const userRoot = resolve(options.userRoot || process.cwd())
const { config: userValaxyConfig, configFile, theme } = await resolveValaxyConfig(options)
let { config: userValaxyConfig, configFile, theme } = await resolveValaxyConfig(options)
const { siteConfig, siteConfigFile } = await resolveSiteConfig(options.userRoot)
// merge with valaxy
userValaxyConfig = defu<ValaxyNodeConfig, any>({ siteConfig }, userValaxyConfig)
const themeRoot = getThemeRoot(theme, options.userRoot)
@ -111,9 +120,10 @@ export async function resolveOptions(options: ValaxyEntryOptions, mode: Resolved
theme,
config: {
...userValaxyConfig,
runtime: { addons: {} },
runtimeConfig: { addons: {} },
},
configFile: configFile || '',
siteConfigFile: siteConfigFile || '',
pages,
addons: [],
}
@ -128,17 +138,17 @@ export async function resolveOptions(options: ValaxyEntryOptions, mode: Resolved
const addonValaxyConfig = await resolveAddonConfig(addons, valaxyOptions)
valaxyConfig = mergeValaxyConfig(valaxyConfig, addonValaxyConfig)
const config = defu(valaxyConfig, defaultSiteConfig)
const config = defu(valaxyConfig, defaultValaxyConfig)
valaxyOptions.config = {
...config,
runtime: {
runtimeConfig: {
addons: {},
},
}
valaxyOptions.addons = addons
addons.forEach((addon) => {
valaxyOptions.config.runtime.addons[addon.name] = addon
valaxyOptions.config.runtimeConfig.addons[addon.name] = addon
})
const addonRoots = addons.map(({ root }) => root)
@ -157,10 +167,11 @@ export async function resolveOptions(options: ValaxyEntryOptions, mode: Resolved
async function processSiteConfig(options: ResolvedValaxyOptions) {
const { config, themeRoot, theme } = options
const siteConfig = config.siteConfig
// optimize config
config.url = ensureSuffix('/', config.url || '')
siteConfig.url = ensureSuffix('/', siteConfig.url || '')
// ensure suffix for cdn prefix
config.cdn!.prefix = ensureSuffix('/', config.cdn!.prefix || '')
siteConfig.cdn!.prefix = ensureSuffix('/', siteConfig.cdn!.prefix || '')
// mount pkg info
const themePkgPath = resolve(themeRoot, 'package.json')

View File

@ -47,7 +47,7 @@ export function createConfigPlugin(options: ResolvedValaxyOptions): Plugin {
// internal
'valaxy',
'/@valaxyjs/site',
'/@valaxyjs/config',
'/@valaxyjs/context',
],
},
@ -111,7 +111,6 @@ export function getDefine(options: ResolvedValaxyOptions): Record<string, any> {
return {
__DEV__: options.mode === 'dev' ? 'true' : 'false',
__ALGOLIA__: options.config?.search?.type === 'algolia',
}
}

View File

@ -4,12 +4,16 @@ import fs from 'fs-extra'
import type { Plugin, ResolvedConfig } from 'vite'
// import consola from 'consola'
import { pascalCase } from 'pascal-case'
import { defu } from 'defu'
import { defaultSiteConfig } from '../config'
import type { ResolvedValaxyOptions, ValaxyServerOptions } from '../options'
import { resolveOptions } from '../options'
import { resolveImportPath, slash, toAtFS } from '../utils'
import { createMarkdownToVueRenderFn } from '../markdown/markdownToVue'
import type { PageDataPayload } from '../../types'
import type { PageDataPayload, SiteConfig } from '../../types'
import type { ValaxyNodeConfig } from '../types'
import { checkMd } from '../markdown/check'
import { resolveSiteConfig } from '../config/site'
/**
* for /@valaxyjs/styles
@ -20,7 +24,7 @@ function generateStyles(roots: string[], options: ResolvedValaxyOptions) {
const imports: string[] = []
// katex
if (options.config.features?.katex) {
if (options.config.siteConfig.features?.katex) {
imports.push(`import "${toAtFS(resolveImportPath('katex/dist/katex.min.css', true))}"`)
imports.push(`import "${toAtFS(join(options.clientRoot, 'styles/third/katex.scss'))}"`)
}
@ -112,12 +116,10 @@ function generateAppVue(root: string) {
* @returns
*/
export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions: ValaxyServerOptions = {}): Plugin {
const { config: valaxyConfig } = options
let { config: valaxyConfig } = options
const valaxyPrefix = '/@valaxy'
let siteConfig = options.config
const roots = options.roots
let markdownToVue: Awaited<ReturnType<typeof createMarkdownToVueRenderFn>>
@ -138,7 +140,7 @@ export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions
options.pages,
viteConfig.define,
viteConfig.command === 'build',
options.config.lastUpdated,
options.config.siteConfig.lastUpdated,
)
},
@ -158,9 +160,9 @@ export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions
},
load(id) {
if (id === '/@valaxyjs/site')
if (id === '/@valaxyjs/config')
// stringify twice for \"
return `export default ${JSON.stringify(JSON.stringify(siteConfig))}`
return `export default ${JSON.stringify(JSON.stringify(valaxyConfig))}`
if (id === '/@valaxyjs/context') {
return `export default ${JSON.stringify(JSON.stringify({
@ -219,23 +221,25 @@ export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions
},
renderStart() {
if (hasDeadLinks && !siteConfig.ignoreDeadLinks)
if (hasDeadLinks && !valaxyConfig.ignoreDeadLinks)
throw new Error('One or more pages contain dead links.')
},
/**
* handle config hmr
* @param ctx
* @returns
*/
async handleHotUpdate(ctx) {
const { file, server, read } = ctx
// handle valaxy.config.ts hmr
if (file === options.configFile) {
const { config } = await resolveOptions({ userRoot: options.userRoot })
const reloadConfigAndEntries = (config: ValaxyNodeConfig) => {
serverOptions.onConfigReload?.(config, options.config)
Object.assign(options.config, config)
siteConfig = config
valaxyConfig = config
const moduleIds = ['/@valaxyjs/site', '/@valaxyjs/context']
const moduleIds = ['/@valaxyjs/config', '/@valaxyjs/context']
const moduleEntries = [
...Array.from(moduleIds).map(id => server.moduleGraph.getModuleById(id)),
].filter(<T>(item: T): item is NonNullable<T> => !!item)
@ -243,6 +247,18 @@ export function createValaxyPlugin(options: ResolvedValaxyOptions, serverOptions
return moduleEntries
}
// handle valaxy.config.ts hmr
if (file === options.configFile) {
const { config } = await resolveOptions({ userRoot: options.userRoot })
return reloadConfigAndEntries(config)
}
if (file === options.siteConfigFile) {
const { siteConfig } = await resolveSiteConfig(options.userRoot)
valaxyConfig.siteConfig = defu<SiteConfig, [SiteConfig]>(siteConfig, defaultSiteConfig)
return reloadConfigAndEntries(valaxyConfig)
}
// send headers
if (file.endsWith('.md')) {
const content = await read()

View File

@ -12,6 +12,7 @@ import Components from 'unplugin-vue-components/vite'
import VueI18n from '@intlify/unplugin-vue-i18n/vite'
import dayjs from 'dayjs'
// import { convert } from 'html-to-text'
import type { ValaxyExtendConfig } from '../types'
import type { ResolvedValaxyOptions, ValaxyServerOptions } from '../options'
import { setupMarkdownPlugins } from '../markdown'
@ -147,8 +148,8 @@ export async function ViteValaxyPlugins(
// options.config.date.format,
// options.config.lastUpdated,
// )
const lastUpdated = options.config.lastUpdated
const format = options.config.date?.format
const lastUpdated = options.config.siteConfig.lastUpdated
const format = options.config.siteConfig.date?.format
if (!data.date)
data.date = fs.statSync(path).mtime
@ -166,6 +167,7 @@ export async function ViteValaxyPlugins(
route.meta = Object.assign(route.meta, {
frontmatter: Object.assign(defaultFrontmatter, data),
excerpt: excerpt ? mdIt.render(excerpt) : '',
// excerpt: convert(excerpt ? mdIt.render(excerpt) : '') || '',
})
// set layout

View File

@ -32,12 +32,14 @@ export const createSafelist = async (options: ResolvedValaxyOptions) => {
'rotate-y-180',
]).concat(safeIcons)
const siteConfig = config.siteConfig
// generate icon safelist
if (config.social?.length)
config.social.forEach(item => safelist.push(item?.icon || ''))
if (siteConfig.social?.length)
siteConfig.social.forEach(item => safelist.push(item?.icon || ''))
// sponsor icon
const methods = config.sponsor?.methods || []
const methods = siteConfig.sponsor?.methods || []
if (methods.length)
methods.forEach(item => safelist.push(item?.icon || ''))

View File

@ -25,31 +25,32 @@ const markdown = MarkdownIt({
*/
export async function build(options: ResolvedValaxyOptions) {
const { config } = options
const siteConfig = config.siteConfig
if (!config.url || config.url === '/') {
consola.error('You must set `url` (like `https://example.com`) in `valaxy.config.ts` to generate rss.')
if (!siteConfig.url || siteConfig.url === '/') {
consola.error('You must set `url` (like `https://example.com`) in `site.config.ts` to generate rss.')
return
}
// url has been ensured '/'
const siteUrl = config.url
const DOMAIN = config.url.slice(0, -1)
const siteUrl = siteConfig.url
const DOMAIN = siteConfig.url.slice(0, -1)
const author: Author = {
name: config?.author?.name,
email: config?.author?.email,
link: config?.author?.link,
name: siteConfig.author?.name,
email: siteConfig.author?.email,
link: siteConfig.author?.link,
}
consola.info(`RSS Site Url: ${cyan(siteUrl)}`)
const ccVersion = (config.license?.type === 'zero') ? '1.0' : '4.0'
const ccVersion = (siteConfig.license?.type === 'zero') ? '1.0' : '4.0'
const feedOptions: FeedOptions = {
title: config.title || 'Valaxy Blog',
description: config.description,
title: siteConfig.title || 'Valaxy Blog',
description: siteConfig.description,
id: siteUrl || 'valaxy',
link: siteUrl,
copyright: `CC ${config.license?.type?.toUpperCase()} ${ccVersion} ${new Date().getFullYear()} © ${config.author?.name}`,
copyright: `CC ${siteConfig.license?.type?.toUpperCase()} ${ccVersion} ${new Date().getFullYear()} © ${siteConfig.author?.name}`,
feedLinks: {
json: `${siteUrl}feed.json`,
atom: `${siteUrl}feed.atom`,
@ -71,7 +72,7 @@ export async function build(options: ResolvedValaxyOptions) {
continue
}
await formatMdDate(data, i, config.date?.format, config.lastUpdated)
await formatMdDate(data, i, siteConfig.date?.format, siteConfig.lastUpdated)
// todo i18n
@ -100,29 +101,29 @@ export async function build(options: ResolvedValaxyOptions) {
// await writeFeed('feed', feedOptions, posts)
// write
const authorAvatar = config.author?.avatar || '/favicon.svg'
const authorAvatar = siteConfig.author?.avatar || '/favicon.svg'
feedOptions.author = author
feedOptions.image = isExternal(authorAvatar)
? config.author?.avatar
? siteConfig.author?.avatar
: `${DOMAIN}${ensurePrefix('/', authorAvatar)}`
feedOptions.favicon = `${DOMAIN}${config.feed?.favicon || config.favicon}`
feedOptions.favicon = `${DOMAIN}${siteConfig.feed?.favicon || siteConfig.favicon}`
const feed = new Feed(feedOptions)
posts.forEach(item => feed.addItem(item))
// items.forEach(i=> console.log(i.title, i.date))
await fs.ensureDir(dirname(`./dist/${config.feed?.name} || 'feed.xml'`))
await fs.ensureDir(dirname(`./dist/${siteConfig.feed?.name} || 'feed.xml'`))
const path = './dist'
const types = ['xml', 'atom', 'json']
types.forEach((type) => {
let data = ''
let name = `${path}/${config.feed?.name || 'feed'}.${type}`
let name = `${path}/${siteConfig.feed?.name || 'feed'}.${type}`
if (type === 'xml') {
data = feed.rss2()
}
else if (type === 'atom') {
if (!config.feed?.name)
if (!siteConfig.feed?.name)
name = `${path}/atom.xml`
data = feed.atom1()
}

View File

@ -4,17 +4,17 @@ import type { VitePluginConfig as UnoCSSConfig } from 'unocss/vite'
import type Pages from 'vite-plugin-pages'
import type { UserConfig as ViteUserConfig } from 'vite'
import type { presetAttributify, presetIcons, presetTypography, presetUno } from 'unocss'
import type { DefaultThemeConfig, UserSiteConfig, ValaxyAddon } from '../types'
import type { DefaultThemeConfig, PartialDeep, ValaxyAddon, ValaxyConfig } from '../types'
import type { ResolvedValaxyOptions } from './options'
import type { MarkdownOptions } from './markdown'
export type ValaxyConfig<ThemeConfig = DefaultThemeConfig> = UserSiteConfig<ThemeConfig> & ValaxyExtendConfig
export type UserConfig<ThemeConfig = DefaultThemeConfig> = ValaxyConfig<ThemeConfig>
export type ValaxyNodeConfig<ThemeConfig = DefaultThemeConfig> = ValaxyConfig<ThemeConfig> & ValaxyExtendConfig
export type UserValaxyNodeConfig<ThemeConfig = DefaultThemeConfig> = PartialDeep<ValaxyNodeConfig<ThemeConfig>>
/**
* fn with options for theme config
*/
export type ValaxyConfigFn<ThemeConfig = DefaultThemeConfig> = (options: ResolvedValaxyOptions<ThemeConfig>) => ValaxyConfig | Promise<ValaxyConfig>
export type ValaxyConfigExport<ThemeConfig = DefaultThemeConfig> = ValaxyConfig<ThemeConfig> | ValaxyConfigFn<ThemeConfig>
export type ValaxyConfigFn<ThemeConfig = DefaultThemeConfig> = (options: ResolvedValaxyOptions<ThemeConfig>) => ValaxyNodeConfig | Promise<ValaxyNodeConfig>
export type ValaxyConfigExport<ThemeConfig = DefaultThemeConfig> = ValaxyNodeConfig<ThemeConfig> | ValaxyConfigFn<ThemeConfig>
export interface ValaxyExtendConfig {
vite?: ViteUserConfig
@ -52,8 +52,8 @@ export interface ValaxyExtendConfig {
export type ValaxyAddonLike = ValaxyAddon | false | null | undefined
export type ValaxyAddons = (ValaxyAddon | string)[] | Record<string, ValaxyAddonLike>
export type ValaxyAddonFn<ThemeConfig = DefaultThemeConfig> = (addonOptions: ValaxyAddonResolver, valaxyOptions: ResolvedValaxyOptions<ThemeConfig>) => ValaxyConfig | Promise<ValaxyConfig>
export type ValaxyAddonExport<ThemeConfig = DefaultThemeConfig> = ValaxyConfig<ThemeConfig> | ValaxyAddonFn<ThemeConfig>
export type ValaxyAddonFn<ThemeConfig = DefaultThemeConfig> = (addonOptions: ValaxyAddonResolver, valaxyOptions: ResolvedValaxyOptions<ThemeConfig>) => ValaxyNodeConfig | Promise<ValaxyNodeConfig>
export type ValaxyAddonExport<ThemeConfig = DefaultThemeConfig> = ValaxyNodeConfig<ThemeConfig> | ValaxyAddonFn<ThemeConfig>
export interface ValaxyAddonResolver {
name: string

View File

@ -2,6 +2,7 @@ import { resolve } from 'path'
import fs from 'fs-extra'
import consola from 'consola'
import defu from 'defu'
import { cyan, yellow } from 'kolorist'
import type { ValaxyAddonResolver, ValaxyAddons } from '../types'
import { getModuleRoot } from './root'
@ -26,7 +27,9 @@ export async function parseAddons(addons: ValaxyAddons, userRoot = process.cwd()
}
}
return Object.values(resolvers).filter(item => item.enable)
const resolvedAddons = Object.values(resolvers).filter(item => item.enable)
consola.info(`Resolve ${cyan('addons:')} ${yellow(resolvedAddons.map(item => item.name).join(', '))}`)
return resolvedAddons
}
/**

View File

@ -1,24 +1,12 @@
import { mergeConfig as mergeViteConfig, normalizePath } from 'vite'
import { mergeConfig as mergeViteConfig } from 'vite'
import { createDefu } from 'defu'
import { isFunction } from '@antfu/utils'
import type { LoadConfigSource } from 'unconfig'
import { loadConfig } from 'unconfig'
import type { ResolvedValaxyOptions, ValaxyEntryOptions } from '../options'
import type { ValaxyAddonFn, ValaxyAddonResolver, ValaxyConfig, ValaxyConfigFn } from '../types'
export interface LoadConfigFromFilesOptions {
cwd?: string
rewrite?: LoadConfigSource['rewrite']
}
export async function loadConfigFromFiles<T>(
files: string,
options: LoadConfigFromFilesOptions = {},
) {
return await loadConfig<T>({
sources: { files, rewrite: options.rewrite },
cwd: options.cwd || process.cwd(),
})
}
import consola from 'consola'
import { cyan } from 'kolorist'
import type { ResolvedValaxyOptions, ValaxyEntryOptions } from '../options'
import type { ValaxyAddonFn, ValaxyAddonResolver, ValaxyConfigFn, ValaxyNodeConfig } from '../types'
import { loadConfigFromFile } from '../config/utils'
/**
* merge valaxy.config
@ -44,8 +32,8 @@ export const mergeValaxyConfig = createDefu((obj: any, key, value) => {
* @returns
*/
export async function resolveValaxyConfigFromRoot(root: string, options?: ResolvedValaxyOptions) {
return loadConfigFromFiles<ValaxyConfig>('valaxy.config', {
rewrite<F = ValaxyConfig | ValaxyConfigFn>(c: F) {
return loadConfigFromFile<ValaxyNodeConfig>('valaxy.config', {
rewrite<F = ValaxyNodeConfig | ValaxyConfigFn>(c: F) {
return (typeof c === 'function' ? c(options || {} as ResolvedValaxyOptions) : c)
},
cwd: root,
@ -60,10 +48,11 @@ export async function resolveValaxyConfigFromRoot(root: string, options?: Resolv
* @returns
*/
export async function resolveValaxyConfig(options: ValaxyEntryOptions) {
consola.info(`Resolve ${cyan('valaxy.config.ts')}`)
// const resolved = await mergeValaxyConfig(options)
// valaxyConfig = mergeValaxyConfig(valaxyConfig, config)
const { config: userValaxyConfig, sources } = await resolveValaxyConfigFromRoot(options.userRoot || process.cwd())
const configFile = normalizePath(sources[0] || '')
const { config: userValaxyConfig, configFile } = await resolveValaxyConfigFromRoot(options.userRoot || process.cwd())
const theme = options.theme || userValaxyConfig.theme || 'yun'
@ -75,17 +64,17 @@ export async function resolveValaxyConfig(options: ValaxyEntryOptions) {
}
export async function resolveAddonConfig(addons: ValaxyAddonResolver[], options?: ResolvedValaxyOptions) {
let valaxyConfig: ValaxyConfig = {}
let valaxyConfig: ValaxyNodeConfig = {} as ValaxyNodeConfig
for (const addon of addons) {
const { config, sources } = await loadConfigFromFiles<ValaxyConfig>('index', {
rewrite<F = ValaxyConfig | ValaxyAddonFn>(obj: F, _filepath: string) {
const { config, configFile } = await loadConfigFromFile<ValaxyNodeConfig>('index', {
rewrite<F = ValaxyNodeConfig | ValaxyAddonFn>(obj: F, _filepath: string) {
return (typeof obj === 'function' ? obj(addon, options!) : obj)
},
cwd: addon.root,
})
if (!config)
continue
addon.configFile = normalizePath(sources[0] || '')
addon.configFile = configFile
valaxyConfig = mergeValaxyConfig(config, valaxyConfig)
}
return valaxyConfig

View File

@ -77,6 +77,7 @@
"feed": "^4.2.2",
"global-dirs": "^3.0.1",
"gray-matter": "^4.0.3",
"html-to-text": "^9.0.3",
"is-installed-globally": "^0.4.0",
"jiti": "^1.16.1",
"katex": "^0.16.4",
@ -119,6 +120,7 @@
"@mdit-vue/shared": "^0.11.2",
"@types/cross-spawn": "^6.0.2",
"@types/ejs": "^3.1.1",
"@types/html-to-text": "^9.0.0",
"@types/katex": "^0.16.0",
"@types/markdown-it": "^12.2.3",
"@types/nprogress": "^0.2.0",

View File

@ -23,7 +23,7 @@ declare module '*.vue' {
}
// vite hmr data
declare module '/@valaxyjs/site' {
declare module '/@valaxyjs/config' {
const config: string
export default config
}

View File

@ -16,7 +16,7 @@ export default defineConfig((options) => {
format: ['cjs', 'esm'],
minify: !options.watch,
external: [
'/@valaxyjs/site',
'/@valaxyjs/config',
'/@valaxyjs/context',
],
outExtension({ format }) {

View File

@ -24,7 +24,7 @@ export interface SocialLink {
}
// shared with valaxy node and client
export interface SiteConfig<T = DefaultThemeConfig> {
export interface SiteConfig {
/**
* enable auto (light/dark mode)
* @default 'auto'
@ -94,13 +94,6 @@ export interface SiteConfig<T = DefaultThemeConfig> {
*/
lastUpdated: boolean
/**
* Don't fail builds due to dead links.
*
* @default true
*/
ignoreDeadLinks: boolean
/**
* icon for your website
*/
@ -160,24 +153,6 @@ export interface SiteConfig<T = DefaultThemeConfig> {
prefix: string
}
/**
* The name of theme
* @description
*/
theme: string
/**
* The config of theme
* @description
*/
themeConfig: T & {
pkg: {
name: string
version: string
homepage?: string
[key: string]: any
}
}
/**
* The license of your posts
* @description 使使 Creative Commons
@ -219,21 +194,59 @@ export interface SiteConfig<T = DefaultThemeConfig> {
icon: string
}[]
}
/**
* Generated Runtime Config
*/
runtime: {
addons: Record<string, ValaxyAddon>
}
}
export type PartialDeep<T> = {
[P in keyof T]?: T[P] extends object ? PartialDeep<T[P]> : T[P]
}
/**
* config generated by runtime
*/
export interface RuntimeConfig {
addons: Record<string, ValaxyAddon>
}
export interface ValaxyConfig<ThemeConfig = DefaultThemeConfig> {
siteConfig: SiteConfig
/**
* The name of theme
* @description
*/
theme: string
/**
* The config of theme
* @description
*/
themeConfig: ThemeConfig & {
pkg: {
name: string
version: string
homepage?: string
[key: string]: any
}
}
/**
* generated by runtime
*/
runtimeConfig: RuntimeConfig
// other in node
/**
* Don't fail builds due to dead links.
*
* @default true
*/
ignoreDeadLinks: boolean
}
/**
* user site config
*/
export type UserSiteConfig = PartialDeep<SiteConfig>
/**
* Valaxy User Config
* @description Valaxy
*/
export type UserSiteConfig<ThemeConfig = DefaultThemeConfig> = PartialDeep<SiteConfig<ThemeConfig>>
export type UserValaxyConfig<ThemeConfig = DefaultThemeConfig> = PartialDeep<ValaxyConfig<ThemeConfig>>

View File

@ -112,6 +112,7 @@ importers:
'@types/body-scroll-lock': ^3.1.0
'@types/cross-spawn': ^6.0.2
'@types/ejs': ^3.1.1
'@types/html-to-text': ^9.0.0
'@types/katex': ^0.16.0
'@types/markdown-it': ^12.2.3
'@types/nprogress': ^0.2.0
@ -131,6 +132,7 @@ importers:
feed: ^4.2.2
global-dirs: ^3.0.1
gray-matter: ^4.0.3
html-to-text: ^9.0.3
https-localhost: ^4.7.1
is-installed-globally: ^0.4.0
jiti: ^1.16.1
@ -184,6 +186,7 @@ importers:
feed: 4.2.2
global-dirs: 3.0.1
gray-matter: 4.0.3
html-to-text: 9.0.3
is-installed-globally: 0.4.0
jiti: 1.16.2
katex: 0.16.4
@ -225,6 +228,7 @@ importers:
'@mdit-vue/shared': 0.11.2
'@types/cross-spawn': 6.0.2
'@types/ejs': 3.1.1
'@types/html-to-text': 9.0.0
'@types/katex': 0.16.0
'@types/markdown-it': 12.2.3
'@types/nprogress': 0.2.0
@ -1148,6 +1152,13 @@ packages:
estree-walker: 2.0.2
picomatch: 2.3.1
/@selderee/plugin-htmlparser2/0.10.0:
resolution: {integrity: sha512-gW69MEamZ4wk1OsOq1nG1jcyhXIQcnrsX5JwixVw/9xaiav8TCyjESAruu1Rz9yyInhgBXxkNwMeygKnN2uxNA==}
dependencies:
domhandler: 5.0.3
selderee: 0.10.0
dev: false
/@tootallnate/once/2.0.0:
resolution: {integrity: sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==}
engines: {node: '>= 10'}
@ -1191,6 +1202,10 @@ packages:
'@types/node': 18.11.18
dev: true
/@types/html-to-text/9.0.0:
resolution: {integrity: sha512-FnF3p2FJZ1kJT/0C/lmBzw7HSlH3RhtACVYyrwUsJoCmFNuiLpusWT2FWWB7P9A48CaYpvD6Q2fprn7sZeffpw==}
dev: true
/@types/json-schema/7.0.11:
resolution: {integrity: sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==}
dev: true
@ -2599,6 +2614,11 @@ packages:
/deep-is/0.1.4:
resolution: {integrity: sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==}
/deepmerge/4.2.2:
resolution: {integrity: sha512-FJ3UgI4gIl+PHZm53knsuSFpE+nESMr7M4v9QcgB7S63Kj/6WqMiFQJpBBYz1Pt+66bZpP3Q7Lye0Oo9MPKEdg==}
engines: {node: '>=0.10.0'}
dev: false
/define-lazy-prop/2.0.0:
resolution: {integrity: sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==}
engines: {node: '>=8'}
@ -2677,7 +2697,6 @@ packages:
domelementtype: 2.3.0
domhandler: 5.0.3
entities: 4.4.0
dev: true
/domelementtype/2.3.0:
resolution: {integrity: sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==}
@ -2701,7 +2720,6 @@ packages:
engines: {node: '>= 4'}
dependencies:
domelementtype: 2.3.0
dev: true
/domutils/2.8.0:
resolution: {integrity: sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==}
@ -2717,7 +2735,6 @@ packages:
dom-serializer: 2.0.0
domelementtype: 2.3.0
domhandler: 5.0.3
dev: true
/duplexer/0.1.2:
resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==}
@ -4002,6 +4019,17 @@ packages:
uglify-js: 3.17.3
dev: false
/html-to-text/9.0.3:
resolution: {integrity: sha512-hxDF1kVCF2uw4VUJ3vr2doc91pXf2D5ngKcNviSitNkhP9OMOaJkDrFIFL6RMvko7NisWTEiqGpQ9LAxcVok1w==}
engines: {node: '>=14'}
dependencies:
'@selderee/plugin-htmlparser2': 0.10.0
deepmerge: 4.2.2
dom-serializer: 2.0.0
htmlparser2: 8.0.1
selderee: 0.10.0
dev: false
/html5parser/2.0.2:
resolution: {integrity: sha512-L0y+IdTVxHsovmye8MBtFgBvWZnq1C9WnI/SmJszxoQjmUH1psX2uzDk21O5k5et6udxdGjwxkbmT9eVRoG05w==}
dependencies:
@ -4015,7 +4043,6 @@ packages:
domhandler: 5.0.3
domutils: 3.0.1
entities: 4.4.0
dev: true
/http-deceiver/1.2.7:
resolution: {integrity: sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==}
@ -4544,6 +4571,10 @@ packages:
/kolorist/1.6.0:
resolution: {integrity: sha512-dLkz37Ab97HWMx9KTes3Tbi3D1ln9fCAy2zr2YVExJasDRPGRaKcoE4fycWNtnCAJfjFqe0cnY+f8KT2JePEXQ==}
/leac/0.6.0:
resolution: {integrity: sha512-y+SqErxb8h7nE/fiEX07jsbuhrpO9lL8eca7/Y1nuWV2moNlXhyd59iDGcRf6moVyDMbmTNzL40SUyrFU/yDpg==}
dev: false
/levn/0.3.0:
resolution: {integrity: sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==}
engines: {node: '>= 0.8.0'}
@ -5237,6 +5268,13 @@ packages:
entities: 4.4.0
dev: false
/parseley/0.11.0:
resolution: {integrity: sha512-VfcwXlBWgTF+unPcr7yu3HSSA6QUdDaDnrHcytVfj5Z8azAyKBDrYnSIfeSxlrEayndNcLmrXzg+Vxbo6DWRXQ==}
dependencies:
leac: 0.6.0
peberminta: 0.8.0
dev: false
/parseurl/1.3.3:
resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==}
engines: {node: '>= 0.8'}
@ -5305,6 +5343,10 @@ packages:
through: 2.3.8
dev: true
/peberminta/0.8.0:
resolution: {integrity: sha512-YYEs+eauIjDH5nUEGi18EohWE0nV2QbGTqmxQcqgZ/0g+laPCQmuIqq7EBLVi9uim9zMgfJv0QBZEnQ3uHw/Tw==}
dev: false
/perfect-debounce/0.1.3:
resolution: {integrity: sha512-NOT9AcKiDGpnV/HBhI22Str++XWcErO/bALvHCuhv33owZW/CjH8KAFLZDCmu3727sihe0wTxpDhyGc6M8qacQ==}
dev: false
@ -5702,6 +5744,12 @@ packages:
extend-shallow: 2.0.1
kind-of: 6.0.3
/selderee/0.10.0:
resolution: {integrity: sha512-DEL/RW/f4qLw/NrVg97xKaEBC8IpzIG2fvxnzCp3Z4yk4jQ3MXom+Imav9wApjxX2dfS3eW7x0DXafJr85i39A==}
dependencies:
parseley: 0.11.0
dev: false
/select-hose/2.0.0:
resolution: {integrity: sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==}
dev: true

View File

@ -1,7 +1,7 @@
import { resolve } from 'path'
import fs from 'fs-extra'
import type { DefaultThemeConfig, SiteConfig } from 'valaxy/types'
import type { ResolvedValaxyOptions, ValaxyConfig } from 'valaxy/node'
import type { DefaultThemeConfig } from 'valaxy/types'
import type { ResolvedValaxyOptions, ValaxyNodeConfig } from 'valaxy/node'
import { getIndexHtml } from '../packages/valaxy/node'
const clientRoot = resolve(__dirname, '../packages/valaxy/client')
@ -11,8 +11,8 @@ const userRoot = resolve(__dirname, 'fixtures/user')
describe('utils', () => {
it('merge index.html', async () => {
const config = {
mode: 'light',
} as ValaxyConfig<DefaultThemeConfig>
siteConfig: { mode: 'light' },
} as ValaxyNodeConfig<DefaultThemeConfig>
const templatePath = resolve(clientRoot, 'template.html')
const indexPath = resolve(clientRoot, 'index.html')
@ -35,8 +35,8 @@ describe('utils', () => {
it('mode light', async () => {
const config = {
mode: 'auto',
} as ValaxyConfig<SiteConfig>
siteConfig: { mode: 'auto' },
} as ValaxyNodeConfig<DefaultThemeConfig>
const indexHtml = await getIndexHtml({ clientRoot, themeRoot, userRoot, config } as ResolvedValaxyOptions)
const head = indexHtml.match(/<head>([\s\S]*?)<\/head>/im)?.[1]