提交 3b689139 编写于 作者: S Shigma 提交者: fgiraud

feat($core): better layout check (#1455)

* better layout check
* enhance resolve SFCs
* fix(layout): fix broken class content
* fix(delete): delete useless use of context
上级 6b5a0020
......@@ -9,7 +9,8 @@ const {
path: { resolve, parse },
moduleResolver: { getThemeResolver },
datatypes: { isString },
logger, chalk
logger,
chalk
} = require('@vuepress/shared-utils')
const ThemeAPI = require('./theme-api')
......@@ -37,7 +38,7 @@ module.exports = function loadTheme (ctx) {
if (!theme.path) {
throw new Error(
'[vuepress] You must specify a theme, or create a local custom theme. \n'
+ 'For more details, refer to https://vuepress.vuejs.org/guide/custom-themes.html#custom-themes. \n'
+ 'For more details, refer to https://vuepress.vuejs.org/guide/custom-themes.html#custom-themes. \n'
)
}
......@@ -55,7 +56,7 @@ module.exports = function loadTheme (ctx) {
logger.debug('theme', theme.name, theme.path)
logger.debug('parentTheme', parentTheme.name, parentTheme.path)
return new ThemeAPI(theme, parentTheme, ctx)
return new ThemeAPI(theme, parentTheme)
}
function normalizeThemePath (resolved) {
......@@ -82,10 +83,11 @@ function resolveTheme (ctx, resolver, ignoreLocal, theme) {
/**
* 1. From `.vuepress/theme` directory.
*/
if (!ignoreLocal
if (
!ignoreLocal
&& !fs.existsSync(theme)
&& fs.existsSync(localThemePath)
&& (fs.readdirSync(localThemePath)).length > 0
&& fs.readdirSync(localThemePath).length > 0
) {
path = localThemePath
name = shortcut = 'local'
......
const { logger, fs, path: { resolve }} = require('@vuepress/shared-utils')
const readdirSync = dir => fs.existsSync(dir) && fs.readdirSync(dir) || []
const {
logger,
fs,
path: { resolve }
} = require('@vuepress/shared-utils')
const readdirSync = dir => (fs.existsSync(dir) && fs.readdirSync(dir)) || []
module.exports = class ThemeAPI {
constructor (theme, parentTheme) {
......@@ -30,12 +34,12 @@ module.exports = class ThemeAPI {
this.componentMap = this.getComponents()
this.layoutComponentMap = this.getLayoutComponentMap()
Object.keys(this.componentMap).forEach((name) => {
Object.keys(this.componentMap).forEach(name => {
const { filename, path } = this.componentMap[name]
alias[`@theme/components/${filename}`] = path
})
Object.keys(this.layoutComponentMap).forEach((name) => {
Object.keys(this.layoutComponentMap).forEach(name => {
const { filename, path } = this.layoutComponentMap[name]
alias[`@theme/layouts/${filename}`] = path
})
......@@ -44,13 +48,9 @@ module.exports = class ThemeAPI {
}
getComponents () {
const componentDirs = [
resolve(this.theme.path, 'components')
]
const componentDirs = [resolve(this.theme.path, 'components')]
if (this.existsParentTheme) {
componentDirs.unshift(
resolve(this.parentTheme.path, 'components'),
)
componentDirs.unshift(resolve(this.parentTheme.path, 'components'))
}
return resolveSFCs(componentDirs)
}
......@@ -63,15 +63,15 @@ module.exports = class ThemeAPI {
if (this.existsParentTheme) {
layoutDirs.unshift(
resolve(this.parentTheme.path, '.'),
resolve(this.parentTheme.path, 'layouts'),
resolve(this.parentTheme.path, 'layouts')
)
}
// built-in named layout or not.
const layoutComponentMap = resolveSFCs(layoutDirs)
const { Layout = {}, NotFound = {}} = layoutComponentMap
const { Layout, NotFound } = layoutComponentMap
// layout component does not exist.
if (!Layout || !fs.existsSync(Layout.path)) {
if (!Layout) {
const fallbackLayoutPath = resolve(__dirname, 'Layout.fallback.vue')
layoutComponentMap.Layout = {
filename: 'Layout.vue',
......@@ -81,10 +81,10 @@ module.exports = class ThemeAPI {
}
logger.warn(
`[vuepress] Cannot resolve Layout.vue file in \n ${Layout.path}, `
+ `fallback to default layout: ${fallbackLayoutPath}`
+ `fallback to default layout: ${fallbackLayoutPath}`
)
}
if (!NotFound || !fs.existsSync(NotFound.path)) {
if (!NotFound) {
layoutComponentMap.NotFound = {
filename: 'NotFound.vue',
componentName: 'NotFound',
......@@ -104,25 +104,28 @@ module.exports = class ThemeAPI {
*/
function resolveSFCs (dirs) {
return dirs.map(
layoutDir => readdirSync(layoutDir)
.filter(filename => filename.endsWith('.vue'))
.map(filename => {
const componentName = getComponentName(filename)
return {
filename,
componentName,
isInternal: isInternal(componentName),
path: resolve(layoutDir, filename)
}
})
).reduce((arr, next) => {
arr.push(...next)
return arr
}, []).reduce((map, component) => {
map[component.componentName] = component
return map
}, {})
return dirs
.map(layoutDir =>
readdirSync(layoutDir)
.filter(filename => filename.endsWith('.vue'))
.map(filename => {
const componentName = getComponentName(filename)
return {
filename,
componentName,
isInternal: isInternal(componentName),
path: resolve(layoutDir, filename)
}
})
)
.reduce((arr, next) => {
arr.push(...next)
return arr
}, [])
.reduce((map, component) => {
map[component.componentName] = component
return map
}, {})
}
/**
......
......@@ -2,7 +2,7 @@
<main class="page">
<slot name="top" />
<Content />
<Content class="theme-default-content" />
<PageEdit />
<PageNav v-bind="{ sidebarItems }" />
......@@ -22,6 +22,8 @@ export default {
</script>
<style lang="stylus">
@require '../styles/wrapper.styl';
.page {
padding-bottom: 2rem;
display: block;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册