diff --git a/docs/.vitepress/config.ts b/docs/.vitepress/config.ts index 8ef0d400..3b4f5aa2 100644 --- a/docs/.vitepress/config.ts +++ b/docs/.vitepress/config.ts @@ -1,4 +1,6 @@ -export default { +import { defineConfig } from '../../src/node' + +export default defineConfig({ lang: 'en-US', title: 'VitePress', description: 'Vite & Vue powered static site generator.', @@ -50,7 +52,7 @@ export default { '/': getGuideSidebar() } } -} +}) function getGuideSidebar() { return [ diff --git a/docs/guide/configuration.md b/docs/guide/configuration.md index 7dc8d1e0..8ffaad52 100644 --- a/docs/guide/configuration.md +++ b/docs/guide/configuration.md @@ -1,5 +1,7 @@ # Configuration +## Overview + Without any configuration, the page is pretty minimal, and the user has no way to navigate around the site. To customize your site, let’s first create a `.vitepress` directory inside your docs directory. This is where all VitePress-specific files will be placed. Your project structure is probably like this: ```bash @@ -21,3 +23,57 @@ module.exports = { ``` Check out the [Config Reference](/config/basics) for a full list of options. + +## Config Intellisense + +Since VitePress ships with TypeScript typings, you can leverage your IDE's intellisense with jsdoc type hints: + +```js +/** + * @type {import('vitepress').UserConfig} + */ +const config = { + // ... +} + +export default config +``` + +Alternatively, you can use the `defineConfig` helper at which should provide intellisense without the need for jsdoc annotations: + +```js +import { defineConfig } from 'vitepress' + +export default defineConfig({ + // ... +}) +``` + +VitePress also directly supports TS config files. You can use `.vitepress/config.ts` with the `defineConfig` helper as well. + +## Typed Theme Config + +By default, `defineConfig` helper leverages the theme config type from default theme: + +```ts +import { defineConfig } from 'vitepress' + +export default defineConfig({ + themeConfig: { + // Type is `DefaultTheme.Config` + } +}) +``` + +If you use a custom theme and want type checks for the theme config, you'll need to use `defineConfigWithTheme` instead, and pass the config type for your custom theme via a generic argument: + +```ts +import { defineConfigWithTheme } from 'vitepress' +import { ThemeConfig } from 'your-theme' + +export default defineConfigWithTheme({ + themeConfig: { + // Type is `ThemeConfig` + } +}) +``` diff --git a/src/client/theme-default/config.ts b/src/client/theme-default/config.ts index d7284871..92869ac4 100644 --- a/src/client/theme-default/config.ts +++ b/src/client/theme-default/config.ts @@ -1,146 +1 @@ -export namespace DefaultTheme { - export interface Config { - logo?: string - nav?: NavItem[] | false - sidebar?: SideBarConfig | MultiSideBarConfig - - /** - * GitHub repository following the format /. - * - * @example `"vuejs/vue-next"` - */ - repo?: string - - /** - * Customize the header label. Defaults to GitHub/Gitlab/Bitbucket - * depending on the provided repo. - * - * @example `"Contribute!"` - */ - repoLabel?: string - - /** - * If your docs are in a different repository from your main project. - * - * @example `"vuejs/docs-next"` - */ - docsRepo?: string - - /** - * If your docs are not at the root of the repo. - * - * @example `"docs"` - */ - docsDir?: string - - /** - * If your docs are in a different branch. Defaults to `master`. - * - * @example `"next"` - */ - docsBranch?: string - - /** - * Enable links to edit pages at the bottom of the page. - */ - editLinks?: boolean - - /** - * Custom text for edit link. Defaults to "Edit this page". - */ - editLinkText?: string - - /** - * Show last updated time at the bottom of the page. Defaults to `false`. - * If given a string, it will be displayed as a prefix (default value: - * "Last Updated"). - */ - lastUpdated?: string | boolean - - prevLinks?: boolean - nextLinks?: boolean - - locales?: Record> - - algolia?: AlgoliaSearchOptions - - carbonAds?: { - carbon: string - custom?: string - placement: string - } - } - - // navbar -------------------------------------------------------------------- - - export type NavItem = NavItemWithLink | NavItemWithChildren - - export interface NavItemBase { - text: string - target?: string - rel?: string - ariaLabel?: string - activeMatch?: string - } - - export interface NavItemWithLink extends NavItemBase { - link: string - } - - export interface NavItemWithChildren extends NavItemBase { - items: NavItemWithLink[] - } - - // sidebar ------------------------------------------------------------------- - - export type SideBarConfig = SideBarItem[] | 'auto' | false - - export interface MultiSideBarConfig { - [path: string]: SideBarConfig - } - - export type SideBarItem = SideBarLink | SideBarGroup - - export interface SideBarLink { - text: string - link: string - } - - export interface SideBarGroup { - text: string - link?: string - - /** - * @default false - */ - collapsable?: boolean - - children: SideBarItem[] - } - - // algolia ------------------------------------------------------------------ - // partially copied from @docsearch/react/dist/esm/DocSearch.d.ts - export interface AlgoliaSearchOptions { - appId?: string - apiKey: string - indexName: string - placeholder?: string - searchParameters?: any - disableUserPersonalization?: boolean - initialQuery?: string - } - - // locales ------------------------------------------------------------------- - - export interface LocaleConfig { - /** - * Text for the language dropdown. - */ - selectText?: string - - /** - * Label for this locale in the language dropdown. - */ - label?: string - } -} +export { DefaultTheme } from '../shared' diff --git a/src/client/theme-default/index.ts b/src/client/theme-default/index.ts index b9c753dd..bcd79051 100644 --- a/src/client/theme-default/index.ts +++ b/src/client/theme-default/index.ts @@ -8,6 +8,7 @@ import { Theme } from 'vitepress' import Layout from './Layout.vue' import NotFound from './NotFound.vue' +export { DefaultTheme } from './config' const theme: Theme = { Layout, NotFound diff --git a/src/client/tsconfig.json b/src/client/tsconfig.json index f7f086aa..92a8af1c 100644 --- a/src/client/tsconfig.json +++ b/src/client/tsconfig.json @@ -12,5 +12,5 @@ "vitepress": ["index.ts"] } }, - "include": [".", "../../types/shared.d.ts"] + "include": ["."] } diff --git a/src/node/config.ts b/src/node/config.ts index d3ff1c70..19130e8a 100644 --- a/src/node/config.ts +++ b/src/node/config.ts @@ -14,7 +14,8 @@ import { SiteData, HeadConfig, LocaleConfig, - createLangDictionary + createLangDictionary, + DefaultTheme } from './shared' import { resolveAliases, APP_PATH, DEFAULT_THEME_PATH } from './alias' import { MarkdownOptions } from './markdown/markdown' @@ -27,7 +28,7 @@ const debug = _debug('vitepress:config') export type { MarkdownOptions } export interface UserConfig { - extends?: RawConfigExports + extends?: RawConfigExports lang?: string base?: string title?: string @@ -56,10 +57,10 @@ export interface UserConfig { mpa?: boolean } -export type RawConfigExports = - | UserConfig - | Promise - | (() => UserConfig | Promise) +export type RawConfigExports = + | UserConfig + | Promise> + | (() => UserConfig | Promise>) export interface SiteConfig extends Pick< @@ -83,7 +84,16 @@ const resolve = (root: string, file: string) => /** * Type config helper */ -export function defineConfig(config: RawConfigExports) { +export function defineConfig(config: UserConfig) { + return config +} + +/** + * Type config helper for custom theme config + */ +export function defineConfigWithTheme( + config: UserConfig +) { return config } diff --git a/src/node/index.ts b/src/node/index.ts index f671e921..dd6b048e 100644 --- a/src/node/index.ts +++ b/src/node/index.ts @@ -4,4 +4,4 @@ export * from './serve/serve' export * from './config' export * from './markdown/markdown' -export type { SiteData, HeadConfig, LocaleConfig } from '../../types/shared' +export type { SiteData, HeadConfig, LocaleConfig, DefaultTheme } from '../../types/shared' diff --git a/src/shared/shared.ts b/src/shared/shared.ts index d3d34eb8..1e1e0a5a 100644 --- a/src/shared/shared.ts +++ b/src/shared/shared.ts @@ -5,7 +5,8 @@ export type { PageData, HeadConfig, LocaleConfig, - Header + Header, + DefaultTheme, } from '../../types/shared' export const EXTERNAL_URL_RE = /^https?:/i diff --git a/src/shared/tsconfig.json b/src/shared/tsconfig.json index 5dd8a6db..a8ed344e 100644 --- a/src/shared/tsconfig.json +++ b/src/shared/tsconfig.json @@ -3,5 +3,5 @@ "compilerOptions": { "baseUrl": "." }, - "include": [".", "../../types/shared.d.ts"] + "include": ["."] } diff --git a/types/default-theme.d.ts b/types/default-theme.d.ts new file mode 100644 index 00000000..d7284871 --- /dev/null +++ b/types/default-theme.d.ts @@ -0,0 +1,146 @@ +export namespace DefaultTheme { + export interface Config { + logo?: string + nav?: NavItem[] | false + sidebar?: SideBarConfig | MultiSideBarConfig + + /** + * GitHub repository following the format /. + * + * @example `"vuejs/vue-next"` + */ + repo?: string + + /** + * Customize the header label. Defaults to GitHub/Gitlab/Bitbucket + * depending on the provided repo. + * + * @example `"Contribute!"` + */ + repoLabel?: string + + /** + * If your docs are in a different repository from your main project. + * + * @example `"vuejs/docs-next"` + */ + docsRepo?: string + + /** + * If your docs are not at the root of the repo. + * + * @example `"docs"` + */ + docsDir?: string + + /** + * If your docs are in a different branch. Defaults to `master`. + * + * @example `"next"` + */ + docsBranch?: string + + /** + * Enable links to edit pages at the bottom of the page. + */ + editLinks?: boolean + + /** + * Custom text for edit link. Defaults to "Edit this page". + */ + editLinkText?: string + + /** + * Show last updated time at the bottom of the page. Defaults to `false`. + * If given a string, it will be displayed as a prefix (default value: + * "Last Updated"). + */ + lastUpdated?: string | boolean + + prevLinks?: boolean + nextLinks?: boolean + + locales?: Record> + + algolia?: AlgoliaSearchOptions + + carbonAds?: { + carbon: string + custom?: string + placement: string + } + } + + // navbar -------------------------------------------------------------------- + + export type NavItem = NavItemWithLink | NavItemWithChildren + + export interface NavItemBase { + text: string + target?: string + rel?: string + ariaLabel?: string + activeMatch?: string + } + + export interface NavItemWithLink extends NavItemBase { + link: string + } + + export interface NavItemWithChildren extends NavItemBase { + items: NavItemWithLink[] + } + + // sidebar ------------------------------------------------------------------- + + export type SideBarConfig = SideBarItem[] | 'auto' | false + + export interface MultiSideBarConfig { + [path: string]: SideBarConfig + } + + export type SideBarItem = SideBarLink | SideBarGroup + + export interface SideBarLink { + text: string + link: string + } + + export interface SideBarGroup { + text: string + link?: string + + /** + * @default false + */ + collapsable?: boolean + + children: SideBarItem[] + } + + // algolia ------------------------------------------------------------------ + // partially copied from @docsearch/react/dist/esm/DocSearch.d.ts + export interface AlgoliaSearchOptions { + appId?: string + apiKey: string + indexName: string + placeholder?: string + searchParameters?: any + disableUserPersonalization?: boolean + initialQuery?: string + } + + // locales ------------------------------------------------------------------- + + export interface LocaleConfig { + /** + * Text for the language dropdown. + */ + selectText?: string + + /** + * Label for this locale in the language dropdown. + */ + label?: string + } +} diff --git a/types/index.d.ts b/types/index.d.ts index 10a5d0c2..ea74a292 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -1,4 +1,4 @@ export * from './shared' +export * from './default-theme' export * from '../dist/node/index' export * from '../dist/client/index' -export * from '../dist/client/theme-default/config' diff --git a/types/shared.d.ts b/types/shared.d.ts index 4f6558a6..2beaf53f 100644 --- a/types/shared.d.ts +++ b/types/shared.d.ts @@ -1,5 +1,7 @@ // types shared between server and client +export { DefaultTheme } from './default-theme' + export interface LocaleConfig { lang: string title?: string