diff --git a/__tests__/e2e/dynamic-routes/[id].md b/__tests__/e2e/dynamic-routes/[id].md index a1ca54a0078..ec1b07621f5 100644 --- a/__tests__/e2e/dynamic-routes/[id].md +++ b/__tests__/e2e/dynamic-routes/[id].md @@ -1,8 +1,3 @@ - - -
{{ page.params }}+
{{ $params }}diff --git a/__tests__/e2e/static-data/static.data.ts b/__tests__/e2e/static-data/static.data.ts index a9ae896bd15..1a70d74a3a5 100644 --- a/__tests__/e2e/static-data/static.data.ts +++ b/__tests__/e2e/static-data/static.data.ts @@ -1,23 +1,20 @@ import fs from 'fs' -import path from 'path' -import { fileURLToPath } from 'url' - -const dirname = path.dirname(fileURLToPath(import.meta.url)) +import { defineLoader } from 'vitepress' type Data = Record
{{ data }}+``` + +Output: + +```json +{ + "data": "hello" +} +``` + +You'll notice the data loader itself does not export the `data`. It is VitePress calling the `load()` method behind the scenes and implicitly exposing the result via the `data` named export. + +This works even if the loader is async: + ```js export default { async load() { + // fetch remote data return (await fetch('...')).json() } } ``` -## Generating Data Based On Local Files +## Data from Local Files + +When you need to generate data based on local files, you should use the `watch` option in the data loader so that changes made to these files can trigger hot updates. + +The `watch` option is also convenient in that you can use [glob patterns](https://github.com/mrmlnc/fast-glob#pattern-syntax) to match multiple files. The patterns can be relative to the loader file itself, and the `load()` function will receive the matched files as absolute paths: ```js -import { readDirSync } from 'node:fs' +import fs from 'node:fs' +import parseFrontmatter from 'gray-matter' export default { - watch: ['*.md'], - async load() { - // + // watch all blog posts + watch: ['./posts/*.md'], + load(watchedFiles) { + // watchedFiles will be an array of absolute paths of the matched files. + // generate an array of blog post metadata that can be used to render + // a list in the theme layout + return watchedFiles.map(file => { + const content = fs.readFileSync(file, 'utf-8') + const { data, excerpt } = parseFrontmatter(content) + return { + file, + data, + excerpt + } + }) } } ``` -## Typed Data +## Typed Data Loaders + +When using TypeScript, you can type your loader and `data` export like so: ```ts +import { defineLoader } from 'vitepress' + export interface Data { // data type } @@ -41,9 +96,11 @@ export interface Data { declare const data: Data export { data } -export default { +export default defineLoader({ + // type checked loader options + glob: ['...'], async load(): Promise { // ... } -} +}) ``` diff --git a/docs/guide/deploying.md b/docs/guide/deploy.md similarity index 98% rename from docs/guide/deploying.md rename to docs/guide/deploy.md index 4f5d76de548..904924c516f 100644 --- a/docs/guide/deploying.md +++ b/docs/guide/deploy.md @@ -1,4 +1,4 @@ -# Deploying +# Deploy Your VitePress Site The following guides are based on some shared assumptions: @@ -17,7 +17,7 @@ The following guides are based on some shared assumptions: ::: tip -If your site is to be served at a subdirectory (`https://example.com/subdir/`), then you have to set `'/subdir/'` as the [`base`](../config/app-config#base) in your `docs/.vitepress/config.js`. +If your site is to be served at a subdirectory (`https://example.com/subdir/`), then you have to set `'/subdir/'` as the [`base`](/reference/site-config#base) in your `docs/.vitepress/config.js`. **Example:** If you're using Github (or GitLab) Pages and deploying to `user.github.io/repo/`, then set your `base` to `/repo/`. diff --git a/docs/guide/extending-default-theme.md b/docs/guide/extending-default-theme.md new file mode 100644 index 00000000000..88647cecca6 --- /dev/null +++ b/docs/guide/extending-default-theme.md @@ -0,0 +1,138 @@ +# Extending the Default Theme + +VitePress' default theme is optimized for documentation, and can be customized. Consult the [Default Theme Config Overview](/reference/default-theme-config) for a comprehensive list of options. + +However, there are a number of cases where configuration alone won't be enough. For example: + +1. You need to tweak the CSS styling; +2. You need to modify the Vue app instance, for example to register global components; +3. You need to inject custom content into the theme via layout slots. + +These advanced customizations will require using a custom theme that "extends" the default theme. + +:::tip +Before proceeding, make sure to first read [Using a Custom Theme](./custom-theme) to understand how custom themes work. +::: + +## Customizing CSS + +The default theme CSS is customizable by overriding root level CSS variables: + +```js +// .vitepress/theme/index.js +import DefaultTheme from 'vitepress/theme' +import './custom.css' + +export default DefaultTheme +``` + +```css +/* .vitepress/theme/custom.css */ +:root { + --vp-c-brand: #646cff; + --vp-c-brand-light: #747bff; +} +``` + +See [default theme CSS variables](https://github.com/vuejs/vitepress/blob/main/src/client/theme-default/styles/vars.css) that can be overridden. + +## Registering Global Components + +```js +// .vitepress/theme/index.js +import DefaultTheme from 'vitepress/theme' + +export default { + extends: DefaultTheme, + enhanceApp(ctx) { + // register your custom global components + ctx.app.component('MyGlobalComponent' /* ... */) + } +} +``` + +Since we are using Vite, you can also leverage Vite's [glob import feature](https://vitejs.dev/guide/features.html#glob-import) to auto register a directory of components. + +## Layout Slots + +The default theme's `