docs: add how to add default frontmatter

This commit is contained in:
YunYouJun 2023-10-28 23:28:18 +08:00
parent 92645ba3d2
commit e717b89ee7
23 changed files with 731 additions and 127 deletions

View File

@ -0,0 +1,8 @@
---
title: Time Warning Test
date: 2020-10-01
categories:
- test
---
This is a test page for time warning.

View File

@ -92,3 +92,7 @@ features:
tooltip:
edit_this_page: Edit this page on GitHub
toc:
base-config: Base Config
extend-config: Extend Config

View File

@ -92,3 +92,7 @@ features:
tooltip:
edit_this_page: 在 GitHub 上编辑此页
toc:
base-config: 基础配置
extend-config: 扩展配置

View File

@ -16,9 +16,9 @@ pnpm add [valaxy-addon-package1] [valaxy-addon-package2]
```ts
// valaxy.config.ts
import { defineConfig } from 'valaxy'
import { defineValaxyConfig } from 'valaxy'
export default defineConfig({
export default defineValaxyConfig({
addons: [
'valaxy-addon-package1',
// pass addon options
@ -26,3 +26,25 @@ export default defineConfig({
]
})
```
### Addon With Options
譬如开启 Waline 评论:
```ts
import { defineValaxyConfig } from 'valaxy'
import { addonWaline } from 'valaxy-addon-waline'
export default defineValaxyConfig({
// 启用评论
comment: {
enable: true
},
// 设置 valaxy-addon-waline 配置项
addons: [
addonWaline({
serverURL: 'https://your-waline-url',
}),
],
})
```

View File

@ -0,0 +1,103 @@
---
title: Extend Config
title_zh-CN: 扩展配置
categories:
- config
---
> [packages/valaxy/node/type.ts](https://github.com/YunYouJun/valaxy/blob/main/packages/valaxy/node/types.ts)
### Unocss Presets
```ts
// types
export interface ValaxyExtendConfig {
/**
* Markdown Feature
*/
features: {
/**
* enable katex for global
*/
katex: boolean
}
vite?: ViteUserConfig
vue?: Parameters<typeof Vue>[0]
components?: Parameters<typeof Components>[0]
unocss?: UnoCSSConfig
/**
* unocss presets
*/
unocssPresets?: {
uno?: Parameters<typeof presetUno>[0]
attributify?: Parameters<typeof presetAttributify>[0]
icons?: Parameters<typeof presetIcons>[0]
typography?: Parameters<typeof presetTypography>[0]
}
pages?: Parameters<typeof Pages>[0]
/**
* for markdown
*/
markdown?: MarkdownOptions
extendMd?: (ctx: {
route: {
meta: { frontmatter: Record<string, any>; layout?: string } & object
path: string
component: string
}
data: Readonly<Record<string, any>>
content: string
excerpt?: string
path: string
}) => void
addons?: ValaxyAddons
}
```
::: zh-CN
所以,你可以像这样使用:
:::
::: en
So you can use it like this:
:::
```ts
// valaxy.config.ts
import { defineValaxyConfig } from 'valaxy'
import type { ThemeConfig } from 'valaxy-theme-yun'
import { addonComponents } from 'valaxy-addon-components'
import Inspect from 'vite-plugin-inspect'
const safelist = [
'i-ri-home-line',
]
export default defineValaxyConfig<ThemeConfig>({
// site config see site.config.ts or write in siteConfig
siteConfig: {},
theme: 'yun',
themeConfig: {
banner: {
enable: true,
title: '云游君的小站',
},
},
vite: {
// https://github.com/antfu/vite-plugin-inspect
// Visit http://localhost:3333/__inspect/ to see the inspector
plugins: [Inspect()],
},
unocss: {
safelist,
},
addons: [
addonComponents()
],
})
```

View File

@ -4,7 +4,6 @@ title_zh-CN: 基础配置
categories:
- config
end: false
top: 10
---
## 配置说明 {lang="zh-CN"}
@ -14,12 +13,12 @@ top: 10
::: zh-CN
为了便于配置Valaxy 将配置分为了三种。
`valaxy.config.ts` 是配置的主入口。
`valaxy.config.ts` 是配置的主入口,它包含了一下配置
- `siteConfig`: 站点**信息**配置,这部分内容面向站点展示且在任何主题也是通用的格式
- `themeConfig`: 主题配置,这部分内容仅在特定主题生效
- `runtimeConfig`: 运行时的配置(由 Valaxy 自动生成),用户无需配置
- 其他 Valaxy 通用配置内容(如需要在 Node 端处理的配置)
- 其他 Valaxy 通用配置内容(如需要在 Node 端处理的配置 `unocss`/`addons`
譬如:
:::
@ -188,6 +187,28 @@ export default defineSiteConfig({
:::
### Default Frontmatter
为所有文章设置默认的 Frontmatter。
譬如:
> 设置 `time_warning: false`,则所有文章都不会显示阅读时间警告。
```ts {8-10}
// site.config.ts
import { defineSiteConfig } from 'valaxy'
export default defineSiteConfig({
/**
* 默认 Frontmatter
*/
frontmatter: {
time_warning: false,
}
})
```
### 社交图标 {lang="zh-CN"}
### Social Icons {lang="en"}
@ -400,104 +421,3 @@ export default defineSiteConfig({
::: en
Please refer to [Using Themes](/themes/use) and the theme you are using to configure it.
:::
## Valaxy 扩展配置 {lang="zh-CN"}
## Valaxy Extended Configuration {lang="zh-CN"}
> [packages/valaxy/node/type.ts](https://github.com/YunYouJun/valaxy/blob/main/packages/valaxy/node/types.ts)
### Unocss Presets
```ts
// types
export interface ValaxyExtendConfig {
/**
* Markdown Feature
*/
features: {
/**
* enable katex for global
*/
katex: boolean
}
vite?: ViteUserConfig
vue?: Parameters<typeof Vue>[0]
components?: Parameters<typeof Components>[0]
unocss?: UnoCSSConfig
/**
* unocss presets
*/
unocssPresets?: {
uno?: Parameters<typeof presetUno>[0]
attributify?: Parameters<typeof presetAttributify>[0]
icons?: Parameters<typeof presetIcons>[0]
typography?: Parameters<typeof presetTypography>[0]
}
pages?: Parameters<typeof Pages>[0]
/**
* for markdown
*/
markdown?: MarkdownOptions
extendMd?: (ctx: {
route: {
meta: { frontmatter: Record<string, any>; layout?: string } & object
path: string
component: string
}
data: Readonly<Record<string, any>>
content: string
excerpt?: string
path: string
}) => void
addons?: ValaxyAddons
}
```
::: zh-CN
所以,你可以像这样使用:
:::
::: en
So you can use it like this:
:::
```ts
// valaxy.config.ts
import { defineValaxyConfig } from 'valaxy'
import type { ThemeConfig } from 'valaxy-theme-yun'
import { addonComponents } from 'valaxy-addon-components'
import Inspect from 'vite-plugin-inspect'
const safelist = [
'i-ri-home-line',
]
export default defineValaxyConfig<ThemeConfig>({
// site config see site.config.ts or write in siteConfig
siteConfig: {},
theme: 'yun',
themeConfig: {
banner: {
enable: true,
title: '云游君的小站',
},
},
vite: {
// https://github.com/antfu/vite-plugin-inspect
// Visit http://localhost:3333/__inspect/ to see the inspector
plugins: [Inspect()],
},
unocss: {
safelist,
},
addons: [
addonComponents()
],
})
```

View File

@ -216,14 +216,14 @@ npm run dev
::: zh-CN
博客创建完毕,查看本地 `http://localhost:4859/`,玩的开心!
- Valaxy 博客通用的配置可参见 [配置](/guide/config) 与 [自定义扩展](/guide/custom/extend)。
- Valaxy 博客通用的配置可参见 [配置](/guide/config/) 与 [自定义扩展](/guide/custom/extend)。
- Valaxy 主题独有配置请参见对应主题文档。Valaxy Theme Yun 主题文档编写中……)
:::
::: en
See `http://localhost:4859/`, have fun!
- See [Config](/guide/config) and [Custom Extensions](/guide/custom/extend) for the general configuration for Valaxy blogs.
- See [Config](/guide/config/) and [Custom Extensions](/guide/custom/extend) for the general configuration for Valaxy blogs.
- For configuring Valaxy themes, please see the documentation for the corresponding themes. (Docs for Valaxy Theme Yun is still work in progress)
:::

View File

@ -44,14 +44,14 @@ The relationship between Hexo blog directory and Valaxy blog directory is shown
### Migrate Configurations {lang="en"}
::: zh-CN
参考 [Valaxy 配置文档](/guide/config) 将 Hexo `_config.yml` 配置文件中的内容,迁移至 `valaxy.config.ts` 文件中。
参考 [Valaxy 配置文档](/guide/config/) 将 Hexo `_config.yml` 配置文件中的内容,迁移至 `valaxy.config.ts` 文件中。
> 配置示例:[demo/yun/valaxy.config.ts](https://github.com/YunYouJun/valaxy/blob/main/demo/yun/valaxy.config.ts)、[yunyoujun.github.io/valaxy.config.ts](https://github.com/YunYouJun/yunyoujun.github.io/blob/valaxy/valaxy.config.ts)
> `valaxy.config.ts` 提供了完备的类型提示,这意味着你在 VSCode 中可以直接鼠标悬浮查看各参数注释。
:::
::: en
Refer to [Valaxy Config](/guide/config) to migrate configurations from Hexo's `_config.yml` to Valaxy's `valaxy.config.ts`.
Refer to [Valaxy Config](/guide/config/) to migrate configurations from Hexo's `_config.yml` to Valaxy's `valaxy.config.ts`.
> Examples of configuration: [demo/yun/valaxy.config.ts](https://github.com/YunYouJun/valaxy/blob/main/demo/yun/valaxy.config.ts), [yunyoujun.github.io/valaxy.config.ts](https://github.com/YunYouJun/yunyoujun.github.io/blob/valaxy/valaxy.config.ts).
> `valaxy.config.ts` provides a complete type prompt, which means that you can hover on configuration fields directly to view the comments in VSCode.

View File

@ -15,7 +15,7 @@ top: 10
- 将你的文章Markdown 文件)复制至 Valaxy `pages/posts` 目录下。
- 将你的自定义页面(非文章的 Markdown/HTML 文件)复制至 Valaxy `pages` 目录下。
- 将你的静态资源(图片等)复制至 Valaxy `public` 目录下。
- 参考 [配置](/guide/config) 配置你的配置文件 `valaxy.config.ts`/`site.config.ts`。
- 参考 [配置](/guide/config/) 配置你的配置文件 `valaxy.config.ts`/`site.config.ts`。
## 常见问题 {lang="zh-CN"}

View File

@ -37,7 +37,32 @@ export default defineValaxyConfig<PressTheme.Config>({
theme: 'press',
themeConfig: {
logo: '/favicon.svg',
sidebar: ['getting-started', 'guide', 'config', 'migration', 'built-ins', 'third', 'custom', 'examples', 'theme', 'addon', 'dev'],
sidebar: [
'getting-started',
'guide',
{
text: 'category.config',
collapsed: false,
items: [
{
text: 'toc.base-config',
link: '/guide/config/',
},
{
text: 'toc.extend-config',
link: '/guide/config/extend',
},
],
},
'migration',
'built-ins',
'third',
'custom',
'examples',
'theme',
'addon',
'dev',
],
socialLinks: [
{ icon: 'i-ri-github-line', link: 'https://github.com/YunYouJun/valaxy' },
],

View File

@ -32,7 +32,8 @@ function getTitle(post: Post | any) {
v-if="category.total"
p="t-2"
w="full" border="t t-$pr-c-divider-light"
class="category-list-item inline-flex items-center justify-between"
class="press-sidebar-item category-list-item inline-flex items-center justify-between"
text-14px
tabindex="0"
>
<span class="category-name" font="bold" m="l-1" @click="displayCategory ? displayCategory(category.name) : null">
@ -41,7 +42,9 @@ function getTitle(post: Post | any) {
</span>
<button
tabindex="0" role="button" aria-label="toggle section"
class="folder-action inline-flex cursor-pointer" opacity="50" @click="collapsable = !collapsable"
class="caret folder-action inline-flex cursor-pointer"
text-base
@click="collapsable = !collapsable"
>
<div v-if="collapsable" i-ri-folder-add-line />
<div v-else i-ri-folder-reduce-line />

View File

@ -1,6 +1,6 @@
<script lang="ts" setup>
import { computed } from 'vue'
import { removeItemFromCategory, useCategory, usePageList, useSidebar } from 'valaxy'
import { removeItemFromCategory, useCategories, usePageList, useSidebar } from 'valaxy'
import { useThemeConfig } from '../composables'
defineProps<{
@ -10,8 +10,9 @@ defineProps<{
const pages = usePageList()
const themeConfig = useThemeConfig()
const sidebar = computed(() => themeConfig.value.sidebar)
const categories = computed(() => {
const cs = useCategory('', pages.value)
const cs = useCategories('', pages.value)
const cList = cs.value
removeItemFromCategory(cList, 'Uncategorized')
@ -25,6 +26,10 @@ const categories = computed(() => {
return cList
})
function getCategoryByName(name: string) {
return categories.value.children.find(c => c.name === name)
}
const { hasSidebar } = useSidebar()
</script>
@ -35,7 +40,22 @@ const { hasSidebar } = useSidebar()
@click.stop
>
<div text="left" m="2">
<PressCategories :categories="categories.children" :collapsable="false" />
<ul v-for="item in sidebar" :key="item" class="category-list">
<template v-if="typeof item === 'string'">
<PressCategory
v-if="getCategoryByName(item)"
:category="getCategoryByName(item)"
:collapsable="false"
/>
</template>
<PressSidebarItem
v-else
p="t-2"
border="t t-$pr-c-divider-light"
:item="item"
:depth="0"
/>
</ul>
</div>
</aside>
</template>
@ -85,4 +105,54 @@ const { hasSidebar } = useSidebar()
top: 0;
}
}
.category-list {
&:first-child {
.category-list-item {
border-top: 0;
}
}
}
.post-list-item {
a {
color: var(--va-c-text-light);
transition: all 0.2s;
&:hover {
color: var(--va-c-primary);
}
&.active {
color: var(--va-c-primary);
}
}
}
.press-sidebar-item {
.caret {
display: flex;
justify-content: center;
align-items: center;
margin-right: -7px;
width: 32px;
height: 32px;
color: var(--vp-c-text-3);
cursor: pointer;
transition: color 0.25s;
flex-shrink: 0;
}
&:hover .caret {
color: var(--vp-c-text-2);
}
&:hover .caret:hover {
color: var(--vp-c-text-1);
}
}
.category-list+.category-list {
margin-top: 1rem;
}
</style>

View File

@ -0,0 +1,218 @@
<script setup lang="ts">
import { computed } from 'vue'
import type { DefaultTheme } from 'vitepress/theme'
import { useI18n } from 'vue-i18n'
import { useSidebarControl } from '../composables/sidebar'
const props = defineProps<{
item: DefaultTheme.SidebarItem
depth: number
}>()
const {
collapsed,
collapsible,
isLink,
isActiveLink,
hasActiveLink,
hasChildren,
toggle,
} = useSidebarControl(computed(() => props.item))
const sectionTag = computed(() => (hasChildren.value ? 'section' : `div`))
const linkTag = computed(() => (isLink.value ? 'a' : 'div'))
const textTag = computed(() => {
return !hasChildren.value
? 'p'
: props.depth + 2 === 7
? 'p'
: `h${props.depth + 2}`
})
const itemRole = computed(() => (isLink.value ? undefined : 'button'))
const classes = computed(() => [
[`level-${props.depth}`],
{ collapsible: collapsible.value },
{ collapsed: collapsed.value },
{ 'is-link': isLink.value },
{ 'is-active': isActiveLink.value },
{ 'has-active': hasActiveLink.value },
])
function onItemInteraction(e: MouseEvent | Event) {
if ('key' in e && e.key !== 'Enter')
return
!props.item.link && toggle()
}
function onCaretClick() {
props.item.link && toggle()
}
const { t } = useI18n()
const htmlText = computed(() => t(props.item.text || ''))
</script>
<template>
<component
:is="sectionTag"
class="VPSidebarItem" :class="classes"
>
<div
v-if="item.text"
class="press-sidebar-item item"
:role="itemRole"
:tabindex="item.items && 0"
v-on="
item.items
? { click: onItemInteraction, keydown: onItemInteraction }
: {}
"
>
<div class="indicator" />
<AppLink
v-if="item.link"
:tag="linkTag"
class="link"
:href="item.link"
:rel="item.rel"
:target="item.target"
>
<!-- eslint-disable-next-line vue/no-v-text-v-html-on-component -->
<component :is="textTag" class="text ml-1" v-html="htmlText" />
</AppLink>
<!-- eslint-disable-next-line vue/no-v-text-v-html-on-component -->
<component :is="textTag" v-else class="text ml-1" v-html="htmlText" />
<button
v-if="item.collapsed != null"
tabindex="0" role="button" aria-label="toggle section"
class="caret folder-action inline-flex cursor-pointer"
@click="onCaretClick" @keydown.enter="onCaretClick"
>
<div v-if="collapsed" i-ri-folder-add-line />
<div v-else i-ri-folder-reduce-line />
</button>
</div>
<div v-if="item.items && item.items.length" class="items">
<template v-if="depth < 5">
<PressSidebarItem
v-for="i in item.items"
:key="i.text"
:item="i"
:depth="depth + 1"
/>
</template>
</div>
</component>
</template>
<style scoped>
.item {
position: relative;
display: flex;
width: 100%;
}
.VPSidebarItem.collapsible > .item {
cursor: pointer;
}
.indicator {
position: absolute;
top: 6px;
bottom: 6px;
left: -17px;
width: 2px;
border-radius: 2px;
transition: background-color 0.25s;
}
.VPSidebarItem.level-2.is-active > .item > .indicator,
.VPSidebarItem.level-3.is-active > .item > .indicator,
.VPSidebarItem.level-4.is-active > .item > .indicator,
.VPSidebarItem.level-5.is-active > .item > .indicator {
background-color: var(--vp-c-brand-1);
}
.link {
display: flex;
align-items: center;
flex-grow: 1;
}
.text {
flex-grow: 1;
padding: 4px 0;
line-height: 24px;
font-size: 14px;
transition: color 0.25s;
}
.VPSidebarItem.level-0 .text {
font-weight: 700;
color: var(--vp-c-text-1);
}
.VPSidebarItem.level-1 .text,
.VPSidebarItem.level-2 .text,
.VPSidebarItem.level-3 .text,
.VPSidebarItem.level-4 .text,
.VPSidebarItem.level-5 .text {
font-weight: 500;
color: var(--vp-c-text-2);
}
.VPSidebarItem.level-0.is-link > .item > .link:hover .text,
.VPSidebarItem.level-1.is-link > .item > .link:hover .text,
.VPSidebarItem.level-2.is-link > .item > .link:hover .text,
.VPSidebarItem.level-3.is-link > .item > .link:hover .text,
.VPSidebarItem.level-4.is-link > .item > .link:hover .text,
.VPSidebarItem.level-5.is-link > .item > .link:hover .text {
color: var(--vp-c-brand-1);
}
.VPSidebarItem.level-0.has-active > .item > .text,
.VPSidebarItem.level-1.has-active > .item > .text,
.VPSidebarItem.level-2.has-active > .item > .text,
.VPSidebarItem.level-3.has-active > .item > .text,
.VPSidebarItem.level-4.has-active > .item > .text,
.VPSidebarItem.level-5.has-active > .item > .text,
.VPSidebarItem.level-0.has-active > .item > .link > .text,
.VPSidebarItem.level-1.has-active > .item > .link > .text,
.VPSidebarItem.level-2.has-active > .item > .link > .text,
.VPSidebarItem.level-3.has-active > .item > .link > .text,
.VPSidebarItem.level-4.has-active > .item > .link > .text,
.VPSidebarItem.level-5.has-active > .item > .link > .text {
color: var(--vp-c-text-1);
}
.VPSidebarItem.level-0.is-active > .item .link > .text,
.VPSidebarItem.level-1.is-active > .item .link > .text,
.VPSidebarItem.level-2.is-active > .item .link > .text,
.VPSidebarItem.level-3.is-active > .item .link > .text,
.VPSidebarItem.level-4.is-active > .item .link > .text,
.VPSidebarItem.level-5.is-active > .item .link > .text {
color: var(--vp-c-brand-1);
}
.VPSidebarItem.level-1 .items,
.VPSidebarItem.level-2 .items,
.VPSidebarItem.level-3 .items,
.VPSidebarItem.level-4 .items,
.VPSidebarItem.level-5 .items {
border-left: 1px solid var(--vp-c-divider);
padding-left: 16px;
}
.VPSidebarItem.collapsed .items {
display: none;
}
</style>

View File

@ -0,0 +1,172 @@
import { isClient } from '@vueuse/core'
import type { DefaultTheme } from 'vitepress/theme'
import {
type ComputedRef,
type Ref,
computed,
onMounted,
onUnmounted,
ref,
watch,
watchEffect,
watchPostEffect,
} from 'vue'
import { useRoute } from 'vue-router'
import type { PressTheme } from 'valaxy-theme-press'
export interface SidebarControl {
collapsed: Ref<boolean>
collapsible: ComputedRef<boolean>
isLink: ComputedRef<boolean>
isActiveLink: Ref<boolean>
hasActiveLink: ComputedRef<boolean>
hasChildren: ComputedRef<boolean>
toggle(): void
}
export const HASH_RE = /#.*$/
export const EXT_RE = /(index)?\.(md|html)$/
export function normalize(path: string): string {
return decodeURI(path).replace(HASH_RE, '').replace(EXT_RE, '')
}
export function isActive(
currentPath: string,
matchPath?: string,
asRegex: boolean = false,
): boolean {
if (matchPath === undefined)
return false
currentPath = normalize(`/${currentPath}`)
if (asRegex)
return new RegExp(matchPath).test(currentPath)
if (normalize(matchPath) !== currentPath)
return false
const hashMatch = matchPath.match(HASH_RE)
if (hashMatch)
return (isClient ? location.hash : '') === hashMatch[0]
return true
}
/**
* a11y: cache the element that opened the Sidebar (the menu button) then
* focus that button again when Menu is closed with Escape key.
*/
export function useCloseSidebarOnEscape(
isOpen: Ref<boolean>,
close: () => void,
) {
let triggerElement: HTMLButtonElement | undefined
watchEffect(() => {
triggerElement = isOpen.value
? (document.activeElement as HTMLButtonElement)
: undefined
})
onMounted(() => {
window.addEventListener('keyup', onEscape)
})
onUnmounted(() => {
window.removeEventListener('keyup', onEscape)
})
function onEscape(e: KeyboardEvent) {
if (e.key === 'Escape' && isOpen.value) {
close()
triggerElement?.focus()
}
}
}
const hashRef = ref(isClient ? location.hash : '')
if (isClient) {
window.addEventListener('hashchange', () => {
hashRef.value = location.hash
})
}
/**
* Check if the given sidebar item contains any active link.
*/
export function containsActiveLink(
path: string,
items: PressTheme.SidebarItem | PressTheme.SidebarItem[],
): boolean {
if (Array.isArray(items))
return items.some(item => containsActiveLink(path, item))
return isActive(path, items.link)
? true
: items.items
? containsActiveLink(path, items.items)
: false
}
export function useSidebarControl(
item: ComputedRef<DefaultTheme.SidebarItem>,
): SidebarControl {
const collapsed = ref(false)
const collapsible = computed(() => {
return item.value.collapsed != null
})
const isLink = computed(() => {
return !!item.value.link
})
const isActiveLink = ref(false)
const route = useRoute()
const updateIsActiveLink = () => {
isActiveLink.value = route.path === item.value.link
}
watch([route, item, hashRef], updateIsActiveLink)
onMounted(updateIsActiveLink)
const hasActiveLink = computed(() => {
if (isActiveLink.value)
return true
return item.value.items
? containsActiveLink(route.path, item.value.items)
: false
})
const hasChildren = computed(() => {
return !!(item.value.items && item.value.items.length)
})
watchEffect(() => {
collapsed.value = !!(collapsible.value && item.value.collapsed)
})
watchPostEffect(() => {
;(isActiveLink.value || hasActiveLink.value) && (collapsed.value = false)
})
function toggle() {
if (collapsible.value)
collapsed.value = !collapsed.value
}
return {
collapsed,
collapsible,
isLink,
isActiveLink,
hasActiveLink,
hasChildren,
toggle,
}
}

View File

@ -30,6 +30,49 @@ export namespace PressTheme {
text?: string
}
export type Sidebar = SidebarItem[] | SidebarMulti
export interface SidebarMulti {
[path: string]: SidebarItem[] | { items: SidebarItem[]; base: string }
}
export interface SidebarItem {
/**
* The text label of the item.
*/
text?: string
/**
* The link of the item.
*/
link?: string
/**
* The children of the item.
*/
items?: SidebarItem[]
/**
* If not specified, group is not collapsible.
*
* If `true`, group is collapsible and collapsed by default
*
* If `false`, group is collapsible but expanded by default
*/
collapsed?: boolean
/**
* Base path for the children items.
*/
base?: string
/**
* Customize text that appears on the footer of previous/next page.
*/
docFooterText?: string
rel?: string
target?: string
}
export interface Config {
logo: string
@ -41,8 +84,8 @@ export namespace PressTheme {
primary: string
}
nav: Array<NavItem>
sidebar: string[]
nav: NavItem[]
sidebar?: Sidebar
editLink: EditLink

View File

@ -16,19 +16,20 @@ dayjs.extend(relativeTime)
const { t } = useI18n()
/**
* when the post is updated more than 30 days ago, show a warning
* default 30 days, you can set `time_warning` in frontmatter to change it
* when the post is updated more than 180 days ago, show a warning
* default 180 days, you can set `time_warning` in frontmatter to change it
*/
const time_warning = computed(() => {
const diff = dayjs().valueOf() - dayjs(props.frontmatter.updated).valueOf()
const diff = dayjs().valueOf() - dayjs(props.frontmatter.updated || props.frontmatter.date).valueOf()
if (typeof props.frontmatter.time_warning === 'number')
return diff > props.frontmatter.time_warning
else
return props.frontmatter.time_warning || diff > 30 * 24 * 60 * 60 * 1000
return props.frontmatter.time_warning
})
</script>
<template>
{{ frontmatter }}
<blockquote v-if="time_warning" op="80">
{{ t('post.time_warning', { ago: dayjs(frontmatter.updated).fromNow() }) }}
</blockquote>

View File

@ -9,5 +9,5 @@ const addon = addonWaline.useAddonWaline()
</script>
<template>
<WalineClient w="full" :options="addon.options" />
<WalineClient w="full" :options="addon.options || {}" />
</template>

View File

@ -10,4 +10,4 @@
如「作者头像」、「站点名称」等属于通用信息,请在 `site.config.ts` 中配置。
可参见 [Site Config | Valaxy Docs](https://valaxy.site/guide/config#site-config)。
可参见 [Site Config | Valaxy Docs](https://valaxy.site/guide/config/#site-config)。

View File

@ -77,6 +77,10 @@ export const defaultSiteConfig: SiteConfig = {
enable: false,
},
frontmatter: {
time_warning: 180 * 24 * 60 * 60 * 1000,
},
cdn: {
prefix: 'https://unpkg.com/',
},

View File

@ -52,7 +52,7 @@ export function createPagesPlugin(options: ResolvedValaxyOptions) {
) {
let path: string = route.component
const defaultFrontmatter = {}
const defaultFrontmatter = valaxyConfig.siteConfig.frontmatter || {}
if (!route.meta) {
route.meta = {
frontmatter: defaultFrontmatter,

View File

@ -30,6 +30,7 @@
"require": "./dist/node/index.cjs"
},
"./types": "./dist/types/index.d.ts",
"./default-theme": "./types/default-theme.d.ts",
"./*": "./*"
},
"main": "dist/node/index.cjs",

View File

@ -3,6 +3,7 @@ import type { FuseOptions } from '@vueuse/integrations/useFuse'
import type { ILazyLoadOptions } from 'vanilla-lazyload'
import type * as DefaultTheme from 'valaxy/default-theme'
import type { ValaxyAddon } from '../types'
import type { PostFrontMatter } from './posts'
import type { FuseListItem } from './node'
export interface SocialLink {
@ -157,6 +158,11 @@ export interface SiteConfig {
}
}
/**
* set post default frontmatter
*/
frontmatter: Partial<PostFrontMatter>
/**
* comment: waline/...
*/