Skip to content

Commit db62430

Browse files
committed
init
0 parents  commit db62430

23 files changed

+3994
-0
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
.DS_Store
2+
node_modules
3+
*.log

README.md

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
# VuePress
2+
3+
> Minimalistic docs generator with Vue component based layout system
4+
5+
## Goals
6+
7+
- Vue-powered: the layout system is a Vue app. It's also pre-rendered into static HTML. And you can register and use Vue components inside markdown content.
8+
9+
- Docs first: most of your content will be in Markdown.
10+
11+
- Largely gitbook compatible: should be easy to migrate existing gitbook docs over, and maintain original URLs.
12+
13+
- GitHub friendly: pages should be able to link to each other using relative links that ends in `.md`. Also should be able to infer relative position if a GitHub repo name is provided.
14+
15+
- Minimal: most of the additional things are expected to be done in your layout using plain Vue/JavaScript.

bin/vuepress.js

+4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
const path = require('path')
2+
const { build } = require('../lib')
3+
4+
build(path.resolve(__dirname, '../docs'))

docs/_components/demo-1.vue

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<template>
2+
<div>
3+
{{ msg }}
4+
</div>
5+
</template>
6+
7+
<script>
8+
export default {
9+
data () {
10+
return {
11+
msg: 'hello'
12+
}
13+
}
14+
}
15+
</script>

docs/index.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# VuePress
2+
3+
> Minimalistic docs generator with Vue component based layout system

docs/kitchen-sink.md

+9
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
foo: 123
2+
bar: 234
3+
---
4+
5+
``` js
6+
const a = 123
7+
```
8+
9+
<demo-1 vue></demo-1>

docs/layout.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Custom Layout
2+
3+
VuePress uses Vue single file components for custom layouts. To use a custom layout, create a `_layout` directory under `docs`, and then create a `Layout.vue` file:
4+
5+
```
6+
- docs
7+
- _layout
8+
- Layout.vue
9+
```
10+
11+
From there it's the same as developing a normal Vue application. There are only a few special things to note:
12+
13+
## Site and Page Metadata
14+
15+
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 in `$site` and `$page` properties which are injected into every component in the app.
16+
17+
// TODO details about $site & $page
18+
19+
## Content Outlet
20+
21+
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.

docs/recipes.md

Whitespace-only changes.

docs/setup.md

+14
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Setup
2+
3+
## Quickstart
4+
5+
``` bash
6+
npm install -D vuepress
7+
mkdir docs
8+
echo '# Hello VuePress!' > docs/index.md
9+
./node_modules/.bin/vuepress build
10+
```
11+
12+
## Configuration
13+
14+
`_config.yml`

lib/app/.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
.temp

lib/app/app.js

+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import Vue from 'vue'
2+
import Router from 'vue-router'
3+
Vue.use(Router)
4+
5+
// layout is resolved dynamically and set as an alias
6+
import Layout from '~layout'
7+
8+
// dynamically generated files:
9+
10+
// register-commponents.js registers all *.vue files found in _components
11+
// as global async components
12+
import './.temp/register-components'
13+
14+
// routes are generated from md files
15+
import routes from './.temp/routes'
16+
17+
const router = new Router({
18+
mode: 'history',
19+
scrollBehavior: () => ({ y: 0 }),
20+
routes
21+
})
22+
23+
// expose Vue Press data
24+
const g = typeof window !== 'undefined' ? window : global
25+
const $site = Vue.prototype.$site = g.VUE_PRESS_DATA
26+
27+
Vue.mixin({
28+
computed: {
29+
$page () {
30+
return $site.pages[this.$route.path]
31+
}
32+
}
33+
})
34+
35+
const app = new Vue({
36+
router,
37+
render: h => h(Layout)
38+
})
39+
40+
export { app, router }

lib/app/clientEntry.js

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { app, router } from './app'
2+
3+
router.onReady(() => {
4+
app.$mount('#app')
5+
})

lib/app/serverEntry.js

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import { app, router } from './app'
2+
3+
export default context => new Promise((resolve, reject) => {
4+
const { url } = context
5+
const { fullPath } = router.resolve(url).route
6+
7+
if (fullPath !== url) {
8+
return reject({ url: fullPath })
9+
}
10+
11+
router.push(url)
12+
router.onReady(() => resolve(app))
13+
})

lib/default-layout/Index.vue

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<template>
2+
<div class="index">
3+
<Content/>
4+
</div>
5+
</template>

lib/default-layout/Layout.vue

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
<template>
2+
<div id="container">
3+
<Index v-if="$page.isIndex" />
4+
<Page v-else />
5+
</div>
6+
</template>
7+
8+
<script>
9+
import Index from './Index.vue'
10+
import Page from './Page.vue'
11+
12+
export default {
13+
components: { Index, Page }
14+
}
15+
</script>

lib/default-layout/Page.vue

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
<template>
2+
<div class="content">
3+
<Content/>
4+
</div>
5+
</template>

lib/default-layout/index.html

Whitespace-only changes.

lib/index.js

+43
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
const fs = require('fs')
2+
const path = require('path')
3+
const globby = require('globby')
4+
const webpack = require('webpack')
5+
const tempPath = path.resolve(__dirname, 'app/.temp')
6+
7+
exports.build = async function build (sourceDir) {
8+
// 1. loadConfig
9+
// const config = await resolveConfig(sourceDir)
10+
11+
// 2. generate dynamic component registration file
12+
await genComponentRegistrationFile(sourceDir)
13+
14+
// 3. generate routes
15+
await genRoutesFile(sourceDir)
16+
17+
// 4. build
18+
}
19+
20+
async function genComponentRegistrationFile (sourceDir) {
21+
const componentDir = path.resolve(sourceDir, '_components')
22+
if (!fs.existsSync(componentDir)) {
23+
return
24+
}
25+
26+
const components = await globby(['*.vue'], { cwd: componentDir })
27+
if (!components.length) {
28+
return
29+
}
30+
31+
const file = `import Vue from 'vue'\n` + components.map(file => {
32+
const name = file.replace(/\.vue$/, '')
33+
const absolutePath = path.resolve(componentDir, file)
34+
const code = `Vue.component(${JSON.stringify(name)}, () => import(${JSON.stringify(absolutePath)}))`
35+
return code
36+
}).join('\n')
37+
38+
fs.writeFileSync(path.join(tempPath, 'register-components.js'), file)
39+
}
40+
41+
async function genRoutesFile () {
42+
43+
}

lib/webpack/baseConfig.js

+115
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
const path = require('path')
2+
3+
module.exports = function createBaseConfig ({
4+
sourceDir,
5+
publicPath = '/',
6+
layoutPath = path.resolve(__dirname, '../default-layout/Layout.vue')
7+
}) {
8+
const Config = require('webpack-chain')
9+
const { VueLoaderPlugin } = require('vue-loader')
10+
const CSSExtractPlugin = require('mini-css-extract-plugin')
11+
12+
const isProd = process.env.NODE_ENV === 'production'
13+
14+
const config = new Config()
15+
16+
config
17+
.set('mode', isProd ? 'production' : 'development')
18+
.output
19+
.path(path.resolve(sourceDir, 'dist'))
20+
.filename('[name].[chunkhash].js')
21+
.publicPath(publicPath)
22+
23+
config.alias
24+
.set('~layout', layoutPath)
25+
26+
config.resolve
27+
.set('symlinks', true)
28+
.extensions
29+
.merge(['.js', '.jsx', '.vue', '.json'])
30+
.end()
31+
.modules
32+
.add('node_modules')
33+
.add(path.resolve(sourceDir, '../node_modules'))
34+
.add(path.resolve(__dirname, '../../node_modules'))
35+
36+
config.resolveLoader
37+
.set('symlinks', true)
38+
.modules
39+
.add('node_modules')
40+
.add(path.resolve(sourceDir, '../node_modules'))
41+
.add(path.resolve(__dirname, '../../node_modules'))
42+
43+
config.module
44+
.noParse(/^(vue|vue-router|vuex|vuex-router-sync)$/)
45+
46+
config.module
47+
.rule('vue')
48+
.test(/\.vue$/)
49+
.use('vue-loader')
50+
.loader('vue-loader')
51+
.options({
52+
compilerOptions: {
53+
preserveWhitespace: false
54+
}
55+
})
56+
57+
config.module
58+
.rule('images')
59+
.test(/\.(png|jpe?g|gif)(\?.*)?$/)
60+
.use('url-loader')
61+
.loader('url-loader')
62+
.options({
63+
limit: 10000,
64+
name: `img/[name].[hash:8].[ext]`
65+
})
66+
67+
// do not base64-inline SVGs.
68+
// https://github.com/facebookincubator/create-react-app/pull/1180
69+
config.module
70+
.rule('svg')
71+
.test(/\.(svg)(\?.*)?$/)
72+
.use('file-loader')
73+
.loader('file-loader')
74+
.options({
75+
name: `img/[name].[hash:8].[ext]`
76+
})
77+
78+
config.module
79+
.rule('media')
80+
.test(/\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/)
81+
.use('url-loader')
82+
.loader('url-loader')
83+
.options({
84+
limit: inlineLimit,
85+
name: `media/[name].[hash:8].[ext]`
86+
})
87+
88+
config.module
89+
.rule('fonts')
90+
.test(/\.(woff2?|eot|ttf|otf)(\?.*)?$/i)
91+
.use('url-loader')
92+
.loader('url-loader')
93+
.options({
94+
limit: inlineLimit,
95+
name: `fonts/[name].[hash:8].[ext]`
96+
})
97+
98+
createCSSRule(config, 'css', /\.css$/)
99+
createCSSRule(config, 'scss', /\.scss$/, 'sass-loader')
100+
createCSSRule(config, 'sass', /\.sass$/, 'sass-loader', { indentedSyntax: true })
101+
createCSSRule(config, 'less', /\.less$/, 'less-loader')
102+
createCSSRule(config, 'stylus', /\.styl(us)?$/, 'stylus-loader')
103+
104+
config
105+
.plugin('vue-loader')
106+
.use(VueLoaderPlugin)
107+
108+
if (isProd) {
109+
config
110+
.plugin('extract-css')
111+
.use(CSSExtractPlugin, [{ filename: 'styles.css' }])
112+
}
113+
114+
return config
115+
}

lib/webpack/clientConfig.js

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
module.exports = function createClientConfig (options) {
2+
const path = require('path')
3+
const createBaseConfig = require('./baseConfig')
4+
5+
const config = createBaseConfig(options)
6+
7+
config
8+
.entry('app')
9+
.add(path.resolve(__dirname, '../app/clientEntry.js'))
10+
11+
config.node
12+
.merge({
13+
// prevent webpack from injecting useless setImmediate polyfill because Vue
14+
// source contains it (although only uses it if it's native).
15+
setImmediate: false,
16+
global: false,
17+
// process is injected via DefinePlugin, although some 3rd party
18+
// libraries may require a mock to work properly (#934)
19+
process: 'mock',
20+
// prevent webpack from injecting mocks to Node native modules
21+
// that does not make sense for the client
22+
dgram: 'empty',
23+
fs: 'empty',
24+
net: 'empty',
25+
tls: 'empty',
26+
child_process: 'empty'
27+
})
28+
29+
// generate client manifest only during build
30+
if (process.env.NODE_ENV === 'production') {
31+
const VueSSRClientPlugin = require('vue-server-renderer/client-plugin')
32+
config
33+
.plugin('ssr-client')
34+
.use(VueSSRClientPlugin)
35+
}
36+
37+
return config
38+
}

0 commit comments

Comments
 (0)