diff --git a/packages/@vuepress/theme-default/components/Page.vue b/packages/@vuepress/theme-default/components/Page.vue index e346021023..328f32c245 100644 --- a/packages/@vuepress/theme-default/components/Page.vue +++ b/packages/@vuepress/theme-default/components/Page.vue @@ -182,7 +182,7 @@ function find (page, items, offset) { const res = [] items.forEach(item => { if (item.type === 'group') { - res.push(...item.children || []) + res.push(...item.descendants || []) } else { res.push(item) } diff --git a/packages/@vuepress/theme-default/components/Sidebar.vue b/packages/@vuepress/theme-default/components/Sidebar.vue index 9ed10ed9b8..a9e5d9293f 100644 --- a/packages/@vuepress/theme-default/components/Sidebar.vue +++ b/packages/@vuepress/theme-default/components/Sidebar.vue @@ -8,10 +8,7 @@ v-if="item.type === 'group'" :item="item" :first="i === 0" - :open="i === openGroupIndex" - :collapsable="item.collapsable || item.collapsible" - @toggle="toggleGroup(i)" - /> + :collapsable="item.collapsable || item.collapsible"/> @@ -23,58 +20,11 @@ import SidebarGroup from './SidebarGroup.vue' import SidebarLink from './SidebarLink.vue' import NavLinks from './NavLinks.vue' -import { isActive } from '../util' export default { components: { SidebarGroup, SidebarLink, NavLinks }, - props: ['items'], - - data () { - return { - openGroupIndex: 0 - } - }, - - created () { - this.refreshIndex() - }, - - watch: { - '$route' () { - this.refreshIndex() - } - }, - - methods: { - refreshIndex () { - const index = resolveOpenGroupIndex( - this.$route, - this.items - ) - if (index > -1) { - this.openGroupIndex = index - } - }, - - toggleGroup (index) { - this.openGroupIndex = index === this.openGroupIndex ? -1 : index - }, - - isActive (page) { - return isActive(this.$route, page.regularPath) - } - } -} - -function resolveOpenGroupIndex (route, items) { - for (let i = 0; i < items.length; i++) { - const item = items[i] - if (item.type === 'group' && item.children.some(c => isActive(route, c.path))) { - return i - } - } - return -1 + props: ['items'] } diff --git a/packages/@vuepress/theme-default/components/SidebarGroup.vue b/packages/@vuepress/theme-default/components/SidebarGroup.vue index 119dfa14c7..7142214426 100644 --- a/packages/@vuepress/theme-default/components/SidebarGroup.vue +++ b/packages/@vuepress/theme-default/components/SidebarGroup.vue @@ -6,7 +6,7 @@
  • - + +
  • @@ -31,13 +34,72 @@ @@ -48,7 +110,7 @@ export default { .sidebar-group padding-left 0.5em &:not(.collapsable) - .sidebar-heading + > .sidebar-heading cursor auto color inherit diff --git a/packages/@vuepress/theme-default/components/SidebarLink.vue b/packages/@vuepress/theme-default/components/SidebarLink.vue index 4b08380ed3..8d516b12ac 100644 --- a/packages/@vuepress/theme-default/components/SidebarLink.vue +++ b/packages/@vuepress/theme-default/components/SidebarLink.vue @@ -4,9 +4,15 @@ import { isActive, hashRE, groupHeaders } from '../util' export default { functional: true, - props: ['item'], + props: ['item', 'sidebarDepth'], - render (h, { parent: { $page, $site, $route }, props: { item }}) { + render ( + h, + { + parent: { $page, $site, $route }, + props: { item, sidebarDepth } + } + ) { // use custom active class matching logic // due to edge case of paths ending with / + hash const selfActive = isActive($route, item.path) @@ -16,10 +22,17 @@ export default { ? selfActive || item.children.some(c => isActive($route, item.basePath + '#' + c.slug)) : selfActive const link = renderLink(h, item.path, item.title || item.path, active) - const configDepth = $page.frontmatter.sidebarDepth != null - ? $page.frontmatter.sidebarDepth - : $site.themeConfig.sidebarDepth + + let configDepth + if ($page.frontmatter.sidebarDepth != null) { + configDepth = $page.frontmatter.sidebarDepth + } else if (sidebarDepth != null) { + configDepth = sidebarDepth + } else { + configDepth = $site.themeConfig.sidebarDepth + } const maxDepth = configDepth == null ? 1 : configDepth + const displayAllHeaders = !!$site.themeConfig.displayAllHeaders if (item.type === 'auto') { return [link, renderChildren(h, item.children, item.basePath, $route, maxDepth)] diff --git a/packages/@vuepress/theme-default/util/index.js b/packages/@vuepress/theme-default/util/index.js index 01937e9888..cf05e2a972 100644 --- a/packages/@vuepress/theme-default/util/index.js +++ b/packages/@vuepress/theme-default/util/index.js @@ -207,26 +207,30 @@ function ensureEndingSlash (path) { : path + '/' } -function resolveItem (item, pages, base, isNested) { +function resolveItem (item, pages, base, groupDepth = 1) { if (typeof item === 'string') { return resolvePage(pages, item, base) } else if (Array.isArray(item)) { return Object.assign(resolvePage(pages, item[0], base), { title: item[1] }) - } else { - if (isNested) { - console.error( - '[vuepress] Nested sidebar groups are not supported. ' + - 'Consider using navbar + categories instead.' - ) - } - const children = item.children || [] + } else if (Array.isArray(item.children)) { + const descendants = [] + const children = item.children.map(child => { + const resolvedItem = resolveItem(child, pages, base, groupDepth + 1) + ;[].push.apply(descendants, resolvedItem.descendants || [resolvedItem]) + return resolvedItem + }) return { type: 'group', title: item.title, - children: children.map(child => resolveItem(child, pages, base, true)), - collapsable: item.collapsable !== false + children, + descendants, + collapsable: item.collapsable !== false, + isolated: item.isolated === true, + initialIsolatedOpen: item.initialIsolatedOpen === true, + sidebarDepth: item.sidebarDepth, + groupDepth } } } diff --git a/packages/docs/docs/theme/default-theme-config.md b/packages/docs/docs/theme/default-theme-config.md index 8abadcd6a6..3615f861fd 100644 --- a/packages/docs/docs/theme/default-theme-config.md +++ b/packages/docs/docs/theme/default-theme-config.md @@ -195,6 +195,12 @@ module.exports = { Sidebar groups are collapsable by default. You can force a group to be always open with `collapsable: false`. +When a group is open, other groups at the same level will be automatically closed. You can isolate a group's open status with `isolated: true`. And then you can config its initial open status with `initialIsolatedOpen: true`. + +You can config a group's sidebarDepth with `sidebarDepth: 2`. + +You can nest sidebar groups. + ### Multiple Sidebars If you wish to display different sidebars for different sections of content, first organize your pages into directories for each desired section: @@ -329,7 +335,7 @@ module.exports = { ``` ::: warning Note -Unlike the [built-in search](#built-in-search) engine which works out of the box, [Algolia DocSearch](https://community.algolia.com/docsearch/) requires you to submit your site to them for indexing before it starts working. +Unlike the [built-in search](#built-in-search) engine which works out of the box, [Algolia DocSearch](https://community.algolia.com/docsearch/) requires you to submit your site to them for indexing before it starts working. ::: For more options, refer to [Algolia DocSearch's documentation](https://github.com/algolia/docsearch#docsearch-options). diff --git a/packages/docs/docs/zh/theme/default-theme-config.md b/packages/docs/docs/zh/theme/default-theme-config.md index 85af4f29df..d664d0e29f 100644 --- a/packages/docs/docs/zh/theme/default-theme-config.md +++ b/packages/docs/docs/zh/theme/default-theme-config.md @@ -192,6 +192,12 @@ module.exports = { 侧边栏的每个子组默认是可折叠的,你可以设置 `collapsable: false` 来让一个组永远都是展开状态。 +当一个子组被展开时,跟它同级的其他子组会被折叠。你可以设置 `isolated: true` 来隔离一个组的展开状态。然后你可以设置 `initialIsolatedOpen: true` 来让一个被隔离的组在一开始就处于展开状态。 + +你可以通过 `sidebarDepth: 2` 来设置一个组的 sidebarDepth。 + +你可以嵌套组。 + ### 多个侧边栏 如果你想为不同的页面组来显示不同的侧边栏,首先,将你的页面文件组织成下述的目录结构: