vocs 2.0.17 → 2.1.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/dist/config.d.ts +1 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/globals.d.ts +16 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/internal/config.d.ts +28 -0
- package/dist/internal/config.d.ts.map +1 -1
- package/dist/internal/config.js +10 -2
- package/dist/internal/config.js.map +1 -1
- package/dist/internal/llms.d.ts +21 -2
- package/dist/internal/llms.d.ts.map +1 -1
- package/dist/internal/llms.js +41 -1
- package/dist/internal/llms.js.map +1 -1
- package/dist/internal/markdown-negotiation.d.ts +36 -0
- package/dist/internal/markdown-negotiation.d.ts.map +1 -0
- package/dist/internal/markdown-negotiation.js +81 -0
- package/dist/internal/markdown-negotiation.js.map +1 -0
- package/dist/internal/markdown.d.ts.map +1 -1
- package/dist/internal/markdown.js +5 -0
- package/dist/internal/markdown.js.map +1 -1
- package/dist/internal/openapi/anchors.d.ts +25 -0
- package/dist/internal/openapi/anchors.d.ts.map +1 -0
- package/dist/internal/openapi/anchors.js +37 -0
- package/dist/internal/openapi/anchors.js.map +1 -0
- package/dist/internal/openapi/app.d.ts +89 -0
- package/dist/internal/openapi/app.d.ts.map +1 -0
- package/dist/internal/openapi/app.js +62 -0
- package/dist/internal/openapi/app.js.map +1 -0
- package/dist/internal/openapi/index.d.ts +8 -0
- package/dist/internal/openapi/index.d.ts.map +1 -0
- package/dist/internal/openapi/index.js +5 -0
- package/dist/internal/openapi/index.js.map +1 -0
- package/dist/internal/openapi/markdown.d.ts +42 -0
- package/dist/internal/openapi/markdown.d.ts.map +1 -0
- package/dist/internal/openapi/markdown.js +235 -0
- package/dist/internal/openapi/markdown.js.map +1 -0
- package/dist/internal/openapi/openapi.d.ts +187 -0
- package/dist/internal/openapi/openapi.d.ts.map +1 -0
- package/dist/internal/openapi/openapi.js +44 -0
- package/dist/internal/openapi/openapi.js.map +1 -0
- package/dist/internal/openapi/openrpc.d.ts +90 -0
- package/dist/internal/openapi/openrpc.d.ts.map +1 -0
- package/dist/internal/openapi/openrpc.js +213 -0
- package/dist/internal/openapi/openrpc.js.map +1 -0
- package/dist/internal/openapi/parser.d.ts +181 -0
- package/dist/internal/openapi/parser.d.ts.map +1 -0
- package/dist/internal/openapi/parser.js +329 -0
- package/dist/internal/openapi/parser.js.map +1 -0
- package/dist/internal/openapi/registry.d.ts +36 -0
- package/dist/internal/openapi/registry.d.ts.map +1 -0
- package/dist/internal/openapi/registry.js +79 -0
- package/dist/internal/openapi/registry.js.map +1 -0
- package/dist/internal/openapi/sample.d.ts +115 -0
- package/dist/internal/openapi/sample.d.ts.map +1 -0
- package/dist/internal/openapi/sample.js +434 -0
- package/dist/internal/openapi/sample.js.map +1 -0
- package/dist/internal/openapi/search.d.ts +19 -0
- package/dist/internal/openapi/search.d.ts.map +1 -0
- package/dist/internal/openapi/search.js +98 -0
- package/dist/internal/openapi/search.js.map +1 -0
- package/dist/internal/openapi/sidebar.d.ts +30 -0
- package/dist/internal/openapi/sidebar.d.ts.map +1 -0
- package/dist/internal/openapi/sidebar.js +67 -0
- package/dist/internal/openapi/sidebar.js.map +1 -0
- package/dist/internal/openapi/union.d.ts +36 -0
- package/dist/internal/openapi/union.d.ts.map +1 -0
- package/dist/internal/openapi/union.js +69 -0
- package/dist/internal/openapi/union.js.map +1 -0
- package/dist/internal/search.d.ts.map +1 -1
- package/dist/internal/search.js +20 -0
- package/dist/internal/search.js.map +1 -1
- package/dist/internal/vite-plugins.d.ts +12 -0
- package/dist/internal/vite-plugins.d.ts.map +1 -1
- package/dist/internal/vite-plugins.js +102 -11
- package/dist/internal/vite-plugins.js.map +1 -1
- package/dist/react/Badge.d.ts +2 -3
- package/dist/react/Badge.d.ts.map +1 -1
- package/dist/react/Layout.client.d.ts.map +1 -1
- package/dist/react/Layout.client.js +2 -2
- package/dist/react/Layout.client.js.map +1 -1
- package/dist/react/OpenApi.d.ts +6 -0
- package/dist/react/OpenApi.d.ts.map +1 -0
- package/dist/react/OpenApi.js +6 -0
- package/dist/react/OpenApi.js.map +1 -0
- package/dist/react/internal/CodeToHtml.client.d.ts +53 -2
- package/dist/react/internal/CodeToHtml.client.d.ts.map +1 -1
- package/dist/react/internal/CodeToHtml.client.js +154 -21
- package/dist/react/internal/CodeToHtml.client.js.map +1 -1
- package/dist/react/internal/Sidebar.d.ts.map +1 -1
- package/dist/react/internal/Sidebar.js +99 -2
- package/dist/react/internal/Sidebar.js.map +1 -1
- package/dist/react/internal/openapi/CodeSample.client.d.ts +21 -0
- package/dist/react/internal/openapi/CodeSample.client.d.ts.map +1 -0
- package/dist/react/internal/openapi/CodeSample.client.js +134 -0
- package/dist/react/internal/openapi/CodeSample.client.js.map +1 -0
- package/dist/react/internal/openapi/CollapsibleChildren.client.d.ts +17 -0
- package/dist/react/internal/openapi/CollapsibleChildren.client.d.ts.map +1 -0
- package/dist/react/internal/openapi/CollapsibleChildren.client.js +18 -0
- package/dist/react/internal/openapi/CollapsibleChildren.client.js.map +1 -0
- package/dist/react/internal/openapi/Disclosure.client.d.ts +28 -0
- package/dist/react/internal/openapi/Disclosure.client.d.ts.map +1 -0
- package/dist/react/internal/openapi/Disclosure.client.js +38 -0
- package/dist/react/internal/openapi/Disclosure.client.js.map +1 -0
- package/dist/react/internal/openapi/Endpoints.d.ts +26 -0
- package/dist/react/internal/openapi/Endpoints.d.ts.map +1 -0
- package/dist/react/internal/openapi/Endpoints.js +33 -0
- package/dist/react/internal/openapi/Endpoints.js.map +1 -0
- package/dist/react/internal/openapi/EndpointsView.d.ts +24 -0
- package/dist/react/internal/openapi/EndpointsView.d.ts.map +1 -0
- package/dist/react/internal/openapi/EndpointsView.js +26 -0
- package/dist/react/internal/openapi/EndpointsView.js.map +1 -0
- package/dist/react/internal/openapi/EnumValues.client.d.ts +14 -0
- package/dist/react/internal/openapi/EnumValues.client.d.ts.map +1 -0
- package/dist/react/internal/openapi/EnumValues.client.js +20 -0
- package/dist/react/internal/openapi/EnumValues.client.js.map +1 -0
- package/dist/react/internal/openapi/HeadingAnchor.d.ts +15 -0
- package/dist/react/internal/openapi/HeadingAnchor.d.ts.map +1 -0
- package/dist/react/internal/openapi/HeadingAnchor.js +12 -0
- package/dist/react/internal/openapi/HeadingAnchor.js.map +1 -0
- package/dist/react/internal/openapi/OpenApiPage.d.ts +79 -0
- package/dist/react/internal/openapi/OpenApiPage.d.ts.map +1 -0
- package/dist/react/internal/openapi/OpenApiPage.js +72 -0
- package/dist/react/internal/openapi/OpenApiPage.js.map +1 -0
- package/dist/react/internal/openapi/Operation.d.ts +25 -0
- package/dist/react/internal/openapi/Operation.d.ts.map +1 -0
- package/dist/react/internal/openapi/Operation.js +101 -0
- package/dist/react/internal/openapi/Operation.js.map +1 -0
- package/dist/react/internal/openapi/Playground.client.d.ts +33 -0
- package/dist/react/internal/openapi/Playground.client.d.ts.map +1 -0
- package/dist/react/internal/openapi/Playground.client.js +170 -0
- package/dist/react/internal/openapi/Playground.client.js.map +1 -0
- package/dist/react/internal/openapi/PropertyExample.client.d.ts +17 -0
- package/dist/react/internal/openapi/PropertyExample.client.d.ts.map +1 -0
- package/dist/react/internal/openapi/PropertyExample.client.js +21 -0
- package/dist/react/internal/openapi/PropertyExample.client.js.map +1 -0
- package/dist/react/internal/openapi/Reference.d.ts +55 -0
- package/dist/react/internal/openapi/Reference.d.ts.map +1 -0
- package/dist/react/internal/openapi/Reference.js +42 -0
- package/dist/react/internal/openapi/Reference.js.map +1 -0
- package/dist/react/internal/openapi/Schema.d.ts +110 -0
- package/dist/react/internal/openapi/Schema.d.ts.map +1 -0
- package/dist/react/internal/openapi/Schema.js +239 -0
- package/dist/react/internal/openapi/Schema.js.map +1 -0
- package/dist/react/internal/openapi/SchemaUnion.client.d.ts +25 -0
- package/dist/react/internal/openapi/SchemaUnion.client.d.ts.map +1 -0
- package/dist/react/internal/openapi/SchemaUnion.client.js +48 -0
- package/dist/react/internal/openapi/SchemaUnion.client.js.map +1 -0
- package/dist/react/internal/openapi/anchor-navigation.client.d.ts +47 -0
- package/dist/react/internal/openapi/anchor-navigation.client.d.ts.map +1 -0
- package/dist/react/internal/openapi/anchor-navigation.client.js +120 -0
- package/dist/react/internal/openapi/anchor-navigation.client.js.map +1 -0
- package/dist/react/internal/openapi/auth.d.ts +28 -0
- package/dist/react/internal/openapi/auth.d.ts.map +1 -0
- package/dist/react/internal/openapi/auth.js +75 -0
- package/dist/react/internal/openapi/auth.js.map +1 -0
- package/dist/react/useLayout.d.ts +2 -0
- package/dist/react/useLayout.d.ts.map +1 -1
- package/dist/react/useLayout.js +2 -0
- package/dist/react/useLayout.js.map +1 -1
- package/dist/server/handlers.d.ts +1 -1
- package/dist/server/handlers.d.ts.map +1 -1
- package/dist/server/handlers.js +26 -5
- package/dist/server/handlers.js.map +1 -1
- package/dist/server/og-assets.d.ts +5 -0
- package/dist/server/og-assets.d.ts.map +1 -0
- package/dist/server/og-assets.js +11 -0
- package/dist/server/og-assets.js.map +1 -0
- package/dist/server/openapi/assets.d.ts +33 -0
- package/dist/server/openapi/assets.d.ts.map +1 -0
- package/dist/server/openapi/assets.generated.d.ts +9 -0
- package/dist/server/openapi/assets.generated.d.ts.map +1 -0
- package/dist/server/openapi/assets.generated.js +1091 -0
- package/dist/server/openapi/assets.generated.js.map +1 -0
- package/dist/server/openapi/assets.js +32 -0
- package/dist/server/openapi/assets.js.map +1 -0
- package/dist/server/openapi/handler.d.ts +103 -0
- package/dist/server/openapi/handler.d.ts.map +1 -0
- package/dist/server/openapi/handler.js +198 -0
- package/dist/server/openapi/handler.js.map +1 -0
- package/dist/server/openapi/handler.test.d.ts +2 -0
- package/dist/server/openapi/handler.test.d.ts.map +1 -0
- package/dist/server/openapi/handler.test.js +203 -0
- package/dist/server/openapi/handler.test.js.map +1 -0
- package/dist/server/openapi/html.d.ts +16 -0
- package/dist/server/openapi/html.d.ts.map +1 -0
- package/dist/server/openapi/html.js +75 -0
- package/dist/server/openapi/html.js.map +1 -0
- package/dist/server/openapi/pages.d.ts +33 -0
- package/dist/server/openapi/pages.d.ts.map +1 -0
- package/dist/server/openapi/pages.js +130 -0
- package/dist/server/openapi/pages.js.map +1 -0
- package/dist/server/openapi/pages.test.d.ts +2 -0
- package/dist/server/openapi/pages.test.d.ts.map +1 -0
- package/dist/server/openapi/pages.test.js +94 -0
- package/dist/server/openapi/pages.test.js.map +1 -0
- package/dist/server/openapi/state.d.ts +42 -0
- package/dist/server/openapi/state.d.ts.map +1 -0
- package/dist/server/openapi/state.js +101 -0
- package/dist/server/openapi/state.js.map +1 -0
- package/dist/styles/index.css +16 -0
- package/dist/styles/markdown.css +9 -7
- package/dist/styles/openapi-playground.css +80 -0
- package/dist/styles/openapi.css +660 -0
- package/dist/vite.d.ts.map +1 -1
- package/dist/vite.js +1 -0
- package/dist/vite.js.map +1 -1
- package/dist/waku/internal/middleware/md-router.d.ts +0 -4
- package/dist/waku/internal/middleware/md-router.d.ts.map +1 -1
- package/dist/waku/internal/middleware/md-router.js +3 -48
- package/dist/waku/internal/middleware/md-router.js.map +1 -1
- package/dist/waku/internal/patches/adapters/vercel-build-enhancer.js +1 -1
- package/dist/waku/internal/patches/adapters/vercel-build-enhancer.js.map +1 -1
- package/dist/waku/internal/patches/router.d.ts.map +1 -1
- package/dist/waku/internal/patches/router.js +114 -1
- package/dist/waku/internal/patches/router.js.map +1 -1
- package/package.json +5 -1
- package/src/config.ts +1 -0
- package/src/globals.d.ts +16 -0
- package/src/index.ts +1 -0
- package/src/internal/config.ts +40 -1
- package/src/internal/llms.ts +51 -1
- package/src/internal/markdown-negotiation.test.ts +42 -0
- package/src/internal/markdown-negotiation.ts +95 -0
- package/src/internal/markdown.ts +5 -0
- package/src/internal/openapi/anchors.ts +44 -0
- package/src/internal/openapi/app.ts +127 -0
- package/src/internal/openapi/index.ts +24 -0
- package/src/internal/openapi/markdown.test.ts +115 -0
- package/src/internal/openapi/markdown.ts +275 -0
- package/src/internal/openapi/openapi.ts +212 -0
- package/src/internal/openapi/openrpc.test.ts +239 -0
- package/src/internal/openapi/openrpc.ts +295 -0
- package/src/internal/openapi/parser.test.ts +203 -0
- package/src/internal/openapi/parser.ts +613 -0
- package/src/internal/openapi/registry.test.ts +89 -0
- package/src/internal/openapi/registry.ts +89 -0
- package/src/internal/openapi/sample.test.ts +283 -0
- package/src/internal/openapi/sample.ts +562 -0
- package/src/internal/openapi/search.test.ts +62 -0
- package/src/internal/openapi/search.ts +108 -0
- package/src/internal/openapi/sidebar.test.ts +131 -0
- package/src/internal/openapi/sidebar.ts +94 -0
- package/src/internal/openapi/union.test.ts +51 -0
- package/src/internal/openapi/union.ts +74 -0
- package/src/internal/search.ts +20 -0
- package/src/internal/test/virtual-config.stub.ts +14 -0
- package/src/internal/vite-plugins.ts +106 -11
- package/src/openapi-app/App.tsx +64 -0
- package/src/openapi-app/blocks.tsx +33 -0
- package/src/openapi-app/client.tsx +25 -0
- package/src/openapi-app/links.test.ts +84 -0
- package/src/openapi-app/links.ts +66 -0
- package/src/openapi-app/payload.ts +20 -0
- package/src/openapi-app/virtual/config.ts +7 -0
- package/src/openapi-app/virtual/group-icons.ts +2 -0
- package/src/openapi-app/virtual/langs.ts +6 -0
- package/src/openapi-app/virtual/openapi.ts +10 -0
- package/src/openapi-app/virtual/search-index.ts +21 -0
- package/src/openapi-app/virtual/slots.ts +4 -0
- package/src/openapi-app/virtual/user-styles.ts +2 -0
- package/src/openapi-app/waku.tsx +154 -0
- package/src/react/Badge.tsx +2 -3
- package/src/react/Layout.client.tsx +17 -4
- package/src/react/OpenApi.tsx +5 -0
- package/src/react/internal/CodeToHtml.client.tsx +283 -22
- package/src/react/internal/Sidebar.tsx +126 -22
- package/src/react/internal/openapi/CodeSample.client.tsx +294 -0
- package/src/react/internal/openapi/CollapsibleChildren.client.tsx +41 -0
- package/src/react/internal/openapi/Disclosure.client.tsx +67 -0
- package/src/react/internal/openapi/Endpoints.tsx +58 -0
- package/src/react/internal/openapi/EndpointsView.tsx +76 -0
- package/src/react/internal/openapi/EnumValues.client.tsx +49 -0
- package/src/react/internal/openapi/HeadingAnchor.tsx +28 -0
- package/src/react/internal/openapi/OpenApiPage.tsx +173 -0
- package/src/react/internal/openapi/Operation.test.tsx +101 -0
- package/src/react/internal/openapi/Operation.tsx +335 -0
- package/src/react/internal/openapi/Playground.client.tsx +234 -0
- package/src/react/internal/openapi/PropertyExample.client.tsx +55 -0
- package/src/react/internal/openapi/Reference.tsx +120 -0
- package/src/react/internal/openapi/Schema.tsx +467 -0
- package/src/react/internal/openapi/SchemaUnion.client.tsx +123 -0
- package/src/react/internal/openapi/anchor-navigation.client.ts +154 -0
- package/src/react/internal/openapi/auth.ts +69 -0
- package/src/react/useLayout.ts +4 -0
- package/src/server/handlers.ts +31 -6
- package/src/server/og-assets.ts +14 -0
- package/src/server/openapi/assets.generated.ts +1093 -0
- package/src/server/openapi/assets.ts +57 -0
- package/src/server/openapi/handler.test.ts +244 -0
- package/src/server/openapi/handler.ts +277 -0
- package/src/server/openapi/html.ts +84 -0
- package/src/server/openapi/pages.test.ts +111 -0
- package/src/server/openapi/pages.ts +153 -0
- package/src/server/openapi/state.ts +136 -0
- package/src/styles/index.css +16 -0
- package/src/styles/markdown.css +9 -7
- package/src/styles/openapi-playground.css +80 -0
- package/src/styles/openapi.css +660 -0
- package/src/vite.ts +1 -0
- package/src/waku/internal/middleware/md-router.ts +8 -52
- package/src/waku/internal/patches/adapters/vercel-build-enhancer.ts +1 -1
- package/src/waku/internal/patches/router.ts +131 -1
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
// Scalar's stylesheet, loaded with this client-only chunk (i.e. only on
|
|
4
|
+
// OpenAPI pages). It is largely unlayered, so it outranks Vocs's layered
|
|
5
|
+
// Tailwind and styles the modal without further layer wiring. During SSR this
|
|
6
|
+
// import is a no-op. A static import is used because Vite reliably injects CSS
|
|
7
|
+
// for static client imports, unlike dynamic `import('*.css')`.
|
|
8
|
+
import '@scalar/api-client/style.css'
|
|
9
|
+
// Maps Scalar's theme variables onto Vocs tokens (loaded after Scalar's CSS so
|
|
10
|
+
// the overrides win). Lives under `src/styles` so the build emits it to
|
|
11
|
+
// `dist/styles` (zile only copies CSS assets reachable from the `./styles/*`
|
|
12
|
+
// export glob; a colocated `./playground.css` would not be emitted).
|
|
13
|
+
import '../../../styles/openapi-playground.css'
|
|
14
|
+
import * as React from 'react'
|
|
15
|
+
import { createPortal } from 'react-dom'
|
|
16
|
+
import LucidePlay from '~icons/lucide/play'
|
|
17
|
+
import type { Ir } from '../../../internal/openapi/parser.js'
|
|
18
|
+
import { useColorScheme } from '../../useColorScheme.js'
|
|
19
|
+
import * as Auth from './auth.js'
|
|
20
|
+
|
|
21
|
+
type OpenFn = (operation: { method: string; path: string; example?: string | undefined }) => void
|
|
22
|
+
|
|
23
|
+
const PlaygroundContext = React.createContext<{ open: OpenFn; ready: boolean } | null>(null)
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Mounts the Scalar API client modal once per spec and exposes an `open`
|
|
27
|
+
* function to its descendants. The modal is a Vue app loaded lazily on the
|
|
28
|
+
* client only (Scalar is untested under SSR), so nothing is imported during
|
|
29
|
+
* server rendering.
|
|
30
|
+
*/
|
|
31
|
+
export function PlaygroundProvider(props: PlaygroundProvider.Props) {
|
|
32
|
+
const { client, children, mount: specMount = '/' } = props
|
|
33
|
+
const containerRef = React.useRef<HTMLDivElement>(null)
|
|
34
|
+
// biome-ignore lint/suspicious/noExplicitAny: Scalar's modal type lives in a client-only module.
|
|
35
|
+
const modalRef = React.useRef<any>(null)
|
|
36
|
+
// The Scalar workspace store backing the modal; kept so cross-page auth
|
|
37
|
+
// updates can be loaded into the live store without reopening the modal.
|
|
38
|
+
// biome-ignore lint/suspicious/noExplicitAny: client-only Scalar store instance.
|
|
39
|
+
const storeRef = React.useRef<any>(null)
|
|
40
|
+
const [ready, setReady] = React.useState(false)
|
|
41
|
+
|
|
42
|
+
React.useEffect(() => {
|
|
43
|
+
let cancelled = false
|
|
44
|
+
// biome-ignore lint/suspicious/noExplicitAny: client-only Scalar app instance.
|
|
45
|
+
let modal: any = null
|
|
46
|
+
|
|
47
|
+
async function mount() {
|
|
48
|
+
try {
|
|
49
|
+
const [{ createWorkspaceStore }, { createApiClientModal }] = await Promise.all([
|
|
50
|
+
import('@scalar/workspace-store/client'),
|
|
51
|
+
import('@scalar/api-client/modal'),
|
|
52
|
+
])
|
|
53
|
+
|
|
54
|
+
// Register a plugin so we're notified whenever the consumer edits
|
|
55
|
+
// credentials in Scalar's "Try" auth UI. We mirror Scalar's exported
|
|
56
|
+
// auth state into localStorage so every other playground instance
|
|
57
|
+
// (other pages, future reloads) picks it up.
|
|
58
|
+
const store = createWorkspaceStore({
|
|
59
|
+
plugins: [
|
|
60
|
+
{
|
|
61
|
+
hooks: {
|
|
62
|
+
onWorkspaceStateChanges(event) {
|
|
63
|
+
if (event.type !== 'auth') return
|
|
64
|
+
const next = serializeAuth(store)
|
|
65
|
+
// Skip writes that match what's already stored — including the
|
|
66
|
+
// change fired by our own `auth.load()` below — to avoid a
|
|
67
|
+
// persist → subscribe → load → persist feedback loop.
|
|
68
|
+
if (next === Auth.read(specMount)) return
|
|
69
|
+
Auth.write(specMount, next)
|
|
70
|
+
},
|
|
71
|
+
},
|
|
72
|
+
},
|
|
73
|
+
],
|
|
74
|
+
})
|
|
75
|
+
storeRef.current = store
|
|
76
|
+
await store.addDocument({
|
|
77
|
+
name: 'default',
|
|
78
|
+
...('url' in client ? { url: client.url } : { document: client.content }),
|
|
79
|
+
})
|
|
80
|
+
if (cancelled) return
|
|
81
|
+
|
|
82
|
+
// Seed credentials captured from a previous "Try" session (this page's
|
|
83
|
+
// first mount, another page, or a prior visit).
|
|
84
|
+
loadStoredAuth(store, specMount)
|
|
85
|
+
|
|
86
|
+
modal = createApiClientModal({
|
|
87
|
+
el: containerRef.current,
|
|
88
|
+
workspaceStore: store,
|
|
89
|
+
})
|
|
90
|
+
modalRef.current = modal
|
|
91
|
+
setReady(true)
|
|
92
|
+
} catch (error) {
|
|
93
|
+
// Surface load failures without breaking the docs page.
|
|
94
|
+
console.error('[vocs] Failed to initialize the OpenAPI playground.', error)
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
mount()
|
|
99
|
+
return () => {
|
|
100
|
+
cancelled = true
|
|
101
|
+
try {
|
|
102
|
+
modal?.app?.unmount()
|
|
103
|
+
} catch {}
|
|
104
|
+
modalRef.current = null
|
|
105
|
+
storeRef.current = null
|
|
106
|
+
}
|
|
107
|
+
}, [client, specMount])
|
|
108
|
+
|
|
109
|
+
// When another playground instance (another page/tab) persists new
|
|
110
|
+
// credentials, load them into this live store so its "Try" stays in sync
|
|
111
|
+
// without reopening the modal.
|
|
112
|
+
React.useEffect(
|
|
113
|
+
() =>
|
|
114
|
+
Auth.subscribe(specMount, () => {
|
|
115
|
+
const store = storeRef.current
|
|
116
|
+
if (store) loadStoredAuth(store, specMount)
|
|
117
|
+
}),
|
|
118
|
+
[specMount],
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
const open = React.useCallback<OpenFn>((operation) => {
|
|
122
|
+
modalRef.current?.open({
|
|
123
|
+
method: operation.method.toLowerCase(),
|
|
124
|
+
path: operation.path,
|
|
125
|
+
// Preselect the JSON-RPC method's request example (expanded OpenRPC
|
|
126
|
+
// operations all share one path + verb, so the example disambiguates).
|
|
127
|
+
...(operation.example ? { example: operation.example } : {}),
|
|
128
|
+
})
|
|
129
|
+
}, [])
|
|
130
|
+
|
|
131
|
+
const value = React.useMemo(() => ({ open, ready }), [open, ready])
|
|
132
|
+
|
|
133
|
+
// Render the Scalar host at `document.body` (client-only) so it sits outside
|
|
134
|
+
// Vocs's layout: a transformed/contained ancestor would otherwise break the
|
|
135
|
+
// modal's `position: fixed` overlay.
|
|
136
|
+
const [mounted, setMounted] = React.useState(false)
|
|
137
|
+
React.useEffect(() => setMounted(true), [])
|
|
138
|
+
|
|
139
|
+
// Scalar's `--scalar-*` theme variables are defined under `.light-mode` /
|
|
140
|
+
// `.dark-mode`; without one of those classes every `var(--scalar-*)` resolves
|
|
141
|
+
// to nothing. Mirror Vocs's active color scheme onto the host.
|
|
142
|
+
const colorScheme = useColorScheme()
|
|
143
|
+
|
|
144
|
+
return (
|
|
145
|
+
<PlaygroundContext.Provider value={value}>
|
|
146
|
+
{children}
|
|
147
|
+
{mounted &&
|
|
148
|
+
createPortal(
|
|
149
|
+
// Scalar scopes ~all of its CSS under `.scalar-app`/`.scalar-client`,
|
|
150
|
+
// so everything it renders must live inside an element with those
|
|
151
|
+
// classes. The dialog teleports (via @headlessui/vue) into
|
|
152
|
+
// `#headlessui-portal-root`; pre-creating that node here — inside the
|
|
153
|
+
// Scalar scope — makes Headless UI reuse it instead of appending a
|
|
154
|
+
// bare node to `<body>`, so the dialog inherits Scalar's styles.
|
|
155
|
+
<div
|
|
156
|
+
className={`scalar-app scalar-client ${colorScheme === 'dark' ? 'dark-mode' : 'light-mode'}`}
|
|
157
|
+
data-v-openapi-playground-root
|
|
158
|
+
>
|
|
159
|
+
<div ref={containerRef} />
|
|
160
|
+
<div id="headlessui-portal-root" />
|
|
161
|
+
</div>,
|
|
162
|
+
document.body,
|
|
163
|
+
)}
|
|
164
|
+
</PlaygroundContext.Provider>
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
export declare namespace PlaygroundProvider {
|
|
169
|
+
type Props = {
|
|
170
|
+
client: Ir['client']
|
|
171
|
+
children: React.ReactNode
|
|
172
|
+
/** Spec mount path; scopes the persisted auth (e.g. `/api`). */
|
|
173
|
+
mount?: string | undefined
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Serializes Scalar's exported auth state to a JSON string for persistence,
|
|
179
|
+
* or `null` when the store holds no credentials.
|
|
180
|
+
*/
|
|
181
|
+
// biome-ignore lint/suspicious/noExplicitAny: client-only Scalar store instance.
|
|
182
|
+
function serializeAuth(store: any): string | null {
|
|
183
|
+
try {
|
|
184
|
+
const data = store.auth.export()
|
|
185
|
+
return data && Object.keys(data).length > 0 ? JSON.stringify(data) : null
|
|
186
|
+
} catch {
|
|
187
|
+
return null
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Loads the persisted auth blob for a mount into a Scalar store. Skips the load
|
|
193
|
+
* when the store already matches what's stored, so the change `auth.load()`
|
|
194
|
+
* fires doesn't churn or feed back into a persist loop.
|
|
195
|
+
*/
|
|
196
|
+
// biome-ignore lint/suspicious/noExplicitAny: client-only Scalar store instance.
|
|
197
|
+
function loadStoredAuth(store: any, mount: string): void {
|
|
198
|
+
const saved = Auth.read(mount)
|
|
199
|
+
if (!saved || saved === serializeAuth(store)) return
|
|
200
|
+
try {
|
|
201
|
+
store.auth.load(JSON.parse(saved))
|
|
202
|
+
} catch {}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Button that opens the Scalar API client modal for a single operation. Renders
|
|
207
|
+
* a disabled placeholder until the modal finishes loading on the client.
|
|
208
|
+
*/
|
|
209
|
+
export function TestRequestButton(props: TestRequestButton.Props) {
|
|
210
|
+
const { method, path, example } = props
|
|
211
|
+
const context = React.useContext(PlaygroundContext)
|
|
212
|
+
|
|
213
|
+
return (
|
|
214
|
+
<button
|
|
215
|
+
type="button"
|
|
216
|
+
data-v-openapi-action
|
|
217
|
+
data-v-openapi-test-request
|
|
218
|
+
disabled={!context?.ready}
|
|
219
|
+
onClick={() => context?.open({ method, path, example })}
|
|
220
|
+
>
|
|
221
|
+
<LucidePlay data-v-openapi-action-icon />
|
|
222
|
+
Try
|
|
223
|
+
</button>
|
|
224
|
+
)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
export declare namespace TestRequestButton {
|
|
228
|
+
type Props = {
|
|
229
|
+
method: string
|
|
230
|
+
path: string
|
|
231
|
+
/** Name of the request example to preselect (JSON-RPC method name). */
|
|
232
|
+
example?: string | undefined
|
|
233
|
+
}
|
|
234
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
'use client'
|
|
2
|
+
|
|
3
|
+
import { useSyncExternalStore } from 'react'
|
|
4
|
+
import {
|
|
5
|
+
hasSampleLine,
|
|
6
|
+
revealSampleLine,
|
|
7
|
+
subscribeSampleAnchors,
|
|
8
|
+
} from './anchor-navigation.client.js'
|
|
9
|
+
|
|
10
|
+
/**
|
|
11
|
+
* A schema/parameter example value. When the sibling code sample renders a line
|
|
12
|
+
* for the same property — a response example line, or a request sample path/
|
|
13
|
+
* query parameter — the value becomes clickable and reveals (switching response
|
|
14
|
+
* tabs / expanding collapsed query params if needed) and flashes that right-hand
|
|
15
|
+
* line: the reverse of clicking a sample line to jump to this row.
|
|
16
|
+
*/
|
|
17
|
+
export function PropertyExample(props: PropertyExample.Props) {
|
|
18
|
+
const { id, value } = props
|
|
19
|
+
|
|
20
|
+
// Re-evaluate once the sibling `CodeSample` mounts and registers its anchors,
|
|
21
|
+
// so the affordance appears even though both mount around the same time.
|
|
22
|
+
const clickable = useSyncExternalStore(
|
|
23
|
+
subscribeSampleAnchors,
|
|
24
|
+
() => Boolean(id) && hasSampleLine(id as string),
|
|
25
|
+
() => false,
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div data-v-openapi-property-example data-clickable={clickable || undefined}>
|
|
30
|
+
<span data-v-openapi-property-example-label>Example</span>
|
|
31
|
+
{clickable ? (
|
|
32
|
+
<button
|
|
33
|
+
type="button"
|
|
34
|
+
data-v-openapi-property-example-value
|
|
35
|
+
onClick={() => {
|
|
36
|
+
void revealSampleLine(id as string)
|
|
37
|
+
}}
|
|
38
|
+
>
|
|
39
|
+
{value}
|
|
40
|
+
</button>
|
|
41
|
+
) : (
|
|
42
|
+
<span data-v-openapi-property-example-value>{value}</span>
|
|
43
|
+
)}
|
|
44
|
+
</div>
|
|
45
|
+
)
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
export declare namespace PropertyExample {
|
|
49
|
+
type Props = {
|
|
50
|
+
/** The property/parameter row's anchor id, matched against sample lines. */
|
|
51
|
+
id?: string | undefined
|
|
52
|
+
/** Example value display string. */
|
|
53
|
+
value: string
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
import type { ReactNode } from 'react'
|
|
2
|
+
import * as Markdown from '../../../internal/markdown.js'
|
|
3
|
+
import type { Ir, IrGroup } from '../../../internal/openapi/parser.js'
|
|
4
|
+
import { HeadingAnchor } from './HeadingAnchor.js'
|
|
5
|
+
import { Operation } from './Operation.js'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Prop-driven OpenAPI renderers shared by the Vite/RSC site integration
|
|
9
|
+
* ({@link file://./OpenApiPage.tsx `OpenApiPage`}) and the standalone client
|
|
10
|
+
* app ({@link file://../../../standalone/openapi/App.client.tsx}).
|
|
11
|
+
*
|
|
12
|
+
* These render only the section content (the `data-v-openapi` tree). They have
|
|
13
|
+
* no dependency on the Waku `Layout`, the `virtual:vocs/openapi` module, or any
|
|
14
|
+
* router — the caller supplies the parsed {@link Ir} and wraps the tree in the
|
|
15
|
+
* appropriate layout/playground provider.
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Renders trusted markdown from the spec (info/category descriptions) with the
|
|
20
|
+
* same typography as MDX content.
|
|
21
|
+
*/
|
|
22
|
+
export function Prose(props: { markdown: string; attr?: string }) {
|
|
23
|
+
return (
|
|
24
|
+
<div
|
|
25
|
+
data-v-openapi-description={props.attr === 'description' ? '' : undefined}
|
|
26
|
+
data-v-content
|
|
27
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: server-rendered trusted spec content
|
|
28
|
+
dangerouslySetInnerHTML={{ __html: Markdown.toHtml(props.markdown) }}
|
|
29
|
+
/>
|
|
30
|
+
)
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Overview / landing page body. Renders the consumer override (or the
|
|
35
|
+
* auto-generated spec header). The domain/endpoint list is opt-in via
|
|
36
|
+
* `<OpenApi.Endpoints />`.
|
|
37
|
+
*/
|
|
38
|
+
export function ReferenceOverview(props: ReferenceOverview.Props) {
|
|
39
|
+
const { ir, intro, endpoints } = props
|
|
40
|
+
return (
|
|
41
|
+
<div data-v-openapi data-v-openapi-landing>
|
|
42
|
+
{intro ? (
|
|
43
|
+
<div data-v-openapi-intro data-v-content>
|
|
44
|
+
{intro}
|
|
45
|
+
</div>
|
|
46
|
+
) : (
|
|
47
|
+
<>
|
|
48
|
+
<header data-v-openapi-header>
|
|
49
|
+
<h1 data-v data-v-openapi-info-title>
|
|
50
|
+
{ir.info.title}
|
|
51
|
+
</h1>
|
|
52
|
+
{ir.info.description && <Prose markdown={ir.info.description} attr="description" />}
|
|
53
|
+
</header>
|
|
54
|
+
{endpoints}
|
|
55
|
+
</>
|
|
56
|
+
)}
|
|
57
|
+
</div>
|
|
58
|
+
)
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export declare namespace ReferenceOverview {
|
|
62
|
+
type Props = {
|
|
63
|
+
ir: Ir
|
|
64
|
+
/** Consumer override rendered in place of the auto-generated header. */
|
|
65
|
+
intro?: ReactNode | undefined
|
|
66
|
+
/**
|
|
67
|
+
* Domain/endpoint list rendered below the auto-generated header (ignored
|
|
68
|
+
* when `intro` is set — overrides control their own content). The caller
|
|
69
|
+
* supplies the framework-specific list; the standalone handler passes it so
|
|
70
|
+
* its Introduction lists every endpoint by default.
|
|
71
|
+
*/
|
|
72
|
+
endpoints?: ReactNode | undefined
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Single category page body: category header (or consumer override) followed by
|
|
78
|
+
* its operations. Does not mount the playground provider — the caller wraps this
|
|
79
|
+
* with `PlaygroundProvider` so a single Scalar modal is shared across the page.
|
|
80
|
+
*/
|
|
81
|
+
export function ReferenceGroup(props: ReferenceGroup.Props) {
|
|
82
|
+
const { ir, group, intro } = props
|
|
83
|
+
return (
|
|
84
|
+
<div data-v-openapi>
|
|
85
|
+
{intro ? (
|
|
86
|
+
// The override keeps the `group.id` anchor so the sidebar "Overview"
|
|
87
|
+
// link and scroll-spy still resolve to this page.
|
|
88
|
+
<div data-v-openapi-intro data-v-content id={group.id}>
|
|
89
|
+
{intro}
|
|
90
|
+
</div>
|
|
91
|
+
) : (
|
|
92
|
+
<header data-v-openapi-header>
|
|
93
|
+
<h1 data-v data-v-openapi-h1 id={group.id}>
|
|
94
|
+
{group.name}
|
|
95
|
+
<HeadingAnchor id={group.id} />
|
|
96
|
+
</h1>
|
|
97
|
+
{group.description && <Prose markdown={group.description} attr="description" />}
|
|
98
|
+
</header>
|
|
99
|
+
)}
|
|
100
|
+
{group.operations.map((operation, index) => (
|
|
101
|
+
<Operation
|
|
102
|
+
key={operation.id}
|
|
103
|
+
operation={operation}
|
|
104
|
+
server={ir.servers[0]?.url}
|
|
105
|
+
headingLevel={2}
|
|
106
|
+
separator={index > 0}
|
|
107
|
+
/>
|
|
108
|
+
))}
|
|
109
|
+
</div>
|
|
110
|
+
)
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export declare namespace ReferenceGroup {
|
|
114
|
+
type Props = {
|
|
115
|
+
ir: Ir
|
|
116
|
+
group: IrGroup
|
|
117
|
+
/** Consumer override rendered in place of the auto-generated category header. */
|
|
118
|
+
intro?: ReactNode | undefined
|
|
119
|
+
}
|
|
120
|
+
}
|