docus 5.8.1 → 5.10.0
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 +1 -1
- package/app/app.config.ts +13 -0
- package/app/app.vue +5 -1
- package/app/components/OgImage/Docs.takumi.vue +43 -0
- package/app/components/OgImage/Landing.takumi.vue +67 -0
- package/app/components/app/AppFooterRight.vue +4 -1
- package/app/components/app/AppHeader.vue +6 -7
- package/app/components/app/AppHeaderBody.vue +6 -2
- package/app/components/app/AppHeaderBottom.vue +6 -2
- package/app/components/app/AppHeaderLeft.vue +16 -0
- package/app/components/docs/DocsAsideLeftBody.vue +6 -1
- package/app/components/docs/DocsAsideMobileBar.vue +11 -1
- package/app/components/docs/DocsAsideRight.vue +6 -1
- package/app/composables/useDocusColorMode.ts +7 -0
- package/app/composables/useUIConfig.ts +30 -0
- package/app/error.vue +3 -0
- package/app/middleware/colorMode.global.ts +8 -0
- package/app/pages/[[lang]]/[...slug].vue +16 -12
- package/app/templates/landing.vue +3 -3
- package/app/utils/ogImage.ts +23 -0
- package/i18n/locales/ar.json +27 -0
- package/i18n/locales/be.json +27 -0
- package/i18n/locales/bg.json +27 -0
- package/i18n/locales/bn.json +27 -0
- package/i18n/locales/ca.json +27 -0
- package/i18n/locales/ckb.json +32 -1
- package/i18n/locales/cs.json +27 -0
- package/i18n/locales/da.json +27 -0
- package/i18n/locales/de.json +27 -0
- package/i18n/locales/el.json +27 -0
- package/i18n/locales/es.json +27 -0
- package/i18n/locales/et.json +27 -0
- package/i18n/locales/fi.json +27 -0
- package/i18n/locales/he.json +27 -0
- package/i18n/locales/hi.json +27 -0
- package/i18n/locales/hy.json +27 -0
- package/i18n/locales/id.json +27 -0
- package/i18n/locales/it.json +27 -0
- package/i18n/locales/ja.json +27 -0
- package/i18n/locales/kk.json +27 -0
- package/i18n/locales/km.json +27 -0
- package/i18n/locales/ko.json +27 -0
- package/i18n/locales/ky.json +27 -0
- package/i18n/locales/lb.json +27 -0
- package/i18n/locales/ms.json +27 -0
- package/i18n/locales/nb.json +27 -0
- package/i18n/locales/nl.json +27 -0
- package/i18n/locales/pl.json +27 -0
- package/i18n/locales/pt-BR.json +27 -0
- package/i18n/locales/ro.json +27 -0
- package/i18n/locales/ru.json +27 -0
- package/i18n/locales/si.json +27 -0
- package/i18n/locales/sl.json +27 -0
- package/i18n/locales/sv.json +27 -0
- package/i18n/locales/tr.json +27 -0
- package/i18n/locales/uk.json +27 -0
- package/i18n/locales/ur.json +27 -0
- package/i18n/locales/vi.json +27 -0
- package/i18n/locales/zh-CN.json +27 -0
- package/index.d.ts +33 -0
- package/modules/assistant/README.md +17 -8
- package/modules/assistant/index.ts +26 -16
- package/modules/assistant/runtime/server/api/search.ts +5 -0
- package/modules/config.ts +7 -2
- package/modules/css.ts +12 -0
- package/modules/skills/index.ts +158 -0
- package/modules/skills/runtime/server/routes/skills-files.ts +49 -0
- package/modules/skills/runtime/server/routes/skills-index.ts +8 -0
- package/nuxt.config.ts +8 -2
- package/nuxt.schema.ts +22 -0
- package/package.json +24 -21
- package/server/mcp/tools/get-page.ts +16 -5
- package/server/mcp/tools/list-pages.ts +13 -3
- package/app/components/OgImage/OgImageDocs.vue +0 -76
- package/app/components/OgImage/OgImageLanding.vue +0 -98
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
[](https://docus.dev)
|
|
2
2
|
|
|
3
3
|
# Docus
|
|
4
4
|
|
package/app/app.config.ts
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export default defineAppConfig({
|
|
2
2
|
docus: {
|
|
3
3
|
locale: 'en',
|
|
4
|
+
colorMode: '',
|
|
4
5
|
},
|
|
5
6
|
ui: {
|
|
6
7
|
colors: {
|
|
@@ -14,6 +15,11 @@ export default defineAppConfig({
|
|
|
14
15
|
itemLeadingIcon: 'size-4 mx-0.5',
|
|
15
16
|
},
|
|
16
17
|
},
|
|
18
|
+
contentToc: {
|
|
19
|
+
defaultVariants: {
|
|
20
|
+
highlight: true,
|
|
21
|
+
},
|
|
22
|
+
},
|
|
17
23
|
contentNavigation: {
|
|
18
24
|
slots: {
|
|
19
25
|
linkLeadingIcon: 'size-4 mr-1',
|
|
@@ -21,6 +27,13 @@ export default defineAppConfig({
|
|
|
21
27
|
},
|
|
22
28
|
defaultVariants: {
|
|
23
29
|
variant: 'link',
|
|
30
|
+
highlight: true,
|
|
31
|
+
},
|
|
32
|
+
},
|
|
33
|
+
navigationMenu: {
|
|
34
|
+
defaultVariants: {
|
|
35
|
+
variant: 'pill',
|
|
36
|
+
highlight: true,
|
|
24
37
|
},
|
|
25
38
|
},
|
|
26
39
|
pageLinks: {
|
package/app/app.vue
CHANGED
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
import type { ContentNavigationItem, PageCollections } from '@nuxt/content'
|
|
3
3
|
import * as nuxtUiLocales from '@nuxt/ui/locale'
|
|
4
4
|
import { transformNavigation } from './utils/navigation'
|
|
5
|
+
import { useDocusColorMode } from './composables/useDocusColorMode'
|
|
5
6
|
import { useSubNavigation } from './composables/useSubNavigation'
|
|
6
7
|
|
|
7
|
-
const
|
|
8
|
+
const appConfig = useAppConfig()
|
|
9
|
+
const { seo } = appConfig
|
|
10
|
+
const { forced: forcedColorMode } = useDocusColorMode()
|
|
8
11
|
const site = useSiteConfig()
|
|
9
12
|
const { locale, locales, isEnabled, switchLocalePath } = useDocusI18n()
|
|
10
13
|
const { isEnabled: isAssistantEnabled, panelWidth: assistantPanelWidth, shouldPushContent } = useAssistant()
|
|
@@ -79,6 +82,7 @@ const { subNavigationMode } = useSubNavigation(navigation)
|
|
|
79
82
|
<LazyUContentSearch
|
|
80
83
|
:files="files"
|
|
81
84
|
:navigation="navigation"
|
|
85
|
+
:color-mode="!forcedColorMode"
|
|
82
86
|
/>
|
|
83
87
|
<template v-if="isAssistantEnabled">
|
|
84
88
|
<LazyAssistantPanel />
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
const { title, description, headline } = defineProps<{ title?: string, description?: string, headline?: string }>()
|
|
3
|
+
|
|
4
|
+
const appConfig = useAppConfig()
|
|
5
|
+
const { name: siteName } = useSiteConfig()
|
|
6
|
+
const primaryColor = appConfig.ui?.colors?.primary ?? 'emerald'
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<div class="w-full h-full flex flex-col justify-between bg-neutral-950 px-[80px] py-[60px]">
|
|
11
|
+
<!-- Radial glow top-right: wide soft layer -->
|
|
12
|
+
<div class="absolute top-0 right-0 w-[700px] h-[700px] bg-[radial-gradient(circle_at_top_right,rgba(255,255,255,0.10)_0%,rgba(255,255,255,0.04)_40%,transparent_70%)]" />
|
|
13
|
+
<!-- Radial glow top-right: tight bright core -->
|
|
14
|
+
<div class="absolute top-0 right-0 w-[350px] h-[350px] bg-[radial-gradient(circle_at_top_right,rgba(255,255,255,0.22)_0%,rgba(255,255,255,0.08)_35%,transparent_65%)]" />
|
|
15
|
+
|
|
16
|
+
<div class="flex-1 flex flex-col justify-center">
|
|
17
|
+
<p
|
|
18
|
+
v-if="headline"
|
|
19
|
+
:class="`uppercase text-[22px] font-bold m-0 mb-5 tracking-[0.05em] text-${primaryColor}-500`"
|
|
20
|
+
>
|
|
21
|
+
{{ headline }}
|
|
22
|
+
</p>
|
|
23
|
+
<h1
|
|
24
|
+
v-if="title"
|
|
25
|
+
class="m-0 mb-6 text-[50px] font-bold text-white leading-[1.1] w-full max-w-[900px] wrap-break-word"
|
|
26
|
+
>
|
|
27
|
+
{{ title?.slice(0, 60) }}
|
|
28
|
+
</h1>
|
|
29
|
+
<p
|
|
30
|
+
v-if="description"
|
|
31
|
+
class="m-0 text-[28px] text-neutral-400 leading-[1.4] w-full max-w-[900px] wrap-break-word"
|
|
32
|
+
>
|
|
33
|
+
{{ description?.slice(0, 200) }}
|
|
34
|
+
</p>
|
|
35
|
+
</div>
|
|
36
|
+
|
|
37
|
+
<div class="flex">
|
|
38
|
+
<div class="text-white text-[18px] font-normal rounded-lg px-5 py-2">
|
|
39
|
+
{{ siteName }}
|
|
40
|
+
</div>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</template>
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
<script lang="ts" setup>
|
|
2
|
+
const { title, description } = defineProps<{ title?: string, description?: string }>()
|
|
3
|
+
|
|
4
|
+
const appConfig = useAppConfig()
|
|
5
|
+
const { name: siteName } = useSiteConfig()
|
|
6
|
+
const primaryColor = appConfig.ui?.colors?.primary ?? 'emerald'
|
|
7
|
+
const logoPath = appConfig.header?.logo?.dark || appConfig.header?.logo?.light
|
|
8
|
+
|
|
9
|
+
const logoSvg = await fetchLogoSvg(logoPath)
|
|
10
|
+
|
|
11
|
+
async function fetchLogoSvg(path?: string): Promise<string> {
|
|
12
|
+
if (!path) return ''
|
|
13
|
+
try {
|
|
14
|
+
const { url: siteUrl } = useSiteConfig()
|
|
15
|
+
const url = path.startsWith('http') ? path : `${siteUrl}${path}`
|
|
16
|
+
const svg = await $fetch<string>(url, { responseType: 'text' })
|
|
17
|
+
return svg.replace('<svg', '<svg width="48" height="48"')
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return ''
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
</script>
|
|
24
|
+
|
|
25
|
+
<template>
|
|
26
|
+
<div class="w-full h-full flex flex-col justify-between bg-neutral-950 px-[80px] py-[60px]">
|
|
27
|
+
<!-- Radial glow top-right: wide soft layer -->
|
|
28
|
+
<div class="absolute top-0 right-0 w-[700px] h-[700px] bg-[radial-gradient(circle_at_top_right,rgba(255,255,255,0.10)_0%,rgba(255,255,255,0.04)_40%,transparent_70%)]" />
|
|
29
|
+
<!-- Radial glow top-right: tight bright core -->
|
|
30
|
+
<div class="absolute top-0 right-0 w-[350px] h-[350px] bg-[radial-gradient(circle_at_top_right,rgba(255,255,255,0.22)_0%,rgba(255,255,255,0.08)_35%,transparent_65%)]" />
|
|
31
|
+
|
|
32
|
+
<div class="flex-1 flex flex-col justify-center w-full">
|
|
33
|
+
<div
|
|
34
|
+
v-if="logoSvg"
|
|
35
|
+
class="flex justify-center mb-8"
|
|
36
|
+
>
|
|
37
|
+
<!-- eslint-disable-next-line vue/no-v-html -->
|
|
38
|
+
<div
|
|
39
|
+
class="w-[48px] h-[48px]"
|
|
40
|
+
v-html="logoSvg"
|
|
41
|
+
/>
|
|
42
|
+
</div>
|
|
43
|
+
<div
|
|
44
|
+
v-if="title"
|
|
45
|
+
class="flex justify-center mb-6"
|
|
46
|
+
>
|
|
47
|
+
<h1 class="m-0 text-[50px] font-bold text-white leading-[1.1] text-center wrap-break-word">
|
|
48
|
+
{{ title?.slice(0, 60) }}
|
|
49
|
+
</h1>
|
|
50
|
+
</div>
|
|
51
|
+
<div
|
|
52
|
+
v-if="description"
|
|
53
|
+
class="flex justify-center"
|
|
54
|
+
>
|
|
55
|
+
<p class="m-0 text-[28px] text-neutral-400 leading-[1.4] text-center wrap-break-word">
|
|
56
|
+
{{ description?.slice(0, 200) }}
|
|
57
|
+
</p>
|
|
58
|
+
</div>
|
|
59
|
+
</div>
|
|
60
|
+
|
|
61
|
+
<div class="flex">
|
|
62
|
+
<div :class="`text-[18px] font-normal rounded-lg px-5 py-2 text-${primaryColor}-500`">
|
|
63
|
+
{{ siteName }}
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
</div>
|
|
67
|
+
</template>
|
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useDocusColorMode } from '../../composables/useDocusColorMode'
|
|
3
|
+
|
|
2
4
|
const appConfig = useAppConfig()
|
|
5
|
+
const { forced: forcedColorMode } = useDocusColorMode()
|
|
3
6
|
|
|
4
7
|
interface FooterLink {
|
|
5
8
|
'icon': string
|
|
@@ -44,5 +47,5 @@ const links = computed<FooterLink[]>(() => {
|
|
|
44
47
|
v-bind="{ color: 'neutral', variant: 'ghost', ...link }"
|
|
45
48
|
/>
|
|
46
49
|
</template>
|
|
47
|
-
<UColorModeButton />
|
|
50
|
+
<UColorModeButton v-if="!forcedColorMode" />
|
|
48
51
|
</template>
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
|
+
import { useDocusColorMode } from '../../composables/useDocusColorMode'
|
|
2
3
|
import { useDocusI18n } from '../../composables/useDocusI18n'
|
|
3
4
|
import { useSubNavigation } from '../../composables/useSubNavigation'
|
|
4
5
|
|
|
5
6
|
const appConfig = useAppConfig()
|
|
6
|
-
const
|
|
7
|
+
const { forced: forcedColorMode } = useDocusColorMode()
|
|
7
8
|
|
|
8
9
|
const { isEnabled: isAssistantEnabled } = useAssistant()
|
|
9
|
-
const {
|
|
10
|
+
const { isEnabled, locales } = useDocusI18n()
|
|
10
11
|
const { subNavigationMode } = useSubNavigation()
|
|
11
12
|
|
|
12
13
|
const links = computed(() => appConfig.github && appConfig.github.url
|
|
@@ -25,13 +26,11 @@ const links = computed(() => appConfig.github && appConfig.github.url
|
|
|
25
26
|
<UHeader
|
|
26
27
|
:ui="{ center: 'flex-1' }"
|
|
27
28
|
:class="{ 'flex flex-col': subNavigationMode === 'header' }"
|
|
28
|
-
:to="localePath('/')"
|
|
29
|
-
:title="appConfig.header?.title || site.name"
|
|
30
29
|
>
|
|
31
30
|
<AppHeaderCenter />
|
|
32
31
|
|
|
33
|
-
<template #
|
|
34
|
-
<
|
|
32
|
+
<template #left>
|
|
33
|
+
<AppHeaderLeft />
|
|
35
34
|
</template>
|
|
36
35
|
|
|
37
36
|
<template #right>
|
|
@@ -58,7 +57,7 @@ const links = computed(() => appConfig.github && appConfig.github.url
|
|
|
58
57
|
|
|
59
58
|
<UContentSearchButton class="lg:hidden" />
|
|
60
59
|
|
|
61
|
-
<ClientOnly>
|
|
60
|
+
<ClientOnly v-if="!forcedColorMode">
|
|
62
61
|
<UColorModeButton />
|
|
63
62
|
|
|
64
63
|
<template #fallback>
|
|
@@ -2,12 +2,16 @@
|
|
|
2
2
|
import type { ContentNavigationItem } from '@nuxt/content'
|
|
3
3
|
|
|
4
4
|
const navigation = inject<Ref<ContentNavigationItem[]>>('navigation')
|
|
5
|
+
|
|
6
|
+
const contentNavVariants = useUIConfig('contentNavigation')
|
|
5
7
|
</script>
|
|
6
8
|
|
|
7
9
|
<template>
|
|
8
10
|
<UContentNavigation
|
|
9
|
-
highlight
|
|
10
|
-
|
|
11
|
+
:highlight="contentNavVariants.highlight ?? true"
|
|
12
|
+
:highlight-color="contentNavVariants.highlightColor"
|
|
13
|
+
:variant="contentNavVariants.variant ?? 'link'"
|
|
14
|
+
:color="contentNavVariants.color"
|
|
11
15
|
:navigation="navigation"
|
|
12
16
|
/>
|
|
13
17
|
</template>
|
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
import { useSubNavigation } from '../../composables/useSubNavigation'
|
|
3
3
|
|
|
4
4
|
const { sections } = useSubNavigation()
|
|
5
|
+
|
|
6
|
+
const navMenuVariants = useUIConfig('navigationMenu')
|
|
5
7
|
</script>
|
|
6
8
|
|
|
7
9
|
<template>
|
|
@@ -10,8 +12,10 @@ const { sections } = useSubNavigation()
|
|
|
10
12
|
<UContainer class="hidden lg:flex items-center justify-between">
|
|
11
13
|
<UNavigationMenu
|
|
12
14
|
:items="sections"
|
|
13
|
-
|
|
14
|
-
highlight
|
|
15
|
+
:highlight="navMenuVariants.highlight ?? true"
|
|
16
|
+
:highlight-color="navMenuVariants.highlightColor"
|
|
17
|
+
:variant="navMenuVariants.variant ?? 'pill'"
|
|
18
|
+
:color="navMenuVariants.color"
|
|
15
19
|
class="-mx-2.5 -mb-px"
|
|
16
20
|
/>
|
|
17
21
|
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
<script setup lang="ts">
|
|
2
|
+
const appConfig = useAppConfig()
|
|
3
|
+
const site = useSiteConfig()
|
|
4
|
+
const { localePath } = useDocusI18n()
|
|
5
|
+
|
|
6
|
+
const ariaLabel = appConfig.header?.title || site.name
|
|
7
|
+
</script>
|
|
8
|
+
|
|
9
|
+
<template>
|
|
10
|
+
<NuxtLink
|
|
11
|
+
:to="localePath('/')"
|
|
12
|
+
:aria-label="ariaLabel"
|
|
13
|
+
>
|
|
14
|
+
<AppHeaderLogo class="h-6 w-auto shrink-0" />
|
|
15
|
+
</NuxtLink>
|
|
16
|
+
</template>
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
<script setup lang="ts">
|
|
2
2
|
const { sidebarNavigation } = useSubNavigation()
|
|
3
|
+
|
|
4
|
+
const contentNavVariants = useUIConfig('contentNavigation')
|
|
3
5
|
</script>
|
|
4
6
|
|
|
5
7
|
<template>
|
|
6
8
|
<UContentNavigation
|
|
7
|
-
highlight
|
|
9
|
+
:highlight="contentNavVariants.highlight ?? true"
|
|
10
|
+
:highlight-color="contentNavVariants.highlightColor"
|
|
11
|
+
:variant="contentNavVariants.variant ?? 'link'"
|
|
12
|
+
:color="contentNavVariants.color"
|
|
8
13
|
:navigation="sidebarNavigation"
|
|
9
14
|
/>
|
|
10
15
|
</template>
|
|
@@ -9,6 +9,9 @@ defineProps<{
|
|
|
9
9
|
const { subNavigationMode, sidebarNavigation, currentSection } = useSubNavigation()
|
|
10
10
|
const { t } = useDocusI18n()
|
|
11
11
|
|
|
12
|
+
const contentNavVariants = useUIConfig('contentNavigation')
|
|
13
|
+
const contentTocVariants = useUIConfig('contentToc')
|
|
14
|
+
|
|
12
15
|
const menuDrawerOpen = ref(false)
|
|
13
16
|
const tocDrawerOpen = ref(false)
|
|
14
17
|
</script>
|
|
@@ -39,10 +42,13 @@ const tocDrawerOpen = ref(false)
|
|
|
39
42
|
<template #body>
|
|
40
43
|
<UContentNavigation
|
|
41
44
|
:navigation="sidebarNavigation"
|
|
45
|
+
:highlight="contentNavVariants.highlight ?? true"
|
|
46
|
+
:highlight-color="contentNavVariants.highlightColor"
|
|
47
|
+
:variant="contentNavVariants.variant ?? 'link'"
|
|
48
|
+
:color="contentNavVariants.color"
|
|
42
49
|
default-open
|
|
43
50
|
trailing-icon="i-lucide-chevron-right"
|
|
44
51
|
:ui="{ linkTrailingIcon: 'group-data-[state=open]:rotate-90' }"
|
|
45
|
-
highlight
|
|
46
52
|
/>
|
|
47
53
|
</template>
|
|
48
54
|
</UDrawer>
|
|
@@ -68,6 +74,10 @@ const tocDrawerOpen = ref(false)
|
|
|
68
74
|
<template #body>
|
|
69
75
|
<UContentToc
|
|
70
76
|
v-if="links?.length"
|
|
77
|
+
:highlight="contentTocVariants.highlight ?? true"
|
|
78
|
+
:highlight-color="contentTocVariants.highlightColor"
|
|
79
|
+
:highlight-variant="contentTocVariants.highlightVariant"
|
|
80
|
+
:color="contentTocVariants.color"
|
|
71
81
|
:links="links"
|
|
72
82
|
:open="true"
|
|
73
83
|
default-open
|
|
@@ -12,13 +12,18 @@ const { shouldPushContent: shouldHideToc } = useAssistant()
|
|
|
12
12
|
const { subNavigationMode } = useSubNavigation()
|
|
13
13
|
const appConfig = useAppConfig()
|
|
14
14
|
const { t } = useDocusI18n()
|
|
15
|
+
|
|
16
|
+
const contentTocVariants = useUIConfig('contentToc')
|
|
15
17
|
</script>
|
|
16
18
|
|
|
17
19
|
<template>
|
|
18
20
|
<div>
|
|
19
21
|
<UContentToc
|
|
20
22
|
v-if="links.length && !shouldHideToc"
|
|
21
|
-
highlight
|
|
23
|
+
:highlight="contentTocVariants.highlight ?? true"
|
|
24
|
+
:highlight-color="contentTocVariants.highlightColor"
|
|
25
|
+
:highlight-variant="contentTocVariants.highlightVariant"
|
|
26
|
+
:color="contentTocVariants.color"
|
|
22
27
|
:title="appConfig.toc?.title || t('docs.toc')"
|
|
23
28
|
:links="links"
|
|
24
29
|
:class="{ 'hidden lg:block': subNavigationMode }"
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
type UIColor = 'primary' | 'secondary' | 'success' | 'info' | 'warning' | 'error' | 'neutral'
|
|
2
|
+
|
|
3
|
+
interface UIConfigMap {
|
|
4
|
+
contentToc: {
|
|
5
|
+
highlight?: boolean
|
|
6
|
+
highlightColor?: UIColor
|
|
7
|
+
highlightVariant?: 'straight' | 'circuit'
|
|
8
|
+
color?: UIColor
|
|
9
|
+
}
|
|
10
|
+
contentNavigation: {
|
|
11
|
+
highlight?: boolean
|
|
12
|
+
highlightColor?: UIColor
|
|
13
|
+
variant?: 'pill' | 'link'
|
|
14
|
+
color?: UIColor
|
|
15
|
+
}
|
|
16
|
+
navigationMenu: {
|
|
17
|
+
highlight?: boolean
|
|
18
|
+
highlightColor?: UIColor
|
|
19
|
+
variant?: 'pill' | 'link'
|
|
20
|
+
color?: UIColor
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function useUIConfig<K extends keyof UIConfigMap>(componentName: K): ComputedRef<UIConfigMap[K]> {
|
|
25
|
+
const appConfig = useAppConfig()
|
|
26
|
+
return computed(() => {
|
|
27
|
+
const ui = appConfig.ui as Record<string, Record<string, Record<string, unknown>>>
|
|
28
|
+
return (ui?.[componentName]?.defaultVariants || {}) as UIConfigMap[K]
|
|
29
|
+
})
|
|
30
|
+
}
|
package/app/error.vue
CHANGED
|
@@ -3,11 +3,13 @@ import type { NuxtError } from '#app'
|
|
|
3
3
|
import type { ContentNavigationItem, PageCollections } from '@nuxt/content'
|
|
4
4
|
import * as nuxtUiLocales from '@nuxt/ui/locale'
|
|
5
5
|
import { transformNavigation } from './utils/navigation'
|
|
6
|
+
import { useDocusColorMode } from './composables/useDocusColorMode'
|
|
6
7
|
|
|
7
8
|
const props = defineProps<{
|
|
8
9
|
error: NuxtError
|
|
9
10
|
}>()
|
|
10
11
|
|
|
12
|
+
const { forced: forcedColorMode } = useDocusColorMode()
|
|
11
13
|
const { locale, locales, isEnabled, t, switchLocalePath } = useDocusI18n()
|
|
12
14
|
|
|
13
15
|
const nuxtUiLocale = computed(() => nuxtUiLocales[locale.value as keyof typeof nuxtUiLocales] || nuxtUiLocales.en)
|
|
@@ -70,6 +72,7 @@ provide('navigation', navigation)
|
|
|
70
72
|
<LazyUContentSearch
|
|
71
73
|
:files="files"
|
|
72
74
|
:navigation="navigation"
|
|
75
|
+
:color-mode="!forcedColorMode"
|
|
73
76
|
/>
|
|
74
77
|
</ClientOnly>
|
|
75
78
|
</UApp>
|
|
@@ -45,8 +45,10 @@ watch(() => navigation?.value, () => {
|
|
|
45
45
|
headline.value = findPageHeadline(navigation?.value, page.value?.path) || headline.value
|
|
46
46
|
})
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
defineOgImage('Docs', {
|
|
49
49
|
headline: headline.value,
|
|
50
|
+
title: title?.slice(0, 60),
|
|
51
|
+
description: formatOgDescription(title, description),
|
|
50
52
|
})
|
|
51
53
|
|
|
52
54
|
const github = computed(() => appConfig.github ? appConfig.github : null)
|
|
@@ -115,17 +117,19 @@ addPrerenderPath(`/raw${route.path}.md`)
|
|
|
115
117
|
>
|
|
116
118
|
{{ t('docs.edit') }}
|
|
117
119
|
</UButton>
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
120
|
+
<template v-if="github?.url">
|
|
121
|
+
<span>{{ t('common.or') }}</span>
|
|
122
|
+
<UButton
|
|
123
|
+
variant="link"
|
|
124
|
+
color="neutral"
|
|
125
|
+
:to="`${github.url}/issues/new/choose`"
|
|
126
|
+
target="_blank"
|
|
127
|
+
icon="i-lucide-alert-circle"
|
|
128
|
+
:ui="{ leadingIcon: 'size-4' }"
|
|
129
|
+
>
|
|
130
|
+
{{ t('docs.report') }}
|
|
131
|
+
</UButton>
|
|
132
|
+
</template>
|
|
129
133
|
</div>
|
|
130
134
|
</USeparator>
|
|
131
135
|
<UContentSurround :surround="surround" />
|
|
@@ -23,9 +23,9 @@ useSeo({
|
|
|
23
23
|
})
|
|
24
24
|
|
|
25
25
|
if (!page.value?.seo?.ogImage) {
|
|
26
|
-
|
|
27
|
-
title,
|
|
28
|
-
description,
|
|
26
|
+
defineOgImage('Landing', {
|
|
27
|
+
title: title?.slice(0, 60),
|
|
28
|
+
description: formatOgDescription(title, description),
|
|
29
29
|
})
|
|
30
30
|
}
|
|
31
31
|
</script>
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// nuxt-og-image caps the encoded URL segment at 200 chars.
|
|
2
|
+
// Fixed overhead (component name, param keys, path encoding) is ~50 chars,
|
|
3
|
+
// leaving a ~150-char budget for title + description combined.
|
|
4
|
+
const OG_BUDGET = 150
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Trims description to fit within the nuxt-og-image 200-char URL segment limit,
|
|
8
|
+
* accounting for the title length and trying to cut at the last sentence boundary.
|
|
9
|
+
*/
|
|
10
|
+
export function formatOgDescription(title: string | undefined, description: string | undefined): string | undefined {
|
|
11
|
+
if (!description) return undefined
|
|
12
|
+
|
|
13
|
+
const titleLen = Math.min(title?.length ?? 0, 60)
|
|
14
|
+
const maxLen = OG_BUDGET - titleLen
|
|
15
|
+
if (maxLen <= 0) return undefined
|
|
16
|
+
|
|
17
|
+
const cleaned = description.replace(/,/g, '')
|
|
18
|
+
if (cleaned.length <= maxLen) return cleaned
|
|
19
|
+
|
|
20
|
+
const truncated = cleaned.slice(0, maxLen)
|
|
21
|
+
const lastDot = truncated.lastIndexOf('.')
|
|
22
|
+
return lastDot > 0 ? truncated.slice(0, lastDot + 1) : truncated
|
|
23
|
+
}
|
package/i18n/locales/ar.json
CHANGED
|
@@ -32,5 +32,32 @@
|
|
|
32
32
|
"wordmarkDownloaded": "تم تحميل العلامة النصية",
|
|
33
33
|
"copyLogoFailed": "فشل نسخ الشعار",
|
|
34
34
|
"copyWordmarkFailed": "فشل نسخ العلامة النصية"
|
|
35
|
+
},
|
|
36
|
+
"assistant": {
|
|
37
|
+
"title": "اسأل الذكاء الاصطناعي",
|
|
38
|
+
"placeholder": "اطرح سؤالاً...",
|
|
39
|
+
"tooltip": "اطرح سؤالاً على الذكاء الاصطناعي",
|
|
40
|
+
"tryAsking": "حاول طرح سؤال",
|
|
41
|
+
"askAnything": "اسأل أي شيء...",
|
|
42
|
+
"clearChat": "محو المحادثة",
|
|
43
|
+
"close": "إغلاق",
|
|
44
|
+
"expand": "توسيع",
|
|
45
|
+
"collapse": "طي",
|
|
46
|
+
"thinking": "التفكير...",
|
|
47
|
+
"askMeAnything": "اسأل عن أي شيء",
|
|
48
|
+
"askMeAnythingDescription": "احصل على المساعدة في التنقل بين الوثائق وفهم المفاهيم والعثور على الإجابات.",
|
|
49
|
+
"faq": "الأسئلة الشائعة",
|
|
50
|
+
"chatCleared": "تم مسح الدردشة عند التحديث",
|
|
51
|
+
"lineBreak": "فاصل الأسطر",
|
|
52
|
+
"explainWithAi": "اشرح باستخدام الذكاء الاصطناعي",
|
|
53
|
+
"toolListPages": "صفحات الوثائق المدرجة",
|
|
54
|
+
"toolReadPage": "قراءة",
|
|
55
|
+
"loading": {
|
|
56
|
+
"searching": "البحث في الوثائق",
|
|
57
|
+
"reading": "قراءة المستندات",
|
|
58
|
+
"analyzing": "تحليل المحتوى",
|
|
59
|
+
"finding": "العثور على أفضل إجابة",
|
|
60
|
+
"finished": "المصادر المستخدمة"
|
|
61
|
+
}
|
|
35
62
|
}
|
|
36
63
|
}
|
package/i18n/locales/be.json
CHANGED
|
@@ -32,5 +32,32 @@
|
|
|
32
32
|
"wordmarkDownloaded": "Словесны знак спампаваны",
|
|
33
33
|
"copyLogoFailed": "Не ўдалося скапіяваць лагатып",
|
|
34
34
|
"copyWordmarkFailed": "Не ўдалося скапіяваць словесны знак"
|
|
35
|
+
},
|
|
36
|
+
"assistant": {
|
|
37
|
+
"title": "Спытаць ІІ",
|
|
38
|
+
"placeholder": "Задаць пытанне...",
|
|
39
|
+
"tooltip": "Задаць пытанне ІІ",
|
|
40
|
+
"tryAsking": "Паспрабуйце задаць пытанне",
|
|
41
|
+
"askAnything": "Спытай што заўгодна...",
|
|
42
|
+
"clearChat": "Ачысціць чат",
|
|
43
|
+
"close": "Закрыць",
|
|
44
|
+
"expand": "Пашырыць",
|
|
45
|
+
"collapse": "Згарнуць",
|
|
46
|
+
"thinking": "Мысленне...",
|
|
47
|
+
"askMeAnything": "Спытаць што-небудзь",
|
|
48
|
+
"askMeAnythingDescription": "Атрымаць дапамогу ў навігацыі па дакументацыі, разуменні канцэпцый і пошуку адказаў.",
|
|
49
|
+
"faq": "Пытанні і адказы",
|
|
50
|
+
"chatCleared": "Чат ачышчаецца пры абнаўленні",
|
|
51
|
+
"lineBreak": "Перапынак у радку",
|
|
52
|
+
"explainWithAi": "Растлумачыць ІІ",
|
|
53
|
+
"toolListPages": "Старонкі дакументацыі",
|
|
54
|
+
"toolReadPage": "Чытаць",
|
|
55
|
+
"loading": {
|
|
56
|
+
"searching": "Пошук дакументацыі",
|
|
57
|
+
"reading": "Чытанне праз дакументы",
|
|
58
|
+
"analyzing": "Аналіз зместу",
|
|
59
|
+
"finding": "Пошук найлепшага адказу",
|
|
60
|
+
"finished": "Выкарыстаныя крыніцы"
|
|
61
|
+
}
|
|
35
62
|
}
|
|
36
63
|
}
|
package/i18n/locales/bg.json
CHANGED
|
@@ -32,5 +32,32 @@
|
|
|
32
32
|
"wordmarkDownloaded": "Словната марка е изтеглена",
|
|
33
33
|
"copyLogoFailed": "Неуспешно копиране на логото",
|
|
34
34
|
"copyWordmarkFailed": "Неуспешно копиране на словната марка"
|
|
35
|
+
},
|
|
36
|
+
"assistant": {
|
|
37
|
+
"title": "Попитайте AI",
|
|
38
|
+
"placeholder": "Задайте въпрос...",
|
|
39
|
+
"tooltip": "Задайте въпрос на AI",
|
|
40
|
+
"tryAsking": "Опитайте да зададете въпрос",
|
|
41
|
+
"askAnything": "Попитайте каквото и да е...",
|
|
42
|
+
"clearChat": "Изчистване на чата",
|
|
43
|
+
"close": "Затваряне",
|
|
44
|
+
"expand": "Разширяване",
|
|
45
|
+
"collapse": "Свиване",
|
|
46
|
+
"thinking": "Мисля си...",
|
|
47
|
+
"askMeAnything": "Попитайте за всичко",
|
|
48
|
+
"askMeAnythingDescription": "Потърсете помощ за навигация в документацията, разбиране на концепциите и намиране на отговори.",
|
|
49
|
+
"faq": "Често задавани въпроси",
|
|
50
|
+
"chatCleared": "Чатът е изчистен при обновяване",
|
|
51
|
+
"lineBreak": "Прекъсване на линията",
|
|
52
|
+
"explainWithAi": "Обяснете с ИИ",
|
|
53
|
+
"toolListPages": "Изброени страници от документацията",
|
|
54
|
+
"toolReadPage": "Четене",
|
|
55
|
+
"loading": {
|
|
56
|
+
"searching": "Търсене в документацията",
|
|
57
|
+
"reading": "Четене на документите",
|
|
58
|
+
"analyzing": "Анализиране на съдържанието",
|
|
59
|
+
"finding": "Намиране на най-добрия отговор",
|
|
60
|
+
"finished": "Използвани източници"
|
|
61
|
+
}
|
|
35
62
|
}
|
|
36
63
|
}
|
package/i18n/locales/bn.json
CHANGED
|
@@ -32,5 +32,32 @@
|
|
|
32
32
|
"wordmarkDownloaded": "ওয়ার্ডমার্ক ডাউনলোড হয়েছে",
|
|
33
33
|
"copyLogoFailed": "লোগো কপি করা যায়নি",
|
|
34
34
|
"copyWordmarkFailed": "ওয়ার্ডমার্ক কপি করা যায়নি"
|
|
35
|
+
},
|
|
36
|
+
"assistant": {
|
|
37
|
+
"title": "AI-কে জিজ্ঞাসা করুন",
|
|
38
|
+
"placeholder": "একটি প্রশ্ন জিজ্ঞাসা করুন...",
|
|
39
|
+
"tooltip": "AI-কে একটি প্রশ্ন জিজ্ঞাসা করুন",
|
|
40
|
+
"tryAsking": "একটি প্রশ্ন জিজ্ঞাসা করার চেষ্টা করুন",
|
|
41
|
+
"askAnything": "যেকোনো কিছু জিজ্ঞাসা করুন...",
|
|
42
|
+
"clearChat": "চ্যাট সাফ করুন",
|
|
43
|
+
"close": "বন্ধ করুন",
|
|
44
|
+
"expand": "প্রসারিত করুন",
|
|
45
|
+
"collapse": "সঙ্কুচিত",
|
|
46
|
+
"thinking": "চিন্তা করা হচ্ছে...",
|
|
47
|
+
"askMeAnything": "যেকোনো কিছু জিজ্ঞাসা করুন",
|
|
48
|
+
"askMeAnythingDescription": "ডকুমেন্টেশন নেভিগেট করতে, ধারণাগুলি বুঝতে এবং উত্তর খুঁজে পেতে সহায়তা পান ।",
|
|
49
|
+
"faq": "প্রায়শই জিজ্ঞাসিত প্রশ্নাবলী",
|
|
50
|
+
"chatCleared": "রিফ্রেশে চ্যাট সাফ করা হয়",
|
|
51
|
+
"lineBreak": "লাইন ব্রেক",
|
|
52
|
+
"explainWithAi": "AI এর সাথে ব্যাখ্যা করুন",
|
|
53
|
+
"toolListPages": "তালিকাভুক্ত ডকুমেন্টেশন পৃষ্ঠাগুলি",
|
|
54
|
+
"toolReadPage": "পড়ুন",
|
|
55
|
+
"loading": {
|
|
56
|
+
"searching": "ডকুমেন্টেশন অনুসন্ধান করা হচ্ছে",
|
|
57
|
+
"reading": "ডকুমেন্টের মাধ্যমে পড়া",
|
|
58
|
+
"analyzing": "বিষয়বস্তু বিশ্লেষণ করা হচ্ছে",
|
|
59
|
+
"finding": "সেরা উত্তর খোঁজা",
|
|
60
|
+
"finished": "ব্যবহৃত উৎসসমূহ"
|
|
61
|
+
}
|
|
35
62
|
}
|
|
36
63
|
}
|