WIP: add side bar
This commit is contained in:
parent
a5367c24e5
commit
befb3df8df
@ -7,42 +7,20 @@ module.exports = {
|
||||
['meta', { name: 'viewport', content: 'width=device-width,initial-scale=1,user-scalable=no' }]
|
||||
],
|
||||
// theme: 'reco',
|
||||
locales: {
|
||||
'/': {
|
||||
lang: 'ja-JP',
|
||||
title: "vuepress-theme-reco",
|
||||
description: 'A simple and beautiful vuepress blog theme.',
|
||||
},
|
||||
},
|
||||
theme: require.resolve('../../packages/vuepress-theme-reco'),
|
||||
themeConfig: {
|
||||
locales: {
|
||||
'/': {
|
||||
recoLocales: {
|
||||
pagation: {
|
||||
prev: '上壹頁',
|
||||
next: '下壹頁',
|
||||
go: '前往',
|
||||
jump: '跳轉至'
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
nav: [
|
||||
{ text: 'Home', link: '/', icon: 'reco-home' },
|
||||
{ text: 'TimeLine', link: '/timeline/', icon: 'reco-date' },
|
||||
{ text: 'Contact',
|
||||
icon: 'reco-message',
|
||||
items: [
|
||||
{ text: 'NPM', link: 'https://www.npmjs.com/~reco_luan', icon: 'reco-npm' },
|
||||
{ text: 'GitHub', link: 'https://github.com/recoluan', icon: 'reco-github' },
|
||||
{ text: '简书', link: 'https://www.jianshu.com/u/cd674a19515e', icon: 'reco-jianshu' },
|
||||
{ text: 'CSDN', link: 'https://blog.csdn.net/recoluan', icon: 'reco-csdn' },
|
||||
{ text: '博客圆', link: 'https://www.cnblogs.com/luanhewei/', icon: 'reco-bokeyuan' },
|
||||
{ text: 'WeChat', link: 'https://mp.weixin.qq.com/s/mXFqeUTegdvPliXknAAG_A', icon: 'reco-wechat' },
|
||||
]
|
||||
}
|
||||
{ text: 'sidebar', link: '/views/sidebar/' }
|
||||
],
|
||||
sidebar: {
|
||||
'/views/sidebar/': [
|
||||
'',
|
||||
'bar1',
|
||||
'bar2'
|
||||
]
|
||||
},
|
||||
type: 'blog',
|
||||
// 博客设置
|
||||
blogConfig: {
|
||||
@ -55,14 +33,14 @@ module.exports = {
|
||||
text: 'Tag' // 默认 “标签”
|
||||
}
|
||||
},
|
||||
type: 'blog',
|
||||
logo: '/head.png',
|
||||
authorAvatar: '/head.png',
|
||||
// 搜索设置
|
||||
search: true,
|
||||
searchMaxSuggestions: 10,
|
||||
// 自动形成侧边导航
|
||||
sidebar: 'auto',
|
||||
// sidebar: 'auto',
|
||||
sidebarDepth: 4,
|
||||
// 最后更新时间
|
||||
lastUpdated: 'Last Updated',
|
||||
// 作者
|
||||
|
@ -1,6 +1,7 @@
|
||||
---
|
||||
title: siderbar test
|
||||
title: sidebar test
|
||||
date: 2019-09-21
|
||||
sidebarDepth: 5
|
||||
tags:
|
||||
- tag2
|
||||
categories:
|
||||
|
2244
example/views/other/webpack.md
Normal file
2244
example/views/other/webpack.md
Normal file
File diff suppressed because it is too large
Load Diff
5
example/views/sidebar/README.md
Normal file
5
example/views/sidebar/README.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
title: 介绍
|
||||
---
|
||||
|
||||
介绍
|
5
example/views/sidebar/bar1.md
Normal file
5
example/views/sidebar/bar1.md
Normal file
@ -0,0 +1,5 @@
|
||||
---
|
||||
title: bar1
|
||||
---
|
||||
|
||||
bar1
|
65
example/views/sidebar/bar2.md
Normal file
65
example/views/sidebar/bar2.md
Normal file
@ -0,0 +1,65 @@
|
||||
---
|
||||
title: bar2
|
||||
---
|
||||
|
||||
bar2
|
||||
|
||||
## 二级标题1
|
||||
|
||||
### 三级标题1-1
|
||||
|
||||
#### 四级标题1-1-1
|
||||
#### 四级标题1-1-2
|
||||
#### 四级标题1-1-3
|
||||
|
||||
### 三体标题1-2
|
||||
|
||||
#### 四级标题1-2-1
|
||||
#### 四级标题1-2-2
|
||||
#### 四级标题1-2-3
|
||||
|
||||
### 三体标题1-3
|
||||
|
||||
#### 四级标题1-3-1
|
||||
#### 四级标题1-3-2
|
||||
#### 四级标题1-3-3
|
||||
|
||||
## 二级标题2
|
||||
|
||||
### 三级标题2-1
|
||||
|
||||
#### 四级标题2-1-1
|
||||
#### 四级标题2-1-2
|
||||
#### 四级标题2-1-3
|
||||
|
||||
### 三体标题2-2
|
||||
|
||||
#### 四级标题2-2-1
|
||||
#### 四级标题2-2-2
|
||||
#### 四级标题2-2-3
|
||||
|
||||
### 三体标题2-3
|
||||
|
||||
#### 四级标题2-3-1
|
||||
#### 四级标题2-3-2
|
||||
#### 四级标题2-3-3
|
||||
|
||||
## 二级标题3
|
||||
|
||||
### 三级标题3-1
|
||||
|
||||
#### 四级标题3-1-1
|
||||
#### 四级标题3-1-2
|
||||
#### 四级标题3-1-3
|
||||
|
||||
### 三体标题3-2
|
||||
|
||||
#### 四级标题3-2-1
|
||||
#### 四级标题3-2-2
|
||||
#### 四级标题3-2-3
|
||||
|
||||
### 三体标题3-3
|
||||
|
||||
#### 四级标题3-3-1
|
||||
#### 四级标题3-3-2
|
||||
#### 四级标题3-3-3
|
@ -128,13 +128,14 @@ export default {
|
||||
},
|
||||
|
||||
shouldShowSidebar () {
|
||||
const { frontmatter } = this.$page
|
||||
return (
|
||||
this.sidebar !== false &&
|
||||
!frontmatter.home &&
|
||||
frontmatter.sidebar !== false &&
|
||||
this.sidebarItems.length
|
||||
)
|
||||
// const { frontmatter } = this.$page
|
||||
// return (
|
||||
// this.sidebar !== false &&
|
||||
// !frontmatter.home &&
|
||||
// frontmatter.sidebar !== false &&
|
||||
// this.sidebarItems.length
|
||||
// )
|
||||
return this.sidebarItems.length > 0
|
||||
},
|
||||
|
||||
pageClasses () {
|
||||
|
@ -73,7 +73,7 @@
|
||||
<Comments v-if="recoShowModule" :isShowComments="shouldShowComments"/>
|
||||
</ModuleTransition>
|
||||
|
||||
<SubSiderbar class="sider-bar" />
|
||||
<SubSidebar class="side-bar" />
|
||||
</main>
|
||||
</template>
|
||||
|
||||
@ -82,11 +82,11 @@ import PageInfo from '@theme/components/PageInfo'
|
||||
import { resolvePage, outboundRE, endingSlashRE } from '@theme/helpers/utils'
|
||||
import ModuleTransition from '@theme/components/ModuleTransition'
|
||||
import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
|
||||
import SubSiderbar from '@theme/components/SubSiderbar'
|
||||
import SubSidebar from '@theme/components/SubSidebar'
|
||||
|
||||
export default {
|
||||
mixins: [moduleTransitonMixin],
|
||||
components: { PageInfo, ModuleTransition, SubSiderbar },
|
||||
components: { PageInfo, ModuleTransition, SubSidebar },
|
||||
|
||||
props: ['sidebarItems'],
|
||||
|
||||
@ -242,10 +242,15 @@ function flatten (items, res) {
|
||||
padding-bottom 2rem
|
||||
padding-right 10rem
|
||||
display block
|
||||
.sider-bar
|
||||
.side-bar
|
||||
position fixed
|
||||
top 10rem
|
||||
bottom 10rem
|
||||
right 2rem
|
||||
overflow-y scroll
|
||||
&::-webkit-scrollbar
|
||||
width: 0
|
||||
height: 0
|
||||
.page-title
|
||||
max-width: $contentWidth;
|
||||
margin: 0 auto;
|
||||
@ -289,7 +294,7 @@ function flatten (items, res) {
|
||||
@media (max-width: $MQMobile)
|
||||
.page
|
||||
padding-right 0
|
||||
.sider-bar
|
||||
.side-bar
|
||||
display none
|
||||
.page-title
|
||||
padding: 0 1rem;
|
||||
|
@ -88,24 +88,24 @@ export default {
|
||||
},
|
||||
|
||||
isInViewPortOfOne () {
|
||||
const siderbarScroll = document.getElementsByClassName('sidebar')[0]
|
||||
const sidebarScroll = document.getElementsByClassName('sidebar')[0]
|
||||
let el = document.getElementsByClassName('active sidebar-link')[1]
|
||||
if (el == null || el == undefined || el.offsetTop == undefined) {
|
||||
el = document.getElementsByClassName('active sidebar-link')[0]
|
||||
}
|
||||
if (el == null || el == undefined || el.offsetTop == undefined) return
|
||||
|
||||
const viewPortHeight = siderbarScroll.clientHeight || window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
|
||||
const viewPortHeight = sidebarScroll.clientHeight || window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
|
||||
const offsetTop = el.offsetTop
|
||||
const offsetBottom = el.offsetTop + el.offsetHeight
|
||||
const scrollTop = siderbarScroll.scrollTop
|
||||
const scrollTop = sidebarScroll.scrollTop
|
||||
const bottomVisible = (offsetBottom <= viewPortHeight + scrollTop)
|
||||
if (!bottomVisible) {
|
||||
siderbarScroll.scrollTop = (offsetBottom + 5 - viewPortHeight)
|
||||
sidebarScroll.scrollTop = (offsetBottom + 5 - viewPortHeight)
|
||||
}
|
||||
const topVisible = (offsetTop >= scrollTop)
|
||||
if (!topVisible) {
|
||||
siderbarScroll.scrollTop = (offsetTop - 5)
|
||||
sidebarScroll.scrollTop = (offsetTop - 5)
|
||||
}
|
||||
},
|
||||
|
||||
|
82
packages/vuepress-theme-reco/components/SubSideBar.vue
Normal file
82
packages/vuepress-theme-reco/components/SubSideBar.vue
Normal file
@ -0,0 +1,82 @@
|
||||
<script>
|
||||
import { isActive } from '@theme/helpers/utils'
|
||||
|
||||
export default {
|
||||
computed: {
|
||||
headers () {
|
||||
const headers = this.$page.headers.filter(header => header.level === 2)
|
||||
return headers
|
||||
}
|
||||
},
|
||||
mounted () {
|
||||
this.activationLink()
|
||||
},
|
||||
methods: {
|
||||
isLinkActive (header) {
|
||||
return isActive(this.$route, this.$page.path + '#' + header.slug)
|
||||
},
|
||||
activationLink () {
|
||||
const subtitleName = decodeURIComponent(this.$route.fullPath)
|
||||
if (!subtitleName || subtitleName == '') return
|
||||
// eslint-disable-next-line no-undef
|
||||
const subtitles = [].slice.call(document.querySelectorAll('.sub-sidebar-wrapper li'))
|
||||
for (let i = 0; i < subtitles.length; i++) {
|
||||
if (decodeURIComponent(subtitles[i].getAttribute('href')).indexOf(subtitleName) != -1) {
|
||||
subtitles[i].click()
|
||||
this.activationAnchor()
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
render (h) {
|
||||
return h('ul', {
|
||||
class: { 'sub-sidebar-wrapper': true }
|
||||
}, [
|
||||
...this.headers.map(header => {
|
||||
return h('li', {
|
||||
class: {
|
||||
active: this.isLinkActive(header),
|
||||
[`level-${header.level}`]: true
|
||||
},
|
||||
attr: { key: header.title }
|
||||
}, [
|
||||
h('router-link', {
|
||||
class: { 'sidebar-link': true },
|
||||
props: { to: `${this.$page.path}#${header.slug}` }
|
||||
}, header.title)
|
||||
])
|
||||
})
|
||||
])
|
||||
}
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.sub-sidebar-wrapper
|
||||
padding-left 0
|
||||
list-style none
|
||||
border-left 1px solid var(--border-color)
|
||||
font-size 12px
|
||||
li
|
||||
padding .5rem 0
|
||||
cursor pointer
|
||||
border-left 1px solid transparent
|
||||
a
|
||||
color var(--text-color)
|
||||
&:hover
|
||||
a
|
||||
color $accentColor
|
||||
&.active
|
||||
border-left 1px solid $accentColor
|
||||
a
|
||||
color $accentColor
|
||||
&.level-1
|
||||
padding-left .4rem
|
||||
&.level-2
|
||||
padding-left .9rem
|
||||
&.level-3
|
||||
padding-left 1.2rem
|
||||
</style>
|
||||
|
@ -1,11 +0,0 @@
|
||||
<template>
|
||||
<div>test</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
export default {
|
||||
mounted () {
|
||||
console.log(this.$page.headers)
|
||||
}
|
||||
}
|
||||
</script>
|
@ -122,42 +122,49 @@ export function resolveSidebarItems (page, regularPath, site, localePath) {
|
||||
? themeConfig.locales[localePath] || themeConfig
|
||||
: themeConfig
|
||||
|
||||
const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
|
||||
if (pageSidebarConfig === 'auto') {
|
||||
return resolveHeaders(page)
|
||||
}
|
||||
// 计算页面的菜单层级
|
||||
// const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
|
||||
// if (pageSidebarConfig === 'auto') {
|
||||
// return resolveHeaders(page)
|
||||
// }
|
||||
|
||||
// const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
|
||||
// if (!sidebarConfig) {
|
||||
// return []
|
||||
// } else {
|
||||
// const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
|
||||
// return config
|
||||
// ? config.map(item => resolveItem(item, pages, base))
|
||||
// : []
|
||||
// }
|
||||
const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
|
||||
if (!sidebarConfig) {
|
||||
return []
|
||||
} else {
|
||||
const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
|
||||
return config
|
||||
? config.map(item => resolveItem(item, pages, base))
|
||||
: []
|
||||
}
|
||||
|
||||
const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
|
||||
return config
|
||||
? config.map(item => resolveItem(item, pages, base))
|
||||
: []
|
||||
}
|
||||
|
||||
/**
|
||||
* @param { Page } page
|
||||
* @returns { SidebarGroup }
|
||||
*/
|
||||
function resolveHeaders (page) {
|
||||
const headers = groupHeaders(page.headers || [])
|
||||
return [{
|
||||
type: 'group',
|
||||
collapsable: false,
|
||||
title: page.title,
|
||||
path: null,
|
||||
children: headers.map(h => ({
|
||||
type: 'auto',
|
||||
title: h.title,
|
||||
basePath: page.path,
|
||||
path: page.path + '#' + h.slug,
|
||||
children: h.children || []
|
||||
}))
|
||||
}]
|
||||
}
|
||||
// function resolveHeaders (page) {
|
||||
// const headers = groupHeaders(page.headers || [])
|
||||
// return [{
|
||||
// type: 'group',
|
||||
// collapsable: false,
|
||||
// title: page.title,
|
||||
// path: null,
|
||||
// children: headers.map(h => ({
|
||||
// type: 'auto',
|
||||
// title: h.title,
|
||||
// basePath: page.path,
|
||||
// path: page.path + '#' + h.slug,
|
||||
// children: h.children || []
|
||||
// }))
|
||||
// }]
|
||||
// }
|
||||
|
||||
export function groupHeaders (headers) {
|
||||
// group h3s under h2
|
||||
|
Loading…
Reference in New Issue
Block a user