Skip to content

Commit

Permalink
feat($core): support global layout (close: #1226)
Browse files Browse the repository at this point in the history
  • Loading branch information
ulivz committed Feb 16, 2019
1 parent fb13864 commit c91f55a
Show file tree
Hide file tree
Showing 4 changed files with 101 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
</template>

<script>
import { getLayoutAsyncComponent } from '../util'
export default {
computed: {
layout () {
if (this.$page.path) {
if (getLayoutAsyncComponent(this.$page.frontmatter.layout)) {
if (this.$vuepress.isLayoutExists(this.$page.frontmatter.layout)) {
return this.$page.frontmatter.layout
}
return 'Layout'
Expand Down
17 changes: 17 additions & 0 deletions packages/@vuepress/core/lib/app/plugins/VuePress.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,24 @@
import Store from './Store'
import {
isPageExists,
isPageLoaded,
getPageAsyncComponent,
isLayoutExists,
isLayoutLoaded,
getLayoutAsyncComponent
} from '../util'

class VuePress extends Store {}

Object.assign(VuePress.prototype, {
isPageExists,
isPageLoaded,
getPageAsyncComponent,
isLayoutExists,
isLayoutLoaded,
getLayoutAsyncComponent
})

export default {
install (Vue) {
const ins = new VuePress()
Expand Down
13 changes: 7 additions & 6 deletions packages/@vuepress/core/lib/internal-plugins/routes.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,23 @@ module.exports = (options, ctx) => ({

// @internal/routes
async clientDynamicModules () {
const code = importCode() + routesCode(ctx.pages)
const code = importCode(ctx.globalLayout) + routesCode(ctx.pages)
return { name: 'routes.js', content: code, dirname: 'internal' }
}
})

/**
* Import utilities
* @param {string} globalLayout path of global layout component
* @returns {string}
*/
function importCode () {
function importCode (globalLayout) {
return `
import { injectComponentOption, ensureAsyncComponentsLoaded } from '@app/util'
import rootMixins from '@internal/root-mixins'
import LayoutDistributor from '@app/components/LayoutDistributor.vue'
import GlobalLayout from ${JSON.stringify(globalLayout)}
injectComponentOption(LayoutDistributor, 'mixins', rootMixins)
injectComponentOption(GlobalLayout, 'mixins', rootMixins)
`
}

Expand All @@ -41,7 +42,7 @@ function routesCode (pages) {
{
name: ${JSON.stringify(componentName)},
path: ${JSON.stringify(pagePath)},
component: LayoutDistributor,
component: GlobalLayout,
beforeEnter: (to, from, next) => {
ensureAsyncComponentsLoaded(${JSON.stringify(layout || 'Layout')}, ${JSON.stringify(componentName)}).then(next)
},${_meta ? `\n meta: ${JSON.stringify(_meta)}` : ''}
Expand Down Expand Up @@ -78,7 +79,7 @@ function routesCode (pages) {
const notFoundRoute = `,
{
path: '*',
component: LayoutDistributor
component: GlobalLayout
}`

return (
Expand Down
76 changes: 76 additions & 0 deletions packages/@vuepress/core/lib/prepare/AppContext.js
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,7 @@ module.exports = class AppContext {
this.normalizeHeadTagUrls()
await this.resolveTheme()
this.resolveTemplates()
this.resolveGlobalLayout()

this.applyInternalPlugins()
this.applyUserPlugins()
Expand Down Expand Up @@ -257,6 +258,58 @@ module.exports = class AppContext {
this.ssrTemplate = ssrTemplate
}

/**
* resolve global layout
*
* @returns {string}
* @api private
*/

resolveGlobalLayout () {
const GLOBAL_LAYOUT_COMPONENT_NAME = `GlobalLayout`

this.globalLayout = this.resolveCommonAgreementFilePath(
'globalLayout',
{
defaultValue: path.resolve(__dirname, `../app/components/${GLOBAL_LAYOUT_COMPONENT_NAME}.vue`),
siteAgreement: `components/${GLOBAL_LAYOUT_COMPONENT_NAME}.vue`,
themeAgreement: `layouts/${GLOBAL_LAYOUT_COMPONENT_NAME}.vue`
}
)

logger.debug('globalLayout: ' + chalk.gray(this.globalLayout))
}

/**
* Resolve a path-type config.
*
* @param {string} configKey
* @param {string} defaultValue an absolute path
* @param {string} siteAgreement a relative path to vuepress dir
* @param {string} themeAgreement a relative path to theme dir
* @returns {string | void}
*/

resolveCommonAgreementFilePath (configKey, {
defaultValue,
siteAgreement,
themeAgreement
}) {
const siteConfigValue = this.siteConfig[configKey]
siteAgreement = path.resolve(this.vuepressDir, siteAgreement)

const themeConfigValue = this.getThemeConfigValue(configKey)
themeAgreement = this.getThemeAgreementFile(themeAgreement)

return fsExistsFallback([
siteConfigValue,
siteAgreement,
themeConfigValue,
themeAgreement,
defaultValue
])
}

/**
* Find all page source files located in sourceDir
*
Expand Down Expand Up @@ -312,6 +365,29 @@ module.exports = class AppContext {
Object.assign(this, (await loadTheme(this)))
}

/**
* Get config value of current active theme.
*
* @param {string} key
* @returns {any}
* @api private
*/

getThemeConfigValue (key) {
return this.themeEntryFile[key] || this.parentThemeEntryFile[key]
}

getThemeAgreementFile (filepath) {
const current = path.resolve(this.themePath, filepath)
if (fs.existsSync(current)) {
return current
}
const parent = path.resolve(this.parentThemePath, filepath)
if (fs.existsSync(parent)) {
return parent
}
}

/**
* Get the data to be delivered to the client.
*
Expand Down

0 comments on commit c91f55a

Please sign in to comment.