mirror of
https://github.com/ArthurDanjou/ui.git
synced 2026-01-23 16:30:45 +01:00
docs: improve multi-source handling (#682)
This commit is contained in:
21
docs/app.vue
21
docs/app.vue
@@ -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')
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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"
|
||||
}
|
||||
|
||||
@@ -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({
|
||||
|
||||
@@ -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: {
|
||||
|
||||
Reference in New Issue
Block a user