From 4e4770169d2e85df10283fc5f8e11f998b4c047d Mon Sep 17 00:00:00 2001 From: Eduardo San Martin Morote Date: Wed, 16 Sep 2020 11:55:17 +0200 Subject: [PATCH] refactor(server): add types and fix out of bounds next/previous --- src/client/app/composables/siteData.ts | 4 +- .../components/NextAndPrevLinks.ts | 5 ++- src/node/server.ts | 42 +++++++++++++------ 3 files changed, 35 insertions(+), 16 deletions(-) diff --git a/src/client/app/composables/siteData.ts b/src/client/app/composables/siteData.ts index 09b3ead3..f27f6c83 100644 --- a/src/client/app/composables/siteData.ts +++ b/src/client/app/composables/siteData.ts @@ -6,8 +6,8 @@ const parse = (data: string) => readonly(JSON.parse(data)) as SiteData export const siteDataRef: Ref = ref(parse(serialized)) -export function useSiteData() { - return siteDataRef +export function useSiteData() { + return siteDataRef as Ref> } // hmr diff --git a/src/client/theme-default/components/NextAndPrevLinks.ts b/src/client/theme-default/components/NextAndPrevLinks.ts index 0c0f0c85..387ef08b 100644 --- a/src/client/theme-default/components/NextAndPrevLinks.ts +++ b/src/client/theme-default/components/NextAndPrevLinks.ts @@ -1,12 +1,15 @@ import { defineComponent, computed } from 'vue' import { usePageData, useSiteData } from 'vitepress' +import { DefaultTheme } from '../config' export default defineComponent({ setup() { const pageData = usePageData() + // TODO: could this be useSiteData or is the siteData + // resolved and has a different structure? const siteData = useSiteData() const resolveLink = (targetLink: string) => { - let target: any = undefined + let target: DefaultTheme.SideBarLink | undefined Object.keys(siteData.value.themeConfig.sidebar).some((k) => { return siteData.value.themeConfig.sidebar[k].some( (v: { children: any }) => { diff --git a/src/node/server.ts b/src/node/server.ts index 644d041a..9ca08a99 100644 --- a/src/node/server.ts +++ b/src/node/server.ts @@ -106,6 +106,7 @@ function createVitePressPlugin({ const pageDataWithLinks = { ...pageData, + // TODO: this doesn't work with locales ...getNextAndPrev(siteData.themeConfig, ctx.path) } await next() @@ -131,21 +132,31 @@ function createVitePressPlugin({ } } +// TODO: share types from SideBarLink, SideBarGroup, etc. We are also assuming +// all themes follow this structure, in which case, we should expose the type +// instead of having any for themeConfig or not nest `sidebar` inside +// `themeConfig`, specially given it must be specified inside `locales` if there +// are any +interface SideBarLink { + text: string + link: string +} + function getNextAndPrev(themeConfig: any, pagePath: string) { if (!themeConfig.sidebar) { return } const sidebar = themeConfig.sidebar - let candidates: { text: string; link: string }[] = [] + let candidates: SideBarLink[] = [] Object.keys(sidebar).forEach((k) => { if (!pagePath.startsWith(k)) { return } - sidebar[k].forEach((sidebarItem: { [key: string]: any }) => { + sidebar[k].forEach((sidebarItem: { children?: SideBarLink[] }) => { if (!sidebarItem.children) { return } - sidebarItem.children.forEach((candidate: any) => { + sidebarItem.children.forEach((candidate) => { candidates.push(candidate) }) }) @@ -153,17 +164,22 @@ function getNextAndPrev(themeConfig: any, pagePath: string) { 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] } - : {}) + + const nextAndPrev: { prev?: SideBarLink; next?: SideBarLink } = {} + + if ( + themeConfig.nextLinks !== false && + currentLinkIndex > -1 && + currentLinkIndex < candidates.length - 1 + ) { + nextAndPrev.next = candidates[currentLinkIndex + 1] } + + if (themeConfig.prevLinks !== false && currentLinkIndex > 0) { + nextAndPrev.next = candidates[currentLinkIndex - 1] + } + + return nextAndPrev } export async function createServer(options: ServerConfig = {}) {