@movk/nuxt-docs 1.4.0 → 1.4.2
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 +0 -41
- package/app/app.config.ts +5 -0
- package/app/app.vue +4 -0
- package/app/components/PageHeaderLinks.vue +16 -3
- package/app/components/header/HeaderLogo.vue +6 -2
- package/app/components/theme-picker/ThemePicker.vue +37 -8
- package/app/composables/useAnalytics.ts +7 -0
- package/app/types/index.d.ts +7 -2
- package/package.json +3 -1
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
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" :debug="appConfig.vercelAnalytics?.debug" />
|
|
49
|
+
<SpeedInsights v-if="appConfig.vercelAnalytics" :debug="appConfig.vercelAnalytics?.debug" />
|
|
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?.debug) 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?.debug) 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?.debug) 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?.debug) track('Page Action', { action: 'Open in Claude' })
|
|
49
|
+
}
|
|
38
50
|
}
|
|
39
51
|
]
|
|
40
52
|
|
|
41
53
|
async function copyPage() {
|
|
54
|
+
if (vercelAnalytics?.debug) 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:
|
|
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?.debug) {
|
|
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?.debug) 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?.debug) 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?.debug) 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?.debug) 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?.debug) 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?.debug) 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?.debug) 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?.debug) 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?.debug) 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
|
-
|
|
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?.debug) 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
|
|
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"
|
package/app/types/index.d.ts
CHANGED
|
@@ -2,6 +2,10 @@ import type { ButtonProps } from '@nuxt/ui'
|
|
|
2
2
|
|
|
3
3
|
declare module 'nuxt/schema' {
|
|
4
4
|
interface AppConfig {
|
|
5
|
+
vercelAnalytics: {
|
|
6
|
+
enable: boolean
|
|
7
|
+
debug: boolean
|
|
8
|
+
}
|
|
5
9
|
seo: {
|
|
6
10
|
titleTemplate: string
|
|
7
11
|
title: string
|
|
@@ -9,6 +13,7 @@ declare module 'nuxt/schema' {
|
|
|
9
13
|
}
|
|
10
14
|
header: {
|
|
11
15
|
title: string
|
|
16
|
+
avatar: string
|
|
12
17
|
to: string
|
|
13
18
|
search: boolean
|
|
14
19
|
colorMode: boolean
|
|
@@ -36,12 +41,12 @@ declare module 'nuxt/schema' {
|
|
|
36
41
|
suffix: string
|
|
37
42
|
per_page: number
|
|
38
43
|
until: string
|
|
39
|
-
author
|
|
44
|
+
author: string
|
|
40
45
|
/**
|
|
41
46
|
* 日期格式化配置
|
|
42
47
|
* @example { locale: 'zh-CN', options: { year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' } }
|
|
43
48
|
*/
|
|
44
|
-
dateFormat
|
|
49
|
+
dateFormat: {
|
|
45
50
|
locale?: string
|
|
46
51
|
options?: Intl.DateTimeFormatOptions
|
|
47
52
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@movk/nuxt-docs",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.4.
|
|
4
|
+
"version": "1.4.2",
|
|
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",
|