Skip to content

Использование пользовательской темы

Разрешение темы

Вы можете включить пользовательскую тему, создав файл .vitepress/theme/index.js или .vitepress/theme/index.ts (файл входа темы):

.
├─ docs                # корневая папка проекта
│  ├─ .vitepress
│  │  ├─ theme
│  │  │  └─ index.js   # вход темы
│  │  └─ config.js     # файл конфигурации
│  └─ index.md
└─ package.json

VitePress всегда будет использовать пользовательскую тему вместо стандартной темы, когда обнаружит файл входа темы. Однако вы можете расширить стандартную тему, чтобы выполнить дополнительные настройки поверх неё.

Интерфейс темы

Пользовательская тема VitePress определяется как объект со следующим интерфейсом:

ts
interface Theme {
  /**
   * Корневой компонент макета для каждой страницы
   * @required
   */
  Layout: Component
  /**
   * Улучшение экземпляра приложения Vue
   * @optional
   */
  enhanceApp?: (ctx: EnhanceAppContext) => Awaitable<void>
  /**
   * Расширение другой темы, вызывая её `enhanceApp` перед нашим
   * @optional
   */
  extends?: Theme
}

interface EnhanceAppContext {
  app: App // экземпляр приложения Vue
  router: Router // экземпляр роутера VitePress
  siteData: Ref<SiteData> // метаданные на уровне сайта
}

Файл входа темы должен экспортировать тему как свой экспорт по умолчанию:

js
// .vitepress/theme/index.js

// Вы можете напрямую импортировать файлы Vue в файле входа темы
// VitePress предварительно настроен с @vitejs/plugin-vue.
import Layout from './Layout.vue'

export default {
  Layout,
  enhanceApp({ app, router, siteData }) {
    // ...
  }
}

Экспорт по умолчанию является единственным контрактом для пользовательской темы, и требуется только свойство Layout. Таким образом, технически, тема VitePress может быть такой же простой, как один компонент Vue.

Внутри вашего компонента макета он работает так же, как обычное приложение Vite + Vue 3. Обратите внимание, что тема также должна быть совместима с SSR.

Создание макета

Самый базовый компонент макета должен содержать компонент <Content />:

vue
<!-- .vitepress/theme/Layout.vue -->
<template>
  <h1>Пользовательский макет!</h1>

  <!-- здесь будет отображаться содержимое markdown -->
  <Content />
</template>

Вышеуказанный макет просто отображает содержимое каждой страницы в виде HTML. Первое улучшение, которое мы можем добавить, - это обработка ошибок 404:

vue
<script setup>
import { useData } from 'vitepress'
const { page } = useData()
</script>

<template>
  <h1>Пользовательский макет!</h1>

  <div v-if="page.isNotFound">
    Пользовательская страница 404!
  </div>
  <Content v-else />
</template>

Помощник useData() предоставляет нам все необходимые данные для условного отображения различных макетов. Одним из других данных, к которым мы можем получить доступ, является frontmatter текущей страницы. Мы можем использовать это, чтобы позволить конечному пользователю управлять макетом на каждой странице. Например, пользователь может указать, что страница должна использовать специальный макет домашней страницы с помощью:

md
---
layout: home
---

И мы можем настроить нашу тему для обработки этого:

vue
<script setup>
import { useData } from 'vitepress'
const { page, frontmatter } = useData()
</script>

<template>
  <h1>Пользовательский макет!</h1>

  <div v-if="page.isNotFound">
    Пользовательская страница 404!
  </div>
  <div v-if="frontmatter.layout === 'home'">
    Пользовательская домашняя страница!
  </div>
  <Content v-else />
</template>

Вы можете, конечно, разделить макет на больше компонентов:

vue
<script setup>
import { useData } from 'vitepress'
import NotFound from './NotFound.vue'
import Home from './Home.vue'
import Page from './Page.vue'

const { page, frontmatter } = useData()
</script>

<template>
  <h1>Пользовательский макет!</h1>

  <NotFound

 v-if="page.isNotFound" />
  <Home v-if="frontmatter.layout === 'home'" />
  <Page v-else /> <!-- <Page /> отображает <Content /> -->
</template>

См. Справочник по API во время выполнения для получения информации обо всем, что доступно в компонентах темы. Кроме того, вы можете использовать Загрузку данных во время сборки для создания макета на основе данных - например, страницы, которая перечисляет все блог-посты в текущем проекте.

Распространение пользовательской темы

Самый простой способ распространения пользовательской темы - предоставить её в виде шаблонного репозитория на GitHub.

Если вы хотите распространять тему как пакет npm, выполните следующие шаги:

  1. Экспортируйте объект темы как экспорт по умолчанию в файле входа вашего пакета.

  2. Если применимо, экспортируйте тип конфигурации вашей темы как ThemeConfig.

  3. Если ваша тема требует настройки конфигурации VitePress, экспортируйте эту конфигурацию под путем подпакета (например, my-theme/config), чтобы пользователь мог её расширить.

  4. Документируйте опции конфигурации темы (как через файл конфигурации, так и через frontmatter).

  5. Предоставьте чёткие инструкции о том, как использовать вашу тему (см. ниже).

Использование пользовательской темы

Чтобы использовать внешнюю тему, импортируйте и повторно экспортируйте её из пользовательского файла входа темы:

js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'

export default Theme

Если тема должна быть расширена:

js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'

export default {
  extends: Theme,
  enhanceApp(ctx) {
    // ...
  }
}

Если тема требует специальной конфигурации VitePress, вам также нужно будет расширить её в своей собственной конфигурации:

ts
// .vitepress/theme/config.ts
import baseConfig from 'awesome-vitepress-theme/config'

export default {
  // расширяем базовую конфигурацию темы (если нужно)
  extends: baseConfig
}

Наконец, если тема предоставляет типы для своей конфигурации темы:

ts
// .vitepress/theme/config.ts
import baseConfig from 'awesome-vitepress-theme/config'
import { defineConfigWithTheme } from 'vitepress'
import type { ThemeConfig } from 'awesome-vitepress-theme'

export default defineConfigWithTheme<ThemeConfig>({
  extends: baseConfig,
  themeConfig: {
    // Тип - `ThemeConfig`
  }
})

Содержание доступно по лицензии MIT