@movk/nuxt-docs 1.16.1 → 1.16.3

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/app/app.config.ts CHANGED
@@ -22,7 +22,6 @@ export default defineAppConfig({
22
22
  },
23
23
  header: {
24
24
  avatar: 'https://docs.mhaibaraai.cn/avatar.png',
25
- title: 'Movk Nuxt Docs',
26
25
  to: '/',
27
26
  search: true,
28
27
  colorMode: true,
@@ -13,9 +13,9 @@ const showExplainWithAi = computed(() => {
13
13
  <template>
14
14
  <UButton
15
15
  v-if="showExplainWithAi"
16
- :icon="aiChat.icons.explain"
16
+ :icon="aiChat.icons?.explain ?? ''"
17
17
  target="_blank"
18
- :label="aiChat.texts.explainWithAi"
18
+ :label="aiChat.texts?.explainWithAi ?? ''"
19
19
  size="sm"
20
20
  variant="ghost"
21
21
  color="neutral"
@@ -4,7 +4,7 @@ import type { ButtonProps } from '@nuxt/ui'
4
4
  const route = useRoute()
5
5
  const { header, github } = useAppConfig()
6
6
 
7
- const links = computed<ButtonProps[]>(() => github && github.url
7
+ const links = computed<ButtonProps[]>(() => (github && github.url
8
8
  ? [
9
9
  {
10
10
  'icon': 'i-simple-icons-github',
@@ -12,9 +12,9 @@ const links = computed<ButtonProps[]>(() => github && github.url
12
12
  'target': '_blank',
13
13
  'aria-label': 'GitHub'
14
14
  },
15
- ...header?.links || []
15
+ ...(header?.links || [])
16
16
  ]
17
- : header.links)
17
+ : header?.links || []) as ButtonProps[])
18
18
  </script>
19
19
 
20
20
  <template>
@@ -4,12 +4,12 @@ const { toggleChat } = useAIChat()
4
4
  </script>
5
5
 
6
6
  <template>
7
- <UTooltip :text="aiChat.texts.trigger">
7
+ <UTooltip :text="aiChat.texts?.trigger ?? ''">
8
8
  <UButton
9
- :icon="aiChat.icons.trigger"
9
+ :icon="aiChat.icons?.trigger ?? ''"
10
10
  variant="ghost"
11
11
  class="rounded-full"
12
- :aria-label="aiChat.texts.trigger"
12
+ :aria-label="aiChat.texts?.trigger ?? ''"
13
13
  @click="toggleChat"
14
14
  />
15
15
  </UTooltip>
@@ -12,7 +12,7 @@ const inputRef = ref<{ inputRef: HTMLInputElement } | null>(null)
12
12
 
13
13
  const isDocsRoute = computed(() => route.meta.layout === 'docs')
14
14
  const isFloatingInputEnabled = computed(() => aiChat.floatingInput !== false)
15
- const focusInputShortcut = computed(() => aiChat.shortcuts.focusInput)
15
+ const focusInputShortcut = computed(() => aiChat.shortcuts?.focusInput ?? 'meta_i')
16
16
 
17
17
  const shortcutDisplayKeys = computed(() => {
18
18
  const shortcut = focusInputShortcut.value
@@ -72,7 +72,7 @@ defineShortcuts(shortcuts)
72
72
  <UInput
73
73
  ref="inputRef"
74
74
  v-model="input"
75
- :placeholder="aiChat.texts.placeholder"
75
+ :placeholder="aiChat.texts?.placeholder ?? ''"
76
76
  size="lg"
77
77
  maxlength="1000"
78
78
  :ui="{
@@ -159,30 +159,30 @@ const faqQuestions = computed<FaqCategory[]>(() => {
159
159
  <USidebar
160
160
  v-model:open="isOpen"
161
161
  side="right"
162
- :title="aiChat.texts.title"
162
+ :title="aiChat.texts?.title ?? ''"
163
163
  rail
164
164
  :style="{ '--sidebar-width': '24rem' }"
165
165
  :ui="{ footer: 'p-0', actions: 'gap-0.5' }"
166
166
  >
167
167
  <template #actions>
168
- <UTooltip v-if="canClear" :text="aiChat.texts.clearChat">
168
+ <UTooltip v-if="canClear" :text="aiChat.texts?.clearChat ?? ''">
169
169
  <UButton
170
- :icon="aiChat.icons.clearChat"
170
+ :icon="aiChat.icons?.clearChat ?? ''"
171
171
  color="neutral"
172
172
  variant="ghost"
173
- :aria-label="aiChat.texts.clearChat"
173
+ :aria-label="aiChat.texts?.clearChat ?? ''"
174
174
  @click="clearMessages"
175
175
  />
176
176
  </UTooltip>
177
177
  </template>
178
178
 
179
179
  <template #close>
180
- <UTooltip :text="aiChat.texts.close">
180
+ <UTooltip :text="aiChat.texts?.close ?? ''">
181
181
  <UButton
182
- :icon="aiChat.icons.close"
182
+ :icon="aiChat.icons?.close ?? ''"
183
183
  color="neutral"
184
184
  variant="ghost"
185
- :aria-label="aiChat.texts.close"
185
+ :aria-label="aiChat.texts?.close ?? ''"
186
186
  @click="isOpen = false"
187
187
  />
188
188
  </UTooltip>
@@ -221,7 +221,7 @@ const faqQuestions = computed<FaqCategory[]>(() => {
221
221
  v-if="isReasoningUIPart(part)"
222
222
  :text="part.text"
223
223
  :streaming="isReasoningStreaming(message, index, chat)"
224
- :icon="aiChat.icons.reasoning"
224
+ :icon="aiChat.icons?.reasoning ?? ''"
225
225
  >
226
226
  <MDCCached
227
227
  :value="part.text"
@@ -262,7 +262,7 @@ const faqQuestions = computed<FaqCategory[]>(() => {
262
262
  <UChatPrompt
263
263
  v-model="input"
264
264
  :error="chat.error"
265
- :placeholder="aiChat.texts.placeholder"
265
+ :placeholder="aiChat.texts?.placeholder ?? ''"
266
266
  variant="naked"
267
267
  size="sm"
268
268
  autofocus
@@ -275,7 +275,7 @@ const faqQuestions = computed<FaqCategory[]>(() => {
275
275
  <AiChatModelSelect v-model="model" />
276
276
 
277
277
  <div class="flex gap-1 justify-between items-center px-1 text-xs text-muted">
278
- <span>{{ aiChat.texts.lineBreak }}</span>
278
+ <span>{{ aiChat.texts?.lineBreak ?? '' }}</span>
279
279
  <UKbd value="shift" />
280
280
  <UKbd value="enter" />
281
281
  </div>
@@ -3,7 +3,7 @@ export function useModels() {
3
3
  const model = useCookie<string>('model', { default: () => config.public.aiChat.model })
4
4
 
5
5
  const { aiChat } = useAppConfig()
6
- const providerIcons = computed(() => aiChat.icons.providers || {})
6
+ const providerIcons = computed(() => (aiChat.icons?.providers ?? {}) as Record<string, string>)
7
7
 
8
8
  function getModelIcon(modelId: string): string {
9
9
  const provider = modelId.split('/')[0] || ''
package/modules/module.ts CHANGED
@@ -1,5 +1,11 @@
1
1
  import { addComponentsDir, createResolver, defineNuxtModule, logger } from '@nuxt/kit'
2
2
  import type { ModuleDependencies } from 'nuxt/schema'
3
+ import { defu } from 'defu'
4
+ import { getGitBranch, getGitEnv, getLocalGitInfo } from '../utils/git'
5
+ import { getPackageJsonMetadata, inferSiteURL } from '../utils/meta'
6
+ import { createComponentMetaExcludeFilters } from '../utils/component-meta'
7
+ import { startCase, kebabCase } from '@movk/core'
8
+ import { updateSiteConfig } from 'nuxt-site-config/kit'
3
9
 
4
10
  export interface ModuleOptions {
5
11
  /**
@@ -29,17 +35,23 @@ export default defineNuxtModule<ModuleOptions>({
29
35
  },
30
36
  moduleDependencies(nuxt): ModuleDependencies {
31
37
  const userOptions = nuxt.options.movkNuxtDocs || {}
38
+
32
39
  return {
33
40
  ...userOptions.a11y !== false && {
34
41
  '@nuxt/a11y': {
35
- version: '^1.0.0-alpha.1'
42
+ version: '^1.0.0-alpha.1',
43
+ defaults: {
44
+ logIssues: false
45
+ }
36
46
  }
37
47
  }
38
48
  }
39
49
  },
40
- setup(options, nuxt) {
50
+ async setup(options, nuxt) {
41
51
  const { resolve } = createResolver(import.meta.url)
42
52
 
53
+ nuxt.options.alias['#ai-chat'] = resolve('./ai-chat/runtime')
54
+
43
55
  if (options.mermaid) {
44
56
  let mermaidAvailable = true
45
57
  try {
@@ -93,6 +105,74 @@ export default defineNuxtModule<ModuleOptions>({
93
105
  log.info('mermaid diagram support enabled')
94
106
  }
95
107
  }
108
+
109
+ const dir = nuxt.options.rootDir
110
+ const url = inferSiteURL()
111
+ const meta = await getPackageJsonMetadata(dir)
112
+ const gitInfo = await getLocalGitInfo(dir) || getGitEnv()
113
+
114
+ const site = defu(nuxt.options.site, {
115
+ url,
116
+ name: kebabCase(meta.name || gitInfo?.name || ''),
117
+ debug: false
118
+ })
119
+ updateSiteConfig(site)
120
+
121
+ const siteName = (typeof nuxt.options.site === 'object' && nuxt.options.site?.name) || meta.name || gitInfo?.name || ''
122
+
123
+ nuxt.options.llms = defu(nuxt.options.llms, {
124
+ domain: url || 'https://example.com',
125
+ title: siteName,
126
+ description: meta.description || '',
127
+ full: {
128
+ title: siteName,
129
+ description: meta.description || ''
130
+ }
131
+ })
132
+
133
+ nuxt.options.appConfig.header = defu(nuxt.options.appConfig.header, {
134
+ title: startCase(siteName)
135
+ })
136
+
137
+ nuxt.options.appConfig.seo = defu(nuxt.options.appConfig.seo, {
138
+ titleTemplate: `%s - ${siteName}`,
139
+ title: siteName,
140
+ description: meta.description || ''
141
+ })
142
+
143
+ nuxt.options.appConfig.github = defu(nuxt.options.appConfig.github, {
144
+ owner: gitInfo?.owner,
145
+ name: gitInfo?.name,
146
+ url: gitInfo?.url,
147
+ commitPath: 'src',
148
+ suffix: 'vue',
149
+ since: '2025-01-31T04:00:00Z',
150
+ branch: getGitBranch(),
151
+ per_page: 100,
152
+ until: new Date().toISOString()
153
+ })
154
+
155
+ const layerPath = resolve('..')
156
+
157
+ // @ts-ignore - component-meta is not typed
158
+ nuxt.hook('component-meta:extend', (options: any) => {
159
+ const userInclude = (nuxt.options.componentMeta && typeof nuxt.options.componentMeta === 'object')
160
+ ? nuxt.options.componentMeta.include || []
161
+ : []
162
+
163
+ options.exclude = [
164
+ ...(options.exclude || []),
165
+ ...createComponentMetaExcludeFilters(resolve, dir, layerPath, userInclude)
166
+ ]
167
+ })
168
+
169
+ nuxt.hook('nitro:config', (nitroConfig) => {
170
+ nitroConfig.publicAssets ||= []
171
+ nitroConfig.publicAssets.push({
172
+ dir: resolve('./runtime/public'),
173
+ maxAge: 60 * 60 * 24 * 30
174
+ })
175
+ })
96
176
  }
97
177
  })
98
178
 
package/nuxt.config.ts CHANGED
@@ -145,10 +145,6 @@ export default defineNuxtConfig({
145
145
  }
146
146
  },
147
147
 
148
- a11y: {
149
- logIssues: false
150
- },
151
-
152
148
  componentMeta: {
153
149
  metaFields: {
154
150
  type: false,
@@ -198,5 +194,15 @@ export default defineNuxtConfig({
198
194
 
199
195
  ogImage: {
200
196
  zeroRuntime: true
197
+ },
198
+
199
+ robots: {
200
+ groups: [
201
+ {
202
+ userAgent: '*',
203
+ allow: '/'
204
+ }
205
+ ],
206
+ sitemap: '/sitemap.xml'
201
207
  }
202
208
  })
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@movk/nuxt-docs",
3
3
  "type": "module",
4
- "version": "1.16.1",
4
+ "version": "1.16.3",
5
5
  "private": false,
6
6
  "description": "Modern Nuxt 4 documentation theme with auto-generated component docs, AI chat assistant, MCP server, and complete developer experience optimization.",
7
7
  "author": "YiXuan <mhaibaraai@gmail.com>",
@@ -71,6 +71,7 @@
71
71
  "nuxt-component-meta": "^0.17.2",
72
72
  "nuxt-llms": "^0.2.0",
73
73
  "nuxt-og-image": "^6.3.0",
74
+ "nuxt-site-config": "^4.0.7",
74
75
  "ohash": "^2.0.11",
75
76
  "pathe": "^2.0.3",
76
77
  "pkg-types": "^2.3.0",
@@ -32,9 +32,9 @@ export default defineCachedEventHandler(async (event) => {
32
32
  const allCommits = await Promise.all(
33
33
  paths.map(path =>
34
34
  octokit.rest.repos.listCommits({
35
- sha: github.branch,
36
- owner: github.owner,
37
- repo: github.name,
35
+ sha: github.branch!,
36
+ owner: github.owner!,
37
+ repo: github.name!,
38
38
  path,
39
39
  since: github.since,
40
40
  per_page: github.per_page || 100,
@@ -29,9 +29,9 @@ export default defineCachedEventHandler(async (event) => {
29
29
 
30
30
  try {
31
31
  const commits = await octokit.rest.repos.listCommits({
32
- sha: github.branch,
33
- owner: github.owner,
34
- repo: github.name,
32
+ sha: github.branch!,
33
+ owner: github.owner!,
34
+ repo: github.name!,
35
35
  path,
36
36
  per_page: 1
37
37
  }).then(res => res.data).catch(() => [])
@@ -58,8 +58,8 @@ export default defineCachedEventHandler(async (event) => {
58
58
  const prMatch = commit.commit.message.match(/#(\d+)/)
59
59
  if (prMatch?.[1]) {
60
60
  const prData = await octokit.rest.pulls.get({
61
- owner: github.owner,
62
- repo: github.name,
61
+ owner: github.owner!,
62
+ repo: github.name!,
63
63
  pull_number: Number.parseInt(prMatch[1])
64
64
  }).then(res => res.data).catch(() => null)
65
65
 
@@ -17,8 +17,8 @@ export default defineCachedEventHandler(async () => {
17
17
  const octokit = new Octokit({ auth: process.env.NUXT_GITHUB_TOKEN })
18
18
 
19
19
  const releases = await octokit.rest.repos.listReleases({
20
- owner: github.owner,
21
- repo: github.name
20
+ owner: github.owner!,
21
+ repo: github.name!
22
22
  }).then(res => res.data).catch(() => [])
23
23
 
24
24
  return releases
package/modules/config.ts DELETED
@@ -1,84 +0,0 @@
1
- import { createResolver, defineNuxtModule } from '@nuxt/kit'
2
- import { defu } from 'defu'
3
- import { getGitBranch, getGitEnv, getLocalGitInfo } from '../utils/git'
4
- import { getPackageJsonMetadata, inferSiteURL } from '../utils/meta'
5
- import { createComponentMetaExcludeFilters } from '../utils/component-meta'
6
-
7
- export default defineNuxtModule({
8
- meta: {
9
- name: 'config'
10
- },
11
- async setup(_options, nuxt) {
12
- const { resolve } = createResolver(import.meta.url)
13
-
14
- nuxt.options.alias['#ai-chat'] = resolve('./ai-chat/runtime')
15
-
16
- const dir = nuxt.options.rootDir
17
- const url = inferSiteURL()
18
- const meta = await getPackageJsonMetadata(dir)
19
- const gitInfo = await getLocalGitInfo(dir) || getGitEnv()
20
-
21
- const site = nuxt.options.site
22
- const siteName = (site && site.name) || meta.name || gitInfo?.name || ''
23
-
24
- nuxt.options.site = defu(nuxt.options.site, {
25
- url,
26
- name: siteName,
27
- debug: false
28
- })
29
-
30
- nuxt.options.llms = defu(nuxt.options.llms, {
31
- domain: url || 'https://example.com',
32
- title: siteName,
33
- description: meta.description || '',
34
- full: {
35
- title: siteName,
36
- description: meta.description || ''
37
- }
38
- })
39
-
40
- nuxt.options.appConfig.header = defu(nuxt.options.appConfig.header, {
41
- title: siteName
42
- })
43
-
44
- nuxt.options.appConfig.seo = defu(nuxt.options.appConfig.seo, {
45
- titleTemplate: `%s - ${siteName}`,
46
- title: siteName,
47
- description: meta.description || ''
48
- })
49
-
50
- nuxt.options.appConfig.github = defu(nuxt.options.appConfig.github, {
51
- owner: gitInfo?.owner,
52
- name: gitInfo?.name,
53
- url: gitInfo?.url,
54
- commitPath: 'src',
55
- suffix: 'vue',
56
- since: '2025-01-31T04:00:00Z',
57
- branch: getGitBranch(),
58
- per_page: 100,
59
- until: new Date().toISOString()
60
- })
61
-
62
- const layerPath = resolve('..')
63
-
64
- // @ts-ignore - component-meta is not typed
65
- nuxt.hook('component-meta:extend', (options: any) => {
66
- const userInclude = (nuxt.options.componentMeta && typeof nuxt.options.componentMeta === 'object')
67
- ? nuxt.options.componentMeta.include || []
68
- : []
69
-
70
- options.exclude = [
71
- ...(options.exclude || []),
72
- ...createComponentMetaExcludeFilters(resolve, dir, layerPath, userInclude)
73
- ]
74
- })
75
-
76
- nuxt.hook('nitro:config', (nitroConfig) => {
77
- nitroConfig.publicAssets ||= []
78
- nitroConfig.publicAssets.push({
79
- dir: resolve('./runtime/public'),
80
- maxAge: 60 * 60 * 24 * 30
81
- })
82
- })
83
- }
84
- })