Skip to content

Commit ba41bb9

Browse files
authored
feat: improve typescript support for config file (#465)
1 parent 51978a3 commit ba41bb9

File tree

12 files changed

+233
-160
lines changed

12 files changed

+233
-160
lines changed

docs/.vitepress/config.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
export default {
1+
import { defineConfig } from '../../src/node'
2+
3+
export default defineConfig({
24
lang: 'en-US',
35
title: 'VitePress',
46
description: 'Vite & Vue powered static site generator.',
@@ -50,7 +52,7 @@ export default {
5052
'/': getGuideSidebar()
5153
}
5254
}
53-
}
55+
})
5456

5557
function getGuideSidebar() {
5658
return [

docs/guide/configuration.md

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
# Configuration
22

3+
## Overview
4+
35
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:
46

57
```bash
@@ -21,3 +23,57 @@ module.exports = {
2123
```
2224

2325
Check out the [Config Reference](/config/basics) for a full list of options.
26+
27+
## Config Intellisense
28+
29+
Since VitePress ships with TypeScript typings, you can leverage your IDE's intellisense with jsdoc type hints:
30+
31+
```js
32+
/**
33+
* @type {import('vitepress').UserConfig}
34+
*/
35+
const config = {
36+
// ...
37+
}
38+
39+
export default config
40+
```
41+
42+
Alternatively, you can use the `defineConfig` helper at which should provide intellisense without the need for jsdoc annotations:
43+
44+
```js
45+
import { defineConfig } from 'vitepress'
46+
47+
export default defineConfig({
48+
// ...
49+
})
50+
```
51+
52+
VitePress also directly supports TS config files. You can use `.vitepress/config.ts` with the `defineConfig` helper as well.
53+
54+
## Typed Theme Config
55+
56+
By default, `defineConfig` helper leverages the theme config type from default theme:
57+
58+
```ts
59+
import { defineConfig } from 'vitepress'
60+
61+
export default defineConfig({
62+
themeConfig: {
63+
// Type is `DefaultTheme.Config`
64+
}
65+
})
66+
```
67+
68+
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:
69+
70+
```ts
71+
import { defineConfigWithTheme } from 'vitepress'
72+
import { ThemeConfig } from 'your-theme'
73+
74+
export default defineConfigWithTheme<ThemeConfig>({
75+
themeConfig: {
76+
// Type is `ThemeConfig`
77+
}
78+
})
79+
```

src/client/theme-default/config.ts

Lines changed: 1 addition & 146 deletions
Original file line numberDiff line numberDiff line change
@@ -1,146 +1 @@
1-
export namespace DefaultTheme {
2-
export interface Config {
3-
logo?: string
4-
nav?: NavItem[] | false
5-
sidebar?: SideBarConfig | MultiSideBarConfig
6-
7-
/**
8-
* GitHub repository following the format <user>/<project>.
9-
*
10-
* @example `"vuejs/vue-next"`
11-
*/
12-
repo?: string
13-
14-
/**
15-
* Customize the header label. Defaults to GitHub/Gitlab/Bitbucket
16-
* depending on the provided repo.
17-
*
18-
* @example `"Contribute!"`
19-
*/
20-
repoLabel?: string
21-
22-
/**
23-
* If your docs are in a different repository from your main project.
24-
*
25-
* @example `"vuejs/docs-next"`
26-
*/
27-
docsRepo?: string
28-
29-
/**
30-
* If your docs are not at the root of the repo.
31-
*
32-
* @example `"docs"`
33-
*/
34-
docsDir?: string
35-
36-
/**
37-
* If your docs are in a different branch. Defaults to `master`.
38-
*
39-
* @example `"next"`
40-
*/
41-
docsBranch?: string
42-
43-
/**
44-
* Enable links to edit pages at the bottom of the page.
45-
*/
46-
editLinks?: boolean
47-
48-
/**
49-
* Custom text for edit link. Defaults to "Edit this page".
50-
*/
51-
editLinkText?: string
52-
53-
/**
54-
* Show last updated time at the bottom of the page. Defaults to `false`.
55-
* If given a string, it will be displayed as a prefix (default value:
56-
* "Last Updated").
57-
*/
58-
lastUpdated?: string | boolean
59-
60-
prevLinks?: boolean
61-
nextLinks?: boolean
62-
63-
locales?: Record<string, LocaleConfig & Omit<Config, 'locales'>>
64-
65-
algolia?: AlgoliaSearchOptions
66-
67-
carbonAds?: {
68-
carbon: string
69-
custom?: string
70-
placement: string
71-
}
72-
}
73-
74-
// navbar --------------------------------------------------------------------
75-
76-
export type NavItem = NavItemWithLink | NavItemWithChildren
77-
78-
export interface NavItemBase {
79-
text: string
80-
target?: string
81-
rel?: string
82-
ariaLabel?: string
83-
activeMatch?: string
84-
}
85-
86-
export interface NavItemWithLink extends NavItemBase {
87-
link: string
88-
}
89-
90-
export interface NavItemWithChildren extends NavItemBase {
91-
items: NavItemWithLink[]
92-
}
93-
94-
// sidebar -------------------------------------------------------------------
95-
96-
export type SideBarConfig = SideBarItem[] | 'auto' | false
97-
98-
export interface MultiSideBarConfig {
99-
[path: string]: SideBarConfig
100-
}
101-
102-
export type SideBarItem = SideBarLink | SideBarGroup
103-
104-
export interface SideBarLink {
105-
text: string
106-
link: string
107-
}
108-
109-
export interface SideBarGroup {
110-
text: string
111-
link?: string
112-
113-
/**
114-
* @default false
115-
*/
116-
collapsable?: boolean
117-
118-
children: SideBarItem[]
119-
}
120-
121-
// algolia ------------------------------------------------------------------
122-
// partially copied from @docsearch/react/dist/esm/DocSearch.d.ts
123-
export interface AlgoliaSearchOptions {
124-
appId?: string
125-
apiKey: string
126-
indexName: string
127-
placeholder?: string
128-
searchParameters?: any
129-
disableUserPersonalization?: boolean
130-
initialQuery?: string
131-
}
132-
133-
// locales -------------------------------------------------------------------
134-
135-
export interface LocaleConfig {
136-
/**
137-
* Text for the language dropdown.
138-
*/
139-
selectText?: string
140-
141-
/**
142-
* Label for this locale in the language dropdown.
143-
*/
144-
label?: string
145-
}
146-
}
1+
export { DefaultTheme } from '../shared'

src/client/theme-default/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { Theme } from 'vitepress'
88
import Layout from './Layout.vue'
99
import NotFound from './NotFound.vue'
1010

11+
export { DefaultTheme } from './config'
1112
const theme: Theme = {
1213
Layout,
1314
NotFound

src/client/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,5 +12,5 @@
1212
"vitepress": ["index.ts"]
1313
}
1414
},
15-
"include": [".", "../../types/shared.d.ts"]
15+
"include": ["."]
1616
}

src/node/config.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ import {
1414
SiteData,
1515
HeadConfig,
1616
LocaleConfig,
17-
createLangDictionary
17+
createLangDictionary,
18+
DefaultTheme
1819
} from './shared'
1920
import { resolveAliases, APP_PATH, DEFAULT_THEME_PATH } from './alias'
2021
import { MarkdownOptions } from './markdown/markdown'
@@ -27,7 +28,7 @@ const debug = _debug('vitepress:config')
2728
export type { MarkdownOptions }
2829

2930
export interface UserConfig<ThemeConfig = any> {
30-
extends?: RawConfigExports
31+
extends?: RawConfigExports<ThemeConfig>
3132
lang?: string
3233
base?: string
3334
title?: string
@@ -56,10 +57,10 @@ export interface UserConfig<ThemeConfig = any> {
5657
mpa?: boolean
5758
}
5859

59-
export type RawConfigExports =
60-
| UserConfig
61-
| Promise<UserConfig>
62-
| (() => UserConfig | Promise<UserConfig>)
60+
export type RawConfigExports<ThemeConfig = any> =
61+
| UserConfig<ThemeConfig>
62+
| Promise<UserConfig<ThemeConfig>>
63+
| (() => UserConfig<ThemeConfig> | Promise<UserConfig<ThemeConfig>>)
6364

6465
export interface SiteConfig<ThemeConfig = any>
6566
extends Pick<
@@ -83,7 +84,16 @@ const resolve = (root: string, file: string) =>
8384
/**
8485
* Type config helper
8586
*/
86-
export function defineConfig(config: RawConfigExports) {
87+
export function defineConfig(config: UserConfig<DefaultTheme.Config>) {
88+
return config
89+
}
90+
91+
/**
92+
* Type config helper for custom theme config
93+
*/
94+
export function defineConfigWithTheme<ThemeConfig>(
95+
config: UserConfig<ThemeConfig>
96+
) {
8797
return config
8898
}
8999

src/node/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ export * from './serve/serve'
44
export * from './config'
55
export * from './markdown/markdown'
66

7-
export type { SiteData, HeadConfig, LocaleConfig } from '../../types/shared'
7+
export type { SiteData, HeadConfig, LocaleConfig, DefaultTheme } from '../../types/shared'

src/shared/shared.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ export type {
55
PageData,
66
HeadConfig,
77
LocaleConfig,
8-
Header
8+
Header,
9+
DefaultTheme,
910
} from '../../types/shared'
1011

1112
export const EXTERNAL_URL_RE = /^https?:/i

src/shared/tsconfig.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,5 +3,5 @@
33
"compilerOptions": {
44
"baseUrl": "."
55
},
6-
"include": [".", "../../types/shared.d.ts"]
6+
"include": ["."]
77
}

0 commit comments

Comments
 (0)