|
| 1 | +import { getExternalBaseUrl } from "../utils/request"; |
| 2 | +import { respond } from "../utils/response"; |
| 3 | + |
| 4 | +function escapeHtml(value: string): string { |
| 5 | + return value |
| 6 | + .replaceAll("&", "&") |
| 7 | + .replaceAll("<", "<") |
| 8 | + .replaceAll(">", ">") |
| 9 | + .replaceAll("\"", """) |
| 10 | + .replaceAll("'", "'"); |
| 11 | +} |
| 12 | + |
| 13 | +function escapeAttributeJson(value: Record<string, unknown>): string { |
| 14 | + return escapeHtml(JSON.stringify(value)); |
| 15 | +} |
| 16 | + |
| 17 | +export default defineEventHandler((event) => { |
| 18 | + const baseUrl = getExternalBaseUrl(event); |
| 19 | + const canonicalUrl = `${baseUrl}/docs`; |
| 20 | + const openApiUrl = `${baseUrl}/openapi.json`; |
| 21 | + const scalarConfig = { |
| 22 | + url: openApiUrl, |
| 23 | + }; |
| 24 | + |
| 25 | + const html = `<!doctype html> |
| 26 | +<html lang="en"> |
| 27 | + <head> |
| 28 | + <meta charset="utf-8"> |
| 29 | + <meta name="viewport" content="width=device-width, initial-scale=1"> |
| 30 | + <title>NitroCraft API Docs</title> |
| 31 | + <meta name="description" content="Interactive NitroCraft API reference powered by Scalar."> |
| 32 | + <link rel="canonical" href="${escapeHtml(canonicalUrl)}"> |
| 33 | + <style> |
| 34 | + :root { |
| 35 | + color-scheme: light dark; |
| 36 | + } |
| 37 | +
|
| 38 | + body { |
| 39 | + margin: 0; |
| 40 | + font-family: "Segoe UI", system-ui, -apple-system, sans-serif; |
| 41 | + background: #0b1220; |
| 42 | + color: #e2e8f0; |
| 43 | + } |
| 44 | +
|
| 45 | + .docs-topbar { |
| 46 | + position: sticky; |
| 47 | + top: 0; |
| 48 | + z-index: 5; |
| 49 | + display: flex; |
| 50 | + align-items: center; |
| 51 | + justify-content: space-between; |
| 52 | + padding: 0.75rem 1rem; |
| 53 | + background: rgba(11, 18, 32, 0.92); |
| 54 | + border-bottom: 1px solid rgba(148, 163, 184, 0.25); |
| 55 | + backdrop-filter: blur(8px); |
| 56 | + } |
| 57 | +
|
| 58 | + .docs-topbar a { |
| 59 | + color: #93c5fd; |
| 60 | + text-decoration: none; |
| 61 | + font-weight: 600; |
| 62 | + } |
| 63 | + </style> |
| 64 | + </head> |
| 65 | + <body> |
| 66 | + <header class="docs-topbar"> |
| 67 | + <a href="/">NitroCraft</a> |
| 68 | + <a href="${escapeHtml(openApiUrl)}">OpenAPI JSON</a> |
| 69 | + </header> |
| 70 | + <script id="api-reference" data-configuration="${escapeAttributeJson(scalarConfig)}"></script> |
| 71 | + <script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script> |
| 72 | + </body> |
| 73 | +</html>`; |
| 74 | + |
| 75 | + return respond(event, { |
| 76 | + status: 1, |
| 77 | + body: html, |
| 78 | + type: "text/html; charset=utf-8", |
| 79 | + cacheControl: "no-cache, max-age=0", |
| 80 | + }); |
| 81 | +}); |
0 commit comments