sourcey 3.3.9 → 3.4.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 +19 -3
- package/dist/cli.js +1 -5
- package/dist/client/scroll-tracker.js +8 -1
- package/dist/components/layout/Head.d.ts.map +1 -1
- package/dist/components/layout/Head.js +2 -1
- package/dist/components/layout/Page.d.ts.map +1 -1
- package/dist/components/layout/Page.js +2 -1
- package/dist/components/layout/Sidebar.d.ts.map +1 -1
- package/dist/components/layout/Sidebar.js +6 -1
- package/dist/components/layout/TableOfContents.js +1 -1
- package/dist/components/mcp/AnnotationBadges.d.ts +15 -0
- package/dist/components/mcp/AnnotationBadges.d.ts.map +1 -0
- package/dist/components/mcp/AnnotationBadges.js +10 -0
- package/dist/components/mcp/McpConnection.d.ts +10 -0
- package/dist/components/mcp/McpConnection.d.ts.map +1 -0
- package/dist/components/mcp/McpConnection.js +32 -0
- package/dist/components/mcp/McpEndpointBar.d.ts +8 -0
- package/dist/components/mcp/McpEndpointBar.d.ts.map +1 -0
- package/dist/components/mcp/McpEndpointBar.js +16 -0
- package/dist/components/mcp/McpReturns.d.ts +18 -0
- package/dist/components/mcp/McpReturns.d.ts.map +1 -0
- package/dist/components/mcp/McpReturns.js +33 -0
- package/dist/components/openapi/Operation.d.ts.map +1 -1
- package/dist/components/openapi/Operation.js +5 -1
- package/dist/config.d.ts +3 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +8 -3
- package/dist/core/doxygen-loader.js +12 -12
- package/dist/core/mcp-normalizer.d.ts +11 -0
- package/dist/core/mcp-normalizer.d.ts.map +1 -0
- package/dist/core/mcp-normalizer.js +382 -0
- package/dist/core/types.d.ts +26 -2
- package/dist/core/types.d.ts.map +1 -1
- package/dist/dev-server.d.ts.map +1 -1
- package/dist/dev-server.js +46 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -9
- package/dist/renderer/html-builder.d.ts.map +1 -1
- package/dist/renderer/html-builder.js +9 -0
- package/dist/themes/default/sourcey.css +36 -8
- package/dist/utils/markdown.d.ts.map +1 -1
- package/dist/utils/markdown.js +50 -1
- package/package.json +15 -7
package/README.md
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
Sourcey is an open source documentation platform. Point it at an OpenAPI spec, add markdown guides, get a complete docs site. Static HTML you own; no dashboard, no monthly bill, no API calls to render your own documentation. Deploy anywhere.
|
|
6
6
|
|
|
7
7
|
[](https://www.npmjs.com/package/sourcey)
|
|
8
|
-
[](https://github.com/sourcey/sourcey/actions)
|
|
9
9
|
[](https://nodejs.org)
|
|
10
10
|
|
|
11
11
|
```bash
|
|
@@ -14,7 +14,7 @@ npx sourcey init
|
|
|
14
14
|
|
|
15
15
|

|
|
16
16
|
|
|
17
|
-
**[Live demo](https://cheesestore.github.io/)** · [Documentation](https://sourcey.com/docs) · [GitHub](https://github.com/
|
|
17
|
+
**[Live demo](https://cheesestore.github.io/)** · [Documentation](https://sourcey.com/docs) · [GitHub](https://github.com/sourcey/sourcey)
|
|
18
18
|
|
|
19
19
|
## Features
|
|
20
20
|
|
|
@@ -43,6 +43,22 @@ npx sourcey init
|
|
|
43
43
|
| Self-hosted | Yes | No | No | No | Yes | Yes |
|
|
44
44
|
| Pricing | Free / AGPL | $150+/mo | Free / paid | Paid | Free / paid | Free |
|
|
45
45
|
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
# npm (recommended)
|
|
50
|
+
npx sourcey init
|
|
51
|
+
|
|
52
|
+
# Homebrew
|
|
53
|
+
brew tap sourcey/sourcey && brew install sourcey
|
|
54
|
+
|
|
55
|
+
# Docker
|
|
56
|
+
docker run -v $(pwd):/docs sourcey/sourcey build
|
|
57
|
+
|
|
58
|
+
# Nix
|
|
59
|
+
nix run github:sourcey/sourcey
|
|
60
|
+
```
|
|
61
|
+
|
|
46
62
|
## Quick start
|
|
47
63
|
|
|
48
64
|
```bash
|
|
@@ -159,7 +175,7 @@ sourcey validate api.yaml Validate a spec file
|
|
|
159
175
|
## Development
|
|
160
176
|
|
|
161
177
|
```bash
|
|
162
|
-
git clone https://github.com/
|
|
178
|
+
git clone https://github.com/sourcey/sourcey.git
|
|
163
179
|
cd sourcey && npm install
|
|
164
180
|
npm run build && npm test
|
|
165
181
|
|
package/dist/cli.js
CHANGED
|
@@ -1,13 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { defineCommand, runMain } from "citty";
|
|
3
|
-
import { readFileSync } from "node:fs";
|
|
4
|
-
import { dirname, join } from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
3
|
import { buildDocs, buildSiteDocs } from "./index.js";
|
|
7
4
|
import { loadConfig } from "./config.js";
|
|
8
5
|
import { init } from "./init.js";
|
|
9
|
-
|
|
10
|
-
const pkg = JSON.parse(readFileSync(join(__dirname, "..", "package.json"), "utf8"));
|
|
6
|
+
import pkg from "../package.json" with { type: "json" };
|
|
11
7
|
const build = defineCommand({
|
|
12
8
|
meta: {
|
|
13
9
|
name: "build",
|
|
@@ -74,10 +74,17 @@
|
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
// Scroll to element with header offset
|
|
77
|
+
// Scroll to element with header offset.
|
|
78
|
+
// For the first traverse target, scroll to the very top of the page
|
|
79
|
+
// so the title and all top padding are visible.
|
|
78
80
|
function scrollToId(id, behavior) {
|
|
79
81
|
var el = document.getElementById(id);
|
|
80
82
|
if (!el) return;
|
|
83
|
+
var firstTarget = targets.length ? targets[0].getAttribute('data-traverse-target') : null;
|
|
84
|
+
if (id === firstTarget) {
|
|
85
|
+
window.scrollTo({ top: 0, behavior: behavior });
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
81
88
|
var offset = (navbar ? navbar.offsetHeight : 0) - 1;
|
|
82
89
|
window.scrollTo({ top: el.getBoundingClientRect().top + window.scrollY - offset, behavior: behavior });
|
|
83
90
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Head.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Head.tsx"],"names":[],"mappings":"AAKA,wBAAgB,IAAI,iCAqFnB"}
|
|
@@ -2,6 +2,7 @@ import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "preact/jsx-ru
|
|
|
2
2
|
import { useContext } from "preact/hooks";
|
|
3
3
|
import { SpecContext, OptionsContext, PageContext, SiteContext, NavigationContext } from "../../renderer/context.js";
|
|
4
4
|
import { langIconCSS } from "../../utils/lang-icons.js";
|
|
5
|
+
import pkg from "../../../package.json" with { type: "json" };
|
|
5
6
|
export function Head() {
|
|
6
7
|
const site = useContext(SiteContext);
|
|
7
8
|
const spec = useContext(SpecContext);
|
|
@@ -51,5 +52,5 @@ export function Head() {
|
|
|
51
52
|
body { margin: 0; background: rgb(var(--color-background-light)); }
|
|
52
53
|
.dark body { background: rgb(var(--color-background-dark)); }
|
|
53
54
|
`;
|
|
54
|
-
return (_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: pageTitle }), _jsx("meta", { name: "description", content: pageDescription }), _jsx("meta", { name: "sourcey-search", content: `${options.assetBase}search-index.json` }), _jsx("style", { dangerouslySetInnerHTML: { __html: themeCSS } }), _jsx("style", { dangerouslySetInnerHTML: { __html: langIconCSS() } }), site.customCSS && _jsx("style", { dangerouslySetInnerHTML: { __html: site.customCSS } }), _jsx("script", { dangerouslySetInnerHTML: { __html: `(function(){var t=localStorage.getItem('sourcey-theme');if(t==='dark')document.documentElement.classList.add('dark')})()` } }), googleFontsUrl && (_jsxs(_Fragment, { children: [_jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" }), _jsx("link", { rel: "stylesheet", href: googleFontsUrl })] })), _jsx("link", { rel: "stylesheet", href: `${options.assetBase}sourcey.css` }), site.favicon && _jsx("link", { rel: "icon", href: site.favicon })] }));
|
|
55
|
+
return (_jsxs("head", { children: [_jsx("meta", { charset: "utf-8" }), _jsx("meta", { name: "viewport", content: "width=device-width, initial-scale=1" }), _jsx("title", { children: pageTitle }), _jsx("meta", { name: "description", content: pageDescription }), _jsx("meta", { name: "generator", content: `Sourcey ${pkg.version}` }), _jsx("meta", { property: "og:title", content: pageTitle }), _jsx("meta", { property: "og:description", content: pageDescription }), _jsx("meta", { property: "og:type", content: "website" }), siteName && _jsx("meta", { property: "og:site_name", content: siteName }), _jsx("meta", { name: "twitter:card", content: "summary" }), _jsx("meta", { name: "twitter:title", content: pageTitle }), _jsx("meta", { name: "twitter:description", content: pageDescription }), _jsx("meta", { name: "sourcey-search", content: `${options.assetBase}search-index.json` }), _jsx("style", { dangerouslySetInnerHTML: { __html: themeCSS } }), _jsx("style", { dangerouslySetInnerHTML: { __html: langIconCSS() } }), site.customCSS && _jsx("style", { dangerouslySetInnerHTML: { __html: site.customCSS } }), _jsx("script", { dangerouslySetInnerHTML: { __html: `(function(){var t=localStorage.getItem('sourcey-theme');if(t==='dark')document.documentElement.classList.add('dark')})()` } }), googleFontsUrl && (_jsxs(_Fragment, { children: [_jsx("link", { rel: "preconnect", href: "https://fonts.googleapis.com" }), _jsx("link", { rel: "preconnect", href: "https://fonts.gstatic.com", crossOrigin: "anonymous" }), _jsx("link", { rel: "stylesheet", href: googleFontsUrl })] })), _jsx("link", { rel: "stylesheet", href: `${options.assetBase}sourcey.css` }), site.favicon && _jsx("link", { rel: "icon", href: site.favicon })] }));
|
|
55
56
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Page.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Page.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Page.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Page.tsx"],"names":[],"mappings":"AAkPA,wBAAgB,IAAI,iCAqCnB"}
|
|
@@ -10,6 +10,7 @@ import { SecurityDefinitions } from "../openapi/Security.js";
|
|
|
10
10
|
import { Tags } from "../openapi/Tags.js";
|
|
11
11
|
import { Definition } from "../openapi/Definition.js";
|
|
12
12
|
import { SocialIcon } from "../ui/SocialIcon.js";
|
|
13
|
+
import { McpConnection } from "../mcp/McpConnection.js";
|
|
13
14
|
/**
|
|
14
15
|
* Markdown page content with prose typography.
|
|
15
16
|
*/
|
|
@@ -27,7 +28,7 @@ function MarkdownPageContent({ page, className = "" }) {
|
|
|
27
28
|
function SpecPageContent({ className = "" }) {
|
|
28
29
|
const spec = useContext(SpecContext);
|
|
29
30
|
const serverUrl = spec.servers[0]?.url ?? "/";
|
|
30
|
-
return (_jsxs("div", { class: `relative grow box-border flex-col w-full mx-auto px-1 min-w-0 ${className}`, id: "content-area", children: [_jsxs("article", { children: [_jsx("header", { class: "mb-8", children: _jsxs("div", { class: "flex items-baseline gap-3", children: [_jsx("h1", { class: "text-2xl sm:text-3xl font-bold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))] tracking-tight", children: spec.info.title }), _jsxs("span", { class: "text-sm text-[rgb(var(--color-gray-400))]", children: ["v", spec.info.version] })] }) }), _jsx(Introduction, {}), _jsx(SecurityDefinitions, {}), _jsx(Tags, { tags: spec.tags, serverUrl: serverUrl }), Object.keys(spec.schemas).length > 0 && (_jsxs("div", { class: "mt-12", children: [_jsx("div", { class: "mb-6", children: _jsx("h1", { class: "text-xl font-bold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))]", children: "Models" }) }), Object.entries(spec.schemas).map(([name, schema]) => (_jsx(Definition, { name: name, schema: schema }, name)))] }))] }), _jsx(ContentFooter, {})] }));
|
|
31
|
+
return (_jsxs("div", { class: `relative grow box-border flex-col w-full mx-auto px-1 min-w-0 ${className}`, id: "content-area", children: [_jsxs("article", { children: [_jsx("header", { class: "mb-8", children: _jsxs("div", { class: "flex items-baseline gap-3", children: [_jsx("h1", { class: "text-2xl sm:text-3xl font-bold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))] tracking-tight", children: spec.info.title }), _jsxs("span", { class: "text-sm text-[rgb(var(--color-gray-400))]", children: ["v", spec.info.version] })] }) }), _jsx(Introduction, {}), spec.operations[0]?.mcpExtras?.connection && (_jsx(McpConnection, { connection: spec.operations[0].mcpExtras.connection })), _jsx(SecurityDefinitions, {}), _jsx(Tags, { tags: spec.tags, serverUrl: serverUrl }), Object.keys(spec.schemas).length > 0 && (_jsxs("div", { class: "mt-12", children: [_jsx("div", { class: "mb-6", children: _jsx("h1", { class: "text-xl font-bold text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))]", children: "Models" }) }), Object.entries(spec.schemas).map(([name, schema]) => (_jsx(Definition, { name: name, schema: schema }, name)))] }))] }), _jsx(ContentFooter, {})] }));
|
|
31
32
|
}
|
|
32
33
|
function PageNavigation() {
|
|
33
34
|
const nav = useContext(NavigationContext);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Sidebar.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Sidebar.d.ts","sourceRoot":"","sources":["../../../src/components/layout/Sidebar.tsx"],"names":[],"mappings":"AAoFA;;GAEG;AACH,wBAAgB,OAAO,wCAuGtB"}
|
|
@@ -8,7 +8,7 @@ import { Logo } from "../ui/Logo.js";
|
|
|
8
8
|
*/
|
|
9
9
|
function MethodPill({ method }) {
|
|
10
10
|
const m = method.toUpperCase();
|
|
11
|
-
const label = m === "DELETE" ? "DEL" : m;
|
|
11
|
+
const label = m === "DELETE" ? "DEL" : m === "RESOURCE" ? "RES" : m === "PROMPT" ? "PRMT" : m;
|
|
12
12
|
const colors = {
|
|
13
13
|
GET: "bg-green-400/20 dark:bg-green-400/20 text-green-700 dark:text-green-400",
|
|
14
14
|
POST: "bg-blue-400/20 dark:bg-blue-400/20 text-blue-700 dark:text-blue-400",
|
|
@@ -16,6 +16,11 @@ function MethodPill({ method }) {
|
|
|
16
16
|
DELETE: "bg-red-400/20 dark:bg-red-400/20 text-red-700 dark:text-red-400",
|
|
17
17
|
DEL: "bg-red-400/20 dark:bg-red-400/20 text-red-700 dark:text-red-400",
|
|
18
18
|
PATCH: "bg-orange-400/20 dark:bg-orange-400/20 text-orange-700 dark:text-orange-400",
|
|
19
|
+
TOOL: "bg-purple-400/20 dark:bg-purple-400/20 text-purple-700 dark:text-purple-400",
|
|
20
|
+
RESOURCE: "bg-green-400/20 dark:bg-green-400/20 text-green-700 dark:text-green-400",
|
|
21
|
+
RES: "bg-green-400/20 dark:bg-green-400/20 text-green-700 dark:text-green-400",
|
|
22
|
+
PROMPT: "bg-blue-400/20 dark:bg-blue-400/20 text-blue-700 dark:text-blue-400",
|
|
23
|
+
PRMT: "bg-blue-400/20 dark:bg-blue-400/20 text-blue-700 dark:text-blue-400",
|
|
19
24
|
};
|
|
20
25
|
return (_jsx("span", { class: "flex items-center w-8 h-[1lh] shrink-0", children: _jsx("span", { class: `px-1 py-0.5 rounded-md text-[0.55rem] leading-tight font-bold ${colors[m] ?? "bg-gray-400/20 text-gray-700"}`, children: label }) }));
|
|
21
26
|
}
|
|
@@ -16,7 +16,7 @@ function TocList({ headings }) {
|
|
|
16
16
|
groups[groups.length - 1].children.push(h);
|
|
17
17
|
}
|
|
18
18
|
}
|
|
19
|
-
return (_jsx("ul", {
|
|
19
|
+
return (_jsx("ul", { children: groups.map((g) => (_jsxs("li", { children: [_jsx("a", { href: `#${g.root.id}`, class: `${tocLink} py-1`, children: g.root.text }), g.children.length > 0 && (_jsx("ul", { children: g.children.map((c) => (_jsx("li", { children: _jsx("a", { href: `#${c.id}`, class: `${tocLink} pl-3 text-[13px] py-0.5`, children: c.text }) }, c.id))) }))] }, g.root.id))) }));
|
|
20
20
|
}
|
|
21
21
|
export function TableOfContents({ headings }) {
|
|
22
22
|
if (headings.length === 0)
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Renders MCP tool annotation badges inline with the operation title.
|
|
3
|
+
* Same visual pattern as DeprecatedBadge / RequiredBadge / ReadOnlyBadge.
|
|
4
|
+
*/
|
|
5
|
+
interface Annotations {
|
|
6
|
+
readOnlyHint?: boolean;
|
|
7
|
+
destructiveHint?: boolean;
|
|
8
|
+
idempotentHint?: boolean;
|
|
9
|
+
openWorldHint?: boolean;
|
|
10
|
+
}
|
|
11
|
+
export declare function AnnotationBadges({ annotations }: {
|
|
12
|
+
annotations: Annotations;
|
|
13
|
+
}): import("preact").JSX.Element;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=AnnotationBadges.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AnnotationBadges.d.ts","sourceRoot":"","sources":["../../../src/components/mcp/AnnotationBadges.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,UAAU,WAAW;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,aAAa,CAAC,EAAE,OAAO,CAAC;CACzB;AASD,wBAAgB,gBAAgB,CAAC,EAAE,WAAW,EAAE,EAAE;IAAE,WAAW,EAAE,WAAW,CAAA;CAAE,gCAa7E"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment } from "preact/jsx-runtime";
|
|
2
|
+
const badges = [
|
|
3
|
+
{ key: "readOnlyHint", label: "read-only", className: "bg-green-100/50 text-green-600 dark:bg-green-400/10 dark:text-green-300" },
|
|
4
|
+
{ key: "destructiveHint", label: "destructive", className: "bg-red-100/50 text-red-600 dark:bg-red-400/10 dark:text-red-300" },
|
|
5
|
+
{ key: "idempotentHint", label: "idempotent", className: "bg-blue-100/50 text-blue-600 dark:bg-blue-400/10 dark:text-blue-300" },
|
|
6
|
+
{ key: "openWorldHint", label: "open-world", className: "bg-amber-100/50 text-amber-600 dark:bg-amber-400/10 dark:text-amber-300" },
|
|
7
|
+
];
|
|
8
|
+
export function AnnotationBadges({ annotations }) {
|
|
9
|
+
return (_jsx(_Fragment, { children: badges.map(({ key, label, className }) => annotations[key] && (_jsx("span", { class: `whitespace-nowrap rounded-md px-2 py-0.5 text-xs font-medium ${className}`, children: label }, key))) }));
|
|
10
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Connection config card for MCP docs.
|
|
3
|
+
* Rendered below Introduction in SpecPageContent.
|
|
4
|
+
* Uses the same bordered card pattern as Introduction's Base URLs table.
|
|
5
|
+
*/
|
|
6
|
+
import type { McpConnectionInfo } from "../../core/types.js";
|
|
7
|
+
export declare function McpConnection({ connection }: {
|
|
8
|
+
connection: McpConnectionInfo;
|
|
9
|
+
}): import("preact").JSX.Element | null;
|
|
10
|
+
//# sourceMappingURL=McpConnection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpConnection.d.ts","sourceRoot":"","sources":["../../../src/components/mcp/McpConnection.tsx"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAC;AAE7D,wBAAgB,aAAa,CAAC,EAAE,UAAU,EAAE,EAAE;IAAE,UAAU,EAAE,iBAAiB,CAAA;CAAE,uCAwD9E"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
export function McpConnection({ connection }) {
|
|
3
|
+
const transport = connection.transport;
|
|
4
|
+
if (!transport)
|
|
5
|
+
return null;
|
|
6
|
+
// Build the config JSON snippet
|
|
7
|
+
const serverEntry = {};
|
|
8
|
+
if (transport.type === "stdio") {
|
|
9
|
+
if (transport.command)
|
|
10
|
+
serverEntry.command = transport.command;
|
|
11
|
+
if (transport.args?.length)
|
|
12
|
+
serverEntry.args = transport.args;
|
|
13
|
+
}
|
|
14
|
+
else {
|
|
15
|
+
if (transport.url)
|
|
16
|
+
serverEntry.url = transport.url;
|
|
17
|
+
}
|
|
18
|
+
const configJson = JSON.stringify({ mcpServers: { [connection.serverName]: serverEntry } }, null, 2);
|
|
19
|
+
// Capabilities summary
|
|
20
|
+
const caps = [];
|
|
21
|
+
if (connection.capabilities) {
|
|
22
|
+
if (connection.capabilities.tools)
|
|
23
|
+
caps.push("tools");
|
|
24
|
+
if (connection.capabilities.resources)
|
|
25
|
+
caps.push("resources");
|
|
26
|
+
if (connection.capabilities.prompts)
|
|
27
|
+
caps.push("prompts");
|
|
28
|
+
if (connection.capabilities.logging)
|
|
29
|
+
caps.push("logging");
|
|
30
|
+
}
|
|
31
|
+
return (_jsxs("div", { class: "mb-8 rounded-[var(--radius)] border border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-border-dark-subtle)/0.1)] overflow-hidden", children: [_jsx("div", { class: "px-4 py-2.5 text-xs font-semibold text-[rgb(var(--color-gray-600))] dark:text-[rgb(var(--color-gray-300))] border-b border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-border-dark-subtle)/0.1)]", children: "Connect" }), _jsxs("div", { class: "px-4 py-3", children: [_jsx("p", { class: "text-sm text-[rgb(var(--color-gray-500))] mb-3", children: "Add to your MCP client configuration:" }), _jsx("div", { class: "code-group not-prose", children: _jsx("div", { class: "relative w-full px-4 py-3.5 text-sm leading-6 bg-[rgb(var(--color-code-block-light))] dark:bg-[rgb(var(--color-code-block-dark))] overflow-x-auto rounded-[var(--radius)]", style: "font-variant-ligatures: none", children: _jsx("div", { class: "font-mono whitespace-pre text-xs leading-[1.35rem] text-[rgb(var(--color-gray-800))] dark:text-[rgb(var(--color-gray-200))]", children: configJson }) }) }), _jsxs("div", { class: "mt-3 flex flex-wrap gap-x-6 gap-y-1 text-xs text-[rgb(var(--color-gray-500))]", children: [connection.mcpVersion && (_jsxs("span", { children: ["Protocol ", _jsxs("span", { class: "font-medium text-[rgb(var(--color-gray-700))] dark:text-[rgb(var(--color-gray-300))]", children: ["MCP ", connection.mcpVersion] })] })), _jsxs("span", { children: ["Transport ", _jsx("span", { class: "font-medium text-[rgb(var(--color-gray-700))] dark:text-[rgb(var(--color-gray-300))]", children: transport.type })] }), caps.length > 0 && (_jsxs("span", { children: ["Capabilities ", _jsx("span", { class: "font-medium text-[rgb(var(--color-gray-700))] dark:text-[rgb(var(--color-gray-300))]", children: caps.join(", ") })] }))] })] })] }));
|
|
32
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP equivalent of EndpointBar. Shows method pill + tool name or resource URI.
|
|
3
|
+
*/
|
|
4
|
+
export declare function McpEndpointBar({ method, path }: {
|
|
5
|
+
method: string;
|
|
6
|
+
path: string;
|
|
7
|
+
}): import("preact").JSX.Element;
|
|
8
|
+
//# sourceMappingURL=McpEndpointBar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpEndpointBar.d.ts","sourceRoot":"","sources":["../../../src/components/mcp/McpEndpointBar.tsx"],"names":[],"mappings":"AAAA;;GAEG;AAQH,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,EAAE;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,gCAuBhF"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* MCP equivalent of EndpointBar. Shows method pill + tool name or resource URI.
|
|
4
|
+
*/
|
|
5
|
+
const methodColors = {
|
|
6
|
+
tool: "bg-purple-400/20 dark:bg-purple-400/20 text-purple-700 dark:text-purple-400",
|
|
7
|
+
resource: "bg-green-400/20 dark:bg-green-400/20 text-green-700 dark:text-green-400",
|
|
8
|
+
prompt: "bg-blue-400/20 dark:bg-blue-400/20 text-blue-700 dark:text-blue-400",
|
|
9
|
+
};
|
|
10
|
+
export function McpEndpointBar({ method, path }) {
|
|
11
|
+
const colorClass = methodColors[method] ?? "bg-gray-400/20 text-gray-700";
|
|
12
|
+
const label = method.toUpperCase();
|
|
13
|
+
// Split path on {param} segments for dimmed rendering
|
|
14
|
+
const segments = path.split(/(\{[^}]+\})/);
|
|
15
|
+
return (_jsxs("div", { class: "flex items-center gap-2 rounded-[var(--radius)] border border-[rgb(var(--color-gray-200)/0.7)] dark:border-[rgb(var(--color-border-dark-subtle)/0.1)] px-3 py-2.5 mb-6 overflow-hidden", children: [_jsx("span", { class: `rounded-lg font-bold px-1.5 py-0.5 text-sm leading-5 shrink-0 ${colorClass}`, children: label }), _jsx("span", { class: "flex items-center overflow-x-auto flex-1 no-scrollbar font-mono text-sm text-[rgb(var(--color-gray-800))] dark:text-[rgb(var(--color-gray-200))]", children: segments.map((seg, i) => seg.startsWith("{") ? (_jsx("span", { class: "text-[rgb(var(--color-gray-400))] dark:text-[rgb(var(--color-gray-500))]", children: seg }, i)) : (_jsx("span", { children: seg }, i))) })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Returns section — replaces Responses for MCP operations.
|
|
3
|
+
* Renders output schema as a schema view instead of status code tables.
|
|
4
|
+
*/
|
|
5
|
+
import type { NormalizedSchema } from "../../core/types.js";
|
|
6
|
+
/**
|
|
7
|
+
* Left column: "Returns" section label + schema view or fallback text.
|
|
8
|
+
*/
|
|
9
|
+
export declare function McpReturnsCopy({ schema }: {
|
|
10
|
+
schema?: NormalizedSchema;
|
|
11
|
+
}): import("preact").JSX.Element;
|
|
12
|
+
/**
|
|
13
|
+
* Right column (sticky panel): example JSON for the output schema.
|
|
14
|
+
*/
|
|
15
|
+
export declare function McpReturnsExample({ schema }: {
|
|
16
|
+
schema?: NormalizedSchema;
|
|
17
|
+
}): import("preact").JSX.Element;
|
|
18
|
+
//# sourceMappingURL=McpReturns.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"McpReturns.d.ts","sourceRoot":"","sources":["../../../src/components/mcp/McpReturns.tsx"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAK5D;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,gCAavE;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,EAAE,MAAM,EAAE,EAAE;IAAE,MAAM,CAAC,EAAE,gBAAgB,CAAA;CAAE,gCAyB1E"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "preact/jsx-runtime";
|
|
2
|
+
import { SchemaView } from "../schema/SchemaView.js";
|
|
3
|
+
import { ExampleView } from "../schema/ExampleView.js";
|
|
4
|
+
import { SectionLabel } from "../ui/SectionLabel.js";
|
|
5
|
+
/**
|
|
6
|
+
* Left column: "Returns" section label + schema view or fallback text.
|
|
7
|
+
*/
|
|
8
|
+
export function McpReturnsCopy({ schema }) {
|
|
9
|
+
return (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { children: "Returns" }), schema ? (_jsx(SchemaView, { schema: schema })) : (_jsx("p", { class: "text-sm text-[rgb(var(--color-gray-500))]", children: "Returns MCP content array (text, image, or embedded resource)." }))] }));
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Right column (sticky panel): example JSON for the output schema.
|
|
13
|
+
*/
|
|
14
|
+
export function McpReturnsExample({ schema }) {
|
|
15
|
+
if (!schema) {
|
|
16
|
+
return (_jsx(ExampleView, { schema: {
|
|
17
|
+
type: "object",
|
|
18
|
+
properties: {
|
|
19
|
+
content: {
|
|
20
|
+
type: "array",
|
|
21
|
+
items: {
|
|
22
|
+
type: "object",
|
|
23
|
+
properties: {
|
|
24
|
+
type: { type: "string", enum: ["text", "image", "resource"] },
|
|
25
|
+
text: { type: "string", example: "..." },
|
|
26
|
+
},
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
}, title: "Response" }));
|
|
31
|
+
}
|
|
32
|
+
return _jsx(ExampleView, { schema: schema, title: "Response" });
|
|
33
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Operation.d.ts","sourceRoot":"","sources":["../../../src/components/openapi/Operation.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAyB,MAAM,qBAAqB,CAAC;
|
|
1
|
+
{"version":3,"file":"Operation.d.ts","sourceRoot":"","sources":["../../../src/components/openapi/Operation.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,mBAAmB,EAAyB,MAAM,qBAAqB,CAAC;AAgBtF,UAAU,cAAc;IACtB,SAAS,EAAE,mBAAmB,CAAC;IAC/B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,EAAE,SAAS,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,cAAc,gCA0FrE"}
|
|
@@ -11,6 +11,9 @@ import { ResponsesCopy, ResponsesExamples } from "./Responses.js";
|
|
|
11
11
|
import { SecurityCopy } from "./Security.js";
|
|
12
12
|
import { CodeSamplesExamples } from "./CodeSamples.js";
|
|
13
13
|
import { EndpointBar } from "./EndpointBar.js";
|
|
14
|
+
import { McpEndpointBar } from "../mcp/McpEndpointBar.js";
|
|
15
|
+
import { AnnotationBadges } from "../mcp/AnnotationBadges.js";
|
|
16
|
+
import { McpReturnsCopy, McpReturnsExample } from "../mcp/McpReturns.js";
|
|
14
17
|
/**
|
|
15
18
|
* Single operation with sticky code panel:
|
|
16
19
|
* - Endpoint bar at top
|
|
@@ -22,7 +25,8 @@ export function Operation({ operation: op, serverUrl }) {
|
|
|
22
25
|
const id = `operation-${htmlId(op.path)}-${htmlId(op.method)}`;
|
|
23
26
|
const hasParams = op.parameters.length > 0;
|
|
24
27
|
const hasBody = !!op.requestBody;
|
|
25
|
-
|
|
28
|
+
const mcp = op.mcpExtras;
|
|
29
|
+
return (_jsxs("div", { id: id, class: "py-8 border-t border-[rgb(var(--color-gray-100))] dark:border-[rgb(var(--color-gray-800))]", "data-traverse-target": id, children: [_jsx("header", { class: "mb-6", children: op.summary && (_jsxs("div", { class: "flex items-baseline gap-2 flex-wrap", children: [_jsx("h2", { class: "text-2xl sm:text-3xl text-[rgb(var(--color-gray-900))] dark:text-[rgb(var(--color-gray-200))] tracking-tight font-bold mb-2", children: _jsx(Markdown, { content: op.summary, inline: true }) }), op.deprecated && _jsx(DeprecatedBadge, {}), mcp?.annotations && _jsx(AnnotationBadges, { annotations: mcp.annotations })] })) }), mcp ? (_jsx(McpEndpointBar, { method: op.method, path: op.path })) : (_jsx(EndpointBar, { method: op.method, path: op.path, serverUrl: serverUrl })), _jsxs("div", { class: `flex flex-col ${apiFirst ? "lg:flex-row" : "xl:flex-row"} gap-8`, children: [_jsxs("div", { class: "flex-1 min-w-0", children: [op.description && (_jsx(Markdown, { content: op.description, class: "mb-6" })), hasBody && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { meta: bodyMediaType(op.requestBody), children: "Body" }), _jsx(RequestBody, { body: op.requestBody })] })), hasParams && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { children: "Parameters" }), _jsx(Parameters, { parameters: op.parameters })] })), mcp ? (_jsx(McpReturnsCopy, { schema: mcp.outputSchema })) : (op.responses.length > 0 && (_jsxs("div", { class: "mt-6", children: [_jsx(SectionLabel, { children: "Response" }), _jsx(ResponsesCopy, { responses: op.responses })] }))), !mcp && _jsx(SecurityCopy, { security: op.security })] }), _jsxs("aside", { class: `hidden ${apiFirst ? "lg:block" : "xl:block"} w-[28rem] shrink-0 sticky self-start overflow-y-auto space-y-4`, style: "top: calc(var(--header-height) + 2.5rem); max-height: calc(100vh - var(--header-height) - 5rem)", children: [_jsx(CodeSamplesExamples, { operation: op, serverUrl: serverUrl, codeSampleLangs: site.codeSamples }), hasBody && _jsx(RequestBodyExample, { body: op.requestBody }), mcp ? (_jsx(McpReturnsExample, { schema: mcp.outputSchema })) : (_jsx(ResponsesExamples, { responses: op.responses }))] })] }), _jsxs("div", { class: `${apiFirst ? "lg:hidden" : "xl:hidden"} mt-8 space-y-4`, children: [_jsx(CodeSamplesExamples, { operation: op, serverUrl: serverUrl, codeSampleLangs: site.codeSamples }), hasBody && _jsx(RequestBodyExample, { body: op.requestBody }), mcp ? (_jsx(McpReturnsExample, { schema: mcp.outputSchema })) : (_jsx(ResponsesExamples, { responses: op.responses }))] })] }));
|
|
26
30
|
}
|
|
27
31
|
function bodyMediaType(body) {
|
|
28
32
|
const types = Object.keys(body.content);
|
package/dist/config.d.ts
CHANGED
|
@@ -78,6 +78,8 @@ export interface TabConfig {
|
|
|
78
78
|
openapi?: string;
|
|
79
79
|
groups?: GroupConfig[];
|
|
80
80
|
doxygen?: DoxygenConfig;
|
|
81
|
+
/** Path to an mcp.json file (MCP server snapshot). */
|
|
82
|
+
mcp?: string;
|
|
81
83
|
}
|
|
82
84
|
export interface GroupConfig {
|
|
83
85
|
group: string;
|
|
@@ -146,6 +148,7 @@ export interface ResolvedTab {
|
|
|
146
148
|
openapi?: string;
|
|
147
149
|
groups?: ResolvedGroup[];
|
|
148
150
|
doxygen?: ResolvedDoxygenConfig;
|
|
151
|
+
mcp?: string;
|
|
149
152
|
}
|
|
150
153
|
export interface ResolvedPage {
|
|
151
154
|
/** Original config slug (e.g. "run/index") */
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAQA,MAAM,MAAM,WAAW,GAAG,SAAS,GAAG,SAAS,GAAG,WAAW,CAAC;AAE9D,MAAM,WAAW,WAAW;IAC1B,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,MAAM,CAAC,EAAE;QACP,OAAO,EAAE,MAAM,CAAC;QAChB,KAAK,CAAC,EAAE,MAAM,CAAC;QACf,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,KAAK,CAAC,EAAE;QACN,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,MAAM,CAAC,EAAE;QACP,OAAO,CAAC,EAAE,MAAM,CAAC;QACjB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,OAAO,CAAC,EAAE,MAAM,CAAC;KAClB,CAAC;IACF,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,GAAG;QACd,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;IACF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,6DAA6D;IAC7D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,sHAAsH;IACtH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,iJAAiJ;IACjJ,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE;QACV,IAAI,EAAE,SAAS,EAAE,CAAC;KACnB,CAAC;IACF,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;QACrB,OAAO,CAAC,EAAE;YAAE,IAAI,EAAE,QAAQ,CAAC;YAAC,KAAK,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;KAC3D,CAAC;IACF,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;KACtB,CAAC;CACH;AAED,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,YAAY,GAAG,MAAM,GAAG,MAAM,CAAC;AAEjF,MAAM,WAAW,aAAa;IAC5B,2CAA2C;IAC3C,GAAG,EAAE,MAAM,CAAC;IACZ,4CAA4C;IAC5C,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iDAAiD;IACjD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB;;;;;;;OAOG;IACH,KAAK,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAC;CACnC;AAED,MAAM,WAAW,SAAS;IACxB,GAAG,EAAE,MAAM,CAAC;IACZ,oEAAoE;IACpE,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,WAAW,EAAE,CAAC;IACvB,OAAO,CAAC,EAAE,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
|
package/dist/config.js
CHANGED
|
@@ -137,18 +137,23 @@ async function resolveTabs(tabs, configDir) {
|
|
|
137
137
|
if (slugs.has(slug))
|
|
138
138
|
throw new Error(`Duplicate tab slug "${slug}" (from "${tab.tab}")`);
|
|
139
139
|
slugs.add(slug);
|
|
140
|
-
const sources = [tab.openapi, tab.groups, tab.doxygen].filter(Boolean).length;
|
|
140
|
+
const sources = [tab.openapi, tab.groups, tab.doxygen, tab.mcp].filter(Boolean).length;
|
|
141
141
|
if (sources > 1) {
|
|
142
|
-
throw new Error(`Tab "${tab.tab}" has multiple sources; use only one of "openapi", "groups", or "
|
|
142
|
+
throw new Error(`Tab "${tab.tab}" has multiple sources; use only one of "openapi", "groups", "doxygen", or "mcp"`);
|
|
143
143
|
}
|
|
144
144
|
if (sources === 0) {
|
|
145
|
-
throw new Error(`Tab "${tab.tab}" needs one of "openapi", "groups", or "
|
|
145
|
+
throw new Error(`Tab "${tab.tab}" needs one of "openapi", "groups", "doxygen", or "mcp"`);
|
|
146
146
|
}
|
|
147
147
|
if (tab.openapi) {
|
|
148
148
|
const absPath = resolve(configDir, tab.openapi);
|
|
149
149
|
await assertExists(absPath, `OpenAPI spec "${tab.openapi}" in tab "${tab.tab}"`);
|
|
150
150
|
resolved.push({ label: tab.tab, slug, openapi: absPath });
|
|
151
151
|
}
|
|
152
|
+
else if (tab.mcp) {
|
|
153
|
+
const absPath = resolve(configDir, tab.mcp);
|
|
154
|
+
await assertExists(absPath, `MCP spec "${tab.mcp}" in tab "${tab.tab}"`);
|
|
155
|
+
resolved.push({ label: tab.tab, slug, mcp: absPath });
|
|
156
|
+
}
|
|
152
157
|
else if (tab.doxygen) {
|
|
153
158
|
const absXml = resolve(configDir, tab.doxygen.xml);
|
|
154
159
|
await assertExists(absXml, `Doxygen XML directory "${tab.doxygen.xml}" in tab "${tab.tab}"`);
|
|
@@ -108,18 +108,18 @@ function resolveIndexStyle(configured, groupMap, pages) {
|
|
|
108
108
|
/**
|
|
109
109
|
* Build index page HTML using sourcey's existing component markup.
|
|
110
110
|
*/
|
|
111
|
-
function buildIndexHtml(style,
|
|
111
|
+
function buildIndexHtml(style, _tabSlug, _tabLabel, groupMap, pages) {
|
|
112
112
|
if (style === "rich")
|
|
113
|
-
return buildRichIndex(
|
|
113
|
+
return buildRichIndex(groupMap, pages);
|
|
114
114
|
if (style === "structured")
|
|
115
|
-
return buildStructuredIndex(
|
|
116
|
-
return buildFlatIndex(
|
|
115
|
+
return buildStructuredIndex(groupMap, pages);
|
|
116
|
+
return buildFlatIndex(groupMap);
|
|
117
117
|
}
|
|
118
118
|
/**
|
|
119
119
|
* Rich: card grid with module name, description, and type count.
|
|
120
120
|
* Uses sourcey's card-group/card-item CSS.
|
|
121
121
|
*/
|
|
122
|
-
function buildRichIndex(
|
|
122
|
+
function buildRichIndex(groupMap, pages) {
|
|
123
123
|
const cards = [];
|
|
124
124
|
for (const [, items] of groupMap) {
|
|
125
125
|
const groupEntry = items.find((i) => i.kind === "group");
|
|
@@ -129,7 +129,7 @@ function buildRichIndex(tabSlug, groupMap, pages) {
|
|
|
129
129
|
if (!page)
|
|
130
130
|
continue;
|
|
131
131
|
const typeCount = items.filter((i) => i.kind !== "group" && i.kind !== "namespace").length;
|
|
132
|
-
const href = `${
|
|
132
|
+
const href = `${groupEntry.slug}.html`;
|
|
133
133
|
const desc = page.description || "";
|
|
134
134
|
const meta = typeCount > 0
|
|
135
135
|
? `<p style="margin:0.5rem 0 0;font-size:0.8rem;opacity:0.5">${typeCount} type${typeCount !== 1 ? "s" : ""}</p>`
|
|
@@ -149,7 +149,7 @@ function buildRichIndex(tabSlug, groupMap, pages) {
|
|
|
149
149
|
if (typeCount === 0)
|
|
150
150
|
continue;
|
|
151
151
|
const firstItem = items[0];
|
|
152
|
-
const href = `${
|
|
152
|
+
const href = `${firstItem.slug}.html`;
|
|
153
153
|
cards.push(`<a href="${href}" class="card-item">` +
|
|
154
154
|
`<div class="card-item-inner">` +
|
|
155
155
|
`<h3 class="card-item-title">${escHtml(key)}</h3>` +
|
|
@@ -165,7 +165,7 @@ function buildRichIndex(tabSlug, groupMap, pages) {
|
|
|
165
165
|
* Structured: grouped list of types by module/namespace.
|
|
166
166
|
* Rendered as markdown headings with link lists.
|
|
167
167
|
*/
|
|
168
|
-
function buildStructuredIndex(
|
|
168
|
+
function buildStructuredIndex(groupMap, pages) {
|
|
169
169
|
const sections = [];
|
|
170
170
|
for (const [key, items] of groupMap) {
|
|
171
171
|
const groupEntry = items.find((i) => i.kind === "group");
|
|
@@ -175,10 +175,10 @@ function buildStructuredIndex(tabSlug, groupMap, pages) {
|
|
|
175
175
|
continue;
|
|
176
176
|
const links = [];
|
|
177
177
|
if (groupEntry) {
|
|
178
|
-
links.push(`- [Overview](${
|
|
178
|
+
links.push(`- [Overview](${groupEntry.slug}.html)`);
|
|
179
179
|
}
|
|
180
180
|
for (const t of types) {
|
|
181
|
-
links.push(`- [${t.title}](${
|
|
181
|
+
links.push(`- [${t.title}](${t.slug}.html)`);
|
|
182
182
|
}
|
|
183
183
|
sections.push(`### ${title}\n\n${links.join("\n")}`);
|
|
184
184
|
}
|
|
@@ -187,7 +187,7 @@ function buildStructuredIndex(tabSlug, groupMap, pages) {
|
|
|
187
187
|
/**
|
|
188
188
|
* Flat: alphabetical list categorized by kind.
|
|
189
189
|
*/
|
|
190
|
-
function buildFlatIndex(
|
|
190
|
+
function buildFlatIndex(groupMap) {
|
|
191
191
|
const byKind = new Map();
|
|
192
192
|
for (const [, items] of groupMap) {
|
|
193
193
|
for (const item of items) {
|
|
@@ -202,7 +202,7 @@ function buildFlatIndex(tabSlug, groupMap) {
|
|
|
202
202
|
const sections = [];
|
|
203
203
|
for (const [label, items] of byKind) {
|
|
204
204
|
const sorted = items.sort((a, b) => a.title.localeCompare(b.title));
|
|
205
|
-
const links = sorted.map((i) => `- [${i.title}](${
|
|
205
|
+
const links = sorted.map((i) => `- [${i.title}](${i.slug}.html)`).join("\n");
|
|
206
206
|
sections.push(`### ${label}\n\n${links}`);
|
|
207
207
|
}
|
|
208
208
|
return renderMarkdown(sections.join("\n\n"));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Convert an McpSpec (from mcp-parser) into a NormalizedSpec for rendering.
|
|
3
|
+
*
|
|
4
|
+
* This is the bridge between the MCP snapshot format and sourcey's
|
|
5
|
+
* format-agnostic rendering pipeline. Everything downstream (components,
|
|
6
|
+
* search, navigation, themes) works unchanged.
|
|
7
|
+
*/
|
|
8
|
+
import type { McpSpec } from "mcp-parser";
|
|
9
|
+
import type { NormalizedSpec } from "./types.js";
|
|
10
|
+
export declare function normalizeMcpSpec(spec: McpSpec): NormalizedSpec;
|
|
11
|
+
//# sourceMappingURL=mcp-normalizer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mcp-normalizer.d.ts","sourceRoot":"","sources":["../../src/core/mcp-normalizer.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAoE,MAAM,YAAY,CAAC;AAC5G,OAAO,KAAK,EACV,cAAc,EAUf,MAAM,YAAY,CAAC;AAKpB,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,OAAO,GAAG,cAAc,CA+C9D"}
|