docs: improve multi-source handling (#682)

This commit is contained in:
Benjamin Canac
2023-09-15 14:37:53 +02:00
committed by GitHub
parent 81463cd21d
commit 8ec23c042d
10 changed files with 128 additions and 201 deletions

View File

@@ -10,7 +10,7 @@
<Footer />
<ClientOnly>
<LazyUDocsSearch ref="searchRef" :files="files" :navigation="navigation" />
<LazyUDocsSearch ref="searchRef" :files="files" :navigation="navigation" :groups="groups" />
</ClientOnly>
<UNotifications>
@@ -28,29 +28,32 @@
<script setup lang="ts">
import { withoutTrailingSlash } from 'ufo'
import { debounce } from 'perfect-debounce'
import type { ParsedContent } from '@nuxt/content/dist/runtime/types'
const searchRef = ref()
const route = useRoute()
const colorMode = useColorMode()
const { prefix, removePrefixFromNavigation, removePrefixFromFiles } = useContentSource()
const { branch, branches } = useContentSource()
const { data: nav } = await useAsyncData('navigation', () => fetchContentNavigation())
const { data: search } = useLazyFetch('/api/search.json', { default: () => [], server: false })
const { data: files } = useLazyFetch<ParsedContent[]>('/api/search.json', { default: () => [], server: false })
// Computed
const navigation = computed(() => {
const navigation = nav.value.find(link => link._path === prefix.value)?.children || []
const main = nav.value.filter(item => item._path !== '/dev')
const dev = nav.value.find(item => item._path === '/dev')?.children
return prefix.value === '/main' ? removePrefixFromNavigation(navigation) : navigation
return branch.value?.name === 'dev' ? dev : main
})
const files = computed(() => {
const files = search.value.filter(file => file._path.startsWith(prefix.value))
const groups = computed(() => {
if (route.path === '/') {
return []
}
return prefix.value === '/main' ? removePrefixFromFiles(files) : files
return [{ key: 'branch', label: 'Branch', commands: branches.value }]
})
const color = computed(() => colorMode.value === 'dark' ? '#18181b' : 'white')

View File

@@ -10,7 +10,7 @@
color="gray"
:ui="{ icon: { trailing: { padding: { sm: 'pe-1.5' } } } }"
:ui-menu="{ option: { container: 'gap-1.5' } }"
@update:model-value="selectBranch"
@update:model-value="select"
>
<template #label>
<UIcon v-if="branch.icon" :name="branch.icon" class="w-4 h-4 flex-shrink-0 text-gray-600 dark:text-gray-300" />
@@ -32,19 +32,5 @@
</template>
<script setup lang="ts">
const route = useRoute()
const router = useRouter()
const { branches, branch } = useContentSource()
function selectBranch (branch) {
if (branch.name === 'dev') {
if (route.path.startsWith('/dev')) {
return
}
router.push(`/dev${route.path}`)
} else {
router.push(route.path.replace('/dev', ''))
}
}
const { branches, branch, select } = useContentSource()
</script>

View File

@@ -19,7 +19,7 @@
<UDocsSearchButton icon-only />
</UTooltip>
<UColorModeButton v-if="!$colorMode.forced" />
<UColorModeButton />
<USocialButton to="https://github.com/nuxt/ui" target="_blank" icon="i-simple-icons-github" aria-label="GitHub" class="hidden lg:inline-flex" />
</template>

View File

@@ -1,57 +1,43 @@
import type { NavItem, ParsedContent } from '@nuxt/content/dist/runtime/types'
export const useContentSource = () => {
const route = useRoute()
const router = useRouter()
const config = useRuntimeConfig().public
const branches = [{
const branches = computed(() => [{
id: 'dev',
name: 'dev',
icon: 'i-heroicons-cube',
suffix: 'dev',
label: 'Edge'
label: 'Edge',
disabled: route.path.startsWith('/dev'),
click: () => select({ name: 'dev' })
}, {
id: 'main',
name: 'main',
icon: 'i-heroicons-cube',
suffix: 'latest',
label: `v${config.version}`
}]
label: `v${config.version}`,
disabled: !route.path.startsWith('/dev'),
click: () => select({ name: 'main' })
}])
const branch = computed(() => branches.find(b => b.name === (route.path.startsWith('/dev') ? 'dev' : 'main')))
const branch = computed(() => branches.value.find(b => b.name === (route.path.startsWith('/dev') ? 'dev' : 'main')))
const prefix = computed(() => `/${branch.value.name}`)
function removePrefixFromNavigation (navigation: NavItem[]): NavItem[] {
return navigation.map((link) => {
const { _path, children, ...rest } = link
return {
...rest,
_path: route.path.startsWith(prefix.value) ? _path : _path.replace(new RegExp(`^${prefix.value}`, 'g'), ''),
children: children?.length ? removePrefixFromNavigation(children) : undefined
}
})
}
function removePrefixFromFiles (files: ParsedContent[]) {
return files.map((file) => {
if (!file) {
function select (branch) {
if (branch.name === 'dev') {
if (route.path.startsWith('/dev')) {
return
}
const { _path, ...rest } = file
return {
...rest,
_path: route.path.startsWith(prefix.value) ? _path : _path.replace(new RegExp(`^${prefix.value}`, 'g'), '')
}
})
router.push(`/dev${route.path}`)
} else {
router.push(route.path.replace('/dev', ''))
}
}
return {
branches,
branch,
prefix,
removePrefixFromNavigation,
removePrefixFromFiles
select
}
}

View File

@@ -11,7 +11,7 @@
</UContainer>
<ClientOnly>
<UDocsSearch :files="files" :navigation="navigation" />
<LazyUDocsSearch :files="files" :navigation="navigation" />
</ClientOnly>
<UNotifications />
@@ -20,8 +20,7 @@
<script setup lang="ts">
import type { NuxtError } from '#app'
const { prefix, removePrefixFromNavigation, removePrefixFromFiles } = useContentSource()
import type { ParsedContent } from '@nuxt/content/dist/runtime/types'
useSeoMeta({
title: 'Page not found',
@@ -32,22 +31,18 @@ defineProps<{
error: NuxtError
}>()
const { data: navigation } = await useLazyAsyncData('navigation', () => fetchContentNavigation(), {
default: () => [],
transform: (navigation) => {
navigation = navigation.find(link => link._path === prefix.value)?.children || []
const { branch } = useContentSource()
return prefix.value === '/main' ? removePrefixFromNavigation(navigation) : navigation
}
})
const { data: nav } = await useAsyncData('navigation', () => fetchContentNavigation())
const { data: files } = useLazyFetch<ParsedContent[]>('/api/search.json', { default: () => [], server: false })
const { data: files } = await useLazyAsyncData('files', () => queryContent().where({ _type: 'markdown', navigation: { $ne: false } }).find(), {
default: () => [],
transform: (files) => {
files = files.filter(file => file._path.startsWith(prefix.value))
// Computed
return prefix.value === '/main' ? removePrefixFromFiles(files) : files
}
const navigation = computed(() => {
const main = nav.value.filter(item => item._path !== '/dev')
const dev = nav.value.find(item => item._path === '/dev')?.children
return branch.value?.name === 'dev' ? dev : main
})
// Provide

View File

@@ -32,14 +32,13 @@ export default defineNuxtConfig({
},
content: {
sources: {
// overwrite default source AKA `content` directory
content: {
dev: {
prefix: '/dev',
driver: 'fs',
base: resolve('./content')
},
main: {
prefix: '/main',
// overwrite default source AKA `content` directory
content: {
driver: 'github',
repo: 'nuxt/ui',
branch: 'main',

View File

@@ -7,10 +7,10 @@
"devDependencies": {
"@iconify-json/heroicons": "latest",
"@iconify-json/simple-icons": "latest",
"@nuxt/content": "^2.8.2",
"@nuxt/content": "npm:@nuxt/content-edge@2.8.2-28246249.76260da",
"@nuxt/devtools": "^0.8.3",
"@nuxt/eslint-config": "^0.2.0",
"@nuxthq/elements": "npm:@nuxthq/elements-edge@0.0.1-28245159.d523b38",
"@nuxthq/elements": "npm:@nuxthq/elements-edge@0.0.1-28246224.5395dca",
"@nuxthq/studio": "^0.14.1",
"@nuxtjs/fontaine": "^0.4.1",
"@nuxtjs/google-fonts": "^3.0.2",
@@ -24,6 +24,7 @@
"typescript": "^5.2.2",
"ufo": "^1.3.0",
"v-calendar": "^3.0.3",
"valibot": "^0.15.0",
"yup": "^1.2.0",
"zod": "^3.22.2"
}

View File

@@ -7,7 +7,7 @@
<UDivider v-if="surround?.length" />
<UDocsSurround :surround="removePrefixFromFiles(surround)" />
<UDocsSurround :surround="(surround as ParsedContent[])" />
</UPageBody>
<template v-if="page.body?.toc?.links?.length" #right>
@@ -25,25 +25,35 @@
</template>
<script setup lang="ts">
import { withoutTrailingSlash } from 'ufo'
import type { ParsedContent } from '@nuxt/content/dist/runtime/types'
const route = useRoute()
const { prefix, removePrefixFromFiles } = useContentSource()
const { branch } = useContentSource()
const { findPageHeadline } = useElementsHelpers()
definePageMeta({
layout: 'docs'
})
const path = computed(() => route.path.startsWith(prefix.value) ? route.path : `${prefix.value}${route.path}`)
const { data: page } = await useAsyncData(path.value, () => queryContent(path.value).findOne())
const { data: page } = await useAsyncData(route.path, () => queryContent(route.path).findOne())
if (!page.value) {
throw createError({ statusCode: 404, statusMessage: 'Page not found' })
}
const { data: surround } = await useAsyncData(`${path.value}-surround`, () => {
return queryContent(prefix.value)
.where({ _extension: 'md', navigation: { $ne: false } })
.findSurround((path.value.endsWith('/') ? path.value.slice(0, -1) : path.value))
const { data: surround } = await useAsyncData(`${route.path}-surround`, () => {
return queryContent()
.where({
_extension: 'md',
_path: {
[branch.value?.name === 'dev' ? '$eq' : '$ne']: new RegExp('^/dev')
},
navigation: {
$ne: false
}
})
.only(['title', 'description', '_path'])
.findSurround(withoutTrailingSlash(route.path))
})
useSeoMeta({

View File

@@ -2,12 +2,12 @@ import type { Config } from 'tailwindcss'
import defaultTheme from 'tailwindcss/defaultTheme'
export default <Partial<Config>>{
content: {
files: [
'./docs/content/**/*.md',
'./docs/content/**/*.yml'
]
},
// content: {
// files: [
// './docs/content/**/*.md',
// './docs/content/**/*.yml'
// ]
// },
theme: {
extend: {
fontFamily: {