@vkuttyp/docus 5.4.6

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.
Files changed (78) hide show
  1. package/README.md +116 -0
  2. package/app/app.config.ts +33 -0
  3. package/app/app.vue +79 -0
  4. package/app/components/IconMenuToggle.vue +83 -0
  5. package/app/components/LanguageSelect.vue +83 -0
  6. package/app/components/OgImage/OgImageDocs.vue +78 -0
  7. package/app/components/OgImage/OgImageLanding.vue +75 -0
  8. package/app/components/app/AppFooter.vue +11 -0
  9. package/app/components/app/AppFooterLeft.vue +5 -0
  10. package/app/components/app/AppFooterRight.vue +30 -0
  11. package/app/components/app/AppHeader.vue +82 -0
  12. package/app/components/app/AppHeaderBody.vue +13 -0
  13. package/app/components/app/AppHeaderCTA.vue +3 -0
  14. package/app/components/app/AppHeaderCenter.vue +10 -0
  15. package/app/components/app/AppHeaderLogo.vue +16 -0
  16. package/app/components/docs/DocsAsideLeftBody.vue +12 -0
  17. package/app/components/docs/DocsAsideLeftTop.vue +3 -0
  18. package/app/components/docs/DocsAsideRightBottom.vue +18 -0
  19. package/app/components/docs/DocsPageHeaderLinks.vue +96 -0
  20. package/app/composables/useDocusI18n.ts +35 -0
  21. package/app/error.vue +79 -0
  22. package/app/layouts/default.vue +5 -0
  23. package/app/layouts/docs.vue +15 -0
  24. package/app/pages/[[lang]]/[...slug].vue +145 -0
  25. package/app/plugins/i18n.ts +40 -0
  26. package/app/templates/landing.vue +44 -0
  27. package/app/types/index.d.ts +42 -0
  28. package/app/utils/navigation.ts +7 -0
  29. package/app/utils/prerender.ts +12 -0
  30. package/content.config.ts +67 -0
  31. package/i18n/locales/ar.json +22 -0
  32. package/i18n/locales/be.json +23 -0
  33. package/i18n/locales/bg.json +22 -0
  34. package/i18n/locales/bn.json +22 -0
  35. package/i18n/locales/ca.json +22 -0
  36. package/i18n/locales/ckb.json +18 -0
  37. package/i18n/locales/cs.json +22 -0
  38. package/i18n/locales/da.json +22 -0
  39. package/i18n/locales/de.json +22 -0
  40. package/i18n/locales/el.json +22 -0
  41. package/i18n/locales/en.json +22 -0
  42. package/i18n/locales/es.json +22 -0
  43. package/i18n/locales/et.json +22 -0
  44. package/i18n/locales/fi.json +22 -0
  45. package/i18n/locales/fr.json +22 -0
  46. package/i18n/locales/he.json +22 -0
  47. package/i18n/locales/hi.json +22 -0
  48. package/i18n/locales/hy.json +22 -0
  49. package/i18n/locales/it.json +22 -0
  50. package/i18n/locales/ja.json +22 -0
  51. package/i18n/locales/kk.json +22 -0
  52. package/i18n/locales/km.json +22 -0
  53. package/i18n/locales/ko.json +22 -0
  54. package/i18n/locales/ky.json +22 -0
  55. package/i18n/locales/lb.json +22 -0
  56. package/i18n/locales/ms.json +22 -0
  57. package/i18n/locales/nb.json +22 -0
  58. package/i18n/locales/nl.json +22 -0
  59. package/i18n/locales/pl.json +23 -0
  60. package/i18n/locales/ro.json +22 -0
  61. package/i18n/locales/ru.json +23 -0
  62. package/i18n/locales/sl.json +22 -0
  63. package/i18n/locales/sv.json +22 -0
  64. package/i18n/locales/uk.json +22 -0
  65. package/i18n/locales/ur.json +22 -0
  66. package/i18n/locales/vi.json +22 -0
  67. package/modules/config.ts +116 -0
  68. package/modules/css.ts +32 -0
  69. package/modules/routing.ts +41 -0
  70. package/nuxt.config.ts +84 -0
  71. package/nuxt.schema.ts +218 -0
  72. package/package.json +55 -0
  73. package/server/mcp/tools/get-page.ts +60 -0
  74. package/server/mcp/tools/list-pages.ts +60 -0
  75. package/server/routes/raw/[...slug].md.get.ts +45 -0
  76. package/server/utils/content.ts +37 -0
  77. package/utils/git.ts +110 -0
  78. package/utils/meta.ts +29 -0
@@ -0,0 +1,22 @@
1
+ {
2
+ "common": {
3
+ "or": "sau",
4
+ "error": {
5
+ "title": "Pagina nu a fost găsită",
6
+ "description": "Ne pare rău, dar această pagină nu a putut fi găsită."
7
+ }
8
+ },
9
+ "docs": {
10
+ "copy": {
11
+ "page": "Copiază pagina",
12
+ "link": "Copiază pagina în Markdown",
13
+ "view": "Vezi ca Markdown",
14
+ "gpt": "Deschide în ChatGPT",
15
+ "claude": "Deschide în Claude"
16
+ },
17
+ "links": "Comunitate",
18
+ "toc": "Pe această pagină",
19
+ "report": "Raportează o problemă",
20
+ "edit": "Editează această pagină"
21
+ }
22
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "common": {
3
+ "or": "или",
4
+ "error": {
5
+ "title": "Страница не найдена",
6
+ "description": "Извините, но запрашиваемая страница не найдена."
7
+ }
8
+ },
9
+ "docs": {
10
+ "copy": {
11
+ "page": "Копировать страницу",
12
+ "link": "Копировать Markdown-страницу",
13
+ "view": "Просмотреть как Markdown",
14
+ "gpt": "Открыть в ChatGPT",
15
+ "claude": "Открыть в Claude"
16
+ },
17
+ "links": "Сообщество",
18
+ "toc": "На этой странице",
19
+ "report": "Сообщить о проблеме",
20
+ "edit": "Редактировать эту страницу"
21
+ }
22
+ }
23
+
@@ -0,0 +1,22 @@
1
+ {
2
+ "common": {
3
+ "or": "ali",
4
+ "error": {
5
+ "title": "Stran ni bila najdena",
6
+ "description": "Opravičujemo se, vendar stran, ki jo iščete, ni bila najdena."
7
+ }
8
+ },
9
+ "docs": {
10
+ "copy": {
11
+ "page": "Kopiraj stran",
12
+ "link": "Kopiraj Markdown stran",
13
+ "view": "Prikaži kot Markdown",
14
+ "gpt": "Odpri v ChatGPT",
15
+ "claude": "Odpri v Claude"
16
+ },
17
+ "links": "Skupnost",
18
+ "toc": "Na tej strani",
19
+ "report": "Prijavi težavo",
20
+ "edit": "Uredi to stran"
21
+ }
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "common": {
3
+ "or": "eller",
4
+ "error": {
5
+ "title": "Sidan hittades inte",
6
+ "description": "Vi ber om ursäkt, men sidan du letar efter kunde inte hittas."
7
+ }
8
+ },
9
+ "docs": {
10
+ "copy": {
11
+ "page": "Kopiera sida",
12
+ "link": "Kopiera Markdown-sida",
13
+ "view": "Visa som Markdown",
14
+ "gpt": "Öppna i ChatGPT",
15
+ "claude": "Öppna i Claude"
16
+ },
17
+ "links": "Gemenskap",
18
+ "toc": "På denna sida",
19
+ "report": "Rapportera ett problem",
20
+ "edit": "Redigera denna sida"
21
+ }
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "common": {
3
+ "or": "або",
4
+ "error": {
5
+ "title": "Сторінку не знайдено",
6
+ "description": "Вибачте, але сторінку, яку ви шукаєте, не знайдено."
7
+ }
8
+ },
9
+ "docs": {
10
+ "copy": {
11
+ "page": "Скопіювати сторінку",
12
+ "link": "Скопіювати Markdown сторінку",
13
+ "view": "Переглянути як Markdown",
14
+ "gpt": "Відкрити в ChatGPT",
15
+ "claude": "Відкрити в Claude"
16
+ },
17
+ "links": "Спільнота",
18
+ "toc": "На цій сторінці",
19
+ "report": "Повідомити про проблему",
20
+ "edit": "Редагувати цю сторінку"
21
+ }
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "common": {
3
+ "or": "یا",
4
+ "error": {
5
+ "title": "صفحہ نہیں ملا",
6
+ "description": "ہمیں افسوس ہے، لیکن آپ جو صفحہ تلاش کر رہے ہیں وہ موجود نہیں ہے۔"
7
+ }
8
+ },
9
+ "docs": {
10
+ "copy": {
11
+ "page": "صفحہ کاپی کریں",
12
+ "link": "Markdown صفحہ کاپی کریں",
13
+ "view": "Markdown کے طور پر دیکھیں",
14
+ "gpt": "ChatGPT میں کھولیں",
15
+ "claude": "Claude میں کھولیں"
16
+ },
17
+ "links": "کمیونٹی",
18
+ "toc": "اس صفحے پر",
19
+ "report": "مسئلہ کی اطلاع دیں",
20
+ "edit": "اس صفحے کو ترمیم کریں"
21
+ }
22
+ }
@@ -0,0 +1,22 @@
1
+ {
2
+ "common": {
3
+ "or": "hoặc",
4
+ "error": {
5
+ "title": "Không tìm thấy trang",
6
+ "description": "Chúng tôi xin lỗi, nhưng trang bạn đang tìm kiếm không tồn tại."
7
+ }
8
+ },
9
+ "docs": {
10
+ "copy": {
11
+ "page": "Sao chép trang",
12
+ "link": "Sao chép trang Markdown",
13
+ "view": "Xem dưới dạng Markdown",
14
+ "gpt": "Mở trong ChatGPT",
15
+ "claude": "Mở trong Claude"
16
+ },
17
+ "links": "Cộng đồng",
18
+ "toc": "Trên trang này",
19
+ "report": "Báo cáo sự cố",
20
+ "edit": "Chỉnh sửa trang này"
21
+ }
22
+ }
@@ -0,0 +1,116 @@
1
+ import { createResolver, defineNuxtModule } from '@nuxt/kit'
2
+ import { defu } from 'defu'
3
+ import { existsSync } from 'node:fs'
4
+ import { join } from 'node:path'
5
+ import { inferSiteURL, getPackageJsonMetadata } from '../utils/meta'
6
+ import { getGitBranch, getGitEnv, getLocalGitInfo } from '../utils/git'
7
+
8
+ export default defineNuxtModule({
9
+ meta: {
10
+ name: 'config',
11
+ },
12
+ async setup(_options, nuxt) {
13
+ const dir = nuxt.options.rootDir
14
+ const url = inferSiteURL()
15
+ const meta = await getPackageJsonMetadata(dir)
16
+ const gitInfo = await getLocalGitInfo(dir) || getGitEnv()
17
+ const siteName = nuxt.options?.site?.name || meta.name || gitInfo?.name || ''
18
+
19
+ nuxt.options.llms = defu(nuxt.options.llms, {
20
+ domain: url,
21
+ title: siteName,
22
+ description: meta.description || '',
23
+ full: {
24
+ title: siteName,
25
+ description: meta.description || '',
26
+ },
27
+ })
28
+
29
+ nuxt.options.site = defu(nuxt.options.site, {
30
+ url,
31
+ name: siteName,
32
+ debug: false,
33
+ })
34
+
35
+ nuxt.options.appConfig.header = defu(nuxt.options.appConfig.header, {
36
+ title: siteName,
37
+ })
38
+
39
+ nuxt.options.appConfig.seo = defu(nuxt.options.appConfig.seo, {
40
+ titleTemplate: `%s - ${siteName}`,
41
+ title: siteName,
42
+ description: meta.description || '',
43
+ })
44
+
45
+ nuxt.options.appConfig.github = defu(nuxt.options.appConfig.github, {
46
+ owner: gitInfo?.owner,
47
+ name: gitInfo?.name,
48
+ url: gitInfo?.url,
49
+ branch: getGitBranch(),
50
+ })
51
+
52
+ /*
53
+ ** I18N
54
+ */
55
+ if (nuxt.options.i18n && nuxt.options.i18n.locales) {
56
+ const { resolve } = createResolver(import.meta.url)
57
+
58
+ // Filter locales to only include existing ones
59
+ const filteredLocales = nuxt.options.i18n.locales.filter((locale) => {
60
+ const localeCode = typeof locale === 'string' ? locale : locale.code
61
+
62
+ // Check for JSON locale file
63
+ const localeFilePath = resolve('../i18n/locales', `${localeCode}.json`)
64
+ const hasLocaleFile = existsSync(localeFilePath)
65
+
66
+ // Check for content folder
67
+ const contentPath = join(nuxt.options.rootDir, 'content', localeCode)
68
+ const hasContentFolder = existsSync(contentPath)
69
+
70
+ if (!hasLocaleFile) {
71
+ console.warn(`[Docus] Locale file not found: ${localeCode}.json - skipping locale "${localeCode}"`)
72
+ }
73
+
74
+ if (!hasContentFolder) {
75
+ console.warn(`[Docus] Content folder not found: content/${localeCode}/ - skipping locale "${localeCode}"`)
76
+ }
77
+
78
+ return hasLocaleFile && hasContentFolder
79
+ })
80
+
81
+ // Override strategy to prefix
82
+ nuxt.options.i18n = {
83
+ ...nuxt.options.i18n,
84
+ strategy: 'prefix',
85
+ }
86
+
87
+ // Expose filtered locales
88
+ nuxt.options.runtimeConfig.public.docus = {
89
+ filteredLocales,
90
+ }
91
+
92
+ nuxt.hook('i18n:registerModule', (register) => {
93
+ const langDir = resolve('../i18n/locales')
94
+
95
+ const locales = filteredLocales?.map((locale) => {
96
+ return typeof locale === 'string'
97
+ ? {
98
+ code: locale,
99
+ name: locale,
100
+ file: `${locale}.json`,
101
+ }
102
+ : {
103
+ code: locale.code,
104
+ name: locale.name || locale.code,
105
+ file: `${locale.code}.json`,
106
+ }
107
+ })
108
+
109
+ register({
110
+ langDir,
111
+ locales,
112
+ })
113
+ })
114
+ }
115
+ },
116
+ })
package/modules/css.ts ADDED
@@ -0,0 +1,32 @@
1
+ import { defineNuxtModule, addTemplate, createResolver } from '@nuxt/kit'
2
+ import { joinURL } from 'ufo'
3
+ import { resolveModulePath } from 'exsolve'
4
+
5
+ export default defineNuxtModule({
6
+ meta: {
7
+ name: 'css',
8
+ },
9
+ async setup(_options, nuxt) {
10
+ const dir = nuxt.options.rootDir
11
+ const resolver = createResolver(import.meta.url)
12
+
13
+ const contentDir = joinURL(dir, 'content')
14
+ const uiPath = resolveModulePath('@nuxt/ui', { from: import.meta.url, conditions: ['style'] })
15
+ const tailwindPath = resolveModulePath('tailwindcss', { from: import.meta.url, conditions: ['style'] })
16
+ const layerDir = resolver.resolve('../app')
17
+
18
+ const cssTemplate = addTemplate({
19
+ filename: 'docus.css',
20
+ getContents: () => {
21
+ return `@import ${JSON.stringify(tailwindPath)};
22
+ @import ${JSON.stringify(uiPath)};
23
+
24
+ @source "${contentDir.replace(/\\/g, '/')}/**/*";
25
+ @source "${layerDir.replace(/\\/g, '/')}/**/*";
26
+ @source "../../app.config.ts";`
27
+ },
28
+ })
29
+
30
+ nuxt.options.css.unshift(cssTemplate.dst)
31
+ },
32
+ })
@@ -0,0 +1,41 @@
1
+ import { defineNuxtModule, extendPages, createResolver } from '@nuxt/kit'
2
+
3
+ export default defineNuxtModule({
4
+ meta: {
5
+ name: 'routing',
6
+ },
7
+ async setup(_options, nuxt) {
8
+ const { resolve } = createResolver(import.meta.url)
9
+
10
+ const isI18nEnabled = !!(nuxt.options.i18n && nuxt.options.i18n.locales)
11
+
12
+ // Ensure useDocusI18n is available in the app
13
+ nuxt.hook('imports:extend', (imports) => {
14
+ if (imports.some(i => i.name === 'useDocusI18n')) return
15
+
16
+ imports.push({
17
+ name: 'useDocusI18n',
18
+ from: resolve('../app/composables/useDocusI18n'),
19
+ })
20
+ })
21
+
22
+ extendPages((pages) => {
23
+ const landingTemplate = resolve('../app/templates/landing.vue')
24
+
25
+ if (isI18nEnabled) {
26
+ pages.push({
27
+ name: 'lang-index',
28
+ path: '/:lang?',
29
+ file: landingTemplate,
30
+ })
31
+ }
32
+ else {
33
+ pages.push({
34
+ name: 'index',
35
+ path: '/',
36
+ file: landingTemplate,
37
+ })
38
+ }
39
+ })
40
+ },
41
+ })
package/nuxt.config.ts ADDED
@@ -0,0 +1,84 @@
1
+ import { extendViteConfig, createResolver, useNuxt } from '@nuxt/kit'
2
+
3
+ const { resolve } = createResolver(import.meta.url)
4
+
5
+ export default defineNuxtConfig({
6
+ modules: [
7
+ resolve('./modules/config'),
8
+ resolve('./modules/routing'),
9
+ resolve('./modules/css'),
10
+ '@nuxt/ui',
11
+ '@nuxt/content',
12
+ '@nuxt/image',
13
+ '@nuxtjs/robots',
14
+ '@nuxtjs/mcp-toolkit',
15
+ 'nuxt-og-image',
16
+ 'nuxt-llms',
17
+ () => {
18
+ // Update @nuxt/content optimizeDeps options
19
+ extendViteConfig((config) => {
20
+ config.optimizeDeps ||= {}
21
+ config.optimizeDeps.include ||= []
22
+ config.optimizeDeps.include.push('@nuxt/content > slugify')
23
+ config.optimizeDeps.include = config.optimizeDeps.include
24
+ .map(id => id.replace(/^@nuxt\/content > /, 'docus > @nuxt/content > '))
25
+ })
26
+ },
27
+ ],
28
+ devtools: {
29
+ enabled: true,
30
+ },
31
+ content: {
32
+ build: {
33
+ markdown: {
34
+ highlight: {
35
+ langs: ['bash', 'diff', 'json', 'js', 'ts', 'html', 'css', 'vue', 'shell', 'mdc', 'md', 'yaml'],
36
+ },
37
+ remarkPlugins: {
38
+ 'remark-mdc': {
39
+ options: {
40
+ autoUnwrap: true,
41
+ },
42
+ },
43
+ },
44
+ },
45
+ },
46
+ },
47
+ experimental: {
48
+ asyncContext: true,
49
+ },
50
+ compatibilityDate: '2025-07-22',
51
+ nitro: {
52
+ prerender: {
53
+ crawlLinks: true,
54
+ failOnError: false,
55
+ autoSubfolderIndex: false,
56
+ },
57
+ compatibilityDate: {
58
+ // Don't generate observability routes for now
59
+ vercel: '2025-07-14',
60
+ },
61
+ },
62
+ hooks: {
63
+ 'nitro:config'(nitroConfig) {
64
+ const nuxt = useNuxt()
65
+
66
+ const i18nOptions = nuxt.options.i18n
67
+
68
+ const routes: string[] = []
69
+ if (!i18nOptions) {
70
+ routes.push('/')
71
+ }
72
+ else {
73
+ routes.push(...(i18nOptions.locales?.map(locale => typeof locale === 'string' ? `/${locale}` : `/${locale.code}`) || []))
74
+ }
75
+
76
+ nitroConfig.prerender = nitroConfig.prerender || {}
77
+ nitroConfig.prerender.routes = nitroConfig.prerender.routes || []
78
+ nitroConfig.prerender.routes.push(...(routes || []))
79
+ },
80
+ },
81
+ icon: {
82
+ provider: 'iconify',
83
+ },
84
+ })
package/nuxt.schema.ts ADDED
@@ -0,0 +1,218 @@
1
+ import { field, group } from '@nuxt/content/preview'
2
+
3
+ export default defineNuxtSchema({
4
+ appConfig: {
5
+ ui: group({
6
+ title: 'UI',
7
+ description: 'UI Customization.',
8
+ icon: 'i-lucide-palette',
9
+ fields: {
10
+ colors: group({
11
+ title: 'Colors',
12
+ description: 'Manage main colors of your application',
13
+ icon: 'i-lucide-palette',
14
+ fields: {
15
+ primary: field({
16
+ type: 'string',
17
+ title: 'Primary',
18
+ description: 'Primary color of your UI.',
19
+ icon: 'i-lucide-palette',
20
+ default: 'green',
21
+ required: ['red', 'orange', 'amber', 'yellow', 'lime', 'green', 'emerald', 'teal', 'cyan', 'sky', 'blue', 'indigo', 'violet', 'purple', 'fuchsia', 'pink', 'rose'],
22
+ }),
23
+ neutral: field({
24
+ type: 'string',
25
+ title: 'Neutral',
26
+ description: 'Neutral color of your UI.',
27
+ icon: 'i-lucide-palette',
28
+ default: 'slate',
29
+ required: ['slate', 'gray', 'zinc', 'neutral', 'stone'],
30
+ }),
31
+ },
32
+ }),
33
+ icons: group({
34
+ title: 'Icons',
35
+ description: 'Manage icons used in the application.',
36
+ icon: 'i-lucide-settings',
37
+ fields: {
38
+ search: field({
39
+ type: 'icon',
40
+ title: 'Search Bar',
41
+ description: 'Icon to display in the search bar.',
42
+ icon: 'i-lucide-search',
43
+ default: 'i-lucide-search',
44
+ }),
45
+ dark: field({
46
+ type: 'icon',
47
+ title: 'Dark mode',
48
+ description: 'Icon of color mode button for dark mode.',
49
+ icon: 'i-lucide-moon',
50
+ default: 'i-lucide-moon',
51
+ }),
52
+ light: field({
53
+ type: 'icon',
54
+ title: 'Light mode',
55
+ description: 'Icon of color mode button for light mode.',
56
+ icon: 'i-lucide-sun',
57
+ default: 'i-lucide-sun',
58
+ }),
59
+ external: field({
60
+ type: 'icon',
61
+ title: 'External Link',
62
+ description: 'Icon for external link.',
63
+ icon: 'i-lucide-external-link',
64
+ default: 'i-lucide-external-link',
65
+ }),
66
+ chevron: field({
67
+ type: 'icon',
68
+ title: 'Chevron',
69
+ description: 'Icon for chevron.',
70
+ icon: 'i-lucide-chevron-down',
71
+ default: 'i-lucide-chevron-down',
72
+ }),
73
+ hash: field({
74
+ type: 'icon',
75
+ title: 'Hash',
76
+ description: 'Icon for hash anchors.',
77
+ icon: 'i-lucide-hash',
78
+ default: 'i-lucide-hash',
79
+ }),
80
+ },
81
+ }),
82
+ },
83
+ }),
84
+ seo: group({
85
+ title: 'SEO',
86
+ description: 'SEO configuration.',
87
+ icon: 'i-lucide-search',
88
+ fields: {
89
+ title: field({
90
+ type: 'string',
91
+ title: 'Title',
92
+ description: 'Title to display in the header.',
93
+ icon: 'i-lucide-type',
94
+ default: '',
95
+ }),
96
+ description: field({
97
+ type: 'string',
98
+ title: 'Description',
99
+ description: 'Description to display in the header.',
100
+ icon: 'i-lucide-type',
101
+ default: '',
102
+ }),
103
+ },
104
+ }),
105
+ header: group({
106
+ title: 'Header',
107
+ description: 'Header configuration.',
108
+ icon: 'i-lucide-layout',
109
+ fields: {
110
+ title: field({
111
+ type: 'string',
112
+ title: 'Title',
113
+ description: 'Title to display in the header.',
114
+ icon: 'i-lucide-type',
115
+ default: '',
116
+ }),
117
+ logo: group({
118
+ title: 'Logo',
119
+ description: 'Header logo configuration.',
120
+ icon: 'i-lucide-image',
121
+ fields: {
122
+ light: field({
123
+ type: 'media',
124
+ title: 'Light Mode Logo',
125
+ description: 'Pick an image from your gallery.',
126
+ icon: 'i-lucide-sun',
127
+ default: '',
128
+ }),
129
+ dark: field({
130
+ type: 'media',
131
+ title: 'Dark Mode Logo',
132
+ description: 'Pick an image from your gallery.',
133
+ icon: 'i-lucide-moon',
134
+ default: '',
135
+ }),
136
+ alt: field({
137
+ type: 'string',
138
+ title: 'Alt',
139
+ description: 'Alt to display for accessibility.',
140
+ icon: 'i-lucide-text',
141
+ default: '',
142
+ }),
143
+ },
144
+ }),
145
+ },
146
+ }),
147
+ socials: field({
148
+ type: 'object',
149
+ title: 'Social Networks',
150
+ description: 'Social links configuration.',
151
+ icon: 'i-lucide-network',
152
+ default: {},
153
+ }),
154
+ toc: group({
155
+ title: 'Table of contents',
156
+ description: 'TOC configuration.',
157
+ icon: 'i-lucide-list',
158
+ fields: {
159
+ title: field({
160
+ type: 'string',
161
+ title: 'Title',
162
+ description: 'Title of the table of contents.',
163
+ icon: 'i-lucide-heading',
164
+ default: 'On this page',
165
+ }),
166
+ bottom: group({
167
+ title: 'Bottom',
168
+ description: 'Bottom section of the table of contents.',
169
+ icon: 'i-lucide-list',
170
+ fields: {
171
+ title: field({
172
+ type: 'string',
173
+ title: 'Title',
174
+ description: 'Title of the bottom section.',
175
+ icon: 'i-lucide-heading',
176
+ default: 'Community',
177
+ }),
178
+ links: field({
179
+ type: 'array',
180
+ title: 'Links',
181
+ description: 'Links to display in the bottom section.',
182
+ icon: 'i-lucide-link',
183
+ default: [],
184
+ }),
185
+ },
186
+ }),
187
+ },
188
+ }),
189
+ github: group({
190
+ title: 'GitHub',
191
+ description: 'GitHub configuration.',
192
+ icon: 'i-simple-icons-github',
193
+ fields: {
194
+ url: field({
195
+ type: 'string',
196
+ title: 'URL',
197
+ description: 'GitHub URL.',
198
+ icon: 'i-simple-icons-github',
199
+ default: '',
200
+ }),
201
+ branch: field({
202
+ type: 'string',
203
+ title: 'Branch',
204
+ description: 'GitHub branch.',
205
+ icon: 'i-lucide-git-branch',
206
+ default: 'main',
207
+ }),
208
+ rootDir: field({
209
+ type: 'string',
210
+ title: 'Root Directory',
211
+ description: 'Root directory of the GitHub repository.',
212
+ icon: 'i-lucide-folder',
213
+ default: '',
214
+ }),
215
+ },
216
+ }),
217
+ },
218
+ })