mirror of https://github.com/vuejs/vitepress
parent
1be0a0b0a1
commit
3d2f7e27de
@ -0,0 +1,33 @@
|
||||
// TODO dropdowns
|
||||
import { computed } from 'vue'
|
||||
import { useSiteData, useRoute } from 'vitepress'
|
||||
import { withBase } from '../utils'
|
||||
|
||||
const normalizePath = (path: string): string => {
|
||||
path = path
|
||||
.replace(/#.*$/, '')
|
||||
.replace(/\?.*$/, '')
|
||||
.replace(/\.html$/, '')
|
||||
if (path.endsWith('/')) {
|
||||
path += 'index'
|
||||
}
|
||||
return path
|
||||
}
|
||||
|
||||
export default {
|
||||
setup() {
|
||||
const route = useRoute()
|
||||
const isActiveLink = (link: string): boolean => {
|
||||
return normalizePath(withBase(link)) === normalizePath(route.path)
|
||||
}
|
||||
|
||||
return {
|
||||
withBase,
|
||||
isActiveLink,
|
||||
// use computed in dev for hot reload
|
||||
navData: __DEV__
|
||||
? computed(() => useSiteData().value.themeConfig.nav)
|
||||
: useSiteData().value.themeConfig.nav
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,115 @@
|
||||
import { useSiteData, usePageData, useRoute } from 'vitepress'
|
||||
import { computed, h, FunctionalComponent } from 'vue'
|
||||
import { Header } from '../../../../types/shared'
|
||||
import { DefaultTheme } from '../config'
|
||||
|
||||
const SideBarItem: FunctionalComponent<{
|
||||
item: ResolvedSidebarItem
|
||||
}> = (props) => {
|
||||
const {
|
||||
item: { link, text, children }
|
||||
} = props
|
||||
return h('li', [
|
||||
h('a', { href: link }, text),
|
||||
children
|
||||
? h(
|
||||
'ul',
|
||||
children.map((c) => h(SideBarItem, { item: c }))
|
||||
)
|
||||
: null
|
||||
])
|
||||
}
|
||||
|
||||
export default {
|
||||
components: {
|
||||
SideBarItem
|
||||
},
|
||||
|
||||
setup() {
|
||||
const pageData = usePageData()
|
||||
const siteData = useSiteData()
|
||||
const route = useRoute()
|
||||
|
||||
const resolveSidebar = () => {
|
||||
const {
|
||||
headers,
|
||||
frontmatter: { sidebar, sidebarDepth = 2 }
|
||||
} = pageData.value
|
||||
|
||||
if (sidebar === 'auto') {
|
||||
// auto, render headers of current page
|
||||
return resolveAutoSidebar(headers, sidebarDepth)
|
||||
} else if (Array.isArray(sidebar)) {
|
||||
// in-page array config
|
||||
return resolveArraySidebar(sidebar, sidebarDepth)
|
||||
} else if (sidebar === false) {
|
||||
return []
|
||||
} else {
|
||||
// no explicit page sidebar config
|
||||
// check global theme config
|
||||
const { sidebar: themeSidebar } = siteData.value.themeConfig
|
||||
if (themeSidebar === 'auto') {
|
||||
return resolveAutoSidebar(headers, sidebarDepth)
|
||||
} else if (Array.isArray(themeSidebar)) {
|
||||
return resolveArraySidebar(themeSidebar, sidebarDepth)
|
||||
} else if (themeSidebar === false) {
|
||||
return []
|
||||
} else if (typeof themeSidebar === 'object') {
|
||||
return resolveMultiSidebar(themeSidebar, route.path, sidebarDepth)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
items: __DEV__ ? computed(resolveSidebar) : resolveSidebar()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type ResolvedSidebar = ResolvedSidebarItem[]
|
||||
|
||||
interface ResolvedSidebarItem {
|
||||
text: string
|
||||
link?: string
|
||||
isGroup?: boolean
|
||||
children?: ResolvedSidebarItem[]
|
||||
}
|
||||
|
||||
function resolveAutoSidebar(headers: Header[], depth: number): ResolvedSidebar {
|
||||
const ret: ResolvedSidebar = []
|
||||
|
||||
let lastH2: ResolvedSidebarItem | undefined = undefined
|
||||
headers.forEach(({ level, title, slug }) => {
|
||||
if (level - 1 > depth) {
|
||||
return
|
||||
}
|
||||
|
||||
const item: ResolvedSidebarItem = {
|
||||
text: title,
|
||||
link: `#${slug}`
|
||||
}
|
||||
if (level === 2) {
|
||||
lastH2 = item
|
||||
ret.push(item)
|
||||
} else if (lastH2) {
|
||||
;(lastH2.children || (lastH2.children = [])).push(item)
|
||||
}
|
||||
})
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
function resolveArraySidebar(
|
||||
config: DefaultTheme.SideBarItem[],
|
||||
depth: number
|
||||
): ResolvedSidebar {
|
||||
return []
|
||||
}
|
||||
|
||||
function resolveMultiSidebar(
|
||||
config: DefaultTheme.MultiSideBarConfig,
|
||||
path: string,
|
||||
depth: number
|
||||
): ResolvedSidebar {
|
||||
return []
|
||||
}
|
@ -1,5 +1,33 @@
|
||||
<template>
|
||||
<ul class="sidebar">
|
||||
<li>sidebar</li>
|
||||
<div class="sidebar">
|
||||
<ul>
|
||||
<SideBarItem v-for="item of items" :item="item"></SideBarItem>
|
||||
</ul>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script src="./SideBar"></script>
|
||||
|
||||
<style>
|
||||
.sidebar ul {
|
||||
list-style-type: none;
|
||||
line-height: 2;
|
||||
padding-left: 1.5rem;
|
||||
margin: 0;
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.sidebar a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
|
||||
.sidebar a:hover {
|
||||
color: var(--accent-color);
|
||||
}
|
||||
|
||||
.sidebar ul ul {
|
||||
font-weight: 400;
|
||||
font-size: 0.9em;
|
||||
padding-left: 1rem;
|
||||
}
|
||||
</style>
|
||||
|
@ -0,0 +1,58 @@
|
||||
.custom-block .custom-block-title {
|
||||
font-weight: 600;
|
||||
margin-bottom: -0.4rem;
|
||||
}
|
||||
.custom-block.tip,
|
||||
.custom-block.warning,
|
||||
.custom-block.danger {
|
||||
padding: 0.1rem 1.5rem;
|
||||
border-left-width: 0.5rem;
|
||||
border-left-style: solid;
|
||||
margin: 1rem 0;
|
||||
}
|
||||
.custom-block.tip {
|
||||
background-color: #f3f5f7;
|
||||
border-color: #42b983;
|
||||
}
|
||||
.custom-block.warning {
|
||||
background-color: rgba(255, 229, 100, 0.3);
|
||||
border-color: #e7c000;
|
||||
color: #6b5900;
|
||||
}
|
||||
.custom-block.warning .custom-block-title {
|
||||
color: #b29400;
|
||||
}
|
||||
.custom-block.warning a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
.custom-block.danger {
|
||||
background-color: #ffe6e6;
|
||||
border-color: #c00;
|
||||
color: #4d0000;
|
||||
}
|
||||
.custom-block.danger .custom-block-title {
|
||||
color: #900;
|
||||
}
|
||||
.custom-block.danger a {
|
||||
color: var(--text-color);
|
||||
}
|
||||
.custom-block.details {
|
||||
display: block;
|
||||
position: relative;
|
||||
border-radius: 2px;
|
||||
margin: 1.6em 0;
|
||||
padding: 1.6em;
|
||||
background-color: #eee;
|
||||
}
|
||||
.custom-block.details h4 {
|
||||
margin-top: 0;
|
||||
}
|
||||
.custom-block.details figure:last-child,
|
||||
.custom-block.details p:last-child {
|
||||
margin-bottom: 0;
|
||||
padding-bottom: 0;
|
||||
}
|
||||
.custom-block.details summary {
|
||||
outline: none;
|
||||
cursor: pointer;
|
||||
}
|
Loading…
Reference in new issue