docs: update docs for data API change

pull/317/head
Evan You 4 years ago
parent a81b9e0ff1
commit e50ba18fbe

@ -61,9 +61,8 @@ function getGuideSidebar() {
text: 'Advanced', text: 'Advanced',
children: [ children: [
{ text: 'Frontmatter', link: '/guide/frontmatter' }, { text: 'Frontmatter', link: '/guide/frontmatter' },
{ text: 'Global Computed', link: '/guide/global-computed' }, { text: 'Theming', link: '/guide/theming' },
{ text: 'Global Component', link: '/guide/global-component' }, { text: 'API Reference', link: '/guide/api' },
{ text: 'Customization', link: '/guide/customization' },
{ {
text: 'Differences from Vuepress', text: 'Differences from Vuepress',
link: '/guide/differences-from-vuepress' link: '/guide/differences-from-vuepress'

@ -0,0 +1,95 @@
# API Reference
## Helper Methods
The following methods are globally importable from `vitepress` and are typically used in custom theme Vue components. However, they are also usable inside `.md` pages because markdown files are compiled into Vue single-file components.
Methods that start with `use*` indicates that it is a [Vue 3 Composition API](https://v3.vuejs.org/guide/composition-api-introduction.html) function that can only be used inside `setup()` or `<script setup>`.
### `useData`
Returns page-specific data. The returned object has the following type:
```ts
interface VitePressData {
site: Ref<SiteData>
page: Ref<PageData>
theme: Ref<any> // themeConfig from .vitepress/config.js
frontmatter: Ref<PageData['frontmatter']>
title: Ref<string>
description: Ref<string>
lang: Ref<string>
localePath: Ref<string>
}
```
**Example:**
```vue
<script setup>
import { useData } from 'vitepress'
const { theme } = useData()
</script>
<template>
<h1>{{ theme.heroText }}</h1>
</template>
```
### `useRoute`
Returns the current route object with the following type:
```ts
interface Route {
path: string
data: PageData
component: Component | null
}
```
### `useRouter`
Returns the VitePress router instance so you can programmatically navigate to another page.
```ts
interface Router {
route: Route
go: (href?: string) => Promise<void>
}
```
### `withBase`
- **Type**: `(path: string) => string`
Appends the configured [`base`](/config/basics.html#base) to a given URL path. Also see [Base URL](/guide/assets.html#base-url).
## Global Components
VitePress comes with few built-in component that can be used globally. You may use these components in your markdown or your custom theme configuration.
### `<Content/>`
The `<Content/>` component displays the rendered markdown contents. Useful [when creating your own theme](https://vitepress.vuejs.org/guide/customization.html).
```vue
<template>
<h1>Custom Layout!</h1>
<Content />
</template>
```
### `<ClientOnly/>`
The `<ClientOnly/>` component renderes its slot only at client side.
Because VitePress applications are server-rendered in Node.js when generating static builds, any Vue usage must conform to the universal code requirements. In short, make sure to only access Browser / DOM APIs in beforeMount or mounted hooks.
If you are using or demoing components that are not SSR-friendly (for example, contain custom directives), you can wrap them inside the `ClientOnly` component.
```html
<ClientOnly>
<NonSSRFriendlyComponent />
</ClientOnly>
```

@ -26,10 +26,30 @@ Note that you should reference files placed in `public` using root absolute path
If your site is deployed to a non-root URL, you will need to set the `base` option in `.vitepress/config.js`. For example, if you plan to deploy your site to `https://foo.github.io/bar/`, then `base` should be set to `'/bar/'` (it should always start and end with a slash). If your site is deployed to a non-root URL, you will need to set the `base` option in `.vitepress/config.js`. For example, if you plan to deploy your site to `https://foo.github.io/bar/`, then `base` should be set to `'/bar/'` (it should always start and end with a slash).
With a base URL, to reference an image in `public`, you'd have to use URLs like `/bar/image.png`. But this is brittle if you ever decide to change the base. To help with that, VitePress provides a built-in helper `$withBase` (injected onto Vue's prototype) that generates the correct path: All your static asset paths are automatically processed to adjust for different `base` config values. For example, if you have an absolute reference to an asset under `public` in your markdown:
```html ```md
<img :src="$withBase('/foo.png')" alt="foo" /> ![An image](/image-inside-public.png)
```
You do **not** need to update it when you change the `base` config value in this case.
However, if you are authoring a theme component that links to assets dynamically, e.g. an image whose `src` is based on a theme config value:
```vue
<img :src="theme.logoPath" />
``` ```
Note you can use the above syntax not only in theme components, but in your Markdown files as well. In this case it is recommended to wrap the path with the [`withBase` helper](/guide/api.html#withbase) provided by VitePress:
```vue
<script setup>
import { withBase, useData } from 'vitepress'
const { theme } = useData()
</script>
<template>
<img :src="withBase(theme.logoPath)" />
</template>
```

@ -1,51 +0,0 @@
# Customization
You can develop your custom theme by adding the `.vitepress/theme/index.js` file.
```bash
.
├─ docs
│ ├─ .vitepress
│ │ ├─ theme
│ │ │ └─ index.js
│ │ └─ config.js
│ └─ index.md
└─ package.json
```
In `.vitepress/theme/index.js`, you must export theme object and register your own theme layout. Let's say you have your own `Layout` component like this.
```vue
<!-- .vitepress/theme/Layout.vue -->
<template>
<h1>Custom Layout!</h1>
<Content /><!-- make sure to include markdown outlet -->
</template>
```
Then include it in `.vitepress/theme/index.js`.
```js
// .vitepress/theme/index.js
import Layout from './Layout.vue'
export default {
Layout,
NotFound: () => 'custom 404', // <- this is a Vue 3 functional component
enhanceApp({ app, router, siteData }) {
// app is the Vue 3 app instance from `createApp()`. router is VitePress'
// custom router. `siteData`` is a `ref`` of current site-level metadata.
}
}
```
If you want to extend the default theme, you can import it from `vitepress/theme`.
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
export default {
...DefaultTheme
}
```

@ -22,8 +22,8 @@ In case you decide to move your project to VitePress, this is a list of differen
- Components in `.vitepress/components` [are not auto registered as global components](https://vuepress.vuejs.org/) - Components in `.vitepress/components` [are not auto registered as global components](https://vuepress.vuejs.org/)
- Differences - Differences
- [Public files](https://vuepress.vuejs.org/guide/assets.html#public-files) that are directly copied to dist root moved from `.vitepress/public/` is `public/` - [Public files](https://vuepress.vuejs.org/guide/assets.html#public-files) that are directly copied to dist root moved from `.vitepress/public/` is `public/`
- [styling](https://vuepress.vuejs.org/config/#styling) `.vitepress/styles/index.styl` and `.vitepress/styles/palette.styl` is `.vitepress/style.styl` - [styling](https://vuepress.vuejs.org/config/#styling) `.vitepress/styles/index.styl` and `.vitepress/styles/palette.styl` is not supported. See [Customizing CSS](/guide/theming.html#customizing-css).
- [App Level Enhancements](https://vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements) API, app enhancements `.vitepress/enhanceApp.js` is `.vitepress/theme/index.js`. - [App Level Enhancements](https://vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements) API, app enhancements `.vitepress/enhanceApp.js` is now done in `.vitepress/theme/index.js`. See [Extending the Default Theme](/guide/theming.html#extending-the-default-theme).
## Markdown ## Markdown
@ -31,7 +31,6 @@ In case you decide to move your project to VitePress, this is a list of differen
- Support for [toml in frontmatter](https://vuepress.vuejs.org/guide/frontmatter.html#alternative-frontmatter-formats) - Support for [toml in frontmatter](https://vuepress.vuejs.org/guide/frontmatter.html#alternative-frontmatter-formats)
- [details block](https://vuepress.vuejs.org/guide/markdown.html#custom-containers) - [details block](https://vuepress.vuejs.org/guide/markdown.html#custom-containers)
- [markdown slots](https://vuepress.vuejs.org/guide/markdown-slot.html) - [markdown slots](https://vuepress.vuejs.org/guide/markdown-slot.html)
guide/using-vue.html#using-components).
- `~` prefix to explicitly specify a url is a [webpack module request](https://vuepress.vuejs.org/guide/assets.html#relative-urls) - `~` prefix to explicitly specify a url is a [webpack module request](https://vuepress.vuejs.org/guide/assets.html#relative-urls)
## Site Config ## Site Config

@ -9,7 +9,7 @@ editLink: true
--- ---
``` ```
Between the triple-dashed lines, you can set [predefined variables](#predefined-variables), or even create custom ones of your own. These variables can be used via the <code>$frontmatter</code> variable. Between the triple-dashed lines, you can set [predefined variables](#predefined-variables), or even create custom ones of your own. These variables can be used via the special <code>$frontmatter</code> variable.
Heres an example of how you could use it in your Markdown file: Heres an example of how you could use it in your Markdown file:

@ -1,89 +0,0 @@
# Global Computed
In VitePress, some core [computed properties](https://v3.vuejs.org/guide/computed.html#computed-properties) can be used by the default theme or custom themes. Or directly in Markdown pages using vue, for example using `$frontmatter.title` to access the title defined in the frontmatter section of the page.
## $site
This is the `$site` value of the site you're currently reading:
```js
{
base: '/',
lang: 'en-US',
title: 'VitePress',
description: 'Vite & Vue powered static site generator.',
head: [],
locales: {},
themeConfig: $themeConfig
}
```
## $themeConfig
Refers to `$site.themeConfig`.
```js
{
locales: {},
repo: 'vuejs/vitepress',
docsDir: 'docs',
editLinks: true,
editLinkText: 'Edit this page on GitHub',
lastUpdated: 'Last Updated',
nav: [...],
sidebar: { ... }
}
```
## $page
This is the `$page` value of the page you're currently reading:
```js
{
relativePath: 'guide/global-computed.md',
title: 'Global Computed',
headers: [
{ level: 2, title: '$site', slug: 'site' },
{ level: 2, title: '$page', slug: '$page' },
...
],
frontmatter: $frontmatter,
lastUpdated: 1606297645000
}
```
## $frontmatter
Reference of `$page.frontmatter`.
```js
{
title: 'Docs with VitePress',
editLink: true
}
```
## $lang
The language of the current page. Default: `en-US`.
## $localePath
The locale path prefix for the current page. Default: `/`.
## $title
Value of the `<title>` label used for the current page.
## $description
The content value of the `<meta name= "description" content= "...">` for the current page.
## $withBase
Helper method to generate correct path by prepending the `base` path configured in `.vitepress/config.js`. It's useful when you want to link to [public files with base path](./assets#public-files).
```html
<img :src="$withBase('/foo.png')" alt="foo" />
```

@ -0,0 +1,157 @@
# Theming
## Using a Custom Theme
You can enable a custom theme by adding the `.vitepress/theme/index.js` file (the "theme entry file").
```bash
.
├─ docs
│ ├─ .vitepress
│ │ ├─ theme
│ │ │ └─ index.js
│ │ └─ config.js
│ └─ index.md
└─ package.json
```
A VitePress custom theme is simply an object containing three properties and is defined as follows:
```ts
interface Theme {
Layout: Component // Vue 3 component
NotFound?: Component
enhanceApp?: (ctx: EnhanceAppContext) => void
}
interface EnhanceAppContext {
app: App // Vue 3 app instance
router: Router // VitePress router instance
siteData: Ref<SiteData>
}
```
The theme entry file shoud export the theme as its default export:
```js
// .vitepress/theme/index.js
import Layout from './Layout.vue'
export default {
Layout,
NotFound: () => 'custom 404', // <- this is a Vue 3 functional component
enhanceApp({ app, router, siteData }) {
// app is the Vue 3 app instance from `createApp()`. router is VitePress'
// custom router. `siteData`` is a `ref`` of current site-level metadata.
}
}
```
...where the `Layout` component could like this:
```vue
<!-- .vitepress/theme/Layout.vue -->
<template>
<h1>Custom Layout!</h1>
<Content /><!-- this is where markdown content will be rendered -->
</template>
```
The default export is the only contract for a custom theme. Inside your custom theme, it works just like a normal Vite + Vue 3 application. Do note the theme also needs to be [SSR-compatible](/guide/using-vue.html#browser-api-access-restrictions).
To distribute a theme, simply export the object in your package entry. To consume an external theme, import and re-export it from the custom theme entry:
```js
// .vitepress/theme/index.js
import Theme from 'awesome-vitepress-theme'
export default Theme
```
## Extending the Default Theme
If you want to extend and customize the default theme, you can import it from `vitepress/theme` and augment it in a custom theme entry. Here are some examples of common customizations:
### Registering Global Components
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
export default {
...DefaultTheme,
enhanceApp({ app }) {
// register global components
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.
### 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 {
--c-brand: #646cff;
--c-brand-light: #747bff;
}
```
See [default theme CSS variables](https://github.com/vuejs/vitepress/blob/master/src/client/theme-default/styles/vars.css) that can be overridden.
### Layout Slots
The default theme's `<Layout/>` component has a few slots that can be used to inject content at certain locations of the page. Here's an example of injecting a component into the top of the sidebar:
```js
// .vitepress/theme/index.js
import DefaultTheme from 'vitepress/theme'
import MyLayout fro './MyLayout.vue'
export default {
...DefaultTheme,
// override the Layout with a wrapper component that injects the slots
Layout: MyLayout
}
```
```vue
<!--.vitepress/theme/MyLayout.vue-->
<script setup>
import DefaultTheme from 'vitepress/theme'
const { Layout } = DefaultTheme
</script>
<template>
<Layout>
<template #sidebar-top>
My custom sidebar top content
</template>
</Layout>
</template>
```
Full list of slots available in the default theme layout:
- `navbar-search`
- `sidebar-top`
- `sidebar-bottom`
- `page-top-ads`
- `page-top`
- `page-bottom`
- `page-bottom-ads`
- Only when `home: true` is enabled via frontmatter:
- `home-hero`
- `home-features`
- `home-footer`

@ -1,59 +1,8 @@
# Using Vue in Markdown # Using Vue in Markdown
## Browser API Access Restrictions In VitePress, each markdown file is compiled into HTML and then processed as a Vue Single-File Component. This means you can use any Vue features inside the markdown, including dynamic templating, using Vue components, or arbitrary in-page Vue component logic by adding a `<script>` tag.
Because VitePress applications are server-rendered in Node.js when generating static builds, any Vue usage must conform to the [universal code requirements](https://ssr.vuejs.org/en/universal.html). In short, make sure to only access Browser / DOM APIs in `beforeMount` or `mounted` hooks.
If you are using or demoing components that are not SSR-friendly (for example, contain custom directives), you can wrap them inside the built-in `<ClientOnly>` component:
``` md
<ClientOnly>
<NonSSRFriendlyComponent/>
</ClientOnly>
```
Note this does not fix components or libraries that access Browser APIs **on import**. To use code that assumes a browser environment on import, you need to dynamically import them in proper lifecycle hooks:
``` vue
<script>
export default {
mounted () {
import('./lib-that-access-window-on-import').then(module => {
// use code
})
}
}
</script>
```
If your module `export default` a Vue component, you can register it dynamically:
```vue
<template>
<component v-if="dynamicComponent" :is="dynamicComponent"></component>
</template>
<script>
export default {
data() {
return {
dynamicComponent: null
}
},
mounted () {
import('./lib-that-access-window-on-import').then(module => {
this.dynamicComponent = module.default
})
}
}
</script>
```
**Also see:**
- [Vue.js > Dynamic Components](https://v3.vuejs.org/guide/component-dynamic-async.html)
It is also important to know that VitePress leverages Vue 3's compiler to automatically detect and optimize the purely static parts of the markdown. Static contents are optimized into single placeholder nodes and eliminated from the page's JavaScript payload. They are also skipped during client-side hydration. In short, you only pay for the dynamic parts on any given page.
## Templating ## Templating
@ -63,7 +12,7 @@ Each Markdown file is first compiled into HTML and then passed on as a Vue compo
**Input** **Input**
``` md ```md
{{ 1 + 1 }} {{ 1 + 1 }}
``` ```
@ -77,7 +26,7 @@ Directives also work:
**Input** **Input**
``` md ```md
<span v-for="i in 3">{{ i }} </span> <span v-for="i in 3">{{ i }} </span>
``` ```
@ -87,17 +36,22 @@ Directives also work:
### Access to Site & Page Data ### Access to Site & Page Data
The compiled component has access to the [site metadata and computed properties](./global-computed.md). For example: You can use the [`useData` helper](/guide/api.html#usedata) in a `<script>` block and expose the data to the page.
**Input** **Input**
``` md ```md
{{ $page }} <script setup>
import { useData } from 'vitepress'
const { page } = useData()
</script>
<pre>{{ page }}</pre>
``` ```
**Output** **Output**
``` json ```json
{ {
"path": "/using-vue.html", "path": "/using-vue.html",
"title": "Using Vue in Markdown", "title": "Using Vue in Markdown",
@ -111,7 +65,7 @@ By default, fenced code blocks are automatically wrapped with `v-pre`. To displa
**Input** **Input**
``` md ```md
::: v-pre ::: v-pre
`{{ This will be displayed as-is }}` `{{ This will be displayed as-is }}`
::: :::
@ -129,9 +83,13 @@ When you need to have more flexibility, VitePress allows you to extend your auth
### Importing components in markdown ### Importing components in markdown
If your components are going to be used in only a few places, the recommended way to use them is to importing the components in the file where it is used. If your components are going to be used in only a few places, the recommended way to use them is to importing the components in the file where it is used.
```md ```md
<script setup>
import CustomComponent from '../components/CustomComponent.vue'
</script>
# Docs # Docs
This is a .md using a custom component This is a .md using a custom component
@ -141,10 +99,6 @@ This is a .md using a custom component
## More docs ## More docs
... ...
<script setup>
import CustomComponent from '../components/CustomComponent.vue'
</script>
``` ```
### Registering global components in the theme ### Registering global components in the theme
@ -180,9 +134,9 @@ Make sure a custom components name either contains a hyphen or is in PascalCa
You can use Vue components in the headers, but note the difference between the following syntaxes: You can use Vue components in the headers, but note the difference between the following syntaxes:
| Markdown | Output HTML | Parsed Header | | Markdown | Output HTML | Parsed Header |
|--------|-------------|----------------| | ------------------------------------------------------- | ----------------------------------------- | ------------- |
| <pre v-pre><code> # text &lt;Tag/&gt; </code></pre> | `<h1>text <Tag/></h1>` | `text` | | <pre v-pre><code> # text &lt;Tag/&gt; </code></pre> | `<h1>text <Tag/></h1>` | `text` |
| <pre v-pre><code> # text \`&lt;Tag/&gt;\` </code></pre> | `<h1>text <code>&lt;Tag/&gt;</code></h1>` | `text <Tag/>` | | <pre v-pre><code> # text \`&lt;Tag/&gt;\` </code></pre> | `<h1>text <code>&lt;Tag/&gt;</code></h1>` | `text <Tag/>` |
The HTML wrapped by `<code>` will be displayed as-is; only the HTML that is **not** wrapped will be parsed by Vue. The HTML wrapped by `<code>` will be displayed as-is; only the HTML that is **not** wrapped will be parsed by Vue.
@ -208,7 +162,7 @@ npm install -D stylus
Then you can use the following in Markdown and theme components: Then you can use the following in Markdown and theme components:
``` vue ```vue
<style lang="sass"> <style lang="sass">
.title .title
font-size: 20px font-size: 20px
@ -246,4 +200,58 @@ VitePress provides Built-In Vue Components like `ClientOnly` and `OutboundLink`,
**Also see:** **Also see:**
- [Using Components In Headers](#using-components-in-headers) - [Using Components In Headers](#using-components-in-headers)
## Browser API Access Restrictions
Because VitePress applications are server-rendered in Node.js when generating static builds, any Vue usage must conform to the [universal code requirements](https://ssr.vuejs.org/en/universal.html). In short, make sure to only access Browser / DOM APIs in `beforeMount` or `mounted` hooks.
If you are using or demoing components that are not SSR-friendly (for example, contain custom directives), you can wrap them inside the built-in `<ClientOnly>` component:
```md
<ClientOnly>
<NonSSRFriendlyComponent/>
</ClientOnly>
```
Note this does not fix components or libraries that access Browser APIs **on import**. To use code that assumes a browser environment on import, you need to dynamically import them in proper lifecycle hooks:
```vue
<script>
export default {
mounted() {
import('./lib-that-access-window-on-import').then((module) => {
// use code
})
}
}
</script>
```
If your module `export default` a Vue component, you can register it dynamically:
```vue
<template>
<component v-if="dynamicComponent" :is="dynamicComponent"></component>
</template>
<script>
export default {
data() {
return {
dynamicComponent: null
}
},
mounted() {
import('./lib-that-access-window-on-import').then((module) => {
this.dynamicComponent = module.default
})
}
}
</script>
```
**Also see:**
- [Vue.js > Dynamic Components](https://v3.vuejs.org/guide/component-dynamic-async.html)

@ -1,7 +1,11 @@
---
sidebarDepth: 1
---
# What is VitePress? # What is VitePress?
::: warning WARNING ::: warning WARNING
VitePress is early WIP! Currently the focus is on making Vite stable and feature complete first. It is not recommended to use this for anything serious yet. VitePress is currently in 0.x status. It is already suitable for out-of-the-box documentation use, but the config and theming API may still change between minor releases.
::: :::
VitePress is [VuePress](https://vuepress.vuejs.org/)' little brother, built on top of [Vite](https://github.com/vitejs/vite). VitePress is [VuePress](https://vuepress.vuejs.org/)' little brother, built on top of [Vite](https://github.com/vitejs/vite).
@ -10,8 +14,6 @@ VitePress is [VuePress](https://vuepress.vuejs.org/)' little brother, built on t
We love VuePress v1, but being built on top of Webpack, the time it takes to spin up the dev server for a simple doc site with a few pages is just becoming unbearable. Even HMR updates can take up to seconds to reflect in the browser! We love VuePress v1, but being built on top of Webpack, the time it takes to spin up the dev server for a simple doc site with a few pages is just becoming unbearable. Even HMR updates can take up to seconds to reflect in the browser!
As a reference, the [Composition API RFC repo](https://github.com/vuejs/composition-api-rfc) is just two pages, but it takes 4 seconds to spin up the server and almost 2 seconds for any edit to reflect in the browser.
Fundamentally, this is because VuePress v1 is a Webpack app under the hood. Even with just two pages, it's a full on Webpack project (including all the theme source files) being compiled. It gets even worse when the project has many pages every page must first be fully compiled before the server can even display anything! Fundamentally, this is because VuePress v1 is a Webpack app under the hood. Even with just two pages, it's a full on Webpack project (including all the theme source files) being compiled. It gets even worse when the project has many pages every page must first be fully compiled before the server can even display anything!
Incidentally, Vite solves these problems really well: nearly instant server start, an on-demand compilation that only compiles the page being served, and lightning-fast HMR. Plus, there are a few additional design issues I have noted in VuePress v1 over time but never had the time to fix due to the amount of refactoring it would require. Incidentally, Vite solves these problems really well: nearly instant server start, an on-demand compilation that only compiles the page being served, and lightning-fast HMR. Plus, there are a few additional design issues I have noted in VuePress v1 over time but never had the time to fix due to the amount of refactoring it would require.

Loading…
Cancel
Save