Skip to content

Commit

Permalink
feat: add prev/next links (#56)
Browse files Browse the repository at this point in the history
* feat: set Prev/Next to page data
* feat: set links at the bottom of page
* feat: hide next/prev links when themeConfig expressly set false
  • Loading branch information
Spice-Z committed Sep 3, 2020
1 parent 5419abd commit f52b1d5
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 1 deletion.
22 changes: 22 additions & 0 deletions src/client/theme-default/components/NextAndPrevLinks.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
import { defineComponent, computed } from 'vue'
import { usePageData } from 'vitepress'

export default defineComponent({
setup() {
const pageData = usePageData()
const next = computed(() => {
return pageData.value.next
})
const prev = computed(() => {
return pageData.value.prev
})
const hasLinks = computed(() => {
return !!next || !!prev
})
return {
next,
prev,
hasLinks
}
}
})
25 changes: 25 additions & 0 deletions src/client/theme-default/components/NextAndPrevLinks.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<template>
<div v-if="hasLinks" class="links-wrapper">
<div class="prev-link">
<div v-if="prev">
← <a :href="prev.link">{{prev.text}}</a>
</div>
</div>
<div class="next-link">
<div v-if="next">
<a :href="next.link">{{next.text}}</a> →
</div>
</div>
</div>
</template>

<script src="./NextAndPrevLinks"></script>

<style>
.links-wrapper {
padding-top: 1rem;
padding-bottom: 1rem;
display: flex;
justify-content: space-between;
}
</style>
8 changes: 8 additions & 0 deletions src/client/theme-default/components/Page.vue
Original file line number Diff line number Diff line change
@@ -1,9 +1,17 @@
<template>
<div class="content">
<Content />
<NextAndPrevLinks />
</div>
</template>

<script>
import NextAndPrevLinks from './NextAndPrevLinks.vue'
export default {
components:{ NextAndPrevLinks }
}
</script>

<style>
.content {
max-width: 46rem;
Expand Down
41 changes: 40 additions & 1 deletion src/node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -104,13 +104,17 @@ function createVitePressPlugin({
ctx.body = vueSrc
debug(ctx.url, ctx.status)

const pageDataWithLinks = {
...pageData,
...getNextAndPrev(siteData.themeConfig, ctx.path)
}
await next()

// make sure this is the main <script> block
if (!ctx.query.type) {
// inject pageData to generated script
ctx.body += `\nexport const __pageData = ${JSON.stringify(
JSON.stringify(pageData)
JSON.stringify(pageDataWithLinks)
)}`
}
return
Expand All @@ -127,6 +131,41 @@ function createVitePressPlugin({
}
}

function getNextAndPrev(themeConfig: any, pagePath: string) {
if (!themeConfig.sidebar) {
return
}
const sidebar = themeConfig.sidebar
let candidates: { text: string; link: string }[] = []
Object.keys(sidebar).forEach((k) => {
if (!pagePath.startsWith(k)) {
return
}
sidebar[k].forEach((sidebarItem: { [key: string]: any }) => {
if (!sidebarItem.children) {
return
}
sidebarItem.children.forEach((candidate: any) => {
candidates.push(candidate)
})
})
})

const path = pagePath.replace(/\.(md|html)$/, '')
const currentLinkIndex = candidates.findIndex((v) => v.link === path)
const hideNextLink = themeConfig.nextLinks === false
const hidePrevLink = themeConfig.prevLinks === false

return {
...(currentLinkIndex !== -1 && !hideNextLink
? { next: candidates[currentLinkIndex + 1] }
: {}),
...(currentLinkIndex !== -1 && !hidePrevLink
? { prev: candidates[currentLinkIndex - 1] }
: {})
}
}

export async function createServer(options: ServerConfig = {}) {
const config = await resolveConfig(options.root)

Expand Down
2 changes: 2 additions & 0 deletions types/shared.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ export interface PageData {
frontmatter: Record<string, any>
headers: Header[]
lastUpdated: number
next?: { text: string; link: string }
prev?: { text: string; link: string }
}

export interface Header {
Expand Down

0 comments on commit f52b1d5

Please sign in to comment.