feat: initial openapi page with imported api spec

This commit is contained in:
h+
2025-01-05 23:10:35 +01:00
parent c33b6f7457
commit 72e8f4c610
9 changed files with 7146 additions and 219 deletions
+3
View File
@@ -1,4 +1,5 @@
import { fileURLToPath, URL } from 'node:url' import { fileURLToPath, URL } from 'node:url'
import yaml from 'vite-plugin-yaml'
import { defineConfig } from 'vitepress' import { defineConfig } from 'vitepress'
// https://vitepress.dev/reference/site-config // https://vitepress.dev/reference/site-config
export default defineConfig({ export default defineConfig({
@@ -344,6 +345,8 @@ export default defineConfig({
rewrites: {}, rewrites: {},
vite: { vite: {
plugins: [yaml as any],
assetsInclude: ['**/*.yml'],
resolve: { resolve: {
alias: [ alias: [
{ {
@@ -1,5 +1,5 @@
<template> <template>
<div ref="globeContainer" class="absolute -top-20 w-full h-[500px] pointer-events-none"></div> <div ref="globeContainer" class="absolute -top-32 w-full h-[500px] pointer-events-none"></div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -1,8 +1,5 @@
<template> <template>
<div class="relative flex flex-col gap-4 max-w-md"> <div class="relative flex flex-col gap-4 max-w-lg">
<div class="flex flex-row gap-2 z-10">
<VPBadge text="For Coolify Cloud and Self Host" />
</div>
<div class="flex flex-row gap-2 z-10"> <div class="flex flex-row gap-2 z-10">
<h3 class="text-2xl font-bold tracking-wide">{{ referralTitle }}</h3> <h3 class="text-2xl font-bold tracking-wide">{{ referralTitle }}</h3>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 181.42 22.24" class="w-auto size-3 my-auto mr-0 ml-auto"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 181.42 22.24" class="w-auto size-3 my-auto mr-0 ml-auto">
@@ -98,7 +95,7 @@
<path fill="#77B255" d="M31.999 13L36 7.999L33 6z" /> <path fill="#77B255" d="M31.999 13L36 7.999L33 6z" />
</svg> </svg>
<span :class="{ 'ml-2': isCopied }" class="my-auto"> <span :class="{ 'ml-2': isCopied }" class="my-auto">
{{ !isCopied ? referralDescription : 'Copied to clipboard!' }} {{ !isCopied ? '' : 'Copied to clipboard!' }}
</span> </span>
</p> </p>
<ClientOnly> <ClientOnly>
+41 -31
View File
@@ -1,37 +1,47 @@
// https://vitepress.dev/guide/custom-theme // https://vitepress.dev/guide/custom-theme
import { h } from 'vue' import type { Theme } from "vitepress";
import type { Theme } from 'vitepress' import { theme, useOpenapi } from "vitepress-openapi";
import DefaultTheme from 'vitepress/theme' import DefaultTheme from "vitepress/theme";
import './style.css' import "./style.css";
import './tailwind.postcss' import "./tailwind.postcss";
import Card from './components/Card.vue' import "vitepress-openapi/dist/style.css";
import CardGroup from './components/CardGroup.vue' import Card from "./components/Card.vue";
import Landing from './layouts/Landing.vue' import CardGroup from "./components/CardGroup.vue";
import Sections from './components/Landing/Sections.vue' import Landing from "./layouts/Landing.vue";
import Features from './components/Landing/Features.vue' import Sections from "./components/Landing/Sections.vue";
import Installer from './components/Landing/Installer.vue' import Features from "./components/Landing/Features.vue";
import Referral from './components/Landing/Referral.vue' import Installer from "./components/Landing/Installer.vue";
import Callout from './components/Callout.vue' import Referral from "./components/Landing/Referral.vue";
import TabBlock from './components/TabBlock.vue' import Callout from "./components/Callout.vue";
import ZoomableImage from './components/ZoomableImage.vue' import TabBlock from "./components/TabBlock.vue";
import Globe from './components/Landing/Globe.vue' import ZoomableImage from "./components/ZoomableImage.vue";
import Browser from './components/Landing/Browser.vue' import Globe from "./components/Landing/Globe.vue";
import Browser from "./components/Landing/Browser.vue";
import { load } from 'js-yaml'
import rawSpec from '/openapi.yml?raw'
export default { export default {
extends: DefaultTheme, extends: DefaultTheme,
Layout: Landing, Layout: Landing,
enhanceApp({ app, router, siteData }) { enhanceApp({ app, router, siteData }) {
// register your custom global components const spec = load(rawSpec)
app.component('Card', Card) const openapi = useOpenapi({
app.component('CardGroup', CardGroup) spec,
app.component('LandingSection', Sections) base: "/docs/api-reference/api/overview/",
app.component('LandingFeatures', Features) label: "API",
app.component('Referral', Referral) });
app.component('Quickstart', Installer) // Use theme.enhanceApp with both app and openapi
app.component('Callout', Callout) theme.enhanceApp({ app, openapi });
app.component('TabBlock', TabBlock) app.component("Card", Card);
app.component('ZoomableImage', ZoomableImage) app.component("CardGroup", CardGroup);
app.component('Globe', Globe) app.component("LandingSection", Sections);
app.component('Browser', Browser) app.component("LandingFeatures", Features);
} app.component("Referral", Referral);
} satisfies Theme app.component("Quickstart", Installer);
app.component("Callout", Callout);
app.component("TabBlock", TabBlock);
app.component("ZoomableImage", ZoomableImage);
app.component("Globe", Globe);
app.component("Browser", Browser);
},
} satisfies Theme;
+95 -2
View File
@@ -1,6 +1,99 @@
--- ---
title: "API" aside: false
outline: false
title: API
toc: false
--- ---
# API Overiew <script setup lang="ts">
import { useData } from 'vitepress'
import { useTheme, generateCodeSample } from 'vitepress-openapi'
const { isDark } = useData()
useTheme({
codeSamples: {
// List of languages to show in Code Samples section.
langs: [
'bruno',
...useTheme().getCodeSamplesLangs(),
],
// List of available languages to select from.
availableLanguages: [
{
lang: 'bruno',
label: 'Bruno',
highlighter: 'plaintext',
},
...useTheme().getCodeSamplesAvailableLanguages(),
],
defaultLang: 'bruno',
generator: (lang, request) => {
if (lang === 'bruno') {
return generateBruRequest(request)
}
return generateCodeSample(lang, request)
},
},
})
function generateBruRequest(request) {
const { url, method, headers, body, query } = request;
const methodLower = method.toLowerCase();
const queryString = query && Object.keys(query).length
? `${url}?${new URLSearchParams(query).toString()}`
: url;
const headersSection = headers && Object.keys(headers).length
? `headers {\n${Object.entries(headers)
.map(([key, value]) => ` ${key}: ${value}`)
.join('\n')}\n}`
: '';
const bodySection = body
? `body {\n ${JSON.stringify(body, null, 2).replace(/\n/g, '\n ')}\n}`
: '';
const bruRequest = `${methodLower} {
url: ${queryString}
}
${headersSection}
${bodySection}
`;
return bruRequest
.trim()
.replace(/\n{2,}/g, '\n\n') // Remove extra newlines
}
</script>
<style>
:deep(.vp-doc a),
:deep([openapi] a),
:deep(a.grid) {
border-bottom: none !important;
text-decoration: none !important;
}
:deep(.vp-doc a:hover),
:deep([openapi] a:hover),
:deep(a.grid:hover) {
color: var(--vp-c-brand-1);
border-bottom: none !important;
text-decoration: none !important;
}
/* Additional specific override for grid links */
:deep(a.grid.items-center) {
border-bottom: none !important;
text-decoration: none !important;
}
</style>
<OASpec :isDark="isDark" />
File diff suppressed because it is too large Load Diff
Vendored
+14
View File
@@ -0,0 +1,14 @@
declare module "*.yml" {
const content: any;
export default content;
}
declare module "*?url" {
const content: string;
export default content;
}
declare module '*?raw' {
const content: string
export default content
}
+3 -1
View File
@@ -10,6 +10,7 @@
"postcss": "^8.4.20", "postcss": "^8.4.20",
"tailwindcss": "^3.2.4", "tailwindcss": "^3.2.4",
"tsx": "^4.19.2", "tsx": "^4.19.2",
"vite-plugin-yaml": "^1.0.5",
"vitepress": "^1.5.0", "vitepress": "^1.5.0",
"vue": "^3.5.13" "vue": "^3.5.13"
}, },
@@ -28,6 +29,7 @@
}, },
"dependencies": { "dependencies": {
"@vueuse/core": "^12.2.0", "@vueuse/core": "^12.2.0",
"globe.gl": "^2.34.6" "globe.gl": "^2.34.6",
"vitepress-openapi": "0.0.3-alpha.55"
} }
} }
+1645 -179
View File
File diff suppressed because it is too large Load Diff