docus 4.0.0-beta.1 → 4.0.0-beta.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +4 -2
- package/app/app.config.ts +0 -3
- package/app/app.vue +20 -5
- package/app/components/LanguageSelect.vue +82 -0
- package/app/components/app/AppHeader.vue +27 -2
- package/app/components/docs/DocsAsideRightBottom.vue +2 -1
- package/app/components/docs/DocsPageHeaderLinks.vue +6 -5
- package/app/composables/useDocusI18n.ts +31 -0
- package/app/error.vue +7 -7
- package/app/pages/{[...slug].vue → [[lang]]/[...slug].vue} +12 -9
- package/app/pages/{index.vue → [[lang]]/index.vue} +8 -1
- package/content.config.ts +45 -12
- package/modules/default-configs.ts +11 -0
- package/nuxt.config.ts +1 -0
- package/package.json +19 -9
package/README.md
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
[](https://docus.dev)
|
|
2
|
+
|
|
3
|
+
# Docus
|
|
2
4
|
|
|
3
5
|
> A minimal and beautiful Nuxt layer for documentation websites
|
|
4
6
|
|
|
5
7
|
[](https://www.npmjs.com/package/docus)
|
|
6
8
|
[](https://www.npmjs.com/package/docus)
|
|
7
9
|
|
|
8
|
-
This is the official Nuxt layer for [Docus](https://docus.dev), providing a complete documentation theming. It works with the [Docus CLI](https://github.com/nuxtlabs/docus) for rapid project setup.
|
|
10
|
+
This is the official Nuxt layer for [Docus](https://docus.dev), providing a complete documentation theming. It works with the [Docus CLI](https://github.com/nuxtlabs/docus/tree/main/cli) for rapid project setup.
|
|
9
11
|
|
|
10
12
|
## 🚀 Features
|
|
11
13
|
|
package/app/app.config.ts
CHANGED
package/app/app.vue
CHANGED
|
@@ -1,11 +1,25 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import type { PageCollections } from '@nuxt/content'
|
|
3
|
+
import * as locales from '@nuxt/ui-pro/locale'
|
|
4
|
+
|
|
2
5
|
const { seo } = useAppConfig()
|
|
3
6
|
const site = useSiteConfig()
|
|
4
7
|
|
|
5
|
-
const {
|
|
6
|
-
|
|
8
|
+
const { locale, isEnabled } = useDocusI18n()
|
|
9
|
+
|
|
10
|
+
const lang = computed(() => locales[locale.value as keyof typeof locales]?.code || 'en')
|
|
11
|
+
const dir = computed(() => locales[locale.value as keyof typeof locales]?.dir || 'ltr')
|
|
12
|
+
const collectionName = computed(() => isEnabled.value ? `docs_${locale.value}` : 'docs')
|
|
13
|
+
|
|
14
|
+
const { data: navigation } = await useAsyncData(`navigation_${collectionName.value}`, () => queryCollectionNavigation(collectionName.value as keyof PageCollections), {
|
|
15
|
+
transform: (data) => {
|
|
16
|
+
const rootResult = data.find(item => item.path === '/docs')?.children || data || []
|
|
17
|
+
|
|
18
|
+
return rootResult.find(item => item.path === `/${locale.value}`)?.children || rootResult
|
|
19
|
+
},
|
|
20
|
+
watch: [locale],
|
|
7
21
|
})
|
|
8
|
-
const { data: files } = useLazyAsyncData(
|
|
22
|
+
const { data: files } = useLazyAsyncData(`search_${collectionName.value}`, () => queryCollectionSearchSections(collectionName.value as keyof PageCollections), {
|
|
9
23
|
server: false,
|
|
10
24
|
})
|
|
11
25
|
|
|
@@ -17,7 +31,8 @@ useHead({
|
|
|
17
31
|
{ rel: 'icon', href: '/favicon.ico' },
|
|
18
32
|
],
|
|
19
33
|
htmlAttrs: {
|
|
20
|
-
lang
|
|
34
|
+
lang,
|
|
35
|
+
dir,
|
|
21
36
|
},
|
|
22
37
|
})
|
|
23
38
|
|
|
@@ -33,7 +48,7 @@ provide('navigation', navigation)
|
|
|
33
48
|
</script>
|
|
34
49
|
|
|
35
50
|
<template>
|
|
36
|
-
<UApp>
|
|
51
|
+
<UApp :locale="locales[locale as keyof typeof locales]">
|
|
37
52
|
<NuxtLoadingIndicator color="var(--ui-primary)" />
|
|
38
53
|
|
|
39
54
|
<AppHeader />
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const { locale, locales, switchLocalePath } = useDocusI18n()
|
|
3
|
+
|
|
4
|
+
function getEmojiFlag(locale: string): string {
|
|
5
|
+
const languageToCountry: Record<string, string> = {
|
|
6
|
+
ar: 'sa', // Arabic -> Saudi Arabia
|
|
7
|
+
bn: 'bd', // Bengali -> Bangladesh
|
|
8
|
+
ca: 'es', // Catalan -> Spain
|
|
9
|
+
ckb: 'iq', // Central Kurdish -> Iraq
|
|
10
|
+
cs: 'cz', // Czech -> Czech Republic (note: modern country code is actually 'cz')
|
|
11
|
+
da: 'dk', // Danish -> Denmark
|
|
12
|
+
el: 'gr', // Greek -> Greece
|
|
13
|
+
en: 'gb', // English -> Great Britain
|
|
14
|
+
et: 'ee', // Estonian -> Estonia
|
|
15
|
+
he: 'il', // Hebrew -> Israel
|
|
16
|
+
hi: 'in', // Hindi -> India
|
|
17
|
+
hy: 'am', // Armenian -> Armenia
|
|
18
|
+
ja: 'jp', // Japanese -> Japan
|
|
19
|
+
kk: 'kz', // Kazakh -> Kazakhstan
|
|
20
|
+
km: 'kh', // Khmer -> Cambodia
|
|
21
|
+
ko: 'kr', // Korean -> South Korea
|
|
22
|
+
ky: 'kg', // Kyrgyz -> Kyrgyzstan
|
|
23
|
+
lb: 'lu', // Luxembourgish -> Luxembourg
|
|
24
|
+
ms: 'my', // Malay -> Malaysia
|
|
25
|
+
nb: 'no', // Norwegian Bokmål -> Norway
|
|
26
|
+
sl: 'si', // Slovenian -> Slovenia
|
|
27
|
+
sv: 'se', // Swedish -> Sweden
|
|
28
|
+
uk: 'ua', // Ukrainian -> Ukraine
|
|
29
|
+
ur: 'pk', // Urdu -> Pakistan
|
|
30
|
+
vi: 'vn', // Vietnamese -> Vietnam
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
const baseLanguage = locale.split('-')[0]?.toLowerCase() || locale
|
|
34
|
+
const countryCode = languageToCountry[baseLanguage] || locale.replace(/^.*-/, '').slice(0, 2)
|
|
35
|
+
|
|
36
|
+
return countryCode.toUpperCase()
|
|
37
|
+
.split('')
|
|
38
|
+
.map(char => String.fromCodePoint(0x1F1A5 + char.charCodeAt(0)))
|
|
39
|
+
.join('')
|
|
40
|
+
}
|
|
41
|
+
</script>
|
|
42
|
+
|
|
43
|
+
<template>
|
|
44
|
+
<UPopover
|
|
45
|
+
mode="hover"
|
|
46
|
+
:content="{ align: 'end' }"
|
|
47
|
+
>
|
|
48
|
+
<UButton
|
|
49
|
+
color="neutral"
|
|
50
|
+
variant="ghost"
|
|
51
|
+
class="size-8"
|
|
52
|
+
>
|
|
53
|
+
<template #trailing>
|
|
54
|
+
<span class="text-lg">
|
|
55
|
+
{{ getEmojiFlag(locale) }}
|
|
56
|
+
</span>
|
|
57
|
+
</template>
|
|
58
|
+
</UButton>
|
|
59
|
+
|
|
60
|
+
<template #content>
|
|
61
|
+
<ul class="flex flex-col gap-2">
|
|
62
|
+
<li
|
|
63
|
+
v-for="localeItem in locales"
|
|
64
|
+
:key="localeItem.code"
|
|
65
|
+
>
|
|
66
|
+
<NuxtLink
|
|
67
|
+
class="flex justify-between py-2 px-1.5 gap-1 hover:bg-neutral-100 dark:hover:bg-neutral-800"
|
|
68
|
+
:to="switchLocalePath(localeItem.code) as string"
|
|
69
|
+
:aria-label="localeItem.name"
|
|
70
|
+
>
|
|
71
|
+
<span class="text-sm">
|
|
72
|
+
{{ localeItem.name }}
|
|
73
|
+
</span>
|
|
74
|
+
<span class="size-5 text-center">
|
|
75
|
+
{{ getEmojiFlag(localeItem.code) }}
|
|
76
|
+
</span>
|
|
77
|
+
</NuxtLink>
|
|
78
|
+
</li>
|
|
79
|
+
</ul>
|
|
80
|
+
</template>
|
|
81
|
+
</UPopover>
|
|
82
|
+
</template>
|
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useDocusI18n } from '~/composables/useDocusI18n'
|
|
3
|
+
|
|
2
4
|
const appConfig = useAppConfig()
|
|
3
5
|
const site = useSiteConfig()
|
|
4
6
|
|
|
7
|
+
const { localePath, isEnabled } = useDocusI18n()
|
|
8
|
+
|
|
5
9
|
const links = computed(() => appConfig.github?.url
|
|
6
10
|
? [
|
|
7
11
|
{
|
|
@@ -17,7 +21,7 @@ const links = computed(() => appConfig.github?.url
|
|
|
17
21
|
<template>
|
|
18
22
|
<UHeader
|
|
19
23
|
:ui="{ center: 'flex-1' }"
|
|
20
|
-
to="/"
|
|
24
|
+
:to="localePath('/')"
|
|
21
25
|
:title="appConfig.header?.title || site.name"
|
|
22
26
|
>
|
|
23
27
|
<AppHeaderCenter />
|
|
@@ -29,9 +33,30 @@ const links = computed(() => appConfig.github?.url
|
|
|
29
33
|
<template #right>
|
|
30
34
|
<AppHeaderCTA />
|
|
31
35
|
|
|
36
|
+
<template v-if="isEnabled">
|
|
37
|
+
<ClientOnly>
|
|
38
|
+
<LanguageSelect />
|
|
39
|
+
|
|
40
|
+
<template #fallback>
|
|
41
|
+
<div class="h-8 w-8 animate-pulse bg-neutral-200 dark:bg-neutral-800 rounded-md" />
|
|
42
|
+
</template>
|
|
43
|
+
</ClientOnly>
|
|
44
|
+
|
|
45
|
+
<USeparator
|
|
46
|
+
orientation="vertical"
|
|
47
|
+
class="h-8"
|
|
48
|
+
/>
|
|
49
|
+
</template>
|
|
50
|
+
|
|
32
51
|
<UContentSearchButton class="lg:hidden" />
|
|
33
52
|
|
|
34
|
-
<
|
|
53
|
+
<ClientOnly>
|
|
54
|
+
<UColorModeButton />
|
|
55
|
+
|
|
56
|
+
<template #fallback>
|
|
57
|
+
<div class="h-8 w-8 animate-pulse bg-neutral-200 dark:bg-neutral-800 rounded-md" />
|
|
58
|
+
</template>
|
|
59
|
+
</ClientOnly>
|
|
35
60
|
|
|
36
61
|
<template v-if="links?.length">
|
|
37
62
|
<UButton
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
const appConfig = useAppConfig()
|
|
3
|
+
const { t } = useDocusI18n()
|
|
3
4
|
</script>
|
|
4
5
|
|
|
5
6
|
<template>
|
|
@@ -10,7 +11,7 @@ const appConfig = useAppConfig()
|
|
|
10
11
|
<USeparator type="dashed" />
|
|
11
12
|
|
|
12
13
|
<UPageLinks
|
|
13
|
-
:title="appConfig.toc?.bottom?.title || '
|
|
14
|
+
:title="appConfig.toc?.bottom?.title || t('docs.links')"
|
|
14
15
|
:links="appConfig.toc?.bottom?.links"
|
|
15
16
|
/>
|
|
16
17
|
</div>
|
|
@@ -4,6 +4,7 @@ import { useClipboard } from '@vueuse/core'
|
|
|
4
4
|
const route = useRoute()
|
|
5
5
|
const toast = useToast()
|
|
6
6
|
const { copy, copied } = useClipboard()
|
|
7
|
+
const { t } = useDocusI18n()
|
|
7
8
|
|
|
8
9
|
const markdownLink = computed(() => `${window?.location?.origin}/raw${route.path}.md`)
|
|
9
10
|
|
|
@@ -15,26 +16,26 @@ const items = [
|
|
|
15
16
|
copy(markdownLink.value)
|
|
16
17
|
|
|
17
18
|
toast.add({
|
|
18
|
-
title: '
|
|
19
|
+
title: t('docs.copy.link'),
|
|
19
20
|
icon: 'i-lucide-check-circle',
|
|
20
21
|
color: 'success',
|
|
21
22
|
})
|
|
22
23
|
},
|
|
23
24
|
},
|
|
24
25
|
{
|
|
25
|
-
label: '
|
|
26
|
+
label: t('docs.copy.view'),
|
|
26
27
|
icon: 'i-simple-icons:markdown',
|
|
27
28
|
target: '_blank',
|
|
28
29
|
to: markdownLink.value,
|
|
29
30
|
},
|
|
30
31
|
{
|
|
31
|
-
label: '
|
|
32
|
+
label: t('docs.copy.gpt'),
|
|
32
33
|
icon: 'i-simple-icons:openai',
|
|
33
34
|
target: '_blank',
|
|
34
35
|
to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${markdownLink.value} so I can ask questions about it.`)}`,
|
|
35
36
|
},
|
|
36
37
|
{
|
|
37
|
-
label: '
|
|
38
|
+
label: t('docs.copy.claude'),
|
|
38
39
|
icon: 'i-simple-icons:anthropic',
|
|
39
40
|
target: '_blank',
|
|
40
41
|
to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${markdownLink.value} so I can ask questions about it.`)}`,
|
|
@@ -45,7 +46,7 @@ const items = [
|
|
|
45
46
|
<template>
|
|
46
47
|
<UButtonGroup size="sm">
|
|
47
48
|
<UButton
|
|
48
|
-
label="
|
|
49
|
+
:label="t('docs.copy.page')"
|
|
49
50
|
:icon="copied ? 'i-lucide-copy-check' : 'i-lucide-copy'"
|
|
50
51
|
color="neutral"
|
|
51
52
|
variant="outline"
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import en from '../../i18n/locales/en.json'
|
|
2
|
+
|
|
3
|
+
export const useDocusI18n = () => {
|
|
4
|
+
const config = useRuntimeConfig().public
|
|
5
|
+
const isEnabled = ref(!!config.i18n)
|
|
6
|
+
|
|
7
|
+
if (!isEnabled.value) {
|
|
8
|
+
return {
|
|
9
|
+
isEnabled,
|
|
10
|
+
locale: ref('en'),
|
|
11
|
+
locales: ref([]),
|
|
12
|
+
localePath: (path: string) => path,
|
|
13
|
+
switchLocalePath: () => {},
|
|
14
|
+
t: (key: string): string => {
|
|
15
|
+
const path = key.split('.')
|
|
16
|
+
return path.reduce((acc: unknown, curr) => (acc as Record<string, unknown>)?.[curr], en) as string
|
|
17
|
+
},
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const { locale, locales, t } = useI18n()
|
|
22
|
+
|
|
23
|
+
return {
|
|
24
|
+
isEnabled,
|
|
25
|
+
locale,
|
|
26
|
+
locales,
|
|
27
|
+
t,
|
|
28
|
+
localePath: useLocalePath(),
|
|
29
|
+
switchLocalePath: useSwitchLocalePath(),
|
|
30
|
+
}
|
|
31
|
+
}
|
package/app/error.vue
CHANGED
|
@@ -16,12 +16,12 @@ useSeoMeta({
|
|
|
16
16
|
description: 'We are sorry but this page could not be found.',
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
|
|
20
|
-
const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs'), {
|
|
21
|
-
|
|
22
|
-
})
|
|
19
|
+
// const { data: navigation } = await useAsyncData('navigation', () => queryCollectionNavigation('docs'))
|
|
20
|
+
// const { data: files } = useLazyAsyncData('search', () => queryCollectionSearchSections('docs'), {
|
|
21
|
+
// server: false,
|
|
22
|
+
// })
|
|
23
23
|
|
|
24
|
-
provide('navigation', navigation)
|
|
24
|
+
// provide('navigation', navigation)
|
|
25
25
|
</script>
|
|
26
26
|
|
|
27
27
|
<template>
|
|
@@ -33,10 +33,10 @@ provide('navigation', navigation)
|
|
|
33
33
|
<AppFooter />
|
|
34
34
|
|
|
35
35
|
<ClientOnly>
|
|
36
|
-
<LazyUContentSearch
|
|
36
|
+
<!-- <LazyUContentSearch
|
|
37
37
|
:files="files"
|
|
38
38
|
:navigation="navigation"
|
|
39
|
-
/>
|
|
39
|
+
/> -->
|
|
40
40
|
</ClientOnly>
|
|
41
41
|
</UApp>
|
|
42
42
|
</template>
|
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
import { kebabCase } from 'scule'
|
|
3
|
-
import type { ContentNavigationItem } from '@nuxt/content'
|
|
3
|
+
import type { ContentNavigationItem, Collections, DocsCollectionItem } from '@nuxt/content'
|
|
4
4
|
import { findPageHeadline } from '@nuxt/content/utils'
|
|
5
|
-
import { addPrerenderPath } from '
|
|
5
|
+
import { addPrerenderPath } from '~/utils/prerender'
|
|
6
6
|
|
|
7
7
|
definePageMeta({
|
|
8
8
|
layout: 'docs',
|
|
9
9
|
})
|
|
10
10
|
|
|
11
11
|
const route = useRoute()
|
|
12
|
+
const { locale, isEnabled, t } = useDocusI18n()
|
|
12
13
|
const appConfig = useAppConfig()
|
|
13
14
|
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
|
14
15
|
|
|
16
|
+
const collectionName = computed(() => isEnabled.value ? `docs_${locale.value}` : 'docs')
|
|
17
|
+
|
|
15
18
|
const [{ data: page }, { data: surround }] = await Promise.all([
|
|
16
|
-
useAsyncData(kebabCase(route.path), () => queryCollection(
|
|
19
|
+
useAsyncData(kebabCase(route.path), () => queryCollection(collectionName.value as keyof Collections).path(route.path).first()),
|
|
17
20
|
useAsyncData(`${kebabCase(route.path)}-surround`, () => {
|
|
18
|
-
return queryCollectionItemSurroundings(
|
|
21
|
+
return queryCollectionItemSurroundings(collectionName.value as keyof Collections, route.path, {
|
|
19
22
|
fields: ['description'],
|
|
20
23
|
})
|
|
21
24
|
}),
|
|
@@ -71,7 +74,7 @@ const editLink = computed(() => {
|
|
|
71
74
|
>
|
|
72
75
|
<template #links>
|
|
73
76
|
<UButton
|
|
74
|
-
v-for="(link, index) in page.links"
|
|
77
|
+
v-for="(link, index) in (page as DocsCollectionItem).links"
|
|
75
78
|
:key="index"
|
|
76
79
|
size="sm"
|
|
77
80
|
v-bind="link"
|
|
@@ -100,9 +103,9 @@ const editLink = computed(() => {
|
|
|
100
103
|
icon="i-lucide-pen"
|
|
101
104
|
:ui="{ leadingIcon: 'size-4' }"
|
|
102
105
|
>
|
|
103
|
-
|
|
106
|
+
{{ t('docs.edit') }}
|
|
104
107
|
</UButton>
|
|
105
|
-
or
|
|
108
|
+
<span>{{ t('common.or') }}</span>
|
|
106
109
|
<UButton
|
|
107
110
|
variant="link"
|
|
108
111
|
color="neutral"
|
|
@@ -111,7 +114,7 @@ const editLink = computed(() => {
|
|
|
111
114
|
icon="i-lucide-alert-circle"
|
|
112
115
|
:ui="{ leadingIcon: 'size-4' }"
|
|
113
116
|
>
|
|
114
|
-
|
|
117
|
+
{{ t('docs.report') }}
|
|
115
118
|
</UButton>
|
|
116
119
|
</div>
|
|
117
120
|
</USeparator>
|
|
@@ -124,7 +127,7 @@ const editLink = computed(() => {
|
|
|
124
127
|
>
|
|
125
128
|
<UContentToc
|
|
126
129
|
highlight
|
|
127
|
-
:title="appConfig.toc?.title || '
|
|
130
|
+
:title="appConfig.toc?.title || t('docs.toc')"
|
|
128
131
|
:links="page.body?.toc?.links"
|
|
129
132
|
>
|
|
130
133
|
<template #bottom>
|
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
-
|
|
2
|
+
import type { Collections } from '@nuxt/content'
|
|
3
|
+
|
|
4
|
+
const route = useRoute()
|
|
5
|
+
const { locale, isEnabled } = useDocusI18n()
|
|
6
|
+
|
|
7
|
+
const collectionName = computed(() => isEnabled.value ? `landing_${locale.value}` : 'landing')
|
|
8
|
+
|
|
9
|
+
const { data: page } = await useAsyncData(collectionName.value, () => queryCollection(collectionName.value as keyof Collections).path(route.path).first())
|
|
3
10
|
if (!page.value) {
|
|
4
11
|
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
|
5
12
|
}
|
package/content.config.ts
CHANGED
|
@@ -1,12 +1,50 @@
|
|
|
1
|
+
import type { DefinedCollection } from '@nuxt/content'
|
|
1
2
|
import { defineContentConfig, defineCollection, z } from '@nuxt/content'
|
|
2
3
|
import { useNuxt } from '@nuxt/kit'
|
|
3
4
|
import { joinURL } from 'ufo'
|
|
4
5
|
|
|
5
6
|
const { options } = useNuxt()
|
|
6
7
|
const cwd = joinURL(options.rootDir, 'content')
|
|
8
|
+
const locales = options.i18n?.locales
|
|
7
9
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
+
const createDocsSchema = () => z.object({
|
|
11
|
+
links: z.array(z.object({
|
|
12
|
+
label: z.string(),
|
|
13
|
+
icon: z.string(),
|
|
14
|
+
to: z.string(),
|
|
15
|
+
target: z.string().optional(),
|
|
16
|
+
})).optional(),
|
|
17
|
+
})
|
|
18
|
+
|
|
19
|
+
let collections: Record<string, DefinedCollection>
|
|
20
|
+
|
|
21
|
+
if (locales && Array.isArray(locales)) {
|
|
22
|
+
collections = {}
|
|
23
|
+
for (const locale of locales) {
|
|
24
|
+
const code = typeof locale === 'string' ? locale : locale.code
|
|
25
|
+
|
|
26
|
+
collections[`landing_${code}`] = defineCollection({
|
|
27
|
+
type: 'page',
|
|
28
|
+
source: {
|
|
29
|
+
cwd,
|
|
30
|
+
include: `${code}/index.md`,
|
|
31
|
+
},
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
collections[`docs_${code}`] = defineCollection({
|
|
35
|
+
type: 'page',
|
|
36
|
+
source: {
|
|
37
|
+
cwd,
|
|
38
|
+
include: `${code}/**/*.md`,
|
|
39
|
+
prefix: `/${code}`,
|
|
40
|
+
exclude: [`${code}/index.md`],
|
|
41
|
+
},
|
|
42
|
+
schema: createDocsSchema(),
|
|
43
|
+
})
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
else {
|
|
47
|
+
collections = {
|
|
10
48
|
landing: defineCollection({
|
|
11
49
|
type: 'page',
|
|
12
50
|
source: {
|
|
@@ -21,14 +59,9 @@ export default defineContentConfig({
|
|
|
21
59
|
include: '**',
|
|
22
60
|
exclude: ['index.md'],
|
|
23
61
|
},
|
|
24
|
-
schema:
|
|
25
|
-
links: z.array(z.object({
|
|
26
|
-
label: z.string(),
|
|
27
|
-
icon: z.string(),
|
|
28
|
-
to: z.string(),
|
|
29
|
-
target: z.string().optional(),
|
|
30
|
-
})).optional(),
|
|
31
|
-
}),
|
|
62
|
+
schema: createDocsSchema(),
|
|
32
63
|
}),
|
|
33
|
-
}
|
|
34
|
-
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export default defineContentConfig({ collections })
|
|
@@ -50,5 +50,16 @@ export default defineNuxtModule({
|
|
|
50
50
|
nuxt.options.appConfig.toc = defu(nuxt.options.appConfig.toc, {
|
|
51
51
|
title: 'On this page',
|
|
52
52
|
})
|
|
53
|
+
|
|
54
|
+
/*
|
|
55
|
+
** I18N
|
|
56
|
+
*/
|
|
57
|
+
if (nuxt.options.i18n && nuxt.options.i18n.locales) {
|
|
58
|
+
// Override strategy to prefix
|
|
59
|
+
nuxt.options.i18n = {
|
|
60
|
+
...nuxt.options.i18n,
|
|
61
|
+
strategy: 'prefix',
|
|
62
|
+
}
|
|
63
|
+
}
|
|
53
64
|
},
|
|
54
65
|
})
|
package/nuxt.config.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "docus",
|
|
3
3
|
"description": "Nuxt layer for Docus documentation theme",
|
|
4
|
-
"version": "4.0.0-beta.
|
|
4
|
+
"version": "4.0.0-beta.10",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./nuxt.config.ts",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/nuxtlabs/docus.git"
|
|
10
|
+
},
|
|
7
11
|
"private": false,
|
|
12
|
+
"license": "MIT",
|
|
8
13
|
"files": [
|
|
9
14
|
"app",
|
|
10
15
|
"content.config.ts",
|
|
@@ -16,26 +21,31 @@
|
|
|
16
21
|
"README.md"
|
|
17
22
|
],
|
|
18
23
|
"dependencies": {
|
|
19
|
-
"@iconify-json/lucide": "^1.2.
|
|
20
|
-
"@iconify-json/simple-icons": "^1.2.
|
|
24
|
+
"@iconify-json/lucide": "^1.2.58",
|
|
25
|
+
"@iconify-json/simple-icons": "^1.2.44",
|
|
21
26
|
"@iconify-json/vscode-icons": "^1.2.23",
|
|
22
27
|
"@nuxt/content": "^3.6.3",
|
|
23
28
|
"@nuxt/image": "^1.10.0",
|
|
24
|
-
"@nuxt/kit": "^4.0.
|
|
25
|
-
"@nuxt/ui-pro": "^3.
|
|
26
|
-
"@nuxtjs/
|
|
29
|
+
"@nuxt/kit": "^4.0.1",
|
|
30
|
+
"@nuxt/ui-pro": "^3.3.0",
|
|
31
|
+
"@nuxtjs/i18n": "^10.0.3",
|
|
32
|
+
"@nuxtjs/mdc": "^0.17.2",
|
|
27
33
|
"@nuxtjs/robots": "^5.4.0",
|
|
28
34
|
"@vueuse/core": "^13.5.0",
|
|
29
35
|
"defu": "^6.1.4",
|
|
30
|
-
"
|
|
36
|
+
"git-url-parse": "^16.1.0",
|
|
37
|
+
"minimark": "^0.2.0",
|
|
38
|
+
"motion-v": "^1.6.1",
|
|
31
39
|
"nuxt-llms": "^0.1.3",
|
|
32
40
|
"nuxt-og-image": "^5.1.9",
|
|
41
|
+
"pkg-types": "^2.2.0",
|
|
33
42
|
"scule": "^1.3.0",
|
|
34
43
|
"tailwindcss": "^4.1.11",
|
|
35
|
-
"ufo": "^1.6.1"
|
|
44
|
+
"ufo": "^1.6.1",
|
|
45
|
+
"unist-util-visit": "^5.0.0"
|
|
36
46
|
},
|
|
37
47
|
"peerDependencies": {
|
|
38
48
|
"better-sqlite3": "12.x",
|
|
39
49
|
"nuxt": "4.x"
|
|
40
50
|
}
|
|
41
|
-
}
|
|
51
|
+
}
|