|
1 |
| ---- |
2 |
| -sidebar: auto |
3 |
| ---- |
4 |
| - |
5 | 1 | # Theme
|
6 | 2 |
|
7 | 3 | ::: tip
|
8 | 4 | Theme components are subject to the same [browser API access restrictions](../guide/using-vue.md#browser-api-access-restrictions).
|
9 | 5 | :::
|
10 |
| - |
11 |
| -## Writing a theme |
12 |
| - |
13 |
| -To write a theme, create a `.vuepress/theme` directory in your docs root, and then create a `Layout.vue` file: |
14 |
| - |
15 |
| -::: vue |
16 |
| -. |
17 |
| -└─ .vuepress |
18 |
| - └─ `theme` |
19 |
| - └─ Layout.vue |
20 |
| -::: |
21 |
| - |
22 |
| -From there it's the same as developing a normal Vue application. It is entirely up to you how to organize your theme. |
23 |
| - |
24 |
| -### Directory Structure |
25 |
| - |
26 |
| -Just one `Layout.vue` might not be enough, and you might also want to define more layout components in the theme for using on different pages. You may also want to customize the [palette](../config/README.md#palette), and even apply some plugins. |
27 |
| - |
28 |
| -So it's time to reorganize your theme, an agreed theme directory structure is as follows: |
29 |
| - |
30 |
| -::: vue |
31 |
| -themePath |
32 |
| -├── `global-components` _(**Optional**)_ |
33 |
| -│ └── xxx.vue |
34 |
| -├── `components` _(**Optional**)_ |
35 |
| -│ └── xxx.vue |
36 |
| -├── `layouts` |
37 |
| -│ ├── Layout.vue _(**Required**)_ |
38 |
| -│ └── 404.vue _(**Optional**)_ |
39 |
| -├── `styles` _(**Optional**)_ |
40 |
| -│ ├── index.styl |
41 |
| -│ └── palette.styl |
42 |
| -├── `templates` _(**Optional**)_ |
43 |
| -│ ├── dev.html |
44 |
| -│ └── ssr.html |
45 |
| -├── `index.js` _(**Only required when you publish it as an npm package**)_ |
46 |
| -├── `enhanceApp.js` _(**Optional**)_ |
47 |
| -└── package.json |
48 |
| -::: |
49 |
| - |
50 |
| -- `theme/global-components`: Components under this directory will be automatically registered as global components. For details, please refer to [@vuepress/plugin-register-components](https://github.com/vuejs/vuepress/tree/master/packages/@vuepress/plugin-register-components). |
51 |
| -- `theme/components`: Your components. |
52 |
| -- `theme/layouts`: Layout components of the theme, where `Layout.vue` is required. |
53 |
| -- `theme/styles`: Global style and palette. |
54 |
| -- `theme/templates`: Modify default template. |
55 |
| -- `theme/index.js`: Entry file of theme configuration. |
56 |
| -- `theme/enhanceApp.js`: Theme level enhancements. |
57 |
| - |
58 |
| -::: warning Note |
59 |
| -1. Considering backward compatibility, Vue components located at [themePath](../miscellaneous/glossary.md#theme-side) will also be automatically registered as layout components. But the recommended is placing them under `themePath/layouts` directory, which looks more clearer. |
60 |
| -2. When you want to publish your theme as an npm package, make sure the package has `index.js`, and set `"main"` field at `package.json` to `index.js` so that VuePress can resolve and get the correct [themePath](../miscellaneous/glossary.md#theme-side). |
61 |
| - |
62 |
| -```json |
63 |
| -{ |
64 |
| - ... |
65 |
| - "main": "index.js" |
66 |
| - ... |
67 |
| -} |
68 |
| -``` |
69 |
| - |
70 |
| -::: |
71 |
| - |
72 |
| -### Layout Component |
73 |
| - |
74 |
| -Suppose your theme layouts folder is as follows: |
75 |
| - |
76 |
| -::: vue |
77 |
| -theme |
78 |
| -└── `layouts` |
79 |
| - ├── Layout.vue |
80 |
| - ├── AnotherLayout.vue |
81 |
| - └── 404.vue |
82 |
| -::: |
83 |
| - |
84 |
| -Then, all the pages will use `Layout.vue` as layout component by default, while the routes not matching will use `404.vue`. |
85 |
| - |
86 |
| -If you want to switch the layout of the some page to `AnotherLayout.vue`, you just need to update the frontmatter of this page: |
87 |
| - |
88 |
| -```markdown |
89 |
| ---- |
90 |
| -layout: AnotherLayout |
91 |
| ---- |
92 |
| -```` |
93 |
| - |
94 |
| -### Apply plugins |
95 |
| - |
96 |
| -You can apply some plugins to the theme via `theme/index.js`. |
97 |
| - |
98 |
| -```js |
99 |
| -module.exports = { |
100 |
| - plugins: [ |
101 |
| - '@vuepress/pwa', |
102 |
| - { |
103 |
| - serviceWorker: true, |
104 |
| - updatePopup: true |
105 |
| - } |
106 |
| - ] |
107 |
| -} |
108 |
| -``` |
109 |
| - |
110 |
| -For themes that need to be released to NPM, please do not forget to add it to `dependencies`: |
111 |
| - |
112 |
| -```json |
113 |
| -{ |
114 |
| - "dependencies": { |
115 |
| - "@vuepress/plugin-pwa": "^x.x.x", |
116 |
| - } |
117 |
| -} |
118 |
| -``` |
119 |
| - |
120 |
| -### Site and Page Metadata |
121 |
| - |
122 |
| -The `Layout` component will be invoked once for every `.md` file in `docs`, and the metadata for the entire site and that specific page will be exposed respectively as `this.$site` and `this.$page` properties which are injected into every component in the app. |
123 |
| - |
124 |
| -This is the value of `$site` of this very website: |
125 |
| - |
126 |
| -``` json |
127 |
| -{ |
128 |
| - "title": "VuePress", |
129 |
| - "description": "Vue-powered Static Site Generator", |
130 |
| - "base": "/", |
131 |
| - "pages": [ |
132 |
| - { |
133 |
| - "lastUpdated": 1524027677000, |
134 |
| - "path": "/", |
135 |
| - "title": "VuePress", |
136 |
| - "frontmatter": {} |
137 |
| - }, |
138 |
| - ... |
139 |
| - ] |
140 |
| -} |
141 |
| -``` |
142 |
| - |
143 |
| -`title`, `description` and `base` are copied from respective fields in `.vuepress/config.js`. `pages` contains an array of metadata objects for each page, including its path, page title (explicitly specified in [YAML front matter](../guide/markdown.md#front-matter) or inferred from the first header on the page), and any YAML front matter data in that file. |
144 |
| - |
145 |
| -This is the `$page` object for this page you are looking at: |
146 |
| - |
147 |
| -``` json |
148 |
| -{ |
149 |
| - "lastUpdated": 1524847549000, |
150 |
| - "path": "/guide/custom-themes.html", |
151 |
| - "title": "Custom Themes", |
152 |
| - "headers": [/* ... */], |
153 |
| - "frontmatter": {} |
154 |
| -} |
155 |
| -``` |
156 |
| - |
157 |
| -If the user provided `themeConfig` in `.vuepress/config.js`, it will also be available as `$site.themeConfig`. You can use this to allow users to customize behavior of your theme - for example, specifying categories and page order. You can then use these data together with `$site.pages` to dynamically construct navigation links. |
158 |
| - |
159 |
| -Finally, don't forget that `this.$route` and `this.$router` are also available as part of Vue Router's API. |
160 |
| - |
161 |
| -::: tip |
162 |
| - `lastUpdated` is the UNIX timestamp of this file's last git commit, for more details, refer to [Last Updated](../theme/default-theme-config.md#last-updated). |
163 |
| -::: |
164 |
| - |
165 |
| -### Content Excerpt |
166 |
| - |
167 |
| -If a markdown file contains a `<!-- more -->` comment, any content above the comment will be extracted and exposed as `$page.excerpt`. If you are building custom theme for blogging, this data can be used to render a post list with excerpts. |
168 |
| - |
169 |
| -### Content Outlet |
170 |
| - |
171 |
| -The compiled content of the current `.md` file being rendered will be available as a special `<Content/>` global component. You will need to render it somewhere in your layout in order to display the content of the page. The simplest theme can be just a single `Layout.vue` component with the following content: |
172 |
| - |
173 |
| -``` html |
174 |
| -<template> |
175 |
| - <div class="theme-container"> |
176 |
| - <Content/> |
177 |
| - </div> |
178 |
| -</template> |
179 |
| -``` |
180 |
| - |
181 |
| -### App Level Enhancements |
182 |
| - |
183 |
| -Themes can enhance the Vue app that VuePress uses by exposing an `enhanceApp.js` file at the root of the theme. The file should `export default` a hook function which will receive an object containing some app level values. You can use this hook to install additional Vue plugins, register global components, or add additional router hooks: |
184 |
| - |
185 |
| -``` js |
186 |
| -export default ({ |
187 |
| - Vue, // the version of Vue being used in the VuePress app |
188 |
| - options, // the options for the root Vue instance |
189 |
| - router, // the router instance for the app |
190 |
| - siteData // site metadata |
191 |
| -}) => { |
192 |
| - // ...apply enhancements to the app |
193 |
| -} |
194 |
| -``` |
195 |
| - |
196 |
| -## Using a theme |
197 |
| - |
198 |
| -Using a theme is almost same as using a plugin. |
199 |
| - |
200 |
| -### Use plugins from a dependency |
201 |
| - |
202 |
| -Themes can be published on npm in raw Vue SFC format as `vuepress-theme-xxx`. |
203 |
| - |
204 |
| -``` js |
205 |
| -module.exports = { |
206 |
| - plugins: [ 'vuepress-theme-xx' ] |
207 |
| -} |
208 |
| -``` |
209 |
| - |
210 |
| -### Theme Shorthand |
211 |
| - |
212 |
| -If you prefix the plugin with `vuepress-theme-`, you can use a shorthand to leave out that prefix: |
213 |
| - |
214 |
| -``` js |
215 |
| -module.exports = { |
216 |
| - plugins: [ 'xxx' ] |
217 |
| -} |
218 |
| -``` |
219 |
| - |
220 |
| -Same with: |
221 |
| - |
222 |
| -``` js |
223 |
| -module.exports = { |
224 |
| - plugins: [ 'vuepress-theme-xxx' ] |
225 |
| -} |
226 |
| -``` |
227 |
| - |
228 |
| -This also works with [Scoped Packages](https://docs.npmjs.com/misc/scope): |
229 |
| - |
230 |
| -``` js |
231 |
| -module.exports = { |
232 |
| - plugins: [ '@org/vuepress-theme-xxx', '@vuepress/theme-xxx' ] |
233 |
| -} |
234 |
| -``` |
235 |
| - |
236 |
| -Shorthand: |
237 |
| - |
238 |
| -``` js |
239 |
| -module.exports = { |
240 |
| - plugins: [ '@org/xxx', '@vuepress/xxx' ] |
241 |
| -} |
242 |
| -``` |
243 |
| - |
244 |
| -::: warning Note |
245 |
| -The plugin whose name starts with `@vuepress/theme-` is an officially maintained theme. |
246 |
| -::: |
247 |
| - |
248 |
| -## Options |
249 |
| - |
250 |
| -### plugins |
251 |
| - |
252 |
| -- Type: `Array|Object` |
253 |
| -- Default: undefined |
254 |
| - |
255 |
| -See: [Plugin > Using a plugin](../plugin/README.md#using-a-plugin). |
0 commit comments