Расширение стандартной темы
Стандартная тема VitePress оптимизирована для документации и может быть настроена. См. Обзор конфигурации стандартной темы для получения полного списка опций.
Однако есть ряд случаев, когда конфигурация в одиночку не будет достаточной. Например:
- Вам нужно изменить стили CSS;
- Вам нужно изменить экземпляр приложения Vue, например, для регистрации глобальных компонентов;
- Вам нужно внедрить пользовательский контент в тему через слоты макета.
Эти продвинутые настройки потребуют использования пользовательской темы, которая "расширяет" стандартную тему.
Подсказка
Перед продолжением убедитесь, что вы прочитали Использование пользовательской темы, чтобы понять, как работают пользовательские темы.
Настройка CSS
CSS стандартной темы можно настроить, переопределив переменные CSS на корневом уровне:
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import './custom.css'
export default DefaultTheme
/* .vitepress/theme/custom.css */
:root {
--vp-c-brand-1: #646cff;
--vp-c-brand-2: #747bff;
}
См. переменные CSS стандартной темы, которые можно переопределить.
Использование разных шрифтов
VitePress использует Inter в качестве стандартного шрифта и будет включать шрифты в выходные данные сборки. Шрифт также автоматически предзагружается в продакшене. Однако это может быть нежелательно, если вы хотите использовать другой основной шрифт.
Чтобы избежать включения Inter в выходные данные сборки, импортируйте тему из vitepress/theme-without-fonts
:
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme-without-fonts'
import './my-fonts.css'
export default DefaultTheme
/* .vitepress/theme/custom.css */
:root {
--vp-font-family-base: /* шрифт обычного текста */
--vp-font-family-mono: /* шрифт кода */
}
WARNING
Если вы используете дополнительные компоненты, такие как Страница команды, убедитесь, что вы также импортируете их из vitepress/theme-without-fonts
!
Если ваш шрифт - это локальный файл, на который ссылается через @font-face
, он будет обработан как ресурс и включен в .vitepress/dist/assets
с хешированным именем файла. Чтобы предзагрузить этот файл, используйте хук сборки transformHead:
// .vitepress/config.js
export default {
transformHead({ assets }) {
// настройте регулярное выражение соответственно, чтобы соответствовать вашему шрифту
const myFontFile = assets.find(file => /font-name\.\w+\.woff2/)
if (myFontFile) {
return [
[
'link',
{
rel: 'preload',
href: myFontFile,
as: 'font',
type: 'font/woff2',
crossorigin: ''
}
]
]
}
}
}
Регистрация глобальных компонентов
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
/** @type {import('vitepress').Theme} */
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
// регистрируйте ваши пользовательские глобальные компоненты
app.component('MyGlobalComponent' /* ... */)
}
}
Если вы используете TypeScript:
// .vitepress/theme/index.ts
import type { Theme } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
export default {
extends: DefaultTheme,
enhanceApp({ app }) {
// регистрируйте ваши пользовательские глобальные компоненты
app.component('MyGlobalComponent' /* ... */)
}
} satisfies Theme
Поскольку мы используем Vite, вы также можете воспользоваться функцией глобального импорта Vite, чтобы автоматически зарегистрировать директорию компонент
ов.
Слоты макета
Компонент <Layout/>
стандартной темы имеет несколько слотов, которые можно использовать для внедрения контента в определенные места страницы. Вот пример внедрения компонента в верхнюю часть боковой панели:
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyLayout from './MyLayout.vue'
export default {
extends: DefaultTheme,
// переопределите Layout с помощью компонента-обертки,
// который внедряет слоты
Layout: MyLayout
}
<!--.vitepress/theme/MyLayout.vue-->
<script setup>
import DefaultTheme from 'vitepress/theme'
const { Layout } = DefaultTheme
</script>
<template>
<Layout>
<template #aside-outline-before>
Мой пользовательский контент в верхней части боковой панели
</template>
</Layout>
</template>
Или вы можете использовать функцию рендеринга:
// .vitepress/theme/index.js
import { h } from 'vue'
import DefaultTheme from 'vitepress/theme'
import MyComponent from './MyComponent.vue'
export default {
extends: DefaultTheme,
Layout() {
return h(DefaultTheme.Layout, null, {
'aside-outline-before': () => h(MyComponent)
})
}
}
Полный список слотов, доступных в макете стандартной темы:
- Когда через frontmatter включен
layout: 'doc'
(по умолчанию):doc-top
doc-bottom
doc-footer-before
doc-before
doc-after
sidebar-nav-before
sidebar-nav-after
aside-top
aside-bottom
aside-outline-before
aside-outline-after
aside-ads-before
aside-ads-after
- Когда через frontmatter включен
layout: 'home'
:home-hero-before
home-hero-info-before
home-hero-info
home-hero-info-after
home-hero-actions-after
home-hero-image
home-hero-after
home-features-before
home-features-after
- Когда через frontmatter включен
layout: 'page'
:page-top
page-bottom
- На странице не найдено (404):
not-found
- Всегда:
layout-top
layout-bottom
nav-bar-title-before
nav-bar-title-after
nav-bar-content-before
nav-bar-content-after
nav-screen-content-before
nav-screen-content-after
Использование API переходов между представлениями
При переключении режима отображения
Вы можете расширить стандартную тему, чтобы предоставить пользовательский переход при переключении режима цвета. Пример:
<!-- .vitepress/theme/Layout.vue -->
<script setup lang="ts">
import { useData } from 'vitepress'
import DefaultTheme from 'vitepress/theme'
import { nextTick, provide } from 'vue'
const { isDark } = useData()
const enableTransitions = () =>
'startViewTransition' in document &&
window.matchMedia('(prefers-reduced-motion: no-preference)').matches
provide('toggle-appearance', async ({ clientX: x, clientY: y }: MouseEvent) => {
if (!enableTransitions()) {
isDark.value = !isDark.value
return
}
const clipPath = [
`circle(0px at ${x}px ${y}px)`,
`circle(${Math.hypot(
Math.max(x, innerWidth - x),
Math.max(y, innerHeight - y)
)}px at ${x}px ${y}px)`
]
await document.startViewTransition(async () => {
isDark.value = !isDark.value
await nextTick()
}).ready
document.documentElement.animate(
{ clipPath: isDark.value ? clipPath.reverse() : clipPath },
{
duration: 300,
easing: 'ease-in',
pseudoElement: `::view-transition-${isDark.value ? 'old' : 'new'}(root)`
}
)
})
</script>
<template>
<DefaultTheme.Layout />
</template>
<style>
::view-transition-old(root),
::view-transition-new(root) {
animation: none;
mix-blend-mode: normal;
}
::view-transition-old(root),
.dark::view-transition-new(root) {
z-index: 1;
}
::view-transition-new(root),
.dark::view-transition-old(root) {
z-index: 9999;
}
.VPSwitchAppearance {
width: 22px !important;
}
.VPSwitchAppearance .check {
transform: none !important;
}
</style>
Результат (внимание!: мигающие цвета, внезапные движения, яркие света):
Демо
См. Документацию Chrome для получения дополнительной информации о переходах между представлениями.
При изменении маршрута
Скоро будет.
Переопределение внутренних компонентов
Вы можете использовать алиасы Vite для замены компонентов стандартной темы на ваши собственные:
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vitepress'
export default defineConfig({
vite: {
resolve: {
alias: [
{
find: /^.*\/VPNavBar\.vue$/,
replacement: fileURLToPath(
new URL('./components/CustomNavBar.vue', import.meta.url)
)
}
]
}
}
})
Чтобы узнать точное имя компонента, обратитесь к нашему исходному коду. Поскольку компоненты являются внутренними, есть небольшая вероятность, что их имя будет обновлено между минорными релизами.