├── .editorconfig ├── .eslintrc.js ├── .gitattributes ├── .gitignore ├── .prettierrc.js ├── LICENSE ├── README.md ├── cli.js ├── index.js ├── lib ├── BasicGenerator.js ├── generators │ ├── blog │ │ ├── index.js │ │ ├── meta.json │ │ └── templates │ │ │ ├── _gitignore │ │ │ ├── blog │ │ │ ├── .vuepress │ │ │ │ ├── config.js │ │ │ │ ├── enhanceApp.js │ │ │ │ └── styles │ │ │ │ │ ├── index.styl │ │ │ │ │ └── palette.styl │ │ │ └── _posts │ │ │ │ ├── 2018-11-07-frontmatter-in-vuepress-2.md │ │ │ │ ├── 2018-11-07-frontmatter-in-vuepress-3.md │ │ │ │ ├── 2018-11-07-frontmatter-in-vuepress.md │ │ │ │ ├── 2019-02-26-markdown-slot-2.md │ │ │ │ ├── 2019-02-26-markdown-slot-3.md │ │ │ │ ├── 2019-02-26-markdown-slot-4.md │ │ │ │ ├── 2019-02-26-markdown-slot.md │ │ │ │ ├── 2019-05-06-writing-a-vuepress-theme-2.md │ │ │ │ ├── 2019-05-06-writing-a-vuepress-theme-3.md │ │ │ │ ├── 2019-05-06-writing-a-vuepress-theme-4.md │ │ │ │ └── 2019-05-06-writing-a-vuepress-theme.md │ │ │ └── package.json │ └── docs │ │ ├── index.js │ │ ├── meta.json │ │ └── templates │ │ ├── .gitignore │ │ ├── docs │ │ ├── .vuepress │ │ │ ├── components │ │ │ │ ├── Foo │ │ │ │ │ └── Bar.vue │ │ │ │ ├── OtherComponent.vue │ │ │ │ └── demo-component.vue │ │ │ ├── config.js │ │ │ ├── enhanceApp.js │ │ │ └── styles │ │ │ │ ├── index.styl │ │ │ │ └── palette.styl │ │ ├── README.md │ │ ├── config.md │ │ └── guide │ │ │ ├── README.md │ │ │ └── using-vue.md │ │ └── package.json └── run.js ├── package.json └── yarn.lock /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | indent_style = space 5 | indent_size = 2 6 | end_of_line = lf 7 | charset = utf-8 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | 11 | [*.md] 12 | trim_trailing_whitespace = false -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | root: true, 3 | 4 | env: { 5 | node: true, 6 | es6: true 7 | }, 8 | 9 | extends: ['plugin:prettier/recommended'], 10 | 11 | rules: { 12 | 'no-undef': ['error'] 13 | } 14 | }; 15 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text=auto 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist/ 3 | coverage/ 4 | -------------------------------------------------------------------------------- /.prettierrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | singleQuote: true, 3 | tabWidth: 2, 4 | } 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) Ben Hong (https://github.com/bencodezen) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # create-vuepress-site 2 | 3 | Scaffolding a VuePress project 4 | 5 | ## Getting Started 6 | 7 | ### Run generator 8 | 9 | In the desired folder, run the following command to start the VuePress site generator: 10 | 11 | ```shell 12 | npx create-vuepress-site 13 | # yarn create vuepress-site 14 | ``` 15 | 16 | This will create a scaffolded documentation site in the `docs` directory that is enclosed from the rest of the folder. 17 | 18 | ### Setup local environment 19 | 20 | ```shell 21 | # Navigate into newly scaffolded docs directory 22 | cd docs 23 | 24 | # Install dependencies 25 | npm install 26 | # yarn install 27 | 28 | # Start local dev server 29 | npm run dev 30 | ``` 31 | 32 | By default, you should now see your scaffolded VuePress docs site at https://localhost:8080! 33 | 34 | ## Contributing 35 | 36 | 1. Fork it! 37 | 2. Create your feature branch: `git checkout -b my-new-feature` 38 | 3. Commit your changes: `git commit -am 'Add some feature'` 39 | 4. Push to the branch: `git push origin my-new-feature` 40 | 5. Submit a pull request :D 41 | 42 | ## Hat Tip 43 | 44 | `create-vuepress-site` exists due to the previous work of: 45 | 46 | - [create-vuepress](https://github.com/vuepressjs/create-vuepress) 47 | 48 | - [create-umi](https://github.com/umijs/create-umi) (Direct reuse of scaffolding functions of the library.) 49 | -------------------------------------------------------------------------------- /cli.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | const { existsSync } = require('fs'); 4 | const { join } = require('path'); 5 | const yParser = require('yargs-parser'); 6 | const semver = require('semver'); 7 | const chalk = require('chalk'); 8 | const run = require('./lib/run'); 9 | 10 | // Print version and @local 11 | const args = yParser(process.argv.slice(2)); 12 | 13 | if (args.v || args.version) { 14 | console.log(require('./package').version); 15 | if (existsSync(join(__dirname, '.local'))) { 16 | console.log(chalk.cyan('@local')); 17 | } 18 | process.exit(0); 19 | } 20 | 21 | if (!semver.satisfies(process.version, '>= 8.0.0')) { 22 | console.error( 23 | chalk.red('✘ The generator will only work with Node v8.0.0 and up!') 24 | ); 25 | process.exit(1); 26 | } 27 | 28 | const name = args._[0] || ''; 29 | run({ 30 | name, 31 | args 32 | }); 33 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const run = require('./lib/run'); 2 | 3 | module.exports.run = run; 4 | -------------------------------------------------------------------------------- /lib/BasicGenerator.js: -------------------------------------------------------------------------------- 1 | const { statSync } = require('fs'); 2 | const { basename } = require('path'); 3 | const Generator = require('yeoman-generator'); 4 | const glob = require('glob'); 5 | const debug = require('debug')('create-vuepress:BasicGenerator'); 6 | 7 | function noop() { 8 | return true; 9 | } 10 | 11 | class BasicGenerator extends Generator { 12 | constructor(opts) { 13 | super(opts); 14 | this.opts = opts; 15 | this.name = basename(opts.env.cwd); 16 | } 17 | 18 | isTsFile(f) { 19 | return ( 20 | f.endsWith('.ts') || 21 | f.endsWith('.tsx') || 22 | ['tsconfig.json', 'tslint.yml'].includes(f) 23 | ); 24 | } 25 | 26 | writeFiles({ context, filterFiles = noop }) { 27 | debug(`context: ${JSON.stringify(context)}`); 28 | glob 29 | .sync('**/*', { 30 | cwd: this.templatePath(), 31 | dot: true 32 | }) 33 | .filter(filterFiles) 34 | .forEach(file => { 35 | debug(`copy ${file}`); 36 | const filePath = this.templatePath(file); 37 | if (statSync(filePath).isFile()) { 38 | this.fs.copyTpl( 39 | this.templatePath(filePath), 40 | this.destinationPath(file.replace(/^_/, '.')), 41 | context 42 | ); 43 | } 44 | }); 45 | } 46 | } 47 | 48 | module.exports = BasicGenerator; 49 | -------------------------------------------------------------------------------- /lib/generators/blog/index.js: -------------------------------------------------------------------------------- 1 | const BasicGenerator = require('../../BasicGenerator'); 2 | 3 | class Generator extends BasicGenerator { 4 | prompting() { 5 | const prompts = [ 6 | { 7 | name: 'name', 8 | message: `What's the name of your project?`, 9 | default: this.name 10 | }, 11 | { 12 | name: 'description', 13 | message: `What's the description of your project?` 14 | }, 15 | { 16 | name: 'mail', 17 | message: `What's your email?` 18 | }, 19 | { 20 | name: 'author', 21 | message: `What's your name?` 22 | }, 23 | { 24 | name: 'repo', 25 | message: `What's the repo of your project?` 26 | } 27 | ]; 28 | return this.prompt(prompts).then(props => { 29 | this.prompts = props; 30 | }); 31 | } 32 | 33 | writing() { 34 | this.writeFiles({ 35 | context: this.prompts, 36 | filterFiles: () => { 37 | return true; 38 | } 39 | }); 40 | } 41 | } 42 | 43 | module.exports = Generator; 44 | -------------------------------------------------------------------------------- /lib/generators/blog/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Create a blog with VuePress." 3 | } 4 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/_gitignore: -------------------------------------------------------------------------------- 1 | pids 2 | logs 3 | node_modules 4 | npm-debug.log 5 | coverage/ 6 | run 7 | dist 8 | .DS_Store 9 | .nyc_output 10 | .basement 11 | config.local.js 12 | basement_dist 13 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | title: 'VuePress Blog Example', 3 | description: 'This is a blog example built by VuePress', 4 | theme: '@vuepress/theme-blog', // OR shortcut: @vuepress/blog 5 | themeConfig: { 6 | /** 7 | * Ref: https://vuepress-theme-blog.ulivz.com/#modifyblogpluginoptions 8 | */ 9 | modifyBlogPluginOptions(blogPluginOptions) { 10 | return blogPluginOptions 11 | }, 12 | /** 13 | * Ref: https://vuepress-theme-blog.ulivz.com/#nav 14 | */ 15 | nav: [ 16 | { 17 | text: 'Blog', 18 | link: '/', 19 | }, 20 | { 21 | text: 'Tags', 22 | link: '/tag/', 23 | }, 24 | ], 25 | /** 26 | * Ref: https://vuepress-theme-blog.ulivz.com/#footer 27 | */ 28 | footer: { 29 | contact: [ 30 | { 31 | type: 'github', 32 | link: 'https://github.com/ulivz', 33 | }, 34 | { 35 | type: 'twitter', 36 | link: 'https://twitter.com/_ulivz', 37 | }, 38 | ], 39 | copyright: [ 40 | { 41 | text: 'Privacy Policy', 42 | link: 'https://policies.google.com/privacy?hl=en-US', 43 | }, 44 | { 45 | text: 'MIT Licensed | Copyright © 2018-present Vue.js', 46 | link: '', 47 | }, 48 | ], 49 | }, 50 | }, 51 | } 52 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Client app enhancement file. 3 | * 4 | * https://vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements 5 | */ 6 | 7 | export default ({ 8 | Vue, // the version of Vue being used in the VuePress app 9 | options, // the options for the root Vue instance 10 | router, // the router instance for the app 11 | siteData // site metadata 12 | }) => { 13 | // ...apply enhancements to the app 14 | } 15 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Styles here. 3 | * 4 | * ref:https://v1.vuepress.vuejs.org/config/#index-styl 5 | */ 6 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/.vuepress/styles/palette.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Override default preset here. 3 | * 4 | * ref:https // vuepress.vuejs.org/config/#palette-styl 5 | */ 6 | 7 | // colors 8 | // $accentColor = lighten(#4a154b, 50%) 9 | 10 | // $textColor = #2c3e50 11 | // $darkTextColor = #000 12 | 13 | // $borderColor = rgba(0,0,0,.05) 14 | // $darkBorderColor = #000 15 | 16 | // $codeBgColor = #000 17 | 18 | // $bgColor = #fff 19 | // $headerBgColor = $bgColor; 20 | 21 | // $footerBgColor = #000 22 | // $footerColor = #828282 23 | 24 | // $newsletterBgColor = #f8f8f8 25 | 26 | // layout 27 | // $headerHeight = 80px 28 | // $contentWidth = 740px 29 | 30 | // responsive breakpoints 31 | // $MQNarrow = 959px 32 | // $MQMobile = 719px 33 | // $MQMobileNarrow = 419px 34 | 35 | // code 36 | // $lineNumbersWrapperWidth = 3.5rem 37 | // $codeLang = js ts html md vue css sass scss less stylus go java c sh yaml py docker dockerfile makefile 38 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2018-11-07-frontmatter-in-vuepress-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: frontmatter in vuepress 2 3 | date: 2018-11-07 4 | tags: 5 | - frontmatter 6 | - vuepress 7 | author: ULIVZ 8 | location: Hangzhou 9 | --- 10 | 11 | Any markdown file that contains a YAML front matter block will be processed by [gray-matter](https://github.com/jonschlinkert/gray-matter). The front matter must be the first thing in the markdown file and must take the form of valid YAML set between triple-dashed lines. Here is a basic example: 12 | 13 | ```markdown 14 | --- 15 | title: Blogging Like a Hacker 16 | lang: en-US 17 | --- 18 | ``` 19 | 20 | Between these triple-dashed lines, you can set predefined variables (see [below](#predefined-variables) for a reference), or even create custom ones of your own. These variables will then be available to you to access using [$frontmatter](./global-computed.md#frontmatter) at the rest of the page, plus all custom and theming components. 21 | 22 | ::: tip 23 | Front matter variables are **optional** in VuePress. 24 | ::: 25 | 26 | ## Alternative Front Matter Formats 27 | 28 | In addition, VuePress also supports JSON or [TOML](https://github.com/toml-lang/toml) front matter. 29 | 30 | JSON front matter needs to start and end in curly braces: 31 | 32 | ``` 33 | --- 34 | { 35 | "title": "Blogging Like a Hacker", 36 | "lang": "en-US" 37 | } 38 | --- 39 | ``` 40 | 41 | TOML front matter needs to be explicitly marked as TOML: 42 | 43 | ``` 44 | ---toml 45 | title = "Blogging Like a Hacker" 46 | lang = "en-US" 47 | --- 48 | ``` 49 | 50 | 51 | ## Predefined Variables 52 | 53 | ### title 54 | 55 | - Type: `string` 56 | - Default: `h1_title || siteConfig.title` 57 | 58 | Title of current page. 59 | 60 | ### lang 61 | 62 | - Type: `string` 63 | - Default: `en-US` 64 | 65 | Language of current page. 66 | 67 | ### description 68 | 69 | - Type: `string` 70 | - Default: `siteConfig.description` 71 | 72 | Description of current page. 73 | 74 | ### layout 75 | 76 | - Type: `string` 77 | - Default: `Layout` 78 | 79 | Set the layout component of the current page. 80 | 81 | ### permalink 82 | 83 | - Type: `string` 84 | - Default: `siteConfig.permalink` 85 | 86 | Refer to: [Permalinks](./permalinks.md). 87 | 88 | ### metaTitle 89 | 90 | - Type: `string` 91 | - Default: \`${page.title} | ${siteConfig.title}\` 92 | 93 | Override the default meta title. 94 | 95 | ### meta 96 | 97 | - Type: `array` 98 | - Default: `undefined` 99 | 100 | Specify extra meta tags to be injected: 101 | 102 | ``` yaml 103 | --- 104 | meta: 105 | - name: description 106 | content: hello 107 | - name: keywords 108 | content: super duper SEO 109 | --- 110 | ``` 111 | 112 | ## Predefined Variables Powered By Default Theme 113 | 114 | ### navbar 115 | 116 | - Type: `boolean` 117 | - Default: `undefined` 118 | 119 | See: [Default Theme Config > Disable the Navbar](../theme/default-theme-config.md#disable-the-navbar). 120 | 121 | ### sidebar 122 | 123 | - Type: `boolean|'auto'` 124 | - Default: `undefined` 125 | 126 | See: [Default Theme Config > Sidebar](../theme/default-theme-config.md#sidebar). 127 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2018-11-07-frontmatter-in-vuepress-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: frontmatter in vuepress 3 3 | date: 2018-11-07 4 | tags: 5 | - frontmatter 6 | - vuepress 7 | author: ULIVZ 8 | location: Hangzhou 9 | --- 10 | 11 | Any markdown file that contains a YAML front matter block will be processed by [gray-matter](https://github.com/jonschlinkert/gray-matter). The front matter must be the first thing in the markdown file and must take the form of valid YAML set between triple-dashed lines. Here is a basic example: 12 | 13 | ```markdown 14 | --- 15 | title: Blogging Like a Hacker 16 | lang: en-US 17 | --- 18 | ``` 19 | 20 | Between these triple-dashed lines, you can set predefined variables (see [below](#predefined-variables) for a reference), or even create custom ones of your own. These variables will then be available to you to access using [$frontmatter](./global-computed.md#frontmatter) at the rest of the page, plus all custom and theming components. 21 | 22 | ::: tip 23 | Front matter variables are **optional** in VuePress. 24 | ::: 25 | 26 | ## Alternative Front Matter Formats 27 | 28 | In addition, VuePress also supports JSON or [TOML](https://github.com/toml-lang/toml) front matter. 29 | 30 | JSON front matter needs to start and end in curly braces: 31 | 32 | ``` 33 | --- 34 | { 35 | "title": "Blogging Like a Hacker", 36 | "lang": "en-US" 37 | } 38 | --- 39 | ``` 40 | 41 | TOML front matter needs to be explicitly marked as TOML: 42 | 43 | ``` 44 | ---toml 45 | title = "Blogging Like a Hacker" 46 | lang = "en-US" 47 | --- 48 | ``` 49 | 50 | 51 | ## Predefined Variables 52 | 53 | ### title 54 | 55 | - Type: `string` 56 | - Default: `h1_title || siteConfig.title` 57 | 58 | Title of current page. 59 | 60 | ### lang 61 | 62 | - Type: `string` 63 | - Default: `en-US` 64 | 65 | Language of current page. 66 | 67 | ### description 68 | 69 | - Type: `string` 70 | - Default: `siteConfig.description` 71 | 72 | Description of current page. 73 | 74 | ### layout 75 | 76 | - Type: `string` 77 | - Default: `Layout` 78 | 79 | Set the layout component of the current page. 80 | 81 | ### permalink 82 | 83 | - Type: `string` 84 | - Default: `siteConfig.permalink` 85 | 86 | Refer to: [Permalinks](./permalinks.md). 87 | 88 | ### metaTitle 89 | 90 | - Type: `string` 91 | - Default: \`${page.title} | ${siteConfig.title}\` 92 | 93 | Override the default meta title. 94 | 95 | ### meta 96 | 97 | - Type: `array` 98 | - Default: `undefined` 99 | 100 | Specify extra meta tags to be injected: 101 | 102 | ``` yaml 103 | --- 104 | meta: 105 | - name: description 106 | content: hello 107 | - name: keywords 108 | content: super duper SEO 109 | --- 110 | ``` 111 | 112 | ## Predefined Variables Powered By Default Theme 113 | 114 | ### navbar 115 | 116 | - Type: `boolean` 117 | - Default: `undefined` 118 | 119 | See: [Default Theme Config > Disable the Navbar](../theme/default-theme-config.md#disable-the-navbar). 120 | 121 | ### sidebar 122 | 123 | - Type: `boolean|'auto'` 124 | - Default: `undefined` 125 | 126 | See: [Default Theme Config > Sidebar](../theme/default-theme-config.md#sidebar). 127 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2018-11-07-frontmatter-in-vuepress.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: frontmatter in vuepress 1 3 | date: 2018-11-07 4 | tags: 5 | - frontmatter 6 | - vuepress 7 | author: ULIVZ 8 | location: Hangzhou 9 | --- 10 | 11 | Any markdown file that contains a YAML front matter block will be processed by [gray-matter](https://github.com/jonschlinkert/gray-matter). The front matter must be the first thing in the markdown file and must take the form of valid YAML set between triple-dashed lines. Here is a basic example: 12 | 13 | 14 | 15 | ```markdown 16 | --- 17 | title: Blogging Like a Hacker 18 | lang: en-US 19 | --- 20 | ``` 21 | 22 | Between these triple-dashed lines, you can set predefined variables (see [below](#predefined-variables) for a reference), or even create custom ones of your own. These variables will then be available to you to access using [$frontmatter](./global-computed.md#frontmatter) at the rest of the page, plus all custom and theming components. 23 | 24 | ::: tip 25 | Front matter variables are **optional** in VuePress. 26 | ::: 27 | 28 | ## Alternative Front Matter Formats 29 | 30 | In addition, VuePress also supports JSON or [TOML](https://github.com/toml-lang/toml) front matter. 31 | 32 | JSON front matter needs to start and end in curly braces: 33 | 34 | ``` 35 | --- 36 | { 37 | "title": "Blogging Like a Hacker", 38 | "lang": "en-US" 39 | } 40 | --- 41 | ``` 42 | 43 | TOML front matter needs to be explicitly marked as TOML: 44 | 45 | ``` 46 | ---toml 47 | title = "Blogging Like a Hacker" 48 | lang = "en-US" 49 | --- 50 | ``` 51 | 52 | 53 | ## Predefined Variables 54 | 55 | ### title 56 | 57 | - Type: `string` 58 | - Default: `h1_title || siteConfig.title` 59 | 60 | Title of current page. 61 | 62 | ### lang 63 | 64 | - Type: `string` 65 | - Default: `en-US` 66 | 67 | Language of current page. 68 | 69 | ### description 70 | 71 | - Type: `string` 72 | - Default: `siteConfig.description` 73 | 74 | Description of current page. 75 | 76 | ### layout 77 | 78 | - Type: `string` 79 | - Default: `Layout` 80 | 81 | Set the layout component of the current page. 82 | 83 | ### permalink 84 | 85 | - Type: `string` 86 | - Default: `siteConfig.permalink` 87 | 88 | Refer to: [Permalinks](./permalinks.md). 89 | 90 | ### metaTitle 91 | 92 | - Type: `string` 93 | - Default: \`${page.title} | ${siteConfig.title}\` 94 | 95 | Override the default meta title. 96 | 97 | ### meta 98 | 99 | - Type: `array` 100 | - Default: `undefined` 101 | 102 | Specify extra meta tags to be injected: 103 | 104 | ``` yaml 105 | --- 106 | meta: 107 | - name: description 108 | content: hello 109 | - name: keywords 110 | content: super duper SEO 111 | --- 112 | ``` 113 | 114 | ## Predefined Variables Powered By Default Theme 115 | 116 | ### navbar 117 | 118 | - Type: `boolean` 119 | - Default: `undefined` 120 | 121 | See: [Default Theme Config > Disable the Navbar](../theme/default-theme-config.md#disable-the-navbar). 122 | 123 | ### sidebar 124 | 125 | - Type: `boolean|'auto'` 126 | - Default: `undefined` 127 | 128 | See: [Default Theme Config > Sidebar](../theme/default-theme-config.md#sidebar). 129 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2019-02-26-markdown-slot-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown Slot 2 3 | date: 2019-02-26 4 | tags: 5 | - markdown 6 | - vuepress 7 | author: ULIVZ 8 | location: Hangzhou 9 | --- 10 | 11 | VuePress implements a content distribution API for Markdown. With this feature, you can split your document into multiple fragments to facilitate flexible composition in the layout component. 12 | 13 | ## Why do I need Markdown Slot? 14 | 15 | First, let's review the relationship between layout components and markdown files: 16 | 17 | Markdown files are providers of metadata (Page content, Configuration, etc.), while layout components consume them. We can use `frontmatter` to define some metadata for common data types, but `frontmatter` is hard to do something about markdown / HTML, a complex metadata that involves differences before and after compilation. 18 | 19 | Markdown Slot is to solve this kind of problem. 20 | 21 | ## Named Slots 22 | 23 | You can define a named markdown slot through the following markdown syntax: 24 | 25 | ``` md 26 | ::: slot name 27 | 28 | ::: 29 | ``` 30 | 31 | Use the `Content` component to use the slot in the layout component: 32 | 33 | ``` vue 34 | 35 | ``` 36 | 37 | ::: tip 38 | Here we are using `slot-key` instead of `slot`, because in Vue, `slot` is a reserved prop name. 39 | ::: 40 | 41 | ## Default Slot Content 42 | 43 | By default, the slot-free part of a markdown file becomes the default content of a markdown slot, which you can access directly using the `Content` component: 44 | 45 | ``` vue 46 | 47 | ``` 48 | 49 | ## Example 50 | 51 | Suppose your layout component is as follows: 52 | 53 | ``` vue 54 | 67 | ``` 68 | 69 | If the markdown content of a page is like this: 70 | 71 | ```md 72 | ::: slot header 73 | # Here might be a page title 74 | ::: 75 | 76 | - A Paragraph 77 | - Another Paragraph 78 | 79 | ::: slot footer 80 | Here's some contact info 81 | ::: 82 | ``` 83 | 84 | Then the rendered HTML of this page will be: 85 | 86 | ```html 87 |
88 |
89 |
90 |

Here might be a page title

91 |
92 |
93 |
94 |
95 |
    96 |
  • A Paragraph
  • 97 |
  • Another Paragraph
  • 98 |
99 |
100 |
101 |
102 | 105 |
106 |
107 | ``` 108 | 109 | Note that: 110 | 1. Unlike the slot mechanism provided by [Vue](https://vuejs.org/v2/guide/components-slots.html) itself, each content distribution is wrapped in a `div` whose class is `content` with the name of the slot. 111 | 2. Please ensure the uniqueness of the slot defined. 112 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2019-02-26-markdown-slot-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown Slot 3 3 | date: 2019-02-26 4 | tags: 5 | - markdown 6 | - vuepress 7 | author: ULIVZ 8 | location: Hangzhou 9 | --- 10 | 11 | VuePress implements a content distribution API for Markdown. With this feature, you can split your document into multiple fragments to facilitate flexible composition in the layout component. 12 | 13 | ## Why do I need Markdown Slot? 14 | 15 | First, let's review the relationship between layout components and markdown files: 16 | 17 | Markdown files are providers of metadata (Page content, Configuration, etc.), while layout components consume them. We can use `frontmatter` to define some metadata for common data types, but `frontmatter` is hard to do something about markdown / HTML, a complex metadata that involves differences before and after compilation. 18 | 19 | Markdown Slot is to solve this kind of problem. 20 | 21 | ## Named Slots 22 | 23 | You can define a named markdown slot through the following markdown syntax: 24 | 25 | ``` md 26 | ::: slot name 27 | 28 | ::: 29 | ``` 30 | 31 | Use the `Content` component to use the slot in the layout component: 32 | 33 | ``` vue 34 | 35 | ``` 36 | 37 | ::: tip 38 | Here we are using `slot-key` instead of `slot`, because in Vue, `slot` is a reserved prop name. 39 | ::: 40 | 41 | ## Default Slot Content 42 | 43 | By default, the slot-free part of a markdown file becomes the default content of a markdown slot, which you can access directly using the `Content` component: 44 | 45 | ``` vue 46 | 47 | ``` 48 | 49 | ## Example 50 | 51 | Suppose your layout component is as follows: 52 | 53 | ``` vue 54 | 67 | ``` 68 | 69 | If the markdown content of a page is like this: 70 | 71 | ```md 72 | ::: slot header 73 | # Here might be a page title 74 | ::: 75 | 76 | - A Paragraph 77 | - Another Paragraph 78 | 79 | ::: slot footer 80 | Here's some contact info 81 | ::: 82 | ``` 83 | 84 | Then the rendered HTML of this page will be: 85 | 86 | ```html 87 |
88 |
89 |
90 |

Here might be a page title

91 |
92 |
93 |
94 |
95 |
    96 |
  • A Paragraph
  • 97 |
  • Another Paragraph
  • 98 |
99 |
100 |
101 |
102 | 105 |
106 |
107 | ``` 108 | 109 | Note that: 110 | 1. Unlike the slot mechanism provided by [Vue](https://vuejs.org/v2/guide/components-slots.html) itself, each content distribution is wrapped in a `div` whose class is `content` with the name of the slot. 111 | 2. Please ensure the uniqueness of the slot defined. 112 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2019-02-26-markdown-slot-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown Slot 4 3 | date: 2019-02-26 4 | tags: 5 | - markdown 6 | - vuepress 7 | author: ULIVZ 8 | location: Hangzhou 9 | --- 10 | 11 | VuePress implements a content distribution API for Markdown. With this feature, you can split your document into multiple fragments to facilitate flexible composition in the layout component. 12 | 13 | ## Why do I need Markdown Slot? 14 | 15 | First, let's review the relationship between layout components and markdown files: 16 | 17 | Markdown files are providers of metadata (Page content, Configuration, etc.), while layout components consume them. We can use `frontmatter` to define some metadata for common data types, but `frontmatter` is hard to do something about markdown / HTML, a complex metadata that involves differences before and after compilation. 18 | 19 | Markdown Slot is to solve this kind of problem. 20 | 21 | ## Named Slots 22 | 23 | You can define a named markdown slot through the following markdown syntax: 24 | 25 | ``` md 26 | ::: slot name 27 | 28 | ::: 29 | ``` 30 | 31 | Use the `Content` component to use the slot in the layout component: 32 | 33 | ``` vue 34 | 35 | ``` 36 | 37 | ::: tip 38 | Here we are using `slot-key` instead of `slot`, because in Vue, `slot` is a reserved prop name. 39 | ::: 40 | 41 | ## Default Slot Content 42 | 43 | By default, the slot-free part of a markdown file becomes the default content of a markdown slot, which you can access directly using the `Content` component: 44 | 45 | ``` vue 46 | 47 | ``` 48 | 49 | ## Example 50 | 51 | Suppose your layout component is as follows: 52 | 53 | ``` vue 54 | 67 | ``` 68 | 69 | If the markdown content of a page is like this: 70 | 71 | ```md 72 | ::: slot header 73 | # Here might be a page title 74 | ::: 75 | 76 | - A Paragraph 77 | - Another Paragraph 78 | 79 | ::: slot footer 80 | Here's some contact info 81 | ::: 82 | ``` 83 | 84 | Then the rendered HTML of this page will be: 85 | 86 | ```html 87 |
88 |
89 |
90 |

Here might be a page title

91 |
92 |
93 |
94 |
95 |
    96 |
  • A Paragraph
  • 97 |
  • Another Paragraph
  • 98 |
99 |
100 |
101 |
102 | 105 |
106 |
107 | ``` 108 | 109 | Note that: 110 | 1. Unlike the slot mechanism provided by [Vue](https://vuejs.org/v2/guide/components-slots.html) itself, each content distribution is wrapped in a `div` whose class is `content` with the name of the slot. 111 | 2. Please ensure the uniqueness of the slot defined. 112 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2019-02-26-markdown-slot.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Markdown Slot 1 3 | date: 2019-2-26 4 | tags: 5 | - markdown 6 | - vuepress 7 | author: ULIVZ 8 | location: Hangzhou 9 | --- 10 | 11 | VuePress implements a content distribution API for Markdown. With this feature, you can split your document into multiple fragments to facilitate flexible composition in the layout component. 12 | 13 | 14 | 15 | ## Why do I need Markdown Slot? 16 | 17 | First, let's review the relationship between layout components and markdown files: 18 | 19 | Markdown files are providers of metadata (Page content, Configuration, etc.), while layout components consume them. We can use `frontmatter` to define some metadata for common data types, but `frontmatter` is hard to do something about markdown / HTML, a complex metadata that involves differences before and after compilation. 20 | 21 | Markdown Slot is to solve this kind of problem. 22 | 23 | ## Named Slots 24 | 25 | You can define a named markdown slot through the following markdown syntax: 26 | 27 | ``` md 28 | ::: slot name 29 | 30 | ::: 31 | ``` 32 | 33 | Use the `Content` component to use the slot in the layout component: 34 | 35 | ``` vue 36 | 37 | ``` 38 | 39 | ::: tip 40 | Here we are using `slot-key` instead of `slot`, because in Vue, `slot` is a reserved prop name. 41 | ::: 42 | 43 | ## Default Slot Content 44 | 45 | By default, the slot-free part of a markdown file becomes the default content of a markdown slot, which you can access directly using the `Content` component: 46 | 47 | ``` vue 48 | 49 | ``` 50 | 51 | ## Example 52 | 53 | Suppose your layout component is as follows: 54 | 55 | ``` vue 56 | 69 | ``` 70 | 71 | If the markdown content of a page is like this: 72 | 73 | ```md 74 | ::: slot header 75 | # Here might be a page title 76 | ::: 77 | 78 | - A Paragraph 79 | - Another Paragraph 80 | 81 | ::: slot footer 82 | Here's some contact info 83 | ::: 84 | ``` 85 | 86 | Then the rendered HTML of this page will be: 87 | 88 | ```html 89 |
90 |
91 |
92 |

Here might be a page title

93 |
94 |
95 |
96 |
97 |
    98 |
  • A Paragraph
  • 99 |
  • Another Paragraph
  • 100 |
101 |
102 |
103 |
104 | 107 |
108 |
109 | ``` 110 | 111 | Note that: 112 | 1. Unlike the slot mechanism provided by [Vue](https://vuejs.org/v2/guide/components-slots.html) itself, each content distribution is wrapped in a `div` whose class is `content` with the name of the slot. 113 | 2. Please ensure the uniqueness of the slot defined. 114 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2019-05-06-writing-a-vuepress-theme-2.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: writing a vuepress theme 2 3 | date: 2019-05-06 4 | tags: 5 | - theme 6 | - blog 7 | - vuepress 8 | author: ULIVZ 9 | location: Shanghai 10 | --- 11 | 12 | To write a theme, create a `.vuepress/theme` directory in your docs root, and then create a `Layout.vue` file: 13 | 14 | ``` 15 | . 16 | └─ .vuepress 17 |  └─ `theme` 18 |    └─ Layout.vue 19 | ``` 20 | 21 | From there it's the same as developing a normal Vue application. It is entirely up to you how to organize your theme. 22 | 23 | ## Content Outlet 24 | 25 | The compiled content of the current `.md` file being rendered will be available as a special `` 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: 26 | 27 | ``` html 28 | 33 | ``` 34 | 35 | **Also see:** 36 | 37 | - [Markdown Slot](../guide/markdown-slot.md) 38 | 39 | ## Directory Structure 40 | 41 | 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-styl), and even apply some plugins. 42 | 43 | So it's time to reorganize your theme, an agreed theme directory structure is as follows: 44 | 45 | ::: vue 46 | theme 47 | ├── `global-components` 48 | │ └── xxx.vue 49 | ├── `components` 50 | │ └── xxx.vue 51 | ├── `layouts` 52 | │   ├── Layout.vue _(**Mandatory**)_ 53 | │   └── 404.vue 54 | ├── `styles` 55 | │   ├── index.styl 56 | │   └── palette.styl 57 | ├── `templates` 58 | │   ├── dev.html 59 | │   └── ssr.html 60 | ├── `index.js` 61 | ├── `enhanceApp.js` 62 | └── package.json 63 | ::: 64 | 65 | - `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). 66 | - `theme/components`: Your components. 67 | - `theme/layouts`: Layout components of the theme, where `Layout.vue` is required. 68 | - `theme/styles`: Global style and palette. 69 | - `theme/templates`: Modify default template. 70 | - `theme/index.js`: Entry file of theme configuration. 71 | - `theme/enhanceApp.js`: Theme level enhancements. 72 | 73 | ::: warning Note 74 | When you publish your theme as an NPM package, if you don't have any theme configuration, that means you don't have `theme/index.js`, you'll need to set the `"main"` field to `layouts/Layout.vue` in `package.json`, only in this way VuePress can correctly resolve the theme. 75 | ```json 76 | { 77 | ... 78 | "main": "layouts/Layout.vue", 79 | ... 80 | } 81 | ``` 82 | 83 | ::: 84 | 85 | ## Layout Component 86 | 87 | Suppose your theme layouts folder is as follows: 88 | 89 | ::: vue 90 | theme 91 | └── `layouts` 92 |    ├── Layout.vue 93 |    ├── AnotherLayout.vue 94 |    └── 404.vue 95 | ::: 96 | 97 | Then, all the pages will use `Layout.vue` as layout component by default, while the routes not matching will use `404.vue`. 98 | 99 | If you want to switch the layout of some pages to `AnotherLayout.vue`, you just need to update the frontmatter of this page: 100 | 101 | ```markdown 102 | --- 103 | layout: AnotherLayout 104 | --- 105 | ```` 106 | 107 | ::: tip 108 | Each layout component may render distinct pages. If you want to apply some global UI (e.g. global header), consider using [globalLayout](./option-api.md#globallayout)。 109 | ::: 110 | 111 | ## Apply plugins 112 | 113 | You can apply some plugins to the theme via `theme/index.js`. 114 | 115 | ```js 116 | module.exports = { 117 | plugins: [ 118 | ['@vuepress/pwa', { 119 | serviceWorker: true, 120 | updatePopup: true 121 | }] 122 | ] 123 | } 124 | ``` 125 | 126 | ## Site and Page Metadata 127 | 128 | 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. 129 | 130 | This is the value of `$site` of this very website: 131 | 132 | ``` json 133 | { 134 | "title": "VuePress", 135 | "description": "Vue-powered Static Site Generator", 136 | "base": "/", 137 | "pages": [ 138 | { 139 | "lastUpdated": 1524027677000, 140 | "path": "/", 141 | "title": "VuePress", 142 | "frontmatter": {} 143 | }, 144 | ... 145 | ] 146 | } 147 | ``` 148 | 149 | `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. 150 | 151 | This is the `$page` object for this page you are looking at: 152 | 153 | ``` json 154 | { 155 | "lastUpdated": 1524847549000, 156 | "path": "/guide/custom-themes.html", 157 | "title": "Custom Themes", 158 | "headers": [/* ... */], 159 | "frontmatter": {} 160 | } 161 | ``` 162 | 163 | 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. 164 | 165 | Finally, don't forget that `this.$route` and `this.$router` are also available as part of Vue Router's API. 166 | 167 | ::: tip 168 | `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). 169 | ::: 170 | 171 | ## App Level Enhancements 172 | 173 | 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: 174 | 175 | ``` js 176 | export default ({ 177 | Vue, // the version of Vue being used in the VuePress app 178 | options, // the options for the root Vue instance 179 | router, // the router instance for the app 180 | siteData // site metadata 181 | }) => { 182 | // ...apply enhancements to the app 183 | } 184 | ``` 185 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2019-05-06-writing-a-vuepress-theme-3.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: writing a vuepress theme 3 3 | date: 2019-05-06 4 | tags: 5 | - theme 6 | - blog 7 | - vuepress 8 | author: ULIVZ 9 | location: Shanghai 10 | --- 11 | 12 | To write a theme, create a `.vuepress/theme` directory in your docs root, and then create a `Layout.vue` file: 13 | 14 | ``` 15 | . 16 | └─ .vuepress 17 |  └─ `theme` 18 |    └─ Layout.vue 19 | ``` 20 | 21 | From there it's the same as developing a normal Vue application. It is entirely up to you how to organize your theme. 22 | 23 | ## Content Outlet 24 | 25 | The compiled content of the current `.md` file being rendered will be available as a special `` 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: 26 | 27 | ``` html 28 | 33 | ``` 34 | 35 | **Also see:** 36 | 37 | - [Markdown Slot](../guide/markdown-slot.md) 38 | 39 | ## Directory Structure 40 | 41 | 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-styl), and even apply some plugins. 42 | 43 | So it's time to reorganize your theme, an agreed theme directory structure is as follows: 44 | 45 | ::: vue 46 | theme 47 | ├── `global-components` 48 | │ └── xxx.vue 49 | ├── `components` 50 | │ └── xxx.vue 51 | ├── `layouts` 52 | │   ├── Layout.vue _(**Mandatory**)_ 53 | │   └── 404.vue 54 | ├── `styles` 55 | │   ├── index.styl 56 | │   └── palette.styl 57 | ├── `templates` 58 | │   ├── dev.html 59 | │   └── ssr.html 60 | ├── `index.js` 61 | ├── `enhanceApp.js` 62 | └── package.json 63 | ::: 64 | 65 | - `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). 66 | - `theme/components`: Your components. 67 | - `theme/layouts`: Layout components of the theme, where `Layout.vue` is required. 68 | - `theme/styles`: Global style and palette. 69 | - `theme/templates`: Modify default template. 70 | - `theme/index.js`: Entry file of theme configuration. 71 | - `theme/enhanceApp.js`: Theme level enhancements. 72 | 73 | ::: warning Note 74 | When you publish your theme as an NPM package, if you don't have any theme configuration, that means you don't have `theme/index.js`, you'll need to set the `"main"` field to `layouts/Layout.vue` in `package.json`, only in this way VuePress can correctly resolve the theme. 75 | ```json 76 | { 77 | ... 78 | "main": "layouts/Layout.vue", 79 | ... 80 | } 81 | ``` 82 | 83 | ::: 84 | 85 | ## Layout Component 86 | 87 | Suppose your theme layouts folder is as follows: 88 | 89 | ::: vue 90 | theme 91 | └── `layouts` 92 |    ├── Layout.vue 93 |    ├── AnotherLayout.vue 94 |    └── 404.vue 95 | ::: 96 | 97 | Then, all the pages will use `Layout.vue` as layout component by default, while the routes not matching will use `404.vue`. 98 | 99 | If you want to switch the layout of some pages to `AnotherLayout.vue`, you just need to update the frontmatter of this page: 100 | 101 | ```markdown 102 | --- 103 | layout: AnotherLayout 104 | --- 105 | ```` 106 | 107 | ::: tip 108 | Each layout component may render distinct pages. If you want to apply some global UI (e.g. global header), consider using [globalLayout](./option-api.md#globallayout)。 109 | ::: 110 | 111 | ## Apply plugins 112 | 113 | You can apply some plugins to the theme via `theme/index.js`. 114 | 115 | ```js 116 | module.exports = { 117 | plugins: [ 118 | ['@vuepress/pwa', { 119 | serviceWorker: true, 120 | updatePopup: true 121 | }] 122 | ] 123 | } 124 | ``` 125 | 126 | ## Site and Page Metadata 127 | 128 | 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. 129 | 130 | This is the value of `$site` of this very website: 131 | 132 | ``` json 133 | { 134 | "title": "VuePress", 135 | "description": "Vue-powered Static Site Generator", 136 | "base": "/", 137 | "pages": [ 138 | { 139 | "lastUpdated": 1524027677000, 140 | "path": "/", 141 | "title": "VuePress", 142 | "frontmatter": {} 143 | }, 144 | ... 145 | ] 146 | } 147 | ``` 148 | 149 | `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. 150 | 151 | This is the `$page` object for this page you are looking at: 152 | 153 | ``` json 154 | { 155 | "lastUpdated": 1524847549000, 156 | "path": "/guide/custom-themes.html", 157 | "title": "Custom Themes", 158 | "headers": [/* ... */], 159 | "frontmatter": {} 160 | } 161 | ``` 162 | 163 | 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. 164 | 165 | Finally, don't forget that `this.$route` and `this.$router` are also available as part of Vue Router's API. 166 | 167 | ::: tip 168 | `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). 169 | ::: 170 | 171 | ## App Level Enhancements 172 | 173 | 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: 174 | 175 | ``` js 176 | export default ({ 177 | Vue, // the version of Vue being used in the VuePress app 178 | options, // the options for the root Vue instance 179 | router, // the router instance for the app 180 | siteData // site metadata 181 | }) => { 182 | // ...apply enhancements to the app 183 | } 184 | ``` 185 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2019-05-06-writing-a-vuepress-theme-4.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: writing a vuepress theme 4 3 | date: 2019-05-06 4 | tags: 5 | - theme 6 | - blog 7 | - vuepress 8 | author: ULIVZ 9 | location: Shanghai 10 | --- 11 | 12 | To write a theme, create a `.vuepress/theme` directory in your docs root, and then create a `Layout.vue` file: 13 | 14 | ``` 15 | . 16 | └─ .vuepress 17 |  └─ `theme` 18 |    └─ Layout.vue 19 | ``` 20 | 21 | From there it's the same as developing a normal Vue application. It is entirely up to you how to organize your theme. 22 | 23 | ## Content Outlet 24 | 25 | The compiled content of the current `.md` file being rendered will be available as a special `` 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: 26 | 27 | ``` html 28 | 33 | ``` 34 | 35 | **Also see:** 36 | 37 | - [Markdown Slot](../guide/markdown-slot.md) 38 | 39 | ## Directory Structure 40 | 41 | 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-styl), and even apply some plugins. 42 | 43 | So it's time to reorganize your theme, an agreed theme directory structure is as follows: 44 | 45 | ::: vue 46 | theme 47 | ├── `global-components` 48 | │ └── xxx.vue 49 | ├── `components` 50 | │ └── xxx.vue 51 | ├── `layouts` 52 | │   ├── Layout.vue _(**Mandatory**)_ 53 | │   └── 404.vue 54 | ├── `styles` 55 | │   ├── index.styl 56 | │   └── palette.styl 57 | ├── `templates` 58 | │   ├── dev.html 59 | │   └── ssr.html 60 | ├── `index.js` 61 | ├── `enhanceApp.js` 62 | └── package.json 63 | ::: 64 | 65 | - `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). 66 | - `theme/components`: Your components. 67 | - `theme/layouts`: Layout components of the theme, where `Layout.vue` is required. 68 | - `theme/styles`: Global style and palette. 69 | - `theme/templates`: Modify default template. 70 | - `theme/index.js`: Entry file of theme configuration. 71 | - `theme/enhanceApp.js`: Theme level enhancements. 72 | 73 | ::: warning Note 74 | When you publish your theme as an NPM package, if you don't have any theme configuration, that means you don't have `theme/index.js`, you'll need to set the `"main"` field to `layouts/Layout.vue` in `package.json`, only in this way VuePress can correctly resolve the theme. 75 | ```json 76 | { 77 | ... 78 | "main": "layouts/Layout.vue", 79 | ... 80 | } 81 | ``` 82 | 83 | ::: 84 | 85 | ## Layout Component 86 | 87 | Suppose your theme layouts folder is as follows: 88 | 89 | ::: vue 90 | theme 91 | └── `layouts` 92 |    ├── Layout.vue 93 |    ├── AnotherLayout.vue 94 |    └── 404.vue 95 | ::: 96 | 97 | Then, all the pages will use `Layout.vue` as layout component by default, while the routes not matching will use `404.vue`. 98 | 99 | If you want to switch the layout of some pages to `AnotherLayout.vue`, you just need to update the frontmatter of this page: 100 | 101 | ```markdown 102 | --- 103 | layout: AnotherLayout 104 | --- 105 | ```` 106 | 107 | ::: tip 108 | Each layout component may render distinct pages. If you want to apply some global UI (e.g. global header), consider using [globalLayout](./option-api.md#globallayout)。 109 | ::: 110 | 111 | ## Apply plugins 112 | 113 | You can apply some plugins to the theme via `theme/index.js`. 114 | 115 | ```js 116 | module.exports = { 117 | plugins: [ 118 | ['@vuepress/pwa', { 119 | serviceWorker: true, 120 | updatePopup: true 121 | }] 122 | ] 123 | } 124 | ``` 125 | 126 | ## Site and Page Metadata 127 | 128 | 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. 129 | 130 | This is the value of `$site` of this very website: 131 | 132 | ``` json 133 | { 134 | "title": "VuePress", 135 | "description": "Vue-powered Static Site Generator", 136 | "base": "/", 137 | "pages": [ 138 | { 139 | "lastUpdated": 1524027677000, 140 | "path": "/", 141 | "title": "VuePress", 142 | "frontmatter": {} 143 | }, 144 | ... 145 | ] 146 | } 147 | ``` 148 | 149 | `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. 150 | 151 | This is the `$page` object for this page you are looking at: 152 | 153 | ``` json 154 | { 155 | "lastUpdated": 1524847549000, 156 | "path": "/guide/custom-themes.html", 157 | "title": "Custom Themes", 158 | "headers": [/* ... */], 159 | "frontmatter": {} 160 | } 161 | ``` 162 | 163 | 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. 164 | 165 | Finally, don't forget that `this.$route` and `this.$router` are also available as part of Vue Router's API. 166 | 167 | ::: tip 168 | `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). 169 | ::: 170 | 171 | ## App Level Enhancements 172 | 173 | 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: 174 | 175 | ``` js 176 | export default ({ 177 | Vue, // the version of Vue being used in the VuePress app 178 | options, // the options for the root Vue instance 179 | router, // the router instance for the app 180 | siteData // site metadata 181 | }) => { 182 | // ...apply enhancements to the app 183 | } 184 | ``` 185 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/blog/_posts/2019-05-06-writing-a-vuepress-theme.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Writing a vuepress theme 1 3 | date: 2019-05-06 4 | tags: 5 | - theme 6 | - blog 7 | - vuepress 8 | author: ULIVZ 9 | location: Shanghai 10 | --- 11 | 12 | To write a theme, create a `.vuepress/theme` directory in your docs root, and then create a `Layout.vue` file: 13 | 14 | ``` 15 | . 16 | └─ .vuepress 17 |  └─ `theme` 18 |    └─ Layout.vue 19 | ``` 20 | 21 | From there it's the same as developing a normal Vue application. It is entirely up to you how to organize your theme. 22 | 23 | 24 | 25 | ## Content Outlet 26 | 27 | The compiled content of the current `.md` file being rendered will be available as a special `` 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: 28 | 29 | ``` html 30 | 35 | ``` 36 | 37 | **Also see:** 38 | 39 | - [Markdown Slot](../guide/markdown-slot.md) 40 | 41 | ## Directory Structure 42 | 43 | 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-styl), and even apply some plugins. 44 | 45 | So it's time to reorganize your theme, an agreed theme directory structure is as follows: 46 | 47 | ::: vue 48 | theme 49 | ├── `global-components` 50 | │ └── xxx.vue 51 | ├── `components` 52 | │ └── xxx.vue 53 | ├── `layouts` 54 | │   ├── Layout.vue _(**Mandatory**)_ 55 | │   └── 404.vue 56 | ├── `styles` 57 | │   ├── index.styl 58 | │   └── palette.styl 59 | ├── `templates` 60 | │   ├── dev.html 61 | │   └── ssr.html 62 | ├── `index.js` 63 | ├── `enhanceApp.js` 64 | └── package.json 65 | ::: 66 | 67 | - `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). 68 | - `theme/components`: Your components. 69 | - `theme/layouts`: Layout components of the theme, where `Layout.vue` is required. 70 | - `theme/styles`: Global style and palette. 71 | - `theme/templates`: Modify default template. 72 | - `theme/index.js`: Entry file of theme configuration. 73 | - `theme/enhanceApp.js`: Theme level enhancements. 74 | 75 | ::: warning Note 76 | When you publish your theme as an NPM package, if you don't have any theme configuration, that means you don't have `theme/index.js`, you'll need to set the `"main"` field to `layouts/Layout.vue` in `package.json`, only in this way VuePress can correctly resolve the theme. 77 | ```json 78 | { 79 | ... 80 | "main": "layouts/Layout.vue", 81 | ... 82 | } 83 | ``` 84 | 85 | ::: 86 | 87 | ## Layout Component 88 | 89 | Suppose your theme layouts folder is as follows: 90 | 91 | ::: vue 92 | theme 93 | └── `layouts` 94 |    ├── Layout.vue 95 |    ├── AnotherLayout.vue 96 |    └── 404.vue 97 | ::: 98 | 99 | Then, all the pages will use `Layout.vue` as layout component by default, while the routes not matching will use `404.vue`. 100 | 101 | If you want to switch the layout of some pages to `AnotherLayout.vue`, you just need to update the frontmatter of this page: 102 | 103 | ```markdown 104 | --- 105 | layout: AnotherLayout 106 | --- 107 | ```` 108 | 109 | ::: tip 110 | Each layout component may render distinct pages. If you want to apply some global UI (e.g. global header), consider using [globalLayout](./option-api.md#globallayout)。 111 | ::: 112 | 113 | ## Apply plugins 114 | 115 | You can apply some plugins to the theme via `theme/index.js`. 116 | 117 | ```js 118 | module.exports = { 119 | plugins: [ 120 | ['@vuepress/pwa', { 121 | serviceWorker: true, 122 | updatePopup: true 123 | }] 124 | ] 125 | } 126 | ``` 127 | 128 | ## Site and Page Metadata 129 | 130 | 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. 131 | 132 | This is the value of `$site` of this very website: 133 | 134 | ``` json 135 | { 136 | "title": "VuePress", 137 | "description": "Vue-powered Static Site Generator", 138 | "base": "/", 139 | "pages": [ 140 | { 141 | "lastUpdated": 1524027677000, 142 | "path": "/", 143 | "title": "VuePress", 144 | "frontmatter": {} 145 | }, 146 | ... 147 | ] 148 | } 149 | ``` 150 | 151 | `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. 152 | 153 | This is the `$page` object for this page you are looking at: 154 | 155 | ``` json 156 | { 157 | "lastUpdated": 1524847549000, 158 | "path": "/guide/custom-themes.html", 159 | "title": "Custom Themes", 160 | "headers": [/* ... */], 161 | "frontmatter": {} 162 | } 163 | ``` 164 | 165 | 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. 166 | 167 | Finally, don't forget that `this.$route` and `this.$router` are also available as part of Vue Router's API. 168 | 169 | ::: tip 170 | `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). 171 | ::: 172 | 173 | ## App Level Enhancements 174 | 175 | 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: 176 | 177 | ``` js 178 | export default ({ 179 | Vue, // the version of Vue being used in the VuePress app 180 | options, // the options for the root Vue instance 181 | router, // the router instance for the app 182 | siteData // site metadata 183 | }) => { 184 | // ...apply enhancements to the app 185 | } 186 | ``` 187 | -------------------------------------------------------------------------------- /lib/generators/blog/templates/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= name %>", 3 | "version": "0.0.1", 4 | "description": "<%= description %>", 5 | "main": "index.js", 6 | "authors": { 7 | "name": "<%= author %>", 8 | "email": "<%= mail %>" 9 | }, 10 | "repository": "<%= repo %>/<%= name %>", 11 | "scripts": { 12 | "dev": "vuepress dev blog", 13 | "build": "vuepress build blog" 14 | }, 15 | "license": "MIT", 16 | "devDependencies": { 17 | "vuepress": "^1.6.0", 18 | "@vuepress/theme-blog": "^2.3.2" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /lib/generators/docs/index.js: -------------------------------------------------------------------------------- 1 | const BasicGenerator = require('../../BasicGenerator'); 2 | 3 | class Generator extends BasicGenerator { 4 | prompting() { 5 | const prompts = [ 6 | { 7 | name: 'name', 8 | message: `What's the name of your project?`, 9 | default: this.name 10 | }, 11 | { 12 | name: 'description', 13 | message: `What's the description of your project?` 14 | }, 15 | { 16 | name: 'mail', 17 | message: `What's your email?` 18 | }, 19 | { 20 | name: 'author', 21 | message: `What's your name?` 22 | }, 23 | { 24 | name: 'repo', 25 | message: `What's the repo of your project?` 26 | } 27 | ]; 28 | return this.prompt(prompts).then(props => { 29 | this.prompts = props; 30 | }); 31 | } 32 | 33 | writing() { 34 | this.writeFiles({ 35 | context: this.prompts, 36 | filterFiles: () => { 37 | return true; 38 | } 39 | }); 40 | } 41 | } 42 | 43 | module.exports = Generator; 44 | -------------------------------------------------------------------------------- /lib/generators/docs/meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "description": "Create a documentation site with VuePress." 3 | } 4 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/.gitignore: -------------------------------------------------------------------------------- 1 | pids 2 | logs 3 | node_modules 4 | npm-debug.log 5 | coverage/ 6 | run 7 | dist 8 | .DS_Store 9 | .nyc_output 10 | .basement 11 | config.local.js 12 | basement_dist 13 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/.vuepress/components/Foo/Bar.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/.vuepress/components/OtherComponent.vue: -------------------------------------------------------------------------------- 1 | 4 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/.vuepress/components/demo-component.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/.vuepress/config.js: -------------------------------------------------------------------------------- 1 | const { description } = require('../../package') 2 | 3 | module.exports = { 4 | /** 5 | * Ref:https://v1.vuepress.vuejs.org/config/#title 6 | */ 7 | title: 'Vuepress Docs Boilerplate', 8 | /** 9 | * Ref:https://v1.vuepress.vuejs.org/config/#description 10 | */ 11 | description: description, 12 | 13 | /** 14 | * Extra tags to be injected to the page HTML `` 15 | * 16 | * ref:https://v1.vuepress.vuejs.org/config/#head 17 | */ 18 | head: [ 19 | ['meta', { name: 'theme-color', content: '#3eaf7c' }], 20 | ['meta', { name: 'apple-mobile-web-app-capable', content: 'yes' }], 21 | ['meta', { name: 'apple-mobile-web-app-status-bar-style', content: 'black' }] 22 | ], 23 | 24 | /** 25 | * Theme configuration, here is the default theme configuration for VuePress. 26 | * 27 | * ref:https://v1.vuepress.vuejs.org/theme/default-theme-config.html 28 | */ 29 | themeConfig: { 30 | repo: '', 31 | editLinks: false, 32 | docsDir: '', 33 | editLinkText: '', 34 | lastUpdated: false, 35 | nav: [ 36 | { 37 | text: 'Guide', 38 | link: '/guide/', 39 | }, 40 | { 41 | text: 'Config', 42 | link: '/config' 43 | }, 44 | { 45 | text: 'VuePress', 46 | link: 'https://v1.vuepress.vuejs.org' 47 | } 48 | ], 49 | sidebar: { 50 | '/guide/': [ 51 | { 52 | title: 'Guide', 53 | collapsable: false, 54 | children: [ 55 | '', 56 | 'using-vue', 57 | ] 58 | } 59 | ], 60 | } 61 | }, 62 | 63 | /** 64 | * Apply plugins,ref:https://v1.vuepress.vuejs.org/zh/plugin/ 65 | */ 66 | plugins: [ 67 | '@vuepress/plugin-back-to-top', 68 | '@vuepress/plugin-medium-zoom', 69 | ] 70 | } 71 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/.vuepress/enhanceApp.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Client app enhancement file. 3 | * 4 | * https://v1.vuepress.vuejs.org/guide/basic-config.html#app-level-enhancements 5 | */ 6 | 7 | export default ({ 8 | Vue, // the version of Vue being used in the VuePress app 9 | options, // the options for the root Vue instance 10 | router, // the router instance for the app 11 | siteData // site metadata 12 | }) => { 13 | // ...apply enhancements for the site. 14 | } 15 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/.vuepress/styles/index.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom Styles here. 3 | * 4 | * ref:https://v1.vuepress.vuejs.org/config/#index-styl 5 | */ 6 | 7 | .home .hero img 8 | max-width 450px!important 9 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/.vuepress/styles/palette.styl: -------------------------------------------------------------------------------- 1 | /** 2 | * Custom palette here. 3 | * 4 | * ref:https://v1.vuepress.vuejs.org/zh/config/#palette-styl 5 | */ 6 | 7 | $accentColor = #3eaf7c 8 | $textColor = #2c3e50 9 | $borderColor = #eaecef 10 | $codeBgColor = #282c34 11 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/README.md: -------------------------------------------------------------------------------- 1 | --- 2 | home: true 3 | heroImage: https://v1.vuepress.vuejs.org/hero.png 4 | tagline: <%= description %> 5 | actionText: Quick Start → 6 | actionLink: /guide/ 7 | features: 8 | - title: Feature 1 Title 9 | details: Feature 1 Description 10 | - title: Feature 2 Title 11 | details: Feature 2 Description 12 | - title: Feature 3 Title 13 | details: Feature 3 Description 14 | footer: Made by <%= author %> with ❤️ 15 | --- 16 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/config.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar: auto 3 | --- 4 | 5 | # Config 6 | 7 | ## foo 8 | 9 | - Type: `string` 10 | - Default: `/` 11 | 12 | ## bar 13 | 14 | - Type: `string` 15 | - Default: `/` 16 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/guide/README.md: -------------------------------------------------------------------------------- 1 | # Introduction 2 | 3 | VuePress is composed of two parts: a [minimalistic static site generator](https://github.com/vuejs/vuepress/tree/master/packages/%40vuepress/core) with a Vue-powered [theming system](https://v1.vuepress.vuejs.org/theme/) and [Plugin API](https://v1.vuepress.vuejs.org/plugin/), and a [default theme](https://v1.vuepress.vuejs.org/theme/default-theme-config.html) optimized for writing technical documentation. It was created to support the documentation needs of Vue's own sub projects. 4 | 5 | Each page generated by VuePress has its own pre-rendered static HTML, providing great loading performance and is SEO-friendly. Once the page is loaded, however, Vue takes over the static content and turns it into a full Single-Page Application (SPA). Additional pages are fetched on demand as the user navigates around the site. 6 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/docs/guide/using-vue.md: -------------------------------------------------------------------------------- 1 | # Using Vue in Markdown 2 | 3 | ## Browser API Access Restrictions 4 | 5 | Because VuePress 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. 6 | 7 | If you are using or demoing components that are not SSR friendly (for example containing custom directives), you can wrap them inside the built-in `` component: 8 | 9 | ## 10 | -------------------------------------------------------------------------------- /lib/generators/docs/templates/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "<%= name %>", 3 | "version": "0.0.1", 4 | "description": "<%= description %>", 5 | "main": "index.js", 6 | "authors": { 7 | "name": "<%= author %>", 8 | "email": "<%= mail %>" 9 | }, 10 | "repository": "<%= repo %>/<%= name %>", 11 | "scripts": { 12 | "dev": "vuepress dev docs", 13 | "build": "vuepress build docs" 14 | }, 15 | "license": "MIT", 16 | "devDependencies": { 17 | "vuepress": "^1.5.3" 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lib/run.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | const path = require('path'); 3 | const chalk = require('chalk'); 4 | const mkdirp = require('mkdirp'); 5 | const inquirer = require('inquirer'); 6 | const clipboardy = require('clipboardy'); 7 | 8 | const sequences = ['docs', 'blog']; 9 | 10 | const generators = fs 11 | .readdirSync(`${__dirname}/generators`) 12 | .filter(f => !f.startsWith('.')) 13 | .sort((previous, next) => 14 | sequences.indexOf(previous) > sequences.indexOf(next) ? 1 : -1 15 | ) 16 | .map(f => { 17 | return { 18 | name: `${f.padEnd(15)} - ${chalk.gray( 19 | require(`./generators/${f}/meta.json`).description 20 | )}`, 21 | value: f, 22 | short: f 23 | }; 24 | }); 25 | 26 | const runGenerator = ( 27 | generatorPath, 28 | { name = '', cwd = process.cwd(), args = {} } 29 | ) => { 30 | return new Promise(resolve => { 31 | if (name) { 32 | mkdirp.sync(name); 33 | cwd = path.join(cwd, name); 34 | } 35 | 36 | const Generator = require(generatorPath); 37 | const generator = new Generator({ 38 | name, 39 | env: { 40 | cwd 41 | }, 42 | resolved: require.resolve(generatorPath), 43 | args 44 | }); 45 | 46 | return generator.run(() => { 47 | if (name) { 48 | if (process.platform !== `linux` || process.env.DISPLAY) { 49 | clipboardy.writeSync(`cd ${name}`); 50 | console.log('📋 Copied to clipboard, just use Ctrl+V'); 51 | } 52 | } 53 | 54 | console.log('✨ File Generate Done'); 55 | resolve(true); 56 | }); 57 | }); 58 | }; 59 | 60 | const run = config => { 61 | return inquirer 62 | .prompt([ 63 | { 64 | name: 'type', 65 | message: 'Select the boilerplate type', 66 | type: 'list', 67 | choices: generators 68 | } 69 | ]) 70 | .then(answers => { 71 | return runGenerator(`./generators/${answers.type}`, config); 72 | }) 73 | .catch(error => { 74 | console.error(chalk.red(`> Generate failed`), error); 75 | process.exit(1); 76 | }); 77 | }; 78 | 79 | module.exports = run; 80 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "create-vuepress-site", 3 | "version": "0.4.2-beta", 4 | "description": "Scaffolding a VuePress project", 5 | "repository": { 6 | "type": "git", 7 | "url": "vuepressjs/create-vuepress-site" 8 | }, 9 | "license": "MIT", 10 | "author": "Ben Hong ", 11 | "bin": { 12 | "create-vuepress-site": "cli.js" 13 | }, 14 | "files": [ 15 | "lib", 16 | "cli.js", 17 | "index.js" 18 | ], 19 | "scripts": { 20 | "lint": "eslint . --ext .js" 21 | }, 22 | "husky": { 23 | "hooks": { 24 | "pre-commit": "lint-staged" 25 | } 26 | }, 27 | "lint-staged": { 28 | "*.js": [ 29 | "eslint --fix", 30 | "git add" 31 | ], 32 | "package.json": [ 33 | "sort-package-json", 34 | "git add" 35 | ] 36 | }, 37 | "dependencies": { 38 | "chalk": "^2.4.1", 39 | "clipboardy": "^1.2.3", 40 | "debug": "^3.1.0", 41 | "execa": "^1.0.0", 42 | "fs-extra": "^8.0.1", 43 | "glob": "^7.1.4", 44 | "inquirer": "^6.2.1", 45 | "mkdirp": "^0.5.1", 46 | "prettier": "^1.17.0", 47 | "semver": "^6.1.0", 48 | "sylvanas": "~0.0.3", 49 | "yargs-parser": "^11.0.0", 50 | "yeoman-generator": "^4.0.1" 51 | }, 52 | "devDependencies": { 53 | "eslint": "^7.11.0", 54 | "eslint-config-prettier": "^6.12.0", 55 | "eslint-plugin-prettier": "^3.1.4", 56 | "husky": "1.3.1", 57 | "lint-staged": "8.1.0", 58 | "sort-package-json": "^1.46.0" 59 | }, 60 | "publishConfig": { 61 | "registry": "https://registry.npmjs.org/" 62 | } 63 | } 64 | --------------------------------------------------------------------------------