WIP: add side bar

This commit is contained in:
reco_luan 2020-07-05 15:00:53 +08:00
parent a5367c24e5
commit befb3df8df
12 changed files with 2471 additions and 89 deletions

View File

@ -7,42 +7,20 @@ module.exports = {
['meta', { name: 'viewport', content: 'width=device-width,initial-scale=1,user-scalable=no' }] ['meta', { name: 'viewport', content: 'width=device-width,initial-scale=1,user-scalable=no' }]
], ],
// theme: 'reco', // 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'), theme: require.resolve('../../packages/vuepress-theme-reco'),
themeConfig: { themeConfig: {
locales: {
'/': {
recoLocales: {
pagation: {
prev: '上壹頁',
next: '下壹頁',
go: '前往',
jump: '跳轉至'
}
}
}
},
nav: [ nav: [
{ text: 'Home', link: '/', icon: 'reco-home' }, { text: 'Home', link: '/', icon: 'reco-home' },
{ text: 'TimeLine', link: '/timeline/', icon: 'reco-date' }, { text: 'TimeLine', link: '/timeline/', icon: 'reco-date' },
{ text: 'Contact', { text: 'sidebar', link: '/views/sidebar/' }
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' },
]
}
], ],
sidebar: {
'/views/sidebar/': [
'',
'bar1',
'bar2'
]
},
type: 'blog', type: 'blog',
// 博客设置 // 博客设置
blogConfig: { blogConfig: {
@ -55,14 +33,14 @@ module.exports = {
text: 'Tag' // 默认 “标签” text: 'Tag' // 默认 “标签”
} }
}, },
type: 'blog',
logo: '/head.png', logo: '/head.png',
authorAvatar: '/head.png', authorAvatar: '/head.png',
// 搜索设置 // 搜索设置
search: true, search: true,
searchMaxSuggestions: 10, searchMaxSuggestions: 10,
// 自动形成侧边导航 // 自动形成侧边导航
sidebar: 'auto', // sidebar: 'auto',
sidebarDepth: 4,
// 最后更新时间 // 最后更新时间
lastUpdated: 'Last Updated', lastUpdated: 'Last Updated',
// 作者 // 作者

View File

@ -1,6 +1,7 @@
--- ---
title: siderbar test title: sidebar test
date: 2019-09-21 date: 2019-09-21
sidebarDepth: 5
tags: tags:
- tag2 - tag2
categories: categories:

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,5 @@
---
title: 介绍
---
介绍

View File

@ -0,0 +1,5 @@
---
title: bar1
---
bar1

View 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

View File

@ -128,13 +128,14 @@ export default {
}, },
shouldShowSidebar () { shouldShowSidebar () {
const { frontmatter } = this.$page // const { frontmatter } = this.$page
return ( // return (
this.sidebar !== false && // this.sidebar !== false &&
!frontmatter.home && // !frontmatter.home &&
frontmatter.sidebar !== false && // frontmatter.sidebar !== false &&
this.sidebarItems.length // this.sidebarItems.length
) // )
return this.sidebarItems.length > 0
}, },
pageClasses () { pageClasses () {

View File

@ -73,7 +73,7 @@
<Comments v-if="recoShowModule" :isShowComments="shouldShowComments"/> <Comments v-if="recoShowModule" :isShowComments="shouldShowComments"/>
</ModuleTransition> </ModuleTransition>
<SubSiderbar class="sider-bar" /> <SubSidebar class="side-bar" />
</main> </main>
</template> </template>
@ -82,11 +82,11 @@ import PageInfo from '@theme/components/PageInfo'
import { resolvePage, outboundRE, endingSlashRE } from '@theme/helpers/utils' import { resolvePage, outboundRE, endingSlashRE } from '@theme/helpers/utils'
import ModuleTransition from '@theme/components/ModuleTransition' import ModuleTransition from '@theme/components/ModuleTransition'
import moduleTransitonMixin from '@theme/mixins/moduleTransiton' import moduleTransitonMixin from '@theme/mixins/moduleTransiton'
import SubSiderbar from '@theme/components/SubSiderbar' import SubSidebar from '@theme/components/SubSidebar'
export default { export default {
mixins: [moduleTransitonMixin], mixins: [moduleTransitonMixin],
components: { PageInfo, ModuleTransition, SubSiderbar }, components: { PageInfo, ModuleTransition, SubSidebar },
props: ['sidebarItems'], props: ['sidebarItems'],
@ -242,10 +242,15 @@ function flatten (items, res) {
padding-bottom 2rem padding-bottom 2rem
padding-right 10rem padding-right 10rem
display block display block
.sider-bar .side-bar
position fixed position fixed
top 10rem top 10rem
bottom 10rem
right 2rem right 2rem
overflow-y scroll
&::-webkit-scrollbar
width: 0
height: 0
.page-title .page-title
max-width: $contentWidth; max-width: $contentWidth;
margin: 0 auto; margin: 0 auto;
@ -289,7 +294,7 @@ function flatten (items, res) {
@media (max-width: $MQMobile) @media (max-width: $MQMobile)
.page .page
padding-right 0 padding-right 0
.sider-bar .side-bar
display none display none
.page-title .page-title
padding: 0 1rem; padding: 0 1rem;

View File

@ -88,24 +88,24 @@ export default {
}, },
isInViewPortOfOne () { isInViewPortOfOne () {
const siderbarScroll = document.getElementsByClassName('sidebar')[0] const sidebarScroll = document.getElementsByClassName('sidebar')[0]
let el = document.getElementsByClassName('active sidebar-link')[1] let el = document.getElementsByClassName('active sidebar-link')[1]
if (el == null || el == undefined || el.offsetTop == undefined) { if (el == null || el == undefined || el.offsetTop == undefined) {
el = document.getElementsByClassName('active sidebar-link')[0] el = document.getElementsByClassName('active sidebar-link')[0]
} }
if (el == null || el == undefined || el.offsetTop == undefined) return 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 offsetTop = el.offsetTop
const offsetBottom = el.offsetTop + el.offsetHeight const offsetBottom = el.offsetTop + el.offsetHeight
const scrollTop = siderbarScroll.scrollTop const scrollTop = sidebarScroll.scrollTop
const bottomVisible = (offsetBottom <= viewPortHeight + scrollTop) const bottomVisible = (offsetBottom <= viewPortHeight + scrollTop)
if (!bottomVisible) { if (!bottomVisible) {
siderbarScroll.scrollTop = (offsetBottom + 5 - viewPortHeight) sidebarScroll.scrollTop = (offsetBottom + 5 - viewPortHeight)
} }
const topVisible = (offsetTop >= scrollTop) const topVisible = (offsetTop >= scrollTop)
if (!topVisible) { if (!topVisible) {
siderbarScroll.scrollTop = (offsetTop - 5) sidebarScroll.scrollTop = (offsetTop - 5)
} }
}, },

View 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>

View File

@ -1,11 +0,0 @@
<template>
<div>test</div>
</template>
<script>
export default {
mounted () {
console.log(this.$page.headers)
}
}
</script>

View File

@ -122,42 +122,49 @@ export function resolveSidebarItems (page, regularPath, site, localePath) {
? themeConfig.locales[localePath] || themeConfig ? themeConfig.locales[localePath] || themeConfig
: themeConfig : themeConfig
const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar // 计算页面的菜单层级
if (pageSidebarConfig === 'auto') { // const pageSidebarConfig = page.frontmatter.sidebar || localeConfig.sidebar || themeConfig.sidebar
return resolveHeaders(page) // 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 const sidebarConfig = localeConfig.sidebar || themeConfig.sidebar
if (!sidebarConfig) {
return [] const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig)
} else { return config
const { base, config } = resolveMatchingConfig(regularPath, sidebarConfig) ? config.map(item => resolveItem(item, pages, base))
return config : []
? config.map(item => resolveItem(item, pages, base))
: []
}
} }
/** /**
* @param { Page } page * @param { Page } page
* @returns { SidebarGroup } * @returns { SidebarGroup }
*/ */
function resolveHeaders (page) { // function resolveHeaders (page) {
const headers = groupHeaders(page.headers || []) // const headers = groupHeaders(page.headers || [])
return [{ // return [{
type: 'group', // type: 'group',
collapsable: false, // collapsable: false,
title: page.title, // title: page.title,
path: null, // path: null,
children: headers.map(h => ({ // children: headers.map(h => ({
type: 'auto', // type: 'auto',
title: h.title, // title: h.title,
basePath: page.path, // basePath: page.path,
path: page.path + '#' + h.slug, // path: page.path + '#' + h.slug,
children: h.children || [] // children: h.children || []
})) // }))
}] // }]
} // }
export function groupHeaders (headers) { export function groupHeaders (headers) {
// group h3s under h2 // group h3s under h2