@movk/nuxt-docs 1.4.0 → 1.4.1

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 CHANGED
@@ -159,47 +159,6 @@ icon: i-lucide-rocket
159
159
 
160
160
  了解更多关于 MDC 语法,请查看 [Nuxt Content 文档](https://content.nuxt.com/docs/files/markdown#mdc-syntax)。
161
161
 
162
- ## 🔌 集成第三方服务
163
-
164
- 本主题不内置任何分析或监控工具,你可以根据需求自由选择。
165
-
166
- ### Vercel Analytics
167
-
168
- ```bash [Terminal]
169
- pnpm add @vercel/analytics @vercel/speed-insights
170
- ```
171
-
172
- 创建 `app/plugins/analytics.client.ts`:
173
-
174
- ```typescript [app/plugins/analytics.client.ts]
175
- import { Analytics } from '@vercel/analytics/nuxt'
176
- import { SpeedInsights } from '@vercel/speed-insights/nuxt'
177
- import { createApp, h } from 'vue'
178
-
179
- export default defineNuxtPlugin({
180
- name: 'vercel-analytics',
181
- enforce: 'post',
182
- hooks: {
183
- 'app:mounted': () => {
184
- if (import.meta.dev) return
185
-
186
- const container = document.createElement('div')
187
- container.id = 'vercel-analytics'
188
- document.body.appendChild(container)
189
-
190
- const app = createApp({
191
- render: () => h('div', { style: 'display: none;' }, [
192
- h(Analytics, { debug: false }),
193
- h(SpeedInsights, { debug: false })
194
- ])
195
- })
196
-
197
- app.mount(container)
198
- }
199
- }
200
- })
201
- ```
202
-
203
162
  ### 其他工具
204
163
 
205
164
  - **Google Analytics** - [@nuxtjs/google-analytics](https://google-analytics.nuxtjs.org/)
package/app/app.config.ts CHANGED
@@ -34,7 +34,9 @@ export default defineAppConfig({
34
34
  }
35
35
  }
36
36
  },
37
+ vercelAnalytics: false,
37
38
  header: {
39
+ avatar: 'https://docs.mhaibaraai.cn/avatar.png',
38
40
  title: 'Movk Nuxt Docs',
39
41
  to: '/',
40
42
  search: true,
package/app/app.vue CHANGED
@@ -1,5 +1,7 @@
1
1
  <script setup lang="ts">
2
2
  import colors from 'tailwindcss/colors'
3
+ import { Analytics } from '@vercel/analytics/nuxt'
4
+ import { SpeedInsights } from '@vercel/speed-insights/nuxt'
3
5
 
4
6
  const site = useSiteConfig()
5
7
  const appConfig = useAppConfig()
@@ -43,6 +45,8 @@ provide('navigation', rootNavigation)
43
45
  <template>
44
46
  <UApp :toaster="appConfig.toaster">
45
47
  <NuxtLoadingIndicator color="var(--ui-primary)" :height="2" />
48
+ <Analytics v-if="appConfig.vercelAnalytics" />
49
+ <SpeedInsights v-if="appConfig.vercelAnalytics" />
46
50
 
47
51
  <div :class="{ root: route.path.startsWith('/docs/') }">
48
52
  <template v-if="!route.path.startsWith('/examples')">
@@ -3,6 +3,8 @@ const route = useRoute()
3
3
  const toast = useToast()
4
4
  const { copy, copied } = useClipboard()
5
5
  const site = useSiteConfig()
6
+ const { vercelAnalytics } = useAppConfig()
7
+ const { track } = useAnalytics()
6
8
 
7
9
  const mdPath = computed(() => `${site.url}/raw${route.path}.md`)
8
10
 
@@ -11,6 +13,7 @@ const items = [
11
13
  label: 'Copy Markdown link',
12
14
  icon: 'i-lucide-link',
13
15
  onSelect() {
16
+ if (vercelAnalytics) track ('Page Action', { action: 'Copy Markdown Link' })
14
17
  copy(mdPath.value)
15
18
  toast.add({
16
19
  title: 'Copied to clipboard',
@@ -22,23 +25,33 @@ const items = [
22
25
  label: 'View as Markdown',
23
26
  icon: 'i-simple-icons:markdown',
24
27
  target: '_blank',
25
- to: `/raw${route.path}.md`
28
+ to: `/raw${route.path}.md`,
29
+ onSelect() {
30
+ if (vercelAnalytics) track('Page Action', { action: 'View as Markdown' })
31
+ }
26
32
  },
27
33
  {
28
34
  label: 'Open in ChatGPT',
29
35
  icon: 'i-simple-icons:openai',
30
36
  target: '_blank',
31
- to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
37
+ to: `https://chatgpt.com/?hints=search&q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`,
38
+ onSelect() {
39
+ if (vercelAnalytics) track('Page Action', { action: 'Open in ChatGPT' })
40
+ }
32
41
  },
33
42
  {
34
43
  label: 'Open in Claude',
35
44
  icon: 'i-simple-icons:anthropic',
36
45
  target: '_blank',
37
- to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`
46
+ to: `https://claude.ai/new?q=${encodeURIComponent(`Read ${mdPath.value} so I can ask questions about it.`)}`,
47
+ onSelect() {
48
+ if (vercelAnalytics) track('Page Action', { action: 'Open in Claude' })
49
+ }
38
50
  }
39
51
  ]
40
52
 
41
53
  async function copyPage() {
54
+ if (vercelAnalytics) track('Page Action', { action: 'Copy Page Content' })
42
55
  copy(await $fetch<string>(`/raw${route.path}.md`))
43
56
  }
44
57
  </script>
@@ -1,5 +1,9 @@
1
+ <script lang="ts" setup>
2
+ const { header } = useAppConfig()
3
+ </script>
4
+
1
5
  <template>
2
- <NuxtLink to="/">
3
- <UUser :avatar="{ src: 'https://docs.mhaibaraai.cn/avatar.png' }" name="Movk Nuxt Docs" />
6
+ <NuxtLink :to="header.to">
7
+ <UUser :avatar="{ src: header.avatar }" :name="header.title" />
4
8
  </NuxtLink>
5
9
  </template>
@@ -8,6 +8,16 @@ const appConfig = useAppConfig()
8
8
  const colorMode = useColorMode()
9
9
  const site = useSiteConfig()
10
10
 
11
+ const { track } = useAnalytics()
12
+
13
+ const open = ref(false)
14
+
15
+ watch(open, (isOpen) => {
16
+ if (isOpen && appConfig.vercelAnalytics) {
17
+ track('Theme Picker Opened')
18
+ }
19
+ })
20
+
11
21
  const { copy: copyCSS, copied: copiedCSS } = useClipboard()
12
22
  const { copy: copyAppConfig, copied: copiedAppConfig } = useClipboard()
13
23
 
@@ -19,6 +29,7 @@ const neutral = computed({
19
29
  set(option) {
20
30
  appConfig.ui.colors.neutral = option
21
31
  window.localStorage.setItem(`${site.name}-ui-neutral`, appConfig.ui.colors.neutral)
32
+ if (appConfig.vercelAnalytics) track('Theme Changed', { setting: 'neutral', value: option })
22
33
  }
23
34
  })
24
35
 
@@ -32,6 +43,7 @@ const primary = computed({
32
43
  appConfig.ui.colors.primary = option
33
44
  window.localStorage.setItem(`${site.name}-ui-primary`, appConfig.ui.colors.primary)
34
45
  setBlackAsPrimary(false)
46
+ if (appConfig.vercelAnalytics) track('Theme Changed', { setting: 'primary', value: option })
35
47
  }
36
48
  })
37
49
 
@@ -43,6 +55,7 @@ const radius = computed({
43
55
  set(option) {
44
56
  appConfig.theme.radius = option
45
57
  window.localStorage.setItem(`${site.name}-ui-radius`, String(appConfig.theme.radius))
58
+ if (appConfig.vercelAnalytics) track('Theme Changed', { setting: 'radius', value: option })
46
59
  }
47
60
  })
48
61
 
@@ -57,12 +70,14 @@ const mode = computed({
57
70
  },
58
71
  set(option) {
59
72
  colorMode.preference = option
73
+ if (appConfig.vercelAnalytics) track('Theme Changed', { setting: 'color mode', value: option })
60
74
  }
61
75
  })
62
76
 
63
77
  function setBlackAsPrimary(value: boolean) {
64
78
  appConfig.theme.blackAsPrimary = value
65
79
  window.localStorage.setItem(`${site.name}-ui-black-as-primary`, String(value))
80
+ if (appConfig.vercelAnalytics) track('Theme Changed', { setting: 'black as primary', value })
66
81
  }
67
82
 
68
83
  const fonts = ['Public Sans', 'DM Sans', 'Geist', 'Inter', 'Poppins', 'Outfit', 'Raleway']
@@ -73,6 +88,7 @@ const font = computed({
73
88
  set(option) {
74
89
  appConfig.theme.font = option
75
90
  window.localStorage.setItem(`${site.name}-ui-font`, appConfig.theme.font)
91
+ if (appConfig.vercelAnalytics) track('Theme Changed', { setting: 'font', value: option })
76
92
  }
77
93
  })
78
94
 
@@ -97,6 +113,7 @@ const icon = computed({
97
113
  appConfig.theme.icons = option
98
114
  appConfig.ui.icons = themeIcons[option as keyof typeof themeIcons] as any
99
115
  window.localStorage.setItem(`${site.name}-ui-icons`, appConfig.theme.icons)
116
+ if (appConfig.vercelAnalytics) track('Theme Changed', { setting: 'icons', value: option })
100
117
  }
101
118
  })
102
119
 
@@ -113,6 +130,8 @@ const hasAppConfigChanges = computed(() => {
113
130
  })
114
131
 
115
132
  function exportCSS() {
133
+ if (appConfig.vercelAnalytics) track('Theme Exported', { type: 'css' })
134
+
116
135
  const lines = [
117
136
  '@import "tailwindcss";',
118
137
  '@import "@nuxt/ui";'
@@ -142,6 +161,8 @@ function exportCSS() {
142
161
  }
143
162
 
144
163
  function exportAppConfig() {
164
+ if (appConfig.vercelAnalytics) track('Theme Exported', { type: 'appConfig' })
165
+
145
166
  const config: Record<string, any> = {}
146
167
 
147
168
  if (appConfig.ui.colors.primary !== 'green' || appConfig.ui.colors.neutral !== 'slate') {
@@ -171,25 +192,33 @@ function exportAppConfig() {
171
192
  }
172
193
 
173
194
  function resetTheme() {
174
- primary.value = 'green'
175
- neutral.value = 'slate'
176
- radius.value = 0.25
177
- font.value = 'Public Sans'
178
- icon.value = 'lucide'
179
- setBlackAsPrimary(false)
195
+ if (appConfig.vercelAnalytics) track('Theme Reset')
180
196
 
197
+ // Reset without triggering individual tracking events
198
+ appConfig.ui.colors.primary = 'green'
181
199
  window.localStorage.removeItem(`${site.name}-ui-primary`)
200
+
201
+ appConfig.ui.colors.neutral = 'slate'
182
202
  window.localStorage.removeItem(`${site.name}-ui-neutral`)
203
+
204
+ appConfig.theme.radius = 0.25
183
205
  window.localStorage.removeItem(`${site.name}-ui-radius`)
206
+
207
+ appConfig.theme.font = 'Public Sans'
184
208
  window.localStorage.removeItem(`${site.name}-ui-font`)
209
+
210
+ appConfig.theme.icons = 'lucide'
211
+ appConfig.ui.icons = themeIcons.lucide as any
185
212
  window.localStorage.removeItem(`${site.name}-ui-icons`)
213
+
214
+ appConfig.theme.blackAsPrimary = false
186
215
  window.localStorage.removeItem(`${site.name}-ui-black-as-primary`)
187
216
  }
188
217
  </script>
189
218
 
190
219
  <template>
191
- <UPopover :ui="{ content: 'w-72 px-6 py-4 flex flex-col gap-4 overflow-y-auto max-h-[calc(100vh-5rem)]' }">
192
- <template #default="{ open }">
220
+ <UPopover v-model:open="open" :ui="{ content: 'w-72 px-6 py-4 flex flex-col gap-4 overflow-y-auto max-h-[calc(100vh-5rem)]' }">
221
+ <template #default>
193
222
  <UButton
194
223
  icon="i-lucide-swatch-book"
195
224
  color="neutral"
@@ -0,0 +1,7 @@
1
+ import { track } from '@vercel/analytics'
2
+
3
+ export function useAnalytics() {
4
+ return {
5
+ track
6
+ }
7
+ }
@@ -2,6 +2,7 @@ import type { ButtonProps } from '@nuxt/ui'
2
2
 
3
3
  declare module 'nuxt/schema' {
4
4
  interface AppConfig {
5
+ vercelAnalytics: boolean
5
6
  seo: {
6
7
  titleTemplate: string
7
8
  title: string
@@ -9,6 +10,7 @@ declare module 'nuxt/schema' {
9
10
  }
10
11
  header: {
11
12
  title: string
13
+ avatar: string
12
14
  to: string
13
15
  search: boolean
14
16
  colorMode: boolean
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@movk/nuxt-docs",
3
3
  "type": "module",
4
- "version": "1.4.0",
4
+ "version": "1.4.1",
5
5
  "private": false,
6
6
  "description": "An elegant documentation theme for Nuxt, powered by Nuxt UI and Nuxt Content.",
7
7
  "author": "YiXuan <mhaibaraai@gmail.com>",
@@ -37,6 +37,8 @@
37
37
  "@nuxt/ui": "^4.3.0",
38
38
  "@nuxtjs/seo": "^3.3.0",
39
39
  "@octokit/rest": "^22.0.1",
40
+ "@vercel/analytics": "^1.6.1",
41
+ "@vercel/speed-insights": "^1.3.1",
40
42
  "@vueuse/core": "^14.1.0",
41
43
  "@vueuse/nuxt": "^14.1.0",
42
44
  "defu": "^6.1.4",