first working version

pull/4660/head
Yuxuan Zhang 6 months ago
parent db58af5c66
commit c3c0d71d1d
No known key found for this signature in database
GPG Key ID: 6910B04F3351EF7D

@ -1,7 +1,6 @@
import { defineConfig } from 'vitepress'
import { shared } from './shared'
import { en } from './en'
import { zh } from './zh'
import { pt } from './pt'
import { ru } from './ru'
import { es } from './es'
@ -12,7 +11,7 @@ export default defineConfig({
...shared,
locales: {
root: { label: 'English', ...en },
zh: { label: '简体中文', ...zh },
zh: { label: '简体中文' },
pt: { label: 'Português', ...pt },
ru: { label: 'Русский', ...ru },
es: { label: 'Español', ...es },

@ -9,7 +9,6 @@ import { search as faSearch } from './fa'
import { search as koSearch } from './ko'
import { search as ptSearch } from './pt'
import { search as ruSearch } from './ru'
import { search as zhSearch } from './zh'
export const shared = defineConfig({
title: 'VitePress',
@ -99,7 +98,6 @@ export const shared = defineConfig({
apiKey: '52f578a92b88ad6abde815aae2b0ad7c',
indexName: 'vitepress',
locales: {
...zhSearch,
...ptSearch,
...ruSearch,
...esSearch,

@ -1,16 +1,14 @@
import { createRequire } from 'module'
import { defineConfig, type DefaultTheme } from 'vitepress'
import { type DefaultTheme, type UserConfig } from 'vitepress'
import vitepress from 'vitepress/package.json'
import type { DocSearchProps } from '../../types/docsearch'
const require = createRequire(import.meta.url)
const pkg = require('vitepress/package.json')
export const zh = defineConfig({
export default {
lang: 'zh-Hans',
description: '由 Vite 和 Vue 驱动的静态站点生成器',
themeConfig: {
nav: nav(),
search: { options: searchOptions() } as DefaultTheme.Config['search'],
sidebar: {
'/zh/guide/': { base: '/zh/guide/', items: sidebarGuide() },
'/zh/reference/': { base: '/zh/reference/', items: sidebarReference() }
@ -43,6 +41,13 @@ export const zh = defineConfig({
}
},
notFound: {
title: '页面未找到',
quote: '若你不改变航向,始终凝望远方,你终将抵达前行的彼岸。',
linkLabel: '返回首页',
linkText: '返回首页'
},
langMenuLabel: '多语言',
returnToTopLabel: '回到顶部',
sidebarMenuLabel: '菜单',
@ -51,7 +56,7 @@ export const zh = defineConfig({
darkModeSwitchTitle: '切换到深色模式',
skipToContentLabel: '跳转到内容'
}
})
} as UserConfig<DefaultTheme.Config>
function nav(): DefaultTheme.NavItem[] {
return [
@ -66,7 +71,7 @@ function nav(): DefaultTheme.NavItem[] {
activeMatch: '/zh/reference/'
},
{
text: pkg.version,
text: vitepress.version,
items: [
{
text: '更新日志',
@ -160,8 +165,8 @@ function sidebarReference(): DefaultTheme.SidebarItem[] {
]
}
export const search: DefaultTheme.AlgoliaSearchOptions['locales'] = {
zh: {
function searchOptions(): Partial<DocSearchProps> {
return {
placeholder: '搜索文档',
translations: {
button: {

@ -19,6 +19,7 @@ import {
type SiteData
} from '../shared'
import type { Route } from './router'
import { dirname, stackView } from './utils'
export const dataSymbol: InjectionKey<VitePressData> = Symbol()
@ -69,11 +70,46 @@ if (import.meta.hot) {
})
}
// hierarchical config pre-loading
const extraConfig: Record<string, SiteData> = Object.fromEntries(
Object.entries(
import.meta.glob('/**/config.([cm]?js|ts|json)', {
eager: true
})
).map(([path, module]) => [
dirname(path),
{ __module__: path, ...((module as any)?.default ?? module) }
])
)
function getExtraConfigs(path: string): SiteData[] {
if (!path.startsWith('/')) path = `/${path}`
const configs: SiteData[] = []
const segments = path.split('/').slice(1, -1)
while (segments.length) {
const key = `/${segments.join('/')}/`
if (key in extraConfig) configs.push(extraConfig[key])
segments.pop()
}
// debug info
const summaryTitle = `Extra Configs for ${path}:`
const summary = configs.map((c, i) => ` ${i + 1}. ${(c as any).__module__}`)
summary.push(` ${summary.length + 1}. .vitepress/config (root)`)
console.info(
[summaryTitle, ''.padEnd(summaryTitle.length, '='), ...summary].join('\n')
)
return configs
}
// per-app data
export function initData(route: Route): VitePressData {
const site = computed(() =>
resolveSiteDataByRoute(siteDataRef.value, route.data.relativePath)
const site = computed(() => {
const data = resolveSiteDataByRoute(
siteDataRef.value,
route.data.relativePath
)
return stackView(...getExtraConfigs(route.data.relativePath), data)
})
const appearance = site.value.appearance // fine with reactivity being lost here, config change triggers a restart
const isDark =
@ -124,6 +160,8 @@ export function initData(route: Route): VitePressData {
export function useData<T = any>(): VitePressData<T> {
const data = inject(dataSymbol)
;(window as any).stackView = stackView
;(window as any).data = data
if (!data) {
throw new Error('vitepress data not properly injected in app')
}

@ -140,3 +140,65 @@ function tryOffsetSelector(selector: string, padding: number): number {
if (bot < 0) return 0
return bot + padding
}
export function dirname(path: string) {
const segments = path.split('/')
segments[segments.length - 1] = ''
return segments.join('/')
}
const unpackStackView = Symbol('unpackStackView')
function isStackable(obj: any) {
return typeof obj === 'object' && obj !== null && !Array.isArray(obj)
}
/**
* Creates a deep, merged view of multiple objects without mutating originals.
* Returns a readonly proxy behaving like a merged object of the input objects.
* Layers are merged in descending precedence, i.e. earlier layer is on top.
*/
export function stackView<T extends object>(...layers: T[]): T {
layers = layers.filter((layer) => layer !== undefined)
if (layers.length == 0) return undefined as any as T
if (layers.length == 1 || !isStackable(layers[0])) return layers[0]
layers = layers.filter(isStackable)
if (layers.length == 1) return layers[0]
return new Proxy(
{},
{
get(target, prop) {
if (prop === unpackStackView) {
return layers
}
return stackView(...layers.map((layer) => (layer as any)?.[prop]))
},
set(target, prop, value) {
throw new Error('StackView is read-only and cannot be mutated.')
},
has(target, prop) {
for (const layer of layers) {
if (prop in layer) return true
}
return false
},
ownKeys(target) {
const keys = new Set<string>()
for (const layer of layers) {
for (const key of Object.keys(layer)) {
keys.add(key)
}
}
return Array.from(keys)
},
getOwnPropertyDescriptor(target, prop) {
for (const layer of layers) {
if (prop in layer) {
return Object.getOwnPropertyDescriptor(layer, prop)
}
}
}
}
) as T
}
stackView.unpack = (obj: any) => obj?.[unpackStackView]

@ -15,6 +15,7 @@ export function createSearchTranslate(
const isObject = themeObject && typeof themeObject === 'object'
const locales =
(isObject && themeObject.locales?.[localeIndex.value]?.translations) ||
(isObject && themeObject?.translations) ||
null
const translations = (isObject && themeObject.translations) || null

Loading…
Cancel
Save