@movk/nuxt-docs 1.1.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/README.md +265 -0
- package/app/app.config.ts +53 -0
- package/app/app.vue +73 -0
- package/app/components/AdsCarbon.vue +3 -0
- package/app/components/Footer.vue +32 -0
- package/app/components/PageHeaderLinks.vue +73 -0
- package/app/components/StarsBg.vue +122 -0
- package/app/components/content/ComponentEmits.vue +43 -0
- package/app/components/content/ComponentExample.vue +247 -0
- package/app/components/content/ComponentProps.vue +105 -0
- package/app/components/content/ComponentPropsLinks.vue +20 -0
- package/app/components/content/ComponentPropsSchema.vue +55 -0
- package/app/components/content/ComponentSlots.vue +50 -0
- package/app/components/content/HeroBackground.vue +65 -0
- package/app/components/content/HighlightInlineType.vue +39 -0
- package/app/components/content/Motion.vue +21 -0
- package/app/components/header/Header.vue +60 -0
- package/app/components/header/HeaderBody.vue +19 -0
- package/app/components/header/HeaderBottom.vue +26 -0
- package/app/components/header/HeaderLogo.vue +57 -0
- package/app/components/theme-picker/ThemePicker.vue +152 -0
- package/app/components/theme-picker/ThemePickerButton.vue +37 -0
- package/app/composables/fetchComponentExample.ts +32 -0
- package/app/composables/fetchComponentMeta.ts +34 -0
- package/app/composables/useCategory.ts +5 -0
- package/app/composables/useHeader.ts +6 -0
- package/app/composables/useNavigation.ts +89 -0
- package/app/error.vue +59 -0
- package/app/layouts/default.vue +3 -0
- package/app/layouts/docs.vue +31 -0
- package/app/pages/docs/[...slug].vue +158 -0
- package/app/pages/index.vue +30 -0
- package/app/pages/releases.vue +92 -0
- package/app/plugins/prettier.ts +67 -0
- package/app/plugins/theme.ts +82 -0
- package/app/types/index.d.ts +37 -0
- package/app/workers/prettier.js +36 -0
- package/content.config.ts +68 -0
- package/modules/component-example.ts +128 -0
- package/modules/component-meta.ts +22 -0
- package/modules/config.ts +79 -0
- package/modules/css.ts +33 -0
- package/nuxt.config.ts +80 -0
- package/package.json +55 -0
- package/server/api/component-example.get.ts +19 -0
- package/server/plugins/llms.ts +24 -0
- package/server/routes/raw/[...slug].md.get.ts +27 -0
- package/utils/git.ts +108 -0
- package/utils/meta.ts +29 -0
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { defineNuxtModule } from '@nuxt/kit'
|
|
2
|
+
import type { NuxtComponentMeta } from 'nuxt-component-meta'
|
|
3
|
+
|
|
4
|
+
export default defineNuxtModule({
|
|
5
|
+
meta: {
|
|
6
|
+
name: 'component-meta'
|
|
7
|
+
},
|
|
8
|
+
async setup(_options, nuxt) {
|
|
9
|
+
// @ts-expect-error - Hook is not typed correctly
|
|
10
|
+
nuxt.hook('component-meta:schema', (schema: NuxtComponentMeta) => {
|
|
11
|
+
for (const componentName in schema) {
|
|
12
|
+
const component = schema[componentName]
|
|
13
|
+
// Delete schema from slots to reduce metadata file size
|
|
14
|
+
if (component?.meta?.slots) {
|
|
15
|
+
for (const slot of component.meta.slots) {
|
|
16
|
+
delete (slot as any).schema
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
})
|
|
21
|
+
}
|
|
22
|
+
})
|
|
@@ -0,0 +1,79 @@
|
|
|
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
|
+
|
|
6
|
+
export default defineNuxtModule({
|
|
7
|
+
meta: {
|
|
8
|
+
name: 'config'
|
|
9
|
+
},
|
|
10
|
+
async setup(_options, nuxt) {
|
|
11
|
+
const { resolve } = createResolver(import.meta.url)
|
|
12
|
+
const dir = nuxt.options.rootDir
|
|
13
|
+
const url = inferSiteURL()
|
|
14
|
+
const meta = await getPackageJsonMetadata(dir)
|
|
15
|
+
const gitInfo = await getLocalGitInfo(dir) || getGitEnv()
|
|
16
|
+
const siteName = nuxt.options?.site?.name || meta.name || gitInfo?.name || ''
|
|
17
|
+
|
|
18
|
+
nuxt.options.llms = defu(nuxt.options.llms, {
|
|
19
|
+
domain: url || 'https://example.com',
|
|
20
|
+
title: siteName,
|
|
21
|
+
description: meta.description || '',
|
|
22
|
+
full: {
|
|
23
|
+
title: siteName,
|
|
24
|
+
description: meta.description || ''
|
|
25
|
+
}
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
nuxt.options.site = defu(nuxt.options.site, {
|
|
29
|
+
url,
|
|
30
|
+
name: siteName,
|
|
31
|
+
debug: false
|
|
32
|
+
})
|
|
33
|
+
|
|
34
|
+
nuxt.options.robots = defu(nuxt.options.robots, {
|
|
35
|
+
sitemap: url ? `${url.replace(/\/$/, '')}/sitemap.xml` : undefined
|
|
36
|
+
})
|
|
37
|
+
|
|
38
|
+
nuxt.options.appConfig.header = defu(nuxt.options.appConfig.header, {
|
|
39
|
+
title: siteName
|
|
40
|
+
})
|
|
41
|
+
|
|
42
|
+
nuxt.options.appConfig.seo = defu(nuxt.options.appConfig.seo, {
|
|
43
|
+
titleTemplate: `%s - ${siteName}`,
|
|
44
|
+
title: siteName,
|
|
45
|
+
description: meta.description || ''
|
|
46
|
+
})
|
|
47
|
+
|
|
48
|
+
nuxt.options.appConfig.github = defu(nuxt.options.appConfig.github, {
|
|
49
|
+
owner: gitInfo?.owner,
|
|
50
|
+
name: gitInfo?.name,
|
|
51
|
+
url: gitInfo?.url,
|
|
52
|
+
branch: getGitBranch()
|
|
53
|
+
})
|
|
54
|
+
|
|
55
|
+
const componentsPath = resolve('../app/components')
|
|
56
|
+
|
|
57
|
+
nuxt.options.componentMeta = defu(nuxt.options.componentMeta, {
|
|
58
|
+
exclude: [
|
|
59
|
+
'@nuxt/content',
|
|
60
|
+
'@nuxt/icon',
|
|
61
|
+
'@nuxt/image',
|
|
62
|
+
'@nuxtjs/color-mode',
|
|
63
|
+
'@nuxtjs/mdc',
|
|
64
|
+
'nuxt/dist',
|
|
65
|
+
'nuxt-og-image',
|
|
66
|
+
'@nuxtjs/plausible',
|
|
67
|
+
'@nuxt/ui',
|
|
68
|
+
new RegExp(`${componentsPath.replace(/[/\\]/g, '[/\\\\]')}/(?!content/(ComponentEmits|ComponentProps|ComponentSlots|ComponentExample)\\.vue$)`)
|
|
69
|
+
],
|
|
70
|
+
metaFields: {
|
|
71
|
+
type: false,
|
|
72
|
+
props: true,
|
|
73
|
+
slots: true,
|
|
74
|
+
events: true,
|
|
75
|
+
exposed: false
|
|
76
|
+
}
|
|
77
|
+
})
|
|
78
|
+
}
|
|
79
|
+
})
|
package/modules/css.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { addTemplate, createResolver, defineNuxtModule } 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 { resolve } = createResolver(import.meta.url)
|
|
12
|
+
|
|
13
|
+
const layerDir = resolve('../app')
|
|
14
|
+
const contentDir = joinURL(dir, 'content')
|
|
15
|
+
const uiPath = resolveModulePath('@nuxt/ui', { from: import.meta.url, conditions: ['style'] })
|
|
16
|
+
const tailwindPath = resolveModulePath('tailwindcss', { from: import.meta.url, conditions: ['style'] })
|
|
17
|
+
|
|
18
|
+
const cssTemplate = addTemplate({
|
|
19
|
+
filename: 'movk-nuxt-docs.css',
|
|
20
|
+
getContents: () => {
|
|
21
|
+
return `@import ${JSON.stringify(tailwindPath)};
|
|
22
|
+
@import ${JSON.stringify(tailwindPath)}/theme.css theme(static);
|
|
23
|
+
@import ${JSON.stringify(uiPath)};
|
|
24
|
+
|
|
25
|
+
@source "${contentDir.replace(/\\/g, '/')}/**/*";
|
|
26
|
+
@source "${layerDir.replace(/\\/g, '/')}/**/*";
|
|
27
|
+
@source "../../app.config.ts";`
|
|
28
|
+
}
|
|
29
|
+
})
|
|
30
|
+
|
|
31
|
+
nuxt.options.css.unshift(cssTemplate.dst)
|
|
32
|
+
}
|
|
33
|
+
})
|
package/nuxt.config.ts
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import { createResolver } 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/css'),
|
|
9
|
+
resolve('./modules/component-example'),
|
|
10
|
+
resolve('./modules/component-meta'),
|
|
11
|
+
'@nuxt/ui',
|
|
12
|
+
'@nuxt/content',
|
|
13
|
+
'@nuxt/image',
|
|
14
|
+
'@vueuse/nuxt',
|
|
15
|
+
'@nuxtjs/seo',
|
|
16
|
+
'nuxt-component-meta',
|
|
17
|
+
'motion-v/nuxt',
|
|
18
|
+
'nuxt-llms'
|
|
19
|
+
],
|
|
20
|
+
content: {
|
|
21
|
+
build: {
|
|
22
|
+
markdown: {
|
|
23
|
+
highlight: {
|
|
24
|
+
langs: ['bash', 'ts', 'typescript', 'diff', 'vue', 'json', 'yml', 'css', 'mdc', 'blade', 'edge']
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
},
|
|
29
|
+
mdc: {
|
|
30
|
+
highlight: {
|
|
31
|
+
noApiRoute: false
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
compatibilityDate: 'latest',
|
|
35
|
+
nitro: {
|
|
36
|
+
prerender: {
|
|
37
|
+
routes: ['/', '/sitemap.xml', '/robots.txt', '/404.html'],
|
|
38
|
+
crawlLinks: true,
|
|
39
|
+
autoSubfolderIndex: false
|
|
40
|
+
}
|
|
41
|
+
},
|
|
42
|
+
vite: {
|
|
43
|
+
optimizeDeps: {
|
|
44
|
+
include: [
|
|
45
|
+
'@nuxt/content > slugify',
|
|
46
|
+
'colortranslator',
|
|
47
|
+
'tailwindcss/colors',
|
|
48
|
+
'tailwind-variants',
|
|
49
|
+
'ufo',
|
|
50
|
+
'zod',
|
|
51
|
+
'scule',
|
|
52
|
+
'motion-v',
|
|
53
|
+
'ohash'
|
|
54
|
+
]
|
|
55
|
+
}
|
|
56
|
+
},
|
|
57
|
+
icon: {
|
|
58
|
+
provider: 'iconify'
|
|
59
|
+
},
|
|
60
|
+
linkChecker: {
|
|
61
|
+
report: {
|
|
62
|
+
publish: true,
|
|
63
|
+
html: true,
|
|
64
|
+
markdown: true,
|
|
65
|
+
json: true
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
ogImage: {
|
|
69
|
+
googleFontMirror: 'fonts.loli.net',
|
|
70
|
+
fonts: [
|
|
71
|
+
// 思源黑体 - 支持中文
|
|
72
|
+
'Noto+Sans+SC:400',
|
|
73
|
+
'Noto+Sans+SC:500',
|
|
74
|
+
'Noto+Sans+SC:700',
|
|
75
|
+
// 如果需要英文字体
|
|
76
|
+
'Inter:400',
|
|
77
|
+
'Inter:700'
|
|
78
|
+
]
|
|
79
|
+
}
|
|
80
|
+
})
|
package/package.json
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@movk/nuxt-docs",
|
|
3
|
+
"type": "module",
|
|
4
|
+
"version": "1.1.0",
|
|
5
|
+
"private": false,
|
|
6
|
+
"description": "An elegant documentation theme for Nuxt, powered by Nuxt UI and Nuxt Content.",
|
|
7
|
+
"author": "YiXuan <mhaibaraai@gmail.com>",
|
|
8
|
+
"license": "MIT",
|
|
9
|
+
"homepage": "https://docs.mhaibaraai.cn",
|
|
10
|
+
"repository": {
|
|
11
|
+
"type": "git",
|
|
12
|
+
"url": "git+https://github.com/mhaibaraai/movk-nuxt-docs.git"
|
|
13
|
+
},
|
|
14
|
+
"main": "./nuxt.config.ts",
|
|
15
|
+
"peerDependencies": {
|
|
16
|
+
"better-sqlite3": "12.x",
|
|
17
|
+
"nuxt": "4.x"
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"app",
|
|
21
|
+
"content.config.ts",
|
|
22
|
+
"modules",
|
|
23
|
+
"nuxt.config.ts",
|
|
24
|
+
"server",
|
|
25
|
+
"utils",
|
|
26
|
+
"pnpm-workspace.yaml",
|
|
27
|
+
"README.md"
|
|
28
|
+
],
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"@iconify-json/lucide": "^1.2.69",
|
|
31
|
+
"@iconify-json/simple-icons": "^1.2.54",
|
|
32
|
+
"@iconify-json/vscode-icons": "^1.2.32",
|
|
33
|
+
"@movk/core": "^0.0.5",
|
|
34
|
+
"@nuxt/content": "^3.7.1",
|
|
35
|
+
"@nuxt/image": "^1.11.0",
|
|
36
|
+
"@nuxt/kit": "^4.1.3",
|
|
37
|
+
"@nuxt/ui": "^4.0.1",
|
|
38
|
+
"@nuxtjs/seo": "^3.2.2",
|
|
39
|
+
"@vueuse/core": "^13.9.0",
|
|
40
|
+
"@vueuse/nuxt": "^13.9.0",
|
|
41
|
+
"defu": "^6.1.4",
|
|
42
|
+
"pathe": "^2.0.3",
|
|
43
|
+
"exsolve": "^1.0.7",
|
|
44
|
+
"git-url-parse": "^16.1.0",
|
|
45
|
+
"motion-v": "^1.7.2",
|
|
46
|
+
"nuxt-component-meta": "^0.14.1",
|
|
47
|
+
"prettier": "^3.6.2",
|
|
48
|
+
"nuxt-llms": "^0.1.3",
|
|
49
|
+
"pkg-types": "^2.3.0",
|
|
50
|
+
"scule": "^1.3.0",
|
|
51
|
+
"tailwindcss": "^4.1.14",
|
|
52
|
+
"ohash": "^2.0.11",
|
|
53
|
+
"ufo": "^1.6.1"
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { defineEventHandler, createError, appendHeader } from 'h3'
|
|
2
|
+
import { pascalCase } from 'scule'
|
|
3
|
+
// @ts-expect-error - no types available
|
|
4
|
+
import components from '#component-example/nitro'
|
|
5
|
+
|
|
6
|
+
export default defineEventHandler((event) => {
|
|
7
|
+
appendHeader(event, 'Access-Control-Allow-Origin', '*')
|
|
8
|
+
const componentName = (event.context.params?.['component?'] || '').replace(/\.json$/, '')
|
|
9
|
+
if (componentName) {
|
|
10
|
+
const component = components[pascalCase(componentName)]
|
|
11
|
+
if (!component) {
|
|
12
|
+
throw createError({
|
|
13
|
+
statusMessage: 'Example not found!',
|
|
14
|
+
statusCode: 404
|
|
15
|
+
})
|
|
16
|
+
}
|
|
17
|
+
return component
|
|
18
|
+
}
|
|
19
|
+
})
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export default defineNitroPlugin((nitroApp) => {
|
|
2
|
+
/**
|
|
3
|
+
* @see
|
|
4
|
+
* https://github.com/nuxt-content/nuxt-llms?tab=readme-ov-file#readme
|
|
5
|
+
*/
|
|
6
|
+
nitroApp.hooks.hook('llms:generate', (_, { sections, domain }) => {
|
|
7
|
+
// Transform links except for "Documentation Sets"
|
|
8
|
+
sections.forEach((section) => {
|
|
9
|
+
if (section.title !== 'Documentation Sets') {
|
|
10
|
+
section.links = section.links?.map(link => ({
|
|
11
|
+
...link,
|
|
12
|
+
href: `${link.href.replace(new RegExp(`^${domain}`), `${domain}/raw`)}.md`
|
|
13
|
+
}))
|
|
14
|
+
}
|
|
15
|
+
})
|
|
16
|
+
|
|
17
|
+
// Move "Documentation Sets" to the end
|
|
18
|
+
const docSetIdx = sections.findIndex(s => s.title === 'Documentation Sets')
|
|
19
|
+
if (docSetIdx !== -1) {
|
|
20
|
+
const [docSet] = sections.splice(docSetIdx, 1)
|
|
21
|
+
sections.push(docSet)
|
|
22
|
+
}
|
|
23
|
+
})
|
|
24
|
+
})
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import type { Collections } from '@nuxt/content'
|
|
2
|
+
import { queryCollection } from '@nuxt/content/server'
|
|
3
|
+
import { stringify } from 'minimark/stringify'
|
|
4
|
+
import { withLeadingSlash } from 'ufo'
|
|
5
|
+
|
|
6
|
+
export default eventHandler(async (event) => {
|
|
7
|
+
const slug = getRouterParams(event)['slug.md']
|
|
8
|
+
if (!slug?.endsWith('.md')) {
|
|
9
|
+
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const path = withLeadingSlash(slug.replace('.md', ''))
|
|
13
|
+
|
|
14
|
+
const page = await queryCollection(event, 'docs' as keyof Collections).path(path).first()
|
|
15
|
+
if (!page) {
|
|
16
|
+
throw createError({ statusCode: 404, statusMessage: 'Page not found', fatal: true })
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// Add title and description to the top of the page if missing
|
|
20
|
+
if (page.body.value[0]?.[0] !== 'h1') {
|
|
21
|
+
page.body.value.unshift(['blockquote', {}, page.description])
|
|
22
|
+
page.body.value.unshift(['h1', {}, page.title])
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
setHeader(event, 'Content-Type', 'text/markdown; charset=utf-8')
|
|
26
|
+
return stringify({ ...page.body, type: 'minimark' }, { format: 'markdown/html' })
|
|
27
|
+
})
|
package/utils/git.ts
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
// copy from https://github.com/nuxt-content/docus/tree/main/layer/utils
|
|
2
|
+
import { execSync } from 'node:child_process'
|
|
3
|
+
import gitUrlParse from 'git-url-parse'
|
|
4
|
+
import { readGitConfig } from 'pkg-types'
|
|
5
|
+
|
|
6
|
+
export interface GitInfo {
|
|
7
|
+
// Repository name
|
|
8
|
+
name: string
|
|
9
|
+
// Repository owner/organization
|
|
10
|
+
owner: string
|
|
11
|
+
// Repository URL
|
|
12
|
+
url: string
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export function getGitBranch() {
|
|
16
|
+
const envName
|
|
17
|
+
= process.env.CF_PAGES_BRANCH
|
|
18
|
+
|| process.env.CI_COMMIT_BRANCH
|
|
19
|
+
|| process.env.VERCEL_GIT_COMMIT_REF
|
|
20
|
+
|| process.env.BRANCH
|
|
21
|
+
|| process.env.GITHUB_REF_NAME
|
|
22
|
+
|
|
23
|
+
if (envName && envName !== 'HEAD') {
|
|
24
|
+
return envName
|
|
25
|
+
}
|
|
26
|
+
try {
|
|
27
|
+
const branch = execSync('git rev-parse --abbrev-ref HEAD', { stdio: ['ignore', 'pipe', 'ignore'] }).toString().trim()
|
|
28
|
+
if (branch && branch !== 'HEAD') {
|
|
29
|
+
return branch
|
|
30
|
+
}
|
|
31
|
+
} catch {
|
|
32
|
+
// Ignore error
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return 'main'
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
export async function getLocalGitInfo(rootDir: string): Promise<GitInfo | undefined> {
|
|
39
|
+
const remote = await getLocalGitRemote(rootDir)
|
|
40
|
+
if (!remote) {
|
|
41
|
+
return
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// https://www.npmjs.com/package/git-url-parse#clipboard-example
|
|
45
|
+
const { name, owner, source } = gitUrlParse(remote)
|
|
46
|
+
const url = `https://${source}/${owner}/${name}`
|
|
47
|
+
|
|
48
|
+
return {
|
|
49
|
+
name,
|
|
50
|
+
owner,
|
|
51
|
+
url
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async function getLocalGitRemote(dir: string): Promise<string | undefined> {
|
|
56
|
+
try {
|
|
57
|
+
const parsed = await readGitConfig(dir)
|
|
58
|
+
if (!parsed) {
|
|
59
|
+
return
|
|
60
|
+
}
|
|
61
|
+
return parsed.remote?.origin?.url
|
|
62
|
+
} catch {
|
|
63
|
+
// Ignore error
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export function getGitEnv(): GitInfo {
|
|
68
|
+
// https://github.com/unjs/std-env/issues/59
|
|
69
|
+
const envInfo = {
|
|
70
|
+
// Provider
|
|
71
|
+
provider: process.env.VERCEL_GIT_PROVIDER // vercel
|
|
72
|
+
|| (process.env.GITHUB_SERVER_URL ? 'github' : undefined) // github
|
|
73
|
+
|| '',
|
|
74
|
+
// Owner
|
|
75
|
+
owner: process.env.VERCEL_GIT_REPO_OWNER // vercel
|
|
76
|
+
|| process.env.GITHUB_REPOSITORY_OWNER // github
|
|
77
|
+
|| process.env.CI_PROJECT_PATH?.split('/').shift() // gitlab
|
|
78
|
+
|| '',
|
|
79
|
+
// Name
|
|
80
|
+
name: process.env.VERCEL_GIT_REPO_SLUG
|
|
81
|
+
|| process.env.GITHUB_REPOSITORY?.split('/').pop() // github
|
|
82
|
+
|| process.env.CI_PROJECT_PATH?.split('/').splice(1).join('/') // gitlab
|
|
83
|
+
|| '',
|
|
84
|
+
// Url
|
|
85
|
+
url: process.env.REPOSITORY_URL || '' // netlify
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (!envInfo.url && envInfo.provider && envInfo.owner && envInfo.name) {
|
|
89
|
+
envInfo.url = `https://${envInfo.provider}.com/${envInfo.owner}/${envInfo.name}`
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// If only url available (ex: Netlify)
|
|
93
|
+
if (!envInfo.name && !envInfo.owner && envInfo.url) {
|
|
94
|
+
try {
|
|
95
|
+
const { name, owner } = gitUrlParse(envInfo.url)
|
|
96
|
+
envInfo.name = name
|
|
97
|
+
envInfo.owner = owner
|
|
98
|
+
} catch {
|
|
99
|
+
// Ignore error
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
return {
|
|
104
|
+
name: envInfo.name,
|
|
105
|
+
owner: envInfo.owner,
|
|
106
|
+
url: envInfo.url
|
|
107
|
+
}
|
|
108
|
+
}
|
package/utils/meta.ts
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// copy from https://github.com/nuxt-content/docus/tree/main/layer/utils
|
|
2
|
+
import { readFile } from 'node:fs/promises'
|
|
3
|
+
import { resolve } from 'node:path'
|
|
4
|
+
|
|
5
|
+
export function inferSiteURL() {
|
|
6
|
+
// https://github.com/unjs/std-env/issues/59
|
|
7
|
+
return (
|
|
8
|
+
process.env.NUXT_SITE_URL
|
|
9
|
+
|| (process.env.NEXT_PUBLIC_VERCEL_URL && `https://${process.env.NEXT_PUBLIC_VERCEL_URL}`) // Vercel
|
|
10
|
+
|| process.env.URL // Netlify
|
|
11
|
+
|| process.env.CI_PAGES_URL // Gitlab Pages
|
|
12
|
+
|| process.env.CF_PAGES_URL // Cloudflare Pages
|
|
13
|
+
)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export async function getPackageJsonMetadata(dir: string) {
|
|
17
|
+
try {
|
|
18
|
+
const packageJson = await readFile(resolve(dir, 'package.json'), 'utf-8')
|
|
19
|
+
const parsed = JSON.parse(packageJson)
|
|
20
|
+
return {
|
|
21
|
+
name: parsed.name,
|
|
22
|
+
description: parsed.description
|
|
23
|
+
}
|
|
24
|
+
} catch {
|
|
25
|
+
return {
|
|
26
|
+
name: 'docs'
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
}
|