@movk/nuxt-docs 1.9.0 → 1.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/app/assets/css/main.css +40 -0
- package/app/utils/shiki-transformer-icon-highlight.ts +0 -1
- package/modules/css.ts +17 -32
- package/modules/md-rewrite.ts +1 -1
- package/nuxt.config.ts +33 -22
- package/package.json +16 -11
- package/server/plugins/llms.ts +2 -1
- package/utils/component-meta.ts +0 -12
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
@import "tailwindcss" theme(static) source("../../../..");
|
|
2
|
+
@import "@nuxt/ui";
|
|
3
|
+
|
|
4
|
+
@theme static {
|
|
5
|
+
--container-8xl: 90rem;
|
|
6
|
+
|
|
7
|
+
--font-sans: 'Public Sans', sans-serif;
|
|
8
|
+
|
|
9
|
+
--color-green-50: #EFFDF5;
|
|
10
|
+
--color-green-100: #D9FBE8;
|
|
11
|
+
--color-green-200: #B3F5D1;
|
|
12
|
+
--color-green-300: #75EDAE;
|
|
13
|
+
--color-green-400: #00DC82;
|
|
14
|
+
--color-green-500: #00C16A;
|
|
15
|
+
--color-green-600: #00A155;
|
|
16
|
+
--color-green-700: #007F45;
|
|
17
|
+
--color-green-800: #016538;
|
|
18
|
+
--color-green-900: #0A5331;
|
|
19
|
+
--color-green-950: #052E16;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
:root {
|
|
23
|
+
--ui-container: var(--container-8xl);
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/* Shiki icon highlight transformer styles */
|
|
27
|
+
.shiki-icon-highlight {
|
|
28
|
+
display: inline-block;
|
|
29
|
+
width: 1.25em;
|
|
30
|
+
height: 1.25em;
|
|
31
|
+
vertical-align: -0.25em;
|
|
32
|
+
margin-right: 0.125em;
|
|
33
|
+
background-color: var(--ui-text-highlighted);
|
|
34
|
+
-webkit-mask-repeat: no-repeat;
|
|
35
|
+
mask-repeat: no-repeat;
|
|
36
|
+
-webkit-mask-size: 100% 100%;
|
|
37
|
+
mask-size: 100% 100%;
|
|
38
|
+
-webkit-mask-image: var(--shiki-icon-url);
|
|
39
|
+
mask-image: var(--shiki-icon-url);
|
|
40
|
+
}
|
package/modules/css.ts
CHANGED
|
@@ -1,51 +1,36 @@
|
|
|
1
|
-
import { addTemplate,
|
|
1
|
+
import { addTemplate, defineNuxtModule } from '@nuxt/kit'
|
|
2
|
+
import { fileURLToPath } from 'node:url'
|
|
3
|
+
import { dirname, join } from 'node:path'
|
|
2
4
|
import { joinURL } from 'ufo'
|
|
5
|
+
import { resolveModulePath } from 'exsolve'
|
|
3
6
|
|
|
4
7
|
export default defineNuxtModule({
|
|
5
8
|
meta: {
|
|
6
9
|
name: 'css'
|
|
7
10
|
},
|
|
8
|
-
|
|
9
|
-
const
|
|
10
|
-
const
|
|
11
|
+
setup(_options, nuxt) {
|
|
12
|
+
const currentDir = dirname(fileURLToPath(import.meta.url))
|
|
13
|
+
const mainCssPath = join(currentDir, '../app/assets/css/main.css')
|
|
14
|
+
|
|
15
|
+
nuxt.options.css ||= []
|
|
16
|
+
nuxt.options.css.unshift(mainCssPath)
|
|
11
17
|
|
|
12
|
-
const
|
|
13
|
-
const aiChatDir = resolve('../modules/ai-chat')
|
|
18
|
+
const dir = nuxt.options.rootDir
|
|
14
19
|
|
|
15
20
|
const contentDir = joinURL(dir, 'content')
|
|
21
|
+
const uiPath = resolveModulePath('@nuxt/ui', { from: import.meta.url, conditions: ['style'] })
|
|
22
|
+
const tailwindPath = resolveModulePath('tailwindcss', { from: import.meta.url, conditions: ['style'] })
|
|
16
23
|
|
|
17
24
|
const cssTemplate = addTemplate({
|
|
18
25
|
filename: 'movk-nuxt-docs.css',
|
|
19
26
|
getContents: () => {
|
|
20
|
-
return `@import
|
|
21
|
-
@import
|
|
22
|
-
@import "@nuxt/ui";
|
|
23
|
-
|
|
24
|
-
@source "${contentDir.replace(/\\/g, '/')}/**/*";
|
|
25
|
-
@source "${layerDir.replace(/\\/g, '/')}/**/*";
|
|
26
|
-
@source "${aiChatDir.replace(/\\/g, '/')}/**/*";
|
|
27
|
-
@source "../../app.config.ts";
|
|
27
|
+
return `@import ${JSON.stringify(tailwindPath)};
|
|
28
|
+
@import ${JSON.stringify(uiPath)};
|
|
28
29
|
|
|
29
|
-
|
|
30
|
-
.shiki-icon-highlight {
|
|
31
|
-
display: inline-block;
|
|
32
|
-
width: 1.25em;
|
|
33
|
-
height: 1.25em;
|
|
34
|
-
vertical-align: -0.25em;
|
|
35
|
-
margin-right: 0.125em;
|
|
36
|
-
background-color: var(--ui-text-highlighted);
|
|
37
|
-
-webkit-mask-repeat: no-repeat;
|
|
38
|
-
mask-repeat: no-repeat;
|
|
39
|
-
-webkit-mask-size: 100% 100%;
|
|
40
|
-
mask-size: 100% 100%;
|
|
41
|
-
-webkit-mask-image: var(--shiki-icon-url);
|
|
42
|
-
mask-image: var(--shiki-icon-url);
|
|
43
|
-
}`
|
|
30
|
+
@source "${contentDir.replace(/\\/g, '/')}/**/*";`
|
|
44
31
|
}
|
|
45
32
|
})
|
|
46
33
|
|
|
47
|
-
|
|
48
|
-
nuxt.options.css.unshift(cssTemplate.dst)
|
|
49
|
-
}
|
|
34
|
+
nuxt.options.css.unshift(cssTemplate.dst)
|
|
50
35
|
}
|
|
51
36
|
})
|
package/modules/md-rewrite.ts
CHANGED
package/nuxt.config.ts
CHANGED
|
@@ -1,12 +1,8 @@
|
|
|
1
|
-
import { createResolver, extendViteConfig } from '@nuxt/kit'
|
|
2
1
|
import { defineNuxtConfig } from 'nuxt/config'
|
|
3
2
|
import pkg from './package.json'
|
|
4
3
|
|
|
5
|
-
const { resolve } = createResolver(import.meta.url)
|
|
6
|
-
|
|
7
4
|
export default defineNuxtConfig({
|
|
8
5
|
modules: [
|
|
9
|
-
resolve('./modules/config'),
|
|
10
6
|
'@nuxt/ui',
|
|
11
7
|
'@nuxt/content',
|
|
12
8
|
'@nuxt/image',
|
|
@@ -16,30 +12,16 @@ export default defineNuxtConfig({
|
|
|
16
12
|
'nuxt-component-meta',
|
|
17
13
|
'nuxt-llms',
|
|
18
14
|
'nuxt-og-image',
|
|
19
|
-
'motion-v/nuxt'
|
|
20
|
-
() => {
|
|
21
|
-
extendViteConfig((config) => {
|
|
22
|
-
config.optimizeDeps ||= {}
|
|
23
|
-
config.optimizeDeps.include ||= []
|
|
24
|
-
config.optimizeDeps.include.push(
|
|
25
|
-
'@nuxt/content > slugify',
|
|
26
|
-
'extend',
|
|
27
|
-
'@ai-sdk/gateway > @vercel/oidc',
|
|
28
|
-
'mermaid',
|
|
29
|
-
'dompurify'
|
|
30
|
-
)
|
|
31
|
-
config.optimizeDeps.include = config.optimizeDeps.include
|
|
32
|
-
.map(id => id.replace(/^@nuxt\/content > /, '@movk/nuxt-docs > @nuxt/content > '))
|
|
33
|
-
})
|
|
34
|
-
}
|
|
15
|
+
'motion-v/nuxt'
|
|
35
16
|
],
|
|
17
|
+
|
|
36
18
|
app: {
|
|
37
19
|
rootAttrs: {
|
|
38
20
|
'data-vaul-drawer-wrapper': '',
|
|
39
21
|
'class': 'bg-default'
|
|
40
22
|
}
|
|
41
23
|
},
|
|
42
|
-
|
|
24
|
+
|
|
43
25
|
content: {
|
|
44
26
|
build: {
|
|
45
27
|
markdown: {
|
|
@@ -56,22 +38,25 @@ export default defineNuxtConfig({
|
|
|
56
38
|
}
|
|
57
39
|
}
|
|
58
40
|
},
|
|
41
|
+
|
|
59
42
|
mdc: {
|
|
60
43
|
highlight: {
|
|
61
44
|
noApiRoute: false
|
|
62
45
|
}
|
|
63
46
|
},
|
|
47
|
+
|
|
64
48
|
runtimeConfig: {
|
|
65
49
|
public: {
|
|
66
50
|
version: pkg.version
|
|
67
51
|
}
|
|
68
52
|
},
|
|
53
|
+
|
|
69
54
|
routeRules: {
|
|
70
55
|
'/llms.txt': { isr: true },
|
|
71
56
|
'/llms-full.txt': { isr: true }
|
|
72
57
|
},
|
|
58
|
+
|
|
73
59
|
experimental: {
|
|
74
|
-
typescriptPlugin: true,
|
|
75
60
|
asyncContext: true,
|
|
76
61
|
defaults: {
|
|
77
62
|
nuxtLink: {
|
|
@@ -79,7 +64,9 @@ export default defineNuxtConfig({
|
|
|
79
64
|
}
|
|
80
65
|
}
|
|
81
66
|
},
|
|
67
|
+
|
|
82
68
|
compatibilityDate: 'latest',
|
|
69
|
+
|
|
83
70
|
nitro: {
|
|
84
71
|
prerender: {
|
|
85
72
|
crawlLinks: true,
|
|
@@ -87,9 +74,30 @@ export default defineNuxtConfig({
|
|
|
87
74
|
autoSubfolderIndex: false
|
|
88
75
|
}
|
|
89
76
|
},
|
|
77
|
+
|
|
78
|
+
hooks: {
|
|
79
|
+
// Rewrite optimizeDeps paths for layer architecture
|
|
80
|
+
'vite:extendConfig': (config) => {
|
|
81
|
+
const include = config.optimizeDeps?.include
|
|
82
|
+
if (!include) return
|
|
83
|
+
|
|
84
|
+
const layerPkgs = /^(?:@nuxt\/content|@nuxtjs\/mdc|@nuxt\/a11y) > /
|
|
85
|
+
include.forEach((id, i) => {
|
|
86
|
+
if (layerPkgs.test(id)) include[i] = `@movk/nuxt-docs > ${id}`
|
|
87
|
+
})
|
|
88
|
+
|
|
89
|
+
// Layer dependencies that need pre-bundling
|
|
90
|
+
include.push(
|
|
91
|
+
'@movk/nuxt-docs > @nuxt/content > slugify',
|
|
92
|
+
'@movk/nuxt-docs > @ai-sdk/gateway > @vercel/oidc'
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
},
|
|
96
|
+
|
|
90
97
|
a11y: {
|
|
91
98
|
logIssues: false
|
|
92
99
|
},
|
|
100
|
+
|
|
93
101
|
componentMeta: {
|
|
94
102
|
metaFields: {
|
|
95
103
|
type: false,
|
|
@@ -110,6 +118,7 @@ export default defineNuxtConfig({
|
|
|
110
118
|
'nuxt-og-image'
|
|
111
119
|
]
|
|
112
120
|
},
|
|
121
|
+
|
|
113
122
|
fonts: {
|
|
114
123
|
families: [
|
|
115
124
|
{ name: 'Public Sans', provider: 'google', global: true },
|
|
@@ -121,9 +130,11 @@ export default defineNuxtConfig({
|
|
|
121
130
|
{ name: 'Raleway', provider: 'google', global: true }
|
|
122
131
|
]
|
|
123
132
|
},
|
|
133
|
+
|
|
124
134
|
icon: {
|
|
125
135
|
provider: 'iconify'
|
|
126
136
|
},
|
|
137
|
+
|
|
127
138
|
ogImage: {
|
|
128
139
|
zeroRuntime: true,
|
|
129
140
|
googleFontMirror: 'fonts.loli.net',
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@movk/nuxt-docs",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "1.
|
|
4
|
+
"version": "1.10.0",
|
|
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>",
|
|
@@ -14,7 +14,8 @@
|
|
|
14
14
|
"main": "./nuxt.config.ts",
|
|
15
15
|
"peerDependencies": {
|
|
16
16
|
"better-sqlite3": "12.x",
|
|
17
|
-
"nuxt": "4.x"
|
|
17
|
+
"nuxt": "4.x",
|
|
18
|
+
"tailwindcss": "4.x"
|
|
18
19
|
},
|
|
19
20
|
"files": [
|
|
20
21
|
"app",
|
|
@@ -28,12 +29,12 @@
|
|
|
28
29
|
"README.md"
|
|
29
30
|
],
|
|
30
31
|
"dependencies": {
|
|
31
|
-
"@ai-sdk/gateway": "^3.0.
|
|
32
|
-
"@ai-sdk/mcp": "^1.0.
|
|
33
|
-
"@ai-sdk/vue": "^3.0.
|
|
34
|
-
"@iconify-json/lucide": "^1.2.
|
|
32
|
+
"@ai-sdk/gateway": "^3.0.29",
|
|
33
|
+
"@ai-sdk/mcp": "^1.0.15",
|
|
34
|
+
"@ai-sdk/vue": "^3.0.62",
|
|
35
|
+
"@iconify-json/lucide": "^1.2.87",
|
|
35
36
|
"@iconify-json/ph": "^1.2.2",
|
|
36
|
-
"@iconify-json/simple-icons": "^1.2.
|
|
37
|
+
"@iconify-json/simple-icons": "^1.2.68",
|
|
37
38
|
"@iconify-json/tabler": "^1.2.26",
|
|
38
39
|
"@iconify-json/vscode-icons": "^1.2.40",
|
|
39
40
|
"@movk/core": "^1.1.0",
|
|
@@ -43,19 +44,21 @@
|
|
|
43
44
|
"@nuxt/kit": "^4.3.0",
|
|
44
45
|
"@nuxt/ui": "^4.4.0",
|
|
45
46
|
"@nuxtjs/mcp-toolkit": "^0.6.2",
|
|
47
|
+
"@nuxtjs/mdc": "^0.20.0",
|
|
46
48
|
"@octokit/rest": "^22.0.1",
|
|
47
|
-
"@openrouter/ai-sdk-provider": "^2.
|
|
49
|
+
"@openrouter/ai-sdk-provider": "^2.1.1",
|
|
48
50
|
"@vercel/analytics": "^1.6.1",
|
|
49
51
|
"@vercel/speed-insights": "^1.3.1",
|
|
50
52
|
"@vueuse/core": "^14.1.0",
|
|
51
53
|
"@vueuse/nuxt": "^14.1.0",
|
|
52
|
-
"ai": "^6.0.
|
|
54
|
+
"ai": "^6.0.62",
|
|
53
55
|
"defu": "^6.1.4",
|
|
54
56
|
"dompurify": "^3.3.1",
|
|
55
57
|
"exsolve": "^1.0.8",
|
|
56
58
|
"git-url-parse": "^16.1.0",
|
|
57
59
|
"mermaid": "^11.12.2",
|
|
58
|
-
"
|
|
60
|
+
"minimark": "^0.2.0",
|
|
61
|
+
"motion-v": "^1.10.2",
|
|
59
62
|
"nuxt": "^4.3.0",
|
|
60
63
|
"nuxt-component-meta": "^0.17.1",
|
|
61
64
|
"nuxt-llms": "^0.2.0",
|
|
@@ -69,7 +72,9 @@
|
|
|
69
72
|
"shiki-stream": "^0.1.4",
|
|
70
73
|
"shiki-transformer-color-highlight": "^1.0.0",
|
|
71
74
|
"tailwindcss": "^4.1.18",
|
|
75
|
+
"tailwind-merge": "^3.4.0",
|
|
72
76
|
"ufo": "^1.6.3",
|
|
73
|
-
"zod": "^4.3.6"
|
|
77
|
+
"zod": "^4.3.6",
|
|
78
|
+
"vue-component-meta": "^3.2.4"
|
|
74
79
|
}
|
|
75
80
|
}
|
package/server/plugins/llms.ts
CHANGED
|
@@ -6,9 +6,10 @@ export default defineNitroPlugin((nitroApp) => {
|
|
|
6
6
|
await transformMDC(event, doc as any)
|
|
7
7
|
})
|
|
8
8
|
|
|
9
|
+
// @ts-expect-error - no types available
|
|
9
10
|
nitroApp.hooks.hook('llms:generate', (_, { sections }) => {
|
|
10
11
|
// Move "Documentation Sets" to the end
|
|
11
|
-
const docSetIdx = sections.findIndex(s => s.title === 'Documentation Sets')
|
|
12
|
+
const docSetIdx = sections.findIndex((s: any) => s.title === 'Documentation Sets')
|
|
12
13
|
if (docSetIdx !== -1) {
|
|
13
14
|
const [docSet] = sections.splice(docSetIdx, 1)
|
|
14
15
|
if (docSet) {
|
package/utils/component-meta.ts
CHANGED
|
@@ -3,10 +3,6 @@ import { join } from 'pathe'
|
|
|
3
3
|
|
|
4
4
|
/**
|
|
5
5
|
* 匹配组件是否符合用户定义的 include 模式
|
|
6
|
-
* @param filePath 组件文件路径
|
|
7
|
-
* @param pascalName 组件 PascalCase 名称
|
|
8
|
-
* @param includePatterns 包含模式数组(字符串 glob、正则表达式或函数)
|
|
9
|
-
* @returns 是否匹配
|
|
10
6
|
*/
|
|
11
7
|
function matchesUserInclude(
|
|
12
8
|
filePath: string,
|
|
@@ -35,9 +31,6 @@ function matchesUserInclude(
|
|
|
35
31
|
|
|
36
32
|
/**
|
|
37
33
|
* 检查组件是否为用户组件
|
|
38
|
-
* @param filePath 组件文件路径
|
|
39
|
-
* @param userComponentPaths 用户组件路径数组
|
|
40
|
-
* @returns 是否为用户组件
|
|
41
34
|
*/
|
|
42
35
|
export function isUserComponent(filePath: string, userComponentPaths: string[]): boolean {
|
|
43
36
|
return userComponentPaths.some(path => filePath.startsWith(path))
|
|
@@ -45,11 +38,6 @@ export function isUserComponent(filePath: string, userComponentPaths: string[]):
|
|
|
45
38
|
|
|
46
39
|
/**
|
|
47
40
|
* 创建 component-meta exclude 过滤器
|
|
48
|
-
* @param layerPath layer 路径
|
|
49
|
-
* @param allowedComponents 允许的组件列表
|
|
50
|
-
* @param userComponentPaths 用户组件路径数组
|
|
51
|
-
* @param userInclude 用户定义的 include 模式
|
|
52
|
-
* @returns exclude 过滤器数组
|
|
53
41
|
*/
|
|
54
42
|
export function createComponentMetaExcludeFilters(
|
|
55
43
|
resolve: Resolver['resolve'],
|