Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 5 additions & 19 deletions app/components/docs/DocsAsideMobileBar.vue
Original file line number Diff line number Diff line change
Expand Up @@ -12,19 +12,7 @@ const title = computed(() => mainNavigation.value.find((item) => item.active)?.l

const menuDrawerOpen = ref(false)
const tocDrawerOpen = ref(false)
const navigationRef = ref<HTMLElement | null>(null)
let observer: IntersectionObserver | undefined
const layout = inject('layout')

watch(menuDrawerOpen, (open) => {
nextTick(() => {
if (open) {
observer = observeNavigation(navigationRef)
} else {
observer?.disconnect()
}
})
})
</script>

<template>
Expand Down Expand Up @@ -54,13 +42,11 @@ watch(menuDrawerOpen, (open) => {
/>

<template #body>
<div ref="navigationRef">
<UContentNavigation
:navigation="sidebarNavigation"
variant="link"
:collapsible="false"
/>
</div>
<UContentNavigation
:navigation="sidebarNavigation"
variant="link"
:collapsible="false"
/>
</template>
</UDrawer>

Expand Down
27 changes: 5 additions & 22 deletions app/components/layouts/LayoutsDocs.vue
Original file line number Diff line number Diff line change
@@ -1,34 +1,17 @@
<script setup lang="ts">
const sidebar = useFilteredNavigation()
const navigationRef = ref<HTMLElement | null>(null)
let observer: IntersectionObserver | undefined

onMounted(() => {
// make sure Nuxt finished hydration before observing the navigation
onNuxtReady(() => {
observer = observeNavigation(navigationRef)
watch(sidebar, () => {
nextTick(() => {
observer = observeNavigation(navigationRef, observer)
})
})
})
})
onBeforeUnmount(() => observer?.disconnect())
</script>

<template>
<UContainer>
<UPage>
<template #left>
<UPageAside>
<div ref="navigationRef">
<UContentNavigation
variant="link"
:collapsible="false"
:navigation="sidebar"
/>
</div>
<UContentNavigation
variant="link"
:collapsible="false"
:navigation="sidebar"
/>
</UPageAside>
</template>

Expand Down
105 changes: 104 additions & 1 deletion app/pages/[...slug].vue
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,116 @@
import { joinURL } from 'ufo'
import type { NavigationItem } from 'comark-content'
import { Mermaid } from '@comark/nuxt/plugins/mermaid'
import {
ProseA,
ProseAccordion,
ProseAccordionItem,
ProseBadge,
ProseBlockquote,
ProseCallout,
ProseCard,
ProseCardGroup,
ProseCaution,
ProseCode,
ProseCodeCollapse,
ProseCodeGroup,
ProseCodeIcon,
ProseCodePreview,
ProseCodeTree,
ProseCollapsible,
ProseEm,
ProseField,
ProseFieldGroup,
ProseH1,
ProseH2,
ProseH3,
ProseH4,
ProseHr,
ProseIcon,
ProseImg,
ProseKbd,
ProseLi,
ProseNote,
ProseOl,
ProseP,
ProsePre,
ProsePrompt,
ProseScript,
ProseSteps,
ProseStrong,
ProseTable,
ProseTabs,
ProseTabsItem,
ProseTbody,
ProseTd,
ProseTh,
ProseThead,
ProseTip,
ProseTr,
ProseUl,
ProseWarning,
} from '#components'
import CodeExplorer from '../components/CodeExplorer.vue'
import Browser from '../components/Browser.vue'

definePageMeta({
path: '/:slug(.+)',
})

// Resolve prose eagerly with the docs route instead of the global async components.
const components = {
ProseA,
ProseAccordion,
ProseAccordionItem,
ProseBadge,
ProseBlockquote,
ProseCallout,
ProseCard,
ProseCardGroup,
ProseCaution,
ProseCode,
ProseCodeCollapse,
ProseCodeGroup,
ProseCodeIcon,
ProseCodePreview,
ProseCodeTree,
ProseCollapsible,
ProseEm,
ProseField,
ProseFieldGroup,
ProseH1,
ProseH2,
ProseH3,
ProseH4,
ProseHr,
ProseIcon,
ProseImg,
ProseKbd,
ProseLi,
ProseNote,
ProseOl,
ProseP,
ProsePre,
ProsePrompt,
ProseScript,
ProseSteps,
ProseStrong,
ProseTable,
ProseTabs,
ProseTabsItem,
ProseTbody,
ProseTd,
ProseTh,
ProseThead,
ProseTip,
ProseTr,
ProseUl,
ProseWarning,
Mermaid,
CodeExplorer,
Browser,
}

const { toc, seo } = useAppConfig()
const navigation = inject<Ref<NavigationItem[]>>('navigation')
const content = useDocsContent()
Expand Down Expand Up @@ -36,8 +139,8 @@

const surroundLinks = computed(() => findSurroundLinks(navigation?.value, selfPath.value))

const fm = computed<Record<string, any>>(() => page.value?.data ?? {})

Check warning on line 142 in app/pages/[...slug].vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type
const tocLinks = computed<any[]>(() => (page.value?.meta as any)?.toc?.links ?? [])

Check warning on line 143 in app/pages/[...slug].vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type

Check warning on line 143 in app/pages/[...slug].vue

View workflow job for this annotation

GitHub Actions / ci

Unexpected any. Specify a different type

const title = computed(() => fm.value.seo?.title || fm.value.title)
const description = computed(() => fm.value.seo?.description || fm.value.description)
Expand Down Expand Up @@ -122,7 +225,7 @@
<MarkdownDocument
v-if="tree"
:value="tree"
:components="{ Mermaid, CodeExplorer, Browser }"
:components="components"
/>

<UContentSurround
Expand Down
34 changes: 0 additions & 34 deletions app/utils/navigation.ts
Original file line number Diff line number Diff line change
@@ -1,39 +1,5 @@
import type { NavigationItem } from 'comark-content'

const prefetchedPaths = new Set<string>()
let nuxtApp: ReturnType<typeof useNuxtApp>

function prefetchPath(path?: string) {
if (!path || prefetchedPaths.has(path)) {
return
}
nuxtApp = nuxtApp ?? useNuxtApp()
prefetchedPaths.add(path)
nuxtApp.hooks.callHook('link:prefetch', path)
}

export function observeNavigation(navigationRef: Ref<HTMLElement | null>, observer?: IntersectionObserver) {
if (!navigationRef.value || !window.IntersectionObserver) {
return
}
if (observer) {
observer.disconnect()
}

const prefetchObserver = new IntersectionObserver((entries) => {
for (const entry of entries) {
if (!entry.isIntersecting) {
continue
}

prefetchPath((entry.target as HTMLAnchorElement).href.replace(window.location.origin, ''))
prefetchObserver?.unobserve(entry.target)
}
})
navigationRef.value.querySelectorAll<HTMLElement>('a').forEach((element) => prefetchObserver?.observe(element))
return prefetchObserver
}

export function findPageHeadline(
navigation: NavigationItem[] | undefined | null,
path: string | undefined
Expand Down
6 changes: 6 additions & 0 deletions modules/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,12 @@ export default defineNuxtModule<ComarkDocsOptions>({
'/api/content/pr/*/search-sections': { isr },
'/api/content/search-sections': { isr },
'/api/code-explorer/**': { isr },
'/_payload.json': {
headers: { 'cache-control': `public, max-age=${isr}, s-maxage=${isr}, stale-while-revalidate=60` },
},
'/**/_payload.json': {
headers: { 'cache-control': `public, max-age=${isr}, s-maxage=${isr}, stale-while-revalidate=60` },
},
}

if (existsSync(contentPath)) {
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
"@iconify-json/vscode-icons": "^1.2.74",
"@iconify/vue": "^5.0.1",
"@nuxt/kit": "^4.5.2",
"@nuxt/ui": "^4.11.0",
"@nuxt/ui": "https://pkg.pr.new/@nuxt/ui@fbb9e22",
"@nuxtjs/mcp-toolkit": "^0.18.1",
"@nuxtjs/robots": "^6.2.0",
"@nuxtjs/sitemap": "^8.5.0",
Expand Down
Loading
Loading