Skip to content

Commit

Permalink
first commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ciolt committed Oct 9, 2019
0 parents commit 2eb9e9c
Show file tree
Hide file tree
Showing 108 changed files with 5,559 additions and 0 deletions.
3 changes: 3 additions & 0 deletions .npmignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
__tests__
__mocks__
.temp
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# @vuepress/core

## APIs

### dev(sourceDir, options)

### build(sourceDir, options)

### eject(targetDir)
115 changes: 115 additions & 0 deletions lib/client/app.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
/* global VUEPRESS_TEMP_PATH */
import Vue from 'vue'
import Router from 'vue-router'
import dataMixin from './dataMixin'
import { routes } from '@internal/routes'
import { siteData } from '@internal/siteData'
import appEnhancers from '@internal/app-enhancers'
import globalUIComponents from '@internal/global-ui'
import ClientComputedMixin from '@transform/ClientComputedMixin'
import VuePress from './plugins/VuePress'
import { handleRedirectForCleanUrls } from './redirect.js'
import { getLayoutAsyncComponent } from './util'
import Meta from 'vue-meta'

// built-in components
import Content from './components/Content.js'
import ContentSlotsDistributor from './components/ContentSlotsDistributor'
import OutboundLink from './components/OutboundLink.vue'
import ClientOnly from './components/ClientOnly'

// suggest dev server restart on base change
if (module.hot) {
const prevBase = siteData.base
module.hot.accept(VUEPRESS_TEMP_PATH + '/internal/siteData.js', () => {
if (siteData.base !== prevBase) {
window.alert(
`[vuepress] Site base has changed. `
+ `Please restart dev server to ensure correct asset paths.`
)
}
})
}

Vue.config.productionTip = false

Vue.use(Router)
Vue.use(VuePress)
Vue.use(Meta)
// mixin for exposing $site and $page
Vue.mixin(dataMixin(ClientComputedMixin, siteData))
// component for rendering markdown content and setting title etc.

Vue.component('Content', Content)
Vue.component('ContentSlotsDistributor', ContentSlotsDistributor)
Vue.component('OutboundLink', OutboundLink)
// component for client-only content
Vue.component('ClientOnly', ClientOnly)
// core components
Vue.component('Layout', getLayoutAsyncComponent('Layout'))
Vue.component('NotFound', getLayoutAsyncComponent('NotFound'))

// global helper for adding base path to absolute urls
Vue.prototype.$withBase = function (path) {
const base = this.$site.base
if (path.charAt(0) === '/') {
return base + path.slice(1)
} else {
return path
}
}

export function createApp (isServer) {
const routerBase = typeof window !== 'undefined' && window.__VUEPRESS_ROUTER_BASE__
? window.__VUEPRESS_ROUTER_BASE__
: (siteData.routerBase || siteData.base)

const router = new Router({
base: routerBase,
mode: 'history',
fallback: false,
routes,
scrollBehavior (to, from, savedPosition) {
if (savedPosition) {
return savedPosition
} else if (to.hash) {
if (Vue.$vuepress.$get('disableScrollBehavior')) {
return false
}
return {
selector: to.hash
}
} else {
return { x: 0, y: 0 }
}
}
})

handleRedirectForCleanUrls(router)

const options = {}

try {
appEnhancers.forEach(enhancer => {
if (typeof enhancer === 'function') {
enhancer({ Vue, options, router, siteData, isServer })
}
})
} catch (e) {
console.error(e)
}

const app = new Vue(
Object.assign(options, {
router,
render (h) {
return h('div', { attrs: { id: 'app' }}, [
h('router-view', { ref: 'layout' }),
h('div', { class: 'global-ui' }, globalUIComponents.map(component => h(component)))
])
}
})
)

return { app, router }
}
14 changes: 14 additions & 0 deletions lib/client/clientEntry.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
/* global VUEPRESS_VERSION, LAST_COMMIT_HASH*/

import { createApp } from './app'

const { app, router } = createApp(false /* isServer */)

window.__VUEPRESS__ = {
version: VUEPRESS_VERSION,
hash: LAST_COMMIT_HASH
}

router.onReady(() => {
app.$mount('#app')
})
12 changes: 12 additions & 0 deletions lib/client/components/ClientOnly.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
export default {
functional: true,
render (h, { parent, children }) {
if (parent._isMounted) {
return children
} else {
parent.$once('hook:mounted', () => {
parent.$forceUpdate()
})
}
}
}
29 changes: 29 additions & 0 deletions lib/client/components/Content.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import Vue from 'vue'
import { setGlobalInfo, getPageAsyncComponent } from '@app/util'

export default {
props: {
pageKey: String,
slotKey: {
type: String,
default: 'default'
}
},
render (h) {
const pageKey = this.pageKey || this.$parent.$page.key
setGlobalInfo('pageKey', pageKey)

/**
* This is for use cases that render `<Content />`
* with dynamic pageKey from current $page.
*/
if (!Vue.component(pageKey)) {
Vue.component(pageKey, getPageAsyncComponent(pageKey))
}

if (Vue.component(pageKey)) {
return h(pageKey)
}
return h('')
}
}
17 changes: 17 additions & 0 deletions lib/client/components/ContentSlotsDistributor.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
export default {
functional: true,
props: {
slotKey: String,
required: true
},
render (h, { props, slots }) {
return h('div',
{
class: [
`content__${props.slotKey}`
]
},
slots()[props.slotKey]
)
}
}
32 changes: 32 additions & 0 deletions lib/client/components/GlobalLayout.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
<template>
<component :is="layout"/>
</template>

<script>
import Vue from 'vue'
import { setGlobalInfo } from '@app/util'
export default {
methods: {
getLayout () {
if (this.$page.path) {
const layout = this.$page.frontmatter.layout
if (layout && (this.$vuepress.getLayoutAsyncComponent(layout)
|| this.$vuepress.getVueComponent(layout))) {
return layout
}
return 'Layout'
}
return 'NotFound'
}
},
computed: {
layout () {
const layout = this.getLayout()
setGlobalInfo('layout', layout)
return Vue.component(layout)
}
}
}
</script>
26 changes: 26 additions & 0 deletions lib/client/components/NotFound.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<template>
<div class="theme-container">
<div class="content">
<h1>404</h1>
<blockquote>{{ getMsg() }}</blockquote>
<router-link to="/">Take me home.</router-link>
</div>
</div>
</template>

<script>
const msgs = [
`There's nothing here.`,
`How did we get here?`,
`That's a Four-Oh-Four.`,
`Looks like we've got some broken links.`
]
export default {
methods: {
getMsg () {
return msgs[Math.floor(Math.random() * msgs.length)]
}
}
}
</script>
16 changes: 16 additions & 0 deletions lib/client/components/OutboundLink.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
<template functional>
<svg class="icon outbound" xmlns="http://www.w3.org/2000/svg" aria-hidden="true" x="0px" y="0px" viewBox="0 0 100 100" width="15" height="15">
<path fill="currentColor" d="M18.8,85.1h56l0,0c2.2,0,4-1.8,4-4v-32h-8v28h-48v-48h28v-8h-32l0,0c-2.2,0-4,1.8-4,4v56C14.8,83.3,16.6,85.1,18.8,85.1z"></path>
<polygon fill="currentColor" points="45.7,48.7 51.3,54.3 77.2,28.5 77.2,37.2 85.2,37.2 85.2,14.9 62.8,14.9 62.8,22.9 71.5,22.9"></polygon>
</svg>
</template>

<style>
.icon.outbound {
color: #aaa;
display: inline-block;
vertical-align: middle;
position: relative;
top: -1px;
}
</style>
37 changes: 37 additions & 0 deletions lib/client/dataMixin.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
/* global VUEPRESS_TEMP_PATH */

import GLobalVue from 'vue'

export default function dataMixin (I18n, siteData, Vue = GLobalVue) {
prepare(siteData)
Vue.$vuepress.$set('siteData', siteData)

if (module.hot) {
module.hot.accept(VUEPRESS_TEMP_PATH + '/internal/siteData.js', () => {
prepare(siteData)
Vue.$vuepress.$set('siteData', siteData)
})
}

const I18nConstructor = I18n(Vue.$vuepress.$get('siteData'))
const i18n = new I18nConstructor()
const descriptors = Object.getOwnPropertyDescriptors(Object.getPrototypeOf(i18n))
const computed = {}
Object.keys(descriptors).reduce((computed, key) => {
if (key.startsWith('$')) {
computed[key] = descriptors[key].get
}
return computed
}, computed)

return { computed }
}

function prepare (siteData) {
if (siteData.locales) {
Object.keys(siteData.locales).forEach(path => {
siteData.locales[path].path = path
})
}
Object.freeze(siteData)
}
11 changes: 11 additions & 0 deletions lib/client/index.dev.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title></title>
</head>
<body>
<div id="app"></div>
</body>
</html>
18 changes: 18 additions & 0 deletions lib/client/index.ssr.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="{{ lang }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
{{{ meta.inject().title.text() || `<title>${title}</title>` }}}
{{{ meta.inject().meta.text() }}}
<meta name="description" content="{{ description }}">
{{{ userHeadTags }}}
{{{ pageMeta }}}
{{{ renderResourceHints() }}}
{{{ renderStyles() }}}
</head>
<body>
<!--vue-ssr-outlet-->
{{{ renderScripts() }}}
</body>
</html>
15 changes: 15 additions & 0 deletions lib/client/plugins/Store.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import Vue from 'vue'

export declare class Store {
store: Vue;

$get(key: string): any;

$set(key: string, value: any): void;

$emit: typeof Vue.prototype.$emit;

$on: typeof Vue.prototype.$on;
}


27 changes: 27 additions & 0 deletions lib/client/plugins/Store.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import Vue from 'vue'

export default class Store {
constructor () {
this.store = new Vue({
data: {
state: {}
}
})
}

$get (key) {
return this.store.state[key]
}

$set (key, value) {
Vue.set(this.store.state, key, value)
}

$emit (...args) {
this.store.$emit(...args)
}

$on (...args) {
this.store.$on(...args)
}
}
Loading

0 comments on commit 2eb9e9c

Please sign in to comment.