@farming-labs/docs 0.2.62 → 0.2.64
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/agent-CQTH7NFu.mjs +624 -0
- package/dist/agent-DKKptIgy.mjs +4365 -0
- package/dist/agent-evals-B7MIxuEX.mjs +2144 -0
- package/dist/agent-export-CBgWgPvH.mjs +910 -0
- package/dist/agent-scope-C_U--OZ7.mjs +283 -0
- package/dist/agent-skills-bundle.d.mts +13 -0
- package/dist/agent-skills-bundle.mjs +12 -0
- package/dist/agent-skills-server-CPja6Syt.d.mts +14 -0
- package/dist/agent-skills-server-DraIb6FV.mjs +415 -0
- package/dist/agent-skills-vite.d.mts +31 -0
- package/dist/agent-skills-vite.mjs +70 -0
- package/dist/agents-XWZBub6f.mjs +221 -0
- package/dist/analytics-Bx44lg6d.mjs +177 -0
- package/dist/cli/index.d.mts +15 -0
- package/dist/cli/index.mjs +452 -0
- package/dist/client/react.d.mts +45 -0
- package/dist/client/react.mjs +223 -0
- package/dist/cloud-analytics-CSyFE6SS.mjs +132 -0
- package/dist/cloud-ask-ai-sbpjOR2K.mjs +382 -0
- package/dist/cloud-ask-ai-zpwkdwnF.d.mts +23 -0
- package/dist/cloud-pdNC-tyj.mjs +1615 -0
- package/dist/code-blocks-DnNVNK2M.mjs +871 -0
- package/dist/codeblocks-CFuurVIH.mjs +250 -0
- package/dist/config-Wcdj-D0a.mjs +369 -0
- package/dist/dev-Cmy6DtdF.mjs +1333 -0
- package/dist/docs-cloud-server.d.mts +70 -0
- package/dist/docs-cloud-server.mjs +310 -0
- package/dist/doctor-DtGYZ41i.mjs +2036 -0
- package/dist/downgrade-w7e6Se0L.mjs +184 -0
- package/dist/errors-DbOhkE1h.mjs +20 -0
- package/dist/golden-evaluations-Dj-9Eo3v.mjs +1785 -0
- package/dist/i18n-CCaFUnAN.mjs +40 -0
- package/dist/index.d.mts +1150 -0
- package/dist/index.mjs +10 -0
- package/dist/init-CQY0Woe3.mjs +1264 -0
- package/dist/mcp-B9dcsivk.mjs +156 -0
- package/dist/mcp.d.mts +298 -0
- package/dist/mcp.mjs +4430 -0
- package/dist/metadata-DWExHQnx.mjs +237 -0
- package/dist/package-version-n5AFur8a.mjs +128 -0
- package/dist/reading-time-CYZ5VvKU.mjs +742 -0
- package/dist/review-CLoHTywU.mjs +673 -0
- package/dist/robots-BIpC4j4P.mjs +201 -0
- package/dist/robots-CUTahhoY.mjs +179 -0
- package/dist/search-B6V6qtiI.mjs +1826 -0
- package/dist/search-CaSyi6H6.d.mts +279 -0
- package/dist/search-DSjCeOk7.mjs +104 -0
- package/dist/server.d.mts +343 -0
- package/dist/server.mjs +14 -0
- package/dist/sitemap-Cykpe3Tz.mjs +249 -0
- package/dist/sitemap-server-C_6Wes83.mjs +1137 -0
- package/dist/standards-discovery-C4HUqMd2.d.mts +227 -0
- package/dist/standards-discovery-jkykaXq1.mjs +519 -0
- package/dist/templates-Bq_P7ctv.mjs +2465 -0
- package/dist/types-lMBIdZg0.d.mts +3315 -0
- package/dist/upgrade-oz-GChgt.mjs +56 -0
- package/dist/utils-DpiIioYb.mjs +225 -0
- package/package.json +1 -1
|
@@ -0,0 +1,1137 @@
|
|
|
1
|
+
import { Ft as resolveDocsSitemapConfig } from "./agent-DKKptIgy.mjs";
|
|
2
|
+
import { createRequire } from "node:module";
|
|
3
|
+
import { existsSync, readFileSync, readdirSync, statSync } from "node:fs";
|
|
4
|
+
import path, { basename, join, relative } from "node:path";
|
|
5
|
+
import { getHtmlDocument } from "@scalar/core/libs/html-rendering";
|
|
6
|
+
|
|
7
|
+
//#region src/code-group-mdx.ts
|
|
8
|
+
const codeGroupTitleAttributes = [
|
|
9
|
+
"title",
|
|
10
|
+
"filename",
|
|
11
|
+
"file",
|
|
12
|
+
"name",
|
|
13
|
+
"label"
|
|
14
|
+
];
|
|
15
|
+
const ignoredBareMetaTokens = new Set([
|
|
16
|
+
"copy",
|
|
17
|
+
"no-copy",
|
|
18
|
+
"nocopy",
|
|
19
|
+
"line-numbers",
|
|
20
|
+
"linenumbers",
|
|
21
|
+
"runnable",
|
|
22
|
+
"show-line-numbers",
|
|
23
|
+
"showlinenumbers",
|
|
24
|
+
"wrap"
|
|
25
|
+
]);
|
|
26
|
+
function escapeMetaAttribute(value) {
|
|
27
|
+
return value.replace(/\\/g, "\\\\").replace(/"/g, "\\\"");
|
|
28
|
+
}
|
|
29
|
+
function readCodeGroupTitleAttribute(meta) {
|
|
30
|
+
for (const name of codeGroupTitleAttributes) {
|
|
31
|
+
const match = meta.match(new RegExp(`(?:^|\\s)${name}=["']([^"']+)["']`));
|
|
32
|
+
if (match?.[1]?.trim()) return match[1].trim();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
function readBareCodeGroupTitle(meta) {
|
|
36
|
+
return meta.replace(/\{[^}]*\}/g, " ").split(/\s+/).find((part) => part && !part.includes("=") && !ignoredBareMetaTokens.has(part.toLowerCase()))?.replace(/^["']|["']$/g, "");
|
|
37
|
+
}
|
|
38
|
+
function resolveCodeGroupCodeTitle(meta) {
|
|
39
|
+
const trimmed = meta?.trim();
|
|
40
|
+
if (!trimmed) return void 0;
|
|
41
|
+
return readCodeGroupTitleAttribute(trimmed) ?? readBareCodeGroupTitle(trimmed);
|
|
42
|
+
}
|
|
43
|
+
function ensureCodeGroupCodeTitle(node) {
|
|
44
|
+
const title = resolveCodeGroupCodeTitle(node.meta);
|
|
45
|
+
if (!title) return;
|
|
46
|
+
const meta = node.meta?.trim() ?? "";
|
|
47
|
+
if (/(?:^|\s)title=["']/.test(meta)) return;
|
|
48
|
+
node.meta = `title="${escapeMetaAttribute(title)}"${meta ? ` ${meta}` : ""}`;
|
|
49
|
+
}
|
|
50
|
+
function visitCodeGroups(node) {
|
|
51
|
+
if (node.type === "mdxJsxFlowElement" && node.name === "CodeGroup") {
|
|
52
|
+
for (const child of node.children ?? []) if (child.type === "code") ensureCodeGroupCodeTitle(child);
|
|
53
|
+
}
|
|
54
|
+
for (const child of node.children ?? []) visitCodeGroups(child);
|
|
55
|
+
}
|
|
56
|
+
function remarkCodeGroup() {
|
|
57
|
+
return (tree) => {
|
|
58
|
+
visitCodeGroups(tree);
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
//#endregion
|
|
63
|
+
//#region src/api-reference.ts
|
|
64
|
+
const NEXT_ROUTE_FILE_RE = /^route\.(ts|tsx|js|jsx)$/;
|
|
65
|
+
const SVELTE_ROUTE_FILE_RE = /^\+server\.(ts|js)$/;
|
|
66
|
+
const ASTRO_ROUTE_FILE_RE = /^[^.].*\.(ts|js|mts|mjs)$/;
|
|
67
|
+
const NUXT_ROUTE_FILE_RE = /^[^.].*\.(ts|js|mts|mjs)$/;
|
|
68
|
+
const TANSTACK_ROUTE_FILE_RE = /\.(ts|tsx|js|jsx)$/;
|
|
69
|
+
const METHOD_RE = /export\s+(?:async\s+function|function|const)\s+(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD|ALL)\b/g;
|
|
70
|
+
const METHOD_NAMES = [
|
|
71
|
+
"GET",
|
|
72
|
+
"POST",
|
|
73
|
+
"PUT",
|
|
74
|
+
"PATCH",
|
|
75
|
+
"DELETE",
|
|
76
|
+
"OPTIONS",
|
|
77
|
+
"HEAD"
|
|
78
|
+
];
|
|
79
|
+
const DEFAULT_API_REFERENCE_OPENAPI_ROUTE = "/api/docs?format=openapi";
|
|
80
|
+
function normalizePathSegment(value) {
|
|
81
|
+
return value.replace(/^\/+|\/+$/g, "");
|
|
82
|
+
}
|
|
83
|
+
function resolveApiReferenceConfig(value) {
|
|
84
|
+
if (value === true) return {
|
|
85
|
+
enabled: true,
|
|
86
|
+
path: "api-reference",
|
|
87
|
+
specUrl: void 0,
|
|
88
|
+
renderer: void 0,
|
|
89
|
+
routeRoot: "api",
|
|
90
|
+
exclude: []
|
|
91
|
+
};
|
|
92
|
+
if (!value) return {
|
|
93
|
+
enabled: false,
|
|
94
|
+
path: "api-reference",
|
|
95
|
+
specUrl: void 0,
|
|
96
|
+
renderer: void 0,
|
|
97
|
+
routeRoot: "api",
|
|
98
|
+
exclude: []
|
|
99
|
+
};
|
|
100
|
+
return {
|
|
101
|
+
enabled: value.enabled !== false,
|
|
102
|
+
path: normalizePathSegment(value.path ?? "api-reference"),
|
|
103
|
+
specUrl: normalizeRemoteSpecUrl(value.specUrl),
|
|
104
|
+
renderer: normalizeApiReferenceRenderer(value.renderer),
|
|
105
|
+
routeRoot: normalizePathSegment(value.routeRoot ?? "api") || "api",
|
|
106
|
+
exclude: normalizeApiReferenceExcludes(value.exclude)
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function normalizeApiReferenceRenderer(value) {
|
|
110
|
+
if (value === "fumadocs" || value === "scalar") return value;
|
|
111
|
+
}
|
|
112
|
+
function resolveApiReferenceRenderer(value, framework) {
|
|
113
|
+
const config = resolveApiReferenceConfig(value);
|
|
114
|
+
if (config.renderer) return config.renderer;
|
|
115
|
+
return framework === "next" ? "fumadocs" : "scalar";
|
|
116
|
+
}
|
|
117
|
+
function resolveApiReferenceOpenApiDiscovery(value, options = {}) {
|
|
118
|
+
const config = resolveApiReferenceConfig(value);
|
|
119
|
+
if (!config.enabled) return { enabled: false };
|
|
120
|
+
return {
|
|
121
|
+
enabled: true,
|
|
122
|
+
url: options.route ?? DEFAULT_API_REFERENCE_OPENAPI_ROUTE,
|
|
123
|
+
urlSource: options.route === void 0 ? "default" : "configured",
|
|
124
|
+
source: config.specUrl ? "configured" : "generated",
|
|
125
|
+
specUrl: config.specUrl,
|
|
126
|
+
apiReferencePath: `/${config.path}`
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function isApiReferenceOpenApiRequest(url) {
|
|
130
|
+
return url.searchParams.get("format")?.trim() === "openapi";
|
|
131
|
+
}
|
|
132
|
+
function normalizeRemoteSpecUrl(value) {
|
|
133
|
+
const trimmed = value?.trim();
|
|
134
|
+
if (!trimmed) return void 0;
|
|
135
|
+
return trimmed;
|
|
136
|
+
}
|
|
137
|
+
function isRequestRelativeSpecUrl(value) {
|
|
138
|
+
return typeof value === "string" && value.startsWith("/");
|
|
139
|
+
}
|
|
140
|
+
function buildApiReferencePageTitle(config, title = "API Reference") {
|
|
141
|
+
const template = config.metadata?.titleTemplate;
|
|
142
|
+
if (!template) return title;
|
|
143
|
+
return template.replace("%s", title);
|
|
144
|
+
}
|
|
145
|
+
function buildApiReferenceScalarCss(config) {
|
|
146
|
+
const theme = resolveTheme(config);
|
|
147
|
+
const colors = theme?.ui?.colors;
|
|
148
|
+
const typography = theme?.ui?.typography?.font?.style;
|
|
149
|
+
const layout = theme?.ui?.layout;
|
|
150
|
+
const radius = resolveApiReferenceRadius(theme);
|
|
151
|
+
const primary = colors?.primary ?? "#6366f1";
|
|
152
|
+
const border = colors?.border ?? "#2a2a2a";
|
|
153
|
+
const muted = colors?.muted ?? "#64748b";
|
|
154
|
+
const background = colors?.background ?? "#ffffff";
|
|
155
|
+
const card = colors?.card ?? background;
|
|
156
|
+
const foreground = colors?.foreground ?? inferApiReferenceForeground(theme, background);
|
|
157
|
+
const primaryForeground = colors?.primaryForeground ?? inferContrastingForeground(primary, theme, background);
|
|
158
|
+
const sidebarWidth = layout?.sidebarWidth ?? 280;
|
|
159
|
+
const sans = typography?.sans ?? "\"Geist\", \"Inter\", \"Segoe UI\", sans-serif";
|
|
160
|
+
const mono = typography?.mono ?? "\"Geist Mono\", \"SFMono-Regular\", \"Menlo\", monospace";
|
|
161
|
+
const isPixelBorder = theme?.name?.includes("pixel-border");
|
|
162
|
+
return `
|
|
163
|
+
:root {
|
|
164
|
+
--scalar-font: ${sans};
|
|
165
|
+
--scalar-font-code: ${mono};
|
|
166
|
+
--scalar-radius: ${radius};
|
|
167
|
+
--scalar-radius-sm: calc(${radius} + 2px);
|
|
168
|
+
--scalar-theme-primary: ${primary};
|
|
169
|
+
--scalar-theme-border: ${border};
|
|
170
|
+
--scalar-theme-muted: ${muted};
|
|
171
|
+
--scalar-theme-background: ${background};
|
|
172
|
+
--scalar-theme-card: ${card};
|
|
173
|
+
--scalar-theme-foreground: ${foreground};
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
.dark-mode {
|
|
177
|
+
--scalar-background-1: color-mix(
|
|
178
|
+
in srgb,
|
|
179
|
+
var(--scalar-theme-background) 96%,
|
|
180
|
+
var(--scalar-theme-primary) 4%
|
|
181
|
+
);
|
|
182
|
+
--scalar-background-2: color-mix(in srgb, var(--scalar-theme-card) 94%, var(--scalar-theme-primary) 6%);
|
|
183
|
+
--scalar-background-3: color-mix(
|
|
184
|
+
in srgb,
|
|
185
|
+
var(--scalar-theme-card) 90%,
|
|
186
|
+
var(--scalar-theme-foreground) 10%
|
|
187
|
+
);
|
|
188
|
+
--scalar-color-1: var(--scalar-theme-foreground);
|
|
189
|
+
--scalar-color-2: color-mix(in srgb, var(--scalar-theme-foreground) 72%, transparent);
|
|
190
|
+
--scalar-color-3: color-mix(in srgb, var(--scalar-theme-foreground) 52%, transparent);
|
|
191
|
+
--scalar-color-accent: var(--scalar-theme-primary);
|
|
192
|
+
--scalar-sidebar-background-1: var(--scalar-background-1);
|
|
193
|
+
--scalar-sidebar-background-2: var(--scalar-background-2);
|
|
194
|
+
--scalar-sidebar-color-1: var(--scalar-color-1);
|
|
195
|
+
--scalar-sidebar-color-2: var(--scalar-color-2);
|
|
196
|
+
--scalar-sidebar-search-background: var(--scalar-background-2);
|
|
197
|
+
--scalar-sidebar-search-border-color: var(--scalar-border-color);
|
|
198
|
+
--scalar-sidebar-search-color: var(--scalar-color-2);
|
|
199
|
+
--scalar-sidebar-color-active: var(--scalar-theme-primary);
|
|
200
|
+
--scalar-sidebar-item-active-background: color-mix(
|
|
201
|
+
in srgb,
|
|
202
|
+
var(--scalar-theme-primary) 7%,
|
|
203
|
+
transparent
|
|
204
|
+
);
|
|
205
|
+
--scalar-border-color: ${isPixelBorder ? "color-mix(in srgb, var(--scalar-theme-foreground) 10%, transparent)" : "color-mix(in srgb, var(--scalar-theme-border) 14%, rgba(255, 255, 255, 0.02))"};
|
|
206
|
+
--scalar-button-1: var(--scalar-theme-primary);
|
|
207
|
+
--scalar-button-1-color: ${primaryForeground};
|
|
208
|
+
--scalar-button-1-hover: color-mix(in srgb, var(--scalar-theme-primary) 88%, white 12%);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.light-mode {
|
|
212
|
+
--scalar-background-1: var(--scalar-theme-background);
|
|
213
|
+
--scalar-background-2: color-mix(in srgb, var(--scalar-theme-card) 92%, white 8%);
|
|
214
|
+
--scalar-background-3: color-mix(in srgb, var(--scalar-theme-card) 84%, black 4%);
|
|
215
|
+
--scalar-color-1: var(--scalar-theme-foreground);
|
|
216
|
+
--scalar-color-2: var(--scalar-theme-muted);
|
|
217
|
+
--scalar-color-3: color-mix(in srgb, var(--scalar-theme-muted) 78%, white 22%);
|
|
218
|
+
--scalar-color-accent: var(--scalar-theme-primary);
|
|
219
|
+
--scalar-sidebar-background-1: var(--scalar-background-1);
|
|
220
|
+
--scalar-sidebar-background-2: var(--scalar-background-2);
|
|
221
|
+
--scalar-sidebar-color-1: var(--scalar-color-1);
|
|
222
|
+
--scalar-sidebar-color-2: var(--scalar-color-2);
|
|
223
|
+
--scalar-sidebar-search-background: var(--scalar-background-2);
|
|
224
|
+
--scalar-sidebar-search-border-color: var(--scalar-border-color);
|
|
225
|
+
--scalar-sidebar-search-color: var(--scalar-color-2);
|
|
226
|
+
--scalar-sidebar-color-active: var(--scalar-theme-primary);
|
|
227
|
+
--scalar-sidebar-item-active-background: color-mix(
|
|
228
|
+
in srgb,
|
|
229
|
+
var(--scalar-theme-primary) 5%,
|
|
230
|
+
transparent
|
|
231
|
+
);
|
|
232
|
+
--scalar-border-color: ${isPixelBorder ? "color-mix(in srgb, var(--scalar-theme-foreground) 14%, transparent)" : "color-mix(in srgb, var(--scalar-theme-border) 30%, white 70%)"};
|
|
233
|
+
--scalar-button-1: var(--scalar-theme-primary);
|
|
234
|
+
--scalar-button-1-color: ${primaryForeground};
|
|
235
|
+
--scalar-button-1-hover: color-mix(in srgb, var(--scalar-theme-primary) 88%, black 12%);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
body {
|
|
239
|
+
background: var(--scalar-background-1);
|
|
240
|
+
color: var(--scalar-color-1);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
.t-doc__sidebar {
|
|
244
|
+
width: min(${sidebarWidth}px, 100vw);
|
|
245
|
+
border-right: 1px solid var(--scalar-border-color);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.scalar-card,
|
|
249
|
+
.t-doc__sidebar,
|
|
250
|
+
.references-layout .reference-layout__content .request-card,
|
|
251
|
+
.references-layout .reference-layout__content .response-card,
|
|
252
|
+
.references-layout .reference-layout__content .scalar-card-header,
|
|
253
|
+
.references-layout .reference-layout__content .scalar-card-footer,
|
|
254
|
+
.references-layout .reference-layout__content .section,
|
|
255
|
+
.references-layout .reference-layout__content .section-container {
|
|
256
|
+
border-color: var(--scalar-border-color) !important;
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
.t-doc__sidebar,
|
|
260
|
+
.t-doc__sidebar * {
|
|
261
|
+
font-family: var(--scalar-font);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
.t-doc__sidebar .sidebar-search {
|
|
265
|
+
margin: 0.5rem 0 1rem;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
.t-doc__sidebar .sidebar-search input {
|
|
269
|
+
border-radius: var(--scalar-radius-sm);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
.t-doc__sidebar .sidebar-item,
|
|
273
|
+
.t-doc__sidebar .sidebar-heading {
|
|
274
|
+
border-radius: var(--scalar-radius-sm);
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
.t-doc__sidebar .sidebar-group-label {
|
|
278
|
+
font-size: 0.72rem;
|
|
279
|
+
letter-spacing: 0.08em;
|
|
280
|
+
text-transform: uppercase;
|
|
281
|
+
color: var(--scalar-color-3);
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
.t-doc__sidebar .sidebar-item--active {
|
|
285
|
+
font-weight: 600;
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
.scalar-card,
|
|
289
|
+
.references-layout .reference-layout__content .request-card,
|
|
290
|
+
.references-layout .reference-layout__content .response-card {
|
|
291
|
+
border-radius: var(--scalar-radius);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.references-layout .reference-layout__content {
|
|
295
|
+
padding-top: 1.5rem;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
.references-layout .section-content,
|
|
299
|
+
.references-layout .section-flare {
|
|
300
|
+
background: transparent;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
.references-layout .reference-layout__content,
|
|
304
|
+
.references-layout .reference-layout__content * {
|
|
305
|
+
font-family: var(--scalar-font);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
.references-layout code,
|
|
309
|
+
.references-layout pre,
|
|
310
|
+
.references-layout .scalar-codeblock {
|
|
311
|
+
font-family: var(--scalar-font-code);
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
.references-layout,
|
|
315
|
+
.references-layout * {
|
|
316
|
+
color: inherit;
|
|
317
|
+
}
|
|
318
|
+
|
|
319
|
+
.references-layout .reference-layout__content .introduction,
|
|
320
|
+
.references-layout .reference-layout__content .section,
|
|
321
|
+
.references-layout .reference-layout__content .section-container,
|
|
322
|
+
.references-layout .reference-layout__content .operation-details,
|
|
323
|
+
.references-layout .reference-layout__content .markdown,
|
|
324
|
+
.references-layout .reference-layout__content .markdown *,
|
|
325
|
+
.references-layout .reference-layout__content .property,
|
|
326
|
+
.references-layout .reference-layout__content .property *,
|
|
327
|
+
.references-layout .reference-layout__content .parameter-item,
|
|
328
|
+
.references-layout .reference-layout__content .parameter-item *,
|
|
329
|
+
.references-layout .reference-layout__content .response-card,
|
|
330
|
+
.references-layout .reference-layout__content .response-card *,
|
|
331
|
+
.references-layout .reference-layout__content .request-card,
|
|
332
|
+
.references-layout .reference-layout__content .request-card * {
|
|
333
|
+
color: var(--scalar-color-1);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
.references-layout a,
|
|
337
|
+
.references-layout button {
|
|
338
|
+
color: var(--scalar-color-1);
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
${isPixelBorder ? buildPixelBorderScalarCss() : ""}
|
|
342
|
+
`;
|
|
343
|
+
}
|
|
344
|
+
function buildPixelBorderScalarCss() {
|
|
345
|
+
return `
|
|
346
|
+
.t-doc__sidebar,
|
|
347
|
+
.references-layout .reference-layout__content {
|
|
348
|
+
background-image:
|
|
349
|
+
repeating-linear-gradient(
|
|
350
|
+
-45deg,
|
|
351
|
+
color-mix(in srgb, var(--scalar-theme-border) 12%, transparent),
|
|
352
|
+
color-mix(in srgb, var(--scalar-theme-border) 12%, transparent) 1px,
|
|
353
|
+
transparent 1px,
|
|
354
|
+
transparent 8px
|
|
355
|
+
);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
.t-doc__sidebar .sidebar-group-label,
|
|
359
|
+
.t-doc__sidebar .sidebar-item,
|
|
360
|
+
.references-layout .reference-layout__content .section-header {
|
|
361
|
+
font-family: var(--scalar-font-code);
|
|
362
|
+
text-transform: uppercase;
|
|
363
|
+
letter-spacing: 0.06em;
|
|
364
|
+
}
|
|
365
|
+
`;
|
|
366
|
+
}
|
|
367
|
+
function inferApiReferenceForeground(theme, background) {
|
|
368
|
+
if (looksDarkTheme(theme, background)) return "#f5f5f4";
|
|
369
|
+
return "#1b1b1b";
|
|
370
|
+
}
|
|
371
|
+
function resolveApiReferenceRadius(theme) {
|
|
372
|
+
if (theme?.ui?.radius) return theme.ui.radius;
|
|
373
|
+
const name = theme?.name?.toLowerCase() ?? "";
|
|
374
|
+
if (name.includes("pixel-border") || name.includes("darksharp")) return "0px";
|
|
375
|
+
return "var(--radius, 0.75rem)";
|
|
376
|
+
}
|
|
377
|
+
function inferContrastingForeground(value, theme, background) {
|
|
378
|
+
const rgb = parseCssColor(value);
|
|
379
|
+
if (rgb) return relativeLuminance(rgb) > .58 ? "#0b0b0b" : "#ffffff";
|
|
380
|
+
if (theme?.name?.includes("pixel-border")) return "#0b0b0b";
|
|
381
|
+
if (looksDarkTheme(theme, background)) return "#0b0b0b";
|
|
382
|
+
return "#ffffff";
|
|
383
|
+
}
|
|
384
|
+
function looksDarkTheme(theme, background) {
|
|
385
|
+
const name = theme?.name?.toLowerCase() ?? "";
|
|
386
|
+
if (name.includes("pixel-border") || name.includes("darksharp")) return true;
|
|
387
|
+
const rgb = parseCssColor(background);
|
|
388
|
+
if (!rgb) return false;
|
|
389
|
+
return relativeLuminance(rgb) < .45;
|
|
390
|
+
}
|
|
391
|
+
function parseCssColor(value) {
|
|
392
|
+
const normalized = value.trim().toLowerCase();
|
|
393
|
+
if (normalized.startsWith("#")) return parseHexColor(normalized);
|
|
394
|
+
const rgbMatch = normalized.match(/^rgba?\((.+)\)$/);
|
|
395
|
+
if (rgbMatch) {
|
|
396
|
+
const [r, g, b] = rgbMatch[1].split(",").slice(0, 3).map((part) => Number.parseFloat(part.trim()));
|
|
397
|
+
if ([
|
|
398
|
+
r,
|
|
399
|
+
g,
|
|
400
|
+
b
|
|
401
|
+
].every((channel) => Number.isFinite(channel))) return [
|
|
402
|
+
r,
|
|
403
|
+
g,
|
|
404
|
+
b
|
|
405
|
+
];
|
|
406
|
+
}
|
|
407
|
+
const hslMatch = normalized.match(/^hsla?\((.+)\)$/);
|
|
408
|
+
if (hslMatch) {
|
|
409
|
+
const [h, s, l] = hslMatch[1].split(/[\s,/]+/).filter(Boolean).slice(0, 3);
|
|
410
|
+
const hue = Number.parseFloat(h);
|
|
411
|
+
const saturation = Number.parseFloat(s.replace("%", ""));
|
|
412
|
+
const lightness = Number.parseFloat(l.replace("%", ""));
|
|
413
|
+
if ([
|
|
414
|
+
hue,
|
|
415
|
+
saturation,
|
|
416
|
+
lightness
|
|
417
|
+
].every((channel) => Number.isFinite(channel))) return hslToRgb(hue, saturation / 100, lightness / 100);
|
|
418
|
+
}
|
|
419
|
+
const oklchMatch = normalized.match(/^oklch\((.+)\)$/);
|
|
420
|
+
if (oklchMatch) {
|
|
421
|
+
const [l, c, h] = oklchMatch[1].split(/[\s/]+/).filter(Boolean);
|
|
422
|
+
const lightness = Number.parseFloat(l);
|
|
423
|
+
const chroma = Number.parseFloat(c);
|
|
424
|
+
const hue = Number.parseFloat(h);
|
|
425
|
+
if ([
|
|
426
|
+
lightness,
|
|
427
|
+
chroma,
|
|
428
|
+
hue
|
|
429
|
+
].every((channel) => Number.isFinite(channel))) return oklchToRgb(lightness, chroma, hue);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
function oklchToRgb(l, c, h) {
|
|
433
|
+
const hue = h * Math.PI / 180;
|
|
434
|
+
const a = Math.cos(hue) * c;
|
|
435
|
+
const b = Math.sin(hue) * c;
|
|
436
|
+
const l_ = l + .3963377774 * a + .2158037573 * b;
|
|
437
|
+
const m_ = l - .1055613458 * a - .0638541728 * b;
|
|
438
|
+
const s_ = l - .0894841775 * a - 1.291485548 * b;
|
|
439
|
+
const l3 = l_ ** 3;
|
|
440
|
+
const m3 = m_ ** 3;
|
|
441
|
+
const s3 = s_ ** 3;
|
|
442
|
+
const linearR = 4.0767416621 * l3 - 3.3077115913 * m3 + .2309699292 * s3;
|
|
443
|
+
const linearG = -1.2684380046 * l3 + 2.6097574011 * m3 - .3413193965 * s3;
|
|
444
|
+
const linearB = -.0041960863 * l3 - .7034186147 * m3 + 1.707614701 * s3;
|
|
445
|
+
return [
|
|
446
|
+
srgbFromLinear(linearR),
|
|
447
|
+
srgbFromLinear(linearG),
|
|
448
|
+
srgbFromLinear(linearB)
|
|
449
|
+
];
|
|
450
|
+
}
|
|
451
|
+
function srgbFromLinear(value) {
|
|
452
|
+
const normalized = value <= .0031308 ? value * 12.92 : 1.055 * value ** (1 / 2.4) - .055;
|
|
453
|
+
return Math.max(0, Math.min(255, Math.round(normalized * 255)));
|
|
454
|
+
}
|
|
455
|
+
function parseHexColor(value) {
|
|
456
|
+
const raw = value.slice(1);
|
|
457
|
+
if (raw.length === 3) return [
|
|
458
|
+
Number.parseInt(raw[0] + raw[0], 16),
|
|
459
|
+
Number.parseInt(raw[1] + raw[1], 16),
|
|
460
|
+
Number.parseInt(raw[2] + raw[2], 16)
|
|
461
|
+
];
|
|
462
|
+
if (raw.length === 6 || raw.length === 8) return [
|
|
463
|
+
Number.parseInt(raw.slice(0, 2), 16),
|
|
464
|
+
Number.parseInt(raw.slice(2, 4), 16),
|
|
465
|
+
Number.parseInt(raw.slice(4, 6), 16)
|
|
466
|
+
];
|
|
467
|
+
}
|
|
468
|
+
function hslToRgb(h, s, l) {
|
|
469
|
+
const hue = (h % 360 + 360) % 360 / 360;
|
|
470
|
+
if (s === 0) {
|
|
471
|
+
const gray = Math.round(l * 255);
|
|
472
|
+
return [
|
|
473
|
+
gray,
|
|
474
|
+
gray,
|
|
475
|
+
gray
|
|
476
|
+
];
|
|
477
|
+
}
|
|
478
|
+
const q = l < .5 ? l * (1 + s) : l + s - l * s;
|
|
479
|
+
const p = 2 * l - q;
|
|
480
|
+
const convert = (channel) => {
|
|
481
|
+
let t = channel;
|
|
482
|
+
if (t < 0) t += 1;
|
|
483
|
+
if (t > 1) t -= 1;
|
|
484
|
+
if (t < 1 / 6) return p + (q - p) * 6 * t;
|
|
485
|
+
if (t < 1 / 2) return q;
|
|
486
|
+
if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6;
|
|
487
|
+
return p;
|
|
488
|
+
};
|
|
489
|
+
return [
|
|
490
|
+
Math.round(convert(hue + 1 / 3) * 255),
|
|
491
|
+
Math.round(convert(hue) * 255),
|
|
492
|
+
Math.round(convert(hue - 1 / 3) * 255)
|
|
493
|
+
];
|
|
494
|
+
}
|
|
495
|
+
function relativeLuminance([r, g, b]) {
|
|
496
|
+
const normalize = (channel) => {
|
|
497
|
+
const value = channel / 255;
|
|
498
|
+
return value <= .03928 ? value / 12.92 : ((value + .055) / 1.055) ** 2.4;
|
|
499
|
+
};
|
|
500
|
+
return .2126 * normalize(r) + .7152 * normalize(g) + .0722 * normalize(b);
|
|
501
|
+
}
|
|
502
|
+
function buildApiReferenceOpenApiDocument(config, options) {
|
|
503
|
+
if (resolveApiReferenceConfig(config.apiReference).specUrl) return buildUnavailableOpenApiDocument(config, `Remote OpenAPI specs require the async API reference builder. Use the framework route helper or buildApiReferenceOpenApiDocumentAsync().`);
|
|
504
|
+
const routes = buildApiReferenceRoutes(config, options);
|
|
505
|
+
return buildOpenApiDocumentFromRoutes(config, options.framework, routes, options.baseUrl);
|
|
506
|
+
}
|
|
507
|
+
async function buildApiReferenceOpenApiDocumentAsync(config, options) {
|
|
508
|
+
const apiReference = resolveApiReferenceConfig(config.apiReference);
|
|
509
|
+
if (!apiReference.specUrl) return buildApiReferenceOpenApiDocument(config, options);
|
|
510
|
+
try {
|
|
511
|
+
return normalizeRemoteOpenApiDocument(await fetchRemoteOpenApiDocument(apiReference.specUrl, options.baseUrl), config, options.baseUrl);
|
|
512
|
+
} catch (error) {
|
|
513
|
+
return buildUnavailableOpenApiDocument(config, `Unable to load the remote OpenAPI JSON. ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
function buildOpenApiDocumentFromRoutes(config, framework, routes, baseUrl) {
|
|
517
|
+
const tags = Array.from(new Set(routes.map((route) => route.tag))).map((name) => ({
|
|
518
|
+
name,
|
|
519
|
+
description: `${name} endpoints`
|
|
520
|
+
}));
|
|
521
|
+
return {
|
|
522
|
+
openapi: "3.1.0",
|
|
523
|
+
info: {
|
|
524
|
+
title: "API Reference",
|
|
525
|
+
description: config.metadata?.description ?? `Generated API reference for ${framework}.`,
|
|
526
|
+
version: "0.0.0"
|
|
527
|
+
},
|
|
528
|
+
servers: [{ url: baseUrl ?? "/" }],
|
|
529
|
+
tags,
|
|
530
|
+
paths: buildOpenApiPaths(routes)
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function buildApiReferenceHtmlDocument(config, options) {
|
|
534
|
+
return buildApiReferenceHtmlDocumentFromDocument(config, options, buildApiReferenceOpenApiDocument(config, options));
|
|
535
|
+
}
|
|
536
|
+
async function buildApiReferenceHtmlDocumentAsync(config, options) {
|
|
537
|
+
return buildApiReferenceHtmlDocumentFromDocument(config, options, await buildApiReferenceOpenApiDocumentAsync(config, options));
|
|
538
|
+
}
|
|
539
|
+
function buildApiReferenceHtmlDocumentFromDocument(config, options, document) {
|
|
540
|
+
const apiReference = resolveApiReferenceConfig(config.apiReference);
|
|
541
|
+
const title = options.title ?? "API Reference";
|
|
542
|
+
return getHtmlDocument({
|
|
543
|
+
pageTitle: buildApiReferencePageTitle(config, title),
|
|
544
|
+
title,
|
|
545
|
+
content: () => document,
|
|
546
|
+
theme: "deepSpace",
|
|
547
|
+
layout: "modern",
|
|
548
|
+
customCss: buildApiReferenceScalarCss(config),
|
|
549
|
+
pathRouting: { basePath: `/${apiReference.path}` },
|
|
550
|
+
showSidebar: true,
|
|
551
|
+
defaultOpenFirstTag: true,
|
|
552
|
+
tagsSorter: "alpha",
|
|
553
|
+
operationsSorter: "alpha",
|
|
554
|
+
operationTitleSource: "summary",
|
|
555
|
+
defaultHttpClient: {
|
|
556
|
+
targetKey: "shell",
|
|
557
|
+
clientKey: "curl"
|
|
558
|
+
},
|
|
559
|
+
documentDownloadType: "json"
|
|
560
|
+
});
|
|
561
|
+
}
|
|
562
|
+
async function fetchRemoteOpenApiDocument(specUrl, baseUrl) {
|
|
563
|
+
let url;
|
|
564
|
+
try {
|
|
565
|
+
url = baseUrl ? new URL(specUrl, baseUrl) : new URL(specUrl);
|
|
566
|
+
} catch {
|
|
567
|
+
throw new Error(baseUrl ? "`apiReference.specUrl` must be an absolute URL or a request-relative path." : "`apiReference.specUrl` must be an absolute URL.");
|
|
568
|
+
}
|
|
569
|
+
const response = await fetch(url, { headers: { accept: "application/json" } });
|
|
570
|
+
if (!response.ok) throw new Error(`Received ${response.status} ${response.statusText}`.trim());
|
|
571
|
+
const body = await response.text();
|
|
572
|
+
if (!body.trim()) throw new Error("The remote endpoint returned an empty response.");
|
|
573
|
+
let parsed;
|
|
574
|
+
try {
|
|
575
|
+
parsed = JSON.parse(body);
|
|
576
|
+
} catch {
|
|
577
|
+
throw new Error("The remote endpoint did not return valid JSON.");
|
|
578
|
+
}
|
|
579
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) throw new Error("The remote endpoint returned a JSON value instead of an OpenAPI object.");
|
|
580
|
+
if (!("openapi" in parsed) && !("swagger" in parsed)) throw new Error("The remote JSON does not look like an OpenAPI document.");
|
|
581
|
+
return parsed;
|
|
582
|
+
}
|
|
583
|
+
function normalizeRemoteOpenApiDocument(document, config, baseUrl) {
|
|
584
|
+
const apiReference = resolveApiReferenceConfig(config.apiReference);
|
|
585
|
+
const info = document.info && typeof document.info === "object" && !Array.isArray(document.info) ? document.info : {};
|
|
586
|
+
const normalizedPaths = normalizeRemoteOpenApiPaths(document.paths);
|
|
587
|
+
const normalizedTags = normalizeRemoteOpenApiTags(document.tags, normalizedPaths);
|
|
588
|
+
const normalizedServers = isRequestRelativeSpecUrl(apiReference.specUrl) ? [{ url: baseUrl ?? "/" }] : document.servers;
|
|
589
|
+
return {
|
|
590
|
+
...document,
|
|
591
|
+
info: {
|
|
592
|
+
title: "API Reference",
|
|
593
|
+
version: "0.0.0",
|
|
594
|
+
...info,
|
|
595
|
+
description: typeof info.description === "string" && info.description.trim() ? info.description : config.metadata?.description
|
|
596
|
+
},
|
|
597
|
+
servers: normalizedServers,
|
|
598
|
+
paths: normalizedPaths,
|
|
599
|
+
tags: normalizedTags
|
|
600
|
+
};
|
|
601
|
+
}
|
|
602
|
+
function normalizeRemoteOpenApiPaths(value) {
|
|
603
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return;
|
|
604
|
+
const paths = value;
|
|
605
|
+
const normalized = {};
|
|
606
|
+
for (const [routePath, pathItem] of Object.entries(paths)) {
|
|
607
|
+
if (!pathItem || typeof pathItem !== "object" || Array.isArray(pathItem)) continue;
|
|
608
|
+
const normalizedPathItem = { ...pathItem };
|
|
609
|
+
for (const method of [
|
|
610
|
+
"get",
|
|
611
|
+
"post",
|
|
612
|
+
"put",
|
|
613
|
+
"patch",
|
|
614
|
+
"delete",
|
|
615
|
+
"options",
|
|
616
|
+
"head"
|
|
617
|
+
]) {
|
|
618
|
+
const operation = normalizedPathItem[method];
|
|
619
|
+
if (!operation || typeof operation !== "object" || Array.isArray(operation)) continue;
|
|
620
|
+
const operationRecord = operation;
|
|
621
|
+
const tags = Array.isArray(operationRecord.tags) ? operationRecord.tags.filter((tag) => typeof tag === "string" && tag.trim().length > 0) : [];
|
|
622
|
+
normalizedPathItem[method] = {
|
|
623
|
+
...operationRecord,
|
|
624
|
+
tags: tags.length > 0 ? tags : [inferRemoteOpenApiTag(routePath)]
|
|
625
|
+
};
|
|
626
|
+
}
|
|
627
|
+
normalized[routePath] = normalizedPathItem;
|
|
628
|
+
}
|
|
629
|
+
return normalized;
|
|
630
|
+
}
|
|
631
|
+
function inferRemoteOpenApiTag(routePath) {
|
|
632
|
+
return humanizeSegment(routePath.split("/").filter(Boolean).find((value) => !value.startsWith("{")) ?? "general");
|
|
633
|
+
}
|
|
634
|
+
function normalizeRemoteOpenApiTags(value, paths) {
|
|
635
|
+
const existingTags = Array.isArray(value) ? value.filter((tag) => !!tag && typeof tag === "object") : [];
|
|
636
|
+
const tagsByName = /* @__PURE__ */ new Map();
|
|
637
|
+
for (const tag of existingTags) {
|
|
638
|
+
const name = typeof tag.name === "string" && tag.name.trim() ? tag.name.trim() : void 0;
|
|
639
|
+
if (!name) continue;
|
|
640
|
+
tagsByName.set(name, tag);
|
|
641
|
+
}
|
|
642
|
+
if (paths) for (const pathItem of Object.values(paths)) for (const method of [
|
|
643
|
+
"get",
|
|
644
|
+
"post",
|
|
645
|
+
"put",
|
|
646
|
+
"patch",
|
|
647
|
+
"delete",
|
|
648
|
+
"options",
|
|
649
|
+
"head"
|
|
650
|
+
]) {
|
|
651
|
+
const operation = pathItem[method];
|
|
652
|
+
if (!operation || typeof operation !== "object" || Array.isArray(operation)) continue;
|
|
653
|
+
const tags = Array.isArray(operation.tags) ? operation.tags : [];
|
|
654
|
+
for (const tag of tags) {
|
|
655
|
+
if (typeof tag !== "string" || !tag.trim()) continue;
|
|
656
|
+
if (!tagsByName.has(tag)) tagsByName.set(tag, {
|
|
657
|
+
name: tag,
|
|
658
|
+
description: `${tag} endpoints`
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
if (tagsByName.size === 0) return [{
|
|
663
|
+
name: "General",
|
|
664
|
+
description: "General endpoints"
|
|
665
|
+
}];
|
|
666
|
+
return Array.from(tagsByName.values());
|
|
667
|
+
}
|
|
668
|
+
function buildUnavailableOpenApiDocument(config, description) {
|
|
669
|
+
return {
|
|
670
|
+
openapi: "3.1.0",
|
|
671
|
+
info: {
|
|
672
|
+
title: "API Reference",
|
|
673
|
+
description,
|
|
674
|
+
version: "0.0.0"
|
|
675
|
+
},
|
|
676
|
+
servers: [{ url: "/" }],
|
|
677
|
+
tags: [{
|
|
678
|
+
name: "Unavailable",
|
|
679
|
+
description: config.metadata?.description ?? "OpenAPI spec could not be loaded."
|
|
680
|
+
}],
|
|
681
|
+
paths: {}
|
|
682
|
+
};
|
|
683
|
+
}
|
|
684
|
+
function buildApiReferenceRoutes(config, options) {
|
|
685
|
+
const apiReference = resolveApiReferenceConfig(config.apiReference);
|
|
686
|
+
if (!apiReference.enabled) return [];
|
|
687
|
+
const rootDir = options.rootDir ?? process.cwd();
|
|
688
|
+
switch (options.framework) {
|
|
689
|
+
case "next": return buildFileConventionRoutes({
|
|
690
|
+
rootDir,
|
|
691
|
+
sourceDir: resolveRootedDir(rootDir, apiReference.routeRoot, getNextAppDir(rootDir)),
|
|
692
|
+
routePathBase: toRouteBase(apiReference.routeRoot, getNextAppDir(rootDir)),
|
|
693
|
+
isRouteFile: (name) => NEXT_ROUTE_FILE_RE.test(name),
|
|
694
|
+
toRouteSegments: (relativeFile) => relativeFile.split("/").slice(0, -1).filter(Boolean),
|
|
695
|
+
exclude: apiReference.exclude
|
|
696
|
+
});
|
|
697
|
+
case "sveltekit": return buildFileConventionRoutes({
|
|
698
|
+
rootDir,
|
|
699
|
+
sourceDir: resolveRootedDir(rootDir, apiReference.routeRoot, "src/routes"),
|
|
700
|
+
routePathBase: toRouteBase(apiReference.routeRoot, "src/routes"),
|
|
701
|
+
isRouteFile: (name) => SVELTE_ROUTE_FILE_RE.test(name),
|
|
702
|
+
toRouteSegments: (relativeFile) => relativeFile.split("/").slice(0, -1).filter(Boolean),
|
|
703
|
+
exclude: apiReference.exclude
|
|
704
|
+
});
|
|
705
|
+
case "astro": return buildFileConventionRoutes({
|
|
706
|
+
rootDir,
|
|
707
|
+
sourceDir: resolveRootedDir(rootDir, apiReference.routeRoot, "src/pages"),
|
|
708
|
+
routePathBase: toRouteBase(apiReference.routeRoot, "src/pages"),
|
|
709
|
+
isRouteFile: (name) => ASTRO_ROUTE_FILE_RE.test(name),
|
|
710
|
+
toRouteSegments: (relativeFile) => routeSegmentsFromEndpointFile(relativeFile),
|
|
711
|
+
exclude: apiReference.exclude
|
|
712
|
+
});
|
|
713
|
+
case "nuxt": return buildFileConventionRoutes({
|
|
714
|
+
rootDir,
|
|
715
|
+
sourceDir: resolveRootedDir(rootDir, apiReference.routeRoot, "server"),
|
|
716
|
+
routePathBase: toRouteBase(apiReference.routeRoot, "server"),
|
|
717
|
+
isRouteFile: (name) => NUXT_ROUTE_FILE_RE.test(name),
|
|
718
|
+
toRouteSegments: (relativeFile) => routeSegmentsFromEndpointFile(stripNuxtMethodSuffix(relativeFile)),
|
|
719
|
+
exclude: apiReference.exclude,
|
|
720
|
+
getMethods: (source, file) => extractNuxtMethods(source, file)
|
|
721
|
+
});
|
|
722
|
+
case "tanstack-start": return buildTanstackRoutes(rootDir, apiReference);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
function buildFileConventionRoutes({ rootDir, sourceDir, routePathBase, isRouteFile, toRouteSegments, exclude, getMethods = extractMethods }) {
|
|
726
|
+
const files = scanRouteFiles(sourceDir, isRouteFile);
|
|
727
|
+
const routes = [];
|
|
728
|
+
for (const file of files) {
|
|
729
|
+
const source = readFileSync(file, "utf-8");
|
|
730
|
+
const methods = getMethods(source, file);
|
|
731
|
+
if (methods.length === 0) continue;
|
|
732
|
+
const relativeFile = relative(sourceDir, file).replace(/\\/g, "/");
|
|
733
|
+
const routeSegments = toRouteSegments(relativeFile);
|
|
734
|
+
const routePath = buildRoutePath(routePathBase, routeSegments);
|
|
735
|
+
if (shouldExcludeRoute(exclude, routePath, relativeFile, routeSegments.join("/"))) continue;
|
|
736
|
+
routes.push(createApiReferenceRoute({
|
|
737
|
+
rootDir,
|
|
738
|
+
file,
|
|
739
|
+
source,
|
|
740
|
+
methods,
|
|
741
|
+
routePath
|
|
742
|
+
}));
|
|
743
|
+
}
|
|
744
|
+
return routes.sort((a, b) => a.routePath.localeCompare(b.routePath));
|
|
745
|
+
}
|
|
746
|
+
function buildTanstackRoutes(rootDir, apiReference) {
|
|
747
|
+
const routesDir = join(rootDir, "src", "routes");
|
|
748
|
+
const files = scanRouteFiles(routesDir, (name) => TANSTACK_ROUTE_FILE_RE.test(name));
|
|
749
|
+
const routeBase = `/${normalizePathSegment(apiReference.routeRoot)}`;
|
|
750
|
+
const routes = [];
|
|
751
|
+
for (const file of files) {
|
|
752
|
+
const source = readFileSync(file, "utf-8");
|
|
753
|
+
if (!source.includes("createFileRoute(") || !source.includes("handlers")) continue;
|
|
754
|
+
const pathMatch = source.match(/createFileRoute\(\s*["'`]([^"'`]+)["'`]\s*\)/);
|
|
755
|
+
if (!pathMatch) continue;
|
|
756
|
+
const routePath = normalizeTanstackRoutePath(pathMatch[1]);
|
|
757
|
+
if (!routePath.startsWith(routeBase)) continue;
|
|
758
|
+
const methods = extractTanstackMethods(source);
|
|
759
|
+
if (methods.length === 0) continue;
|
|
760
|
+
const relativeFile = relative(routesDir, file).replace(/\\/g, "/");
|
|
761
|
+
if (shouldExcludeRoute(apiReference.exclude, routePath, relativeFile, relativeFile)) continue;
|
|
762
|
+
routes.push(createApiReferenceRoute({
|
|
763
|
+
rootDir,
|
|
764
|
+
file,
|
|
765
|
+
source,
|
|
766
|
+
methods,
|
|
767
|
+
routePath
|
|
768
|
+
}));
|
|
769
|
+
}
|
|
770
|
+
return routes.sort((a, b) => a.routePath.localeCompare(b.routePath));
|
|
771
|
+
}
|
|
772
|
+
function createApiReferenceRoute({ rootDir, file, source, methods, routePath }) {
|
|
773
|
+
const docBlock = extractDocBlock(source);
|
|
774
|
+
const pathSegments = routePath.split("/").filter(Boolean);
|
|
775
|
+
const titleSegment = pathSegments[pathSegments.length - 1] ?? "overview";
|
|
776
|
+
const tagSegment = pathSegments[0] ?? "general";
|
|
777
|
+
const title = humanizeSegment(titleSegment);
|
|
778
|
+
return {
|
|
779
|
+
title,
|
|
780
|
+
summary: docBlock.summary ?? `${title} endpoint`,
|
|
781
|
+
description: docBlock.description,
|
|
782
|
+
routePath,
|
|
783
|
+
sourceFile: relative(rootDir, file).replace(/\\/g, "/"),
|
|
784
|
+
methods,
|
|
785
|
+
tag: humanizeSegment(tagSegment),
|
|
786
|
+
parameters: buildPathParameters(routePath)
|
|
787
|
+
};
|
|
788
|
+
}
|
|
789
|
+
function buildPathParameters(routePath) {
|
|
790
|
+
const parameters = [];
|
|
791
|
+
for (const segment of routePath.split("/")) {
|
|
792
|
+
const match = segment.match(/^\{(.+)\}$/);
|
|
793
|
+
if (!match) continue;
|
|
794
|
+
parameters.push({
|
|
795
|
+
name: match[1],
|
|
796
|
+
in: "path",
|
|
797
|
+
required: true,
|
|
798
|
+
description: `${humanizeSegment(match[1])} path parameter.`,
|
|
799
|
+
schema: { type: "string" }
|
|
800
|
+
});
|
|
801
|
+
}
|
|
802
|
+
return parameters;
|
|
803
|
+
}
|
|
804
|
+
function buildOpenApiPaths(routes) {
|
|
805
|
+
const paths = {};
|
|
806
|
+
for (const route of routes) {
|
|
807
|
+
const pathItem = {};
|
|
808
|
+
for (const method of route.methods) pathItem[method.toLowerCase()] = {
|
|
809
|
+
tags: [route.tag],
|
|
810
|
+
summary: route.summary,
|
|
811
|
+
description: route.description ?? route.summary,
|
|
812
|
+
operationId: createOperationId(route, method),
|
|
813
|
+
...route.parameters.length > 0 ? { parameters: route.parameters } : {},
|
|
814
|
+
...buildRequestBody(method) ? { requestBody: buildRequestBody(method) } : {},
|
|
815
|
+
responses: buildResponses(method),
|
|
816
|
+
"x-farming-labs-source": route.sourceFile
|
|
817
|
+
};
|
|
818
|
+
paths[route.routePath] = pathItem;
|
|
819
|
+
}
|
|
820
|
+
return paths;
|
|
821
|
+
}
|
|
822
|
+
function buildRequestBody(method) {
|
|
823
|
+
if (![
|
|
824
|
+
"POST",
|
|
825
|
+
"PUT",
|
|
826
|
+
"PATCH"
|
|
827
|
+
].includes(method)) return void 0;
|
|
828
|
+
return {
|
|
829
|
+
required: method === "POST",
|
|
830
|
+
content: { "application/json": {
|
|
831
|
+
schema: {
|
|
832
|
+
type: "object",
|
|
833
|
+
additionalProperties: true
|
|
834
|
+
},
|
|
835
|
+
example: { example: true }
|
|
836
|
+
} }
|
|
837
|
+
};
|
|
838
|
+
}
|
|
839
|
+
function buildResponses(method) {
|
|
840
|
+
return { "200": {
|
|
841
|
+
description: method === "DELETE" ? "Resource removed successfully." : "Request completed successfully.",
|
|
842
|
+
content: { "application/json": {
|
|
843
|
+
schema: {
|
|
844
|
+
type: "object",
|
|
845
|
+
additionalProperties: true
|
|
846
|
+
},
|
|
847
|
+
example: { ok: true }
|
|
848
|
+
} }
|
|
849
|
+
} };
|
|
850
|
+
}
|
|
851
|
+
function createOperationId(route, method) {
|
|
852
|
+
return `${method.toLowerCase()}_${route.routePath.replace(/[^a-zA-Z0-9]+/g, "_").replace(/^_+|_+$/g, "")}`;
|
|
853
|
+
}
|
|
854
|
+
function resolveTheme(config) {
|
|
855
|
+
return config.theme;
|
|
856
|
+
}
|
|
857
|
+
function normalizeApiReferenceExcludes(values) {
|
|
858
|
+
return (values ?? []).map(normalizeExcludeMatcher).filter(Boolean);
|
|
859
|
+
}
|
|
860
|
+
function normalizeExcludeMatcher(value) {
|
|
861
|
+
return value.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "").replace(/\.(ts|tsx|js|jsx|mjs|mts)$/i, "").replace(/\/route$/i, "").replace(/\/\+server$/i, "").replace(/\/index$/i, "").replace(/\.(get|post|put|patch|delete|options|head)$/i, "");
|
|
862
|
+
}
|
|
863
|
+
function shouldExcludeRoute(excludes, routePath, relativeFile, relativeDir) {
|
|
864
|
+
if (excludes.length === 0) return false;
|
|
865
|
+
const candidates = new Set([
|
|
866
|
+
normalizeExcludeMatcher(routePath),
|
|
867
|
+
normalizeExcludeMatcher(routePath.replace(/^\/+/, "")),
|
|
868
|
+
normalizeExcludeMatcher(relativeFile),
|
|
869
|
+
normalizeExcludeMatcher(relativeDir)
|
|
870
|
+
]);
|
|
871
|
+
return excludes.some((entry) => candidates.has(entry));
|
|
872
|
+
}
|
|
873
|
+
function scanRouteFiles(dir, isRouteFile) {
|
|
874
|
+
if (!existsSync(dir)) return [];
|
|
875
|
+
const results = [];
|
|
876
|
+
for (const name of readdirSync(dir)) {
|
|
877
|
+
const full = join(dir, name);
|
|
878
|
+
if (statSync(full).isDirectory()) {
|
|
879
|
+
results.push(...scanRouteFiles(full, isRouteFile));
|
|
880
|
+
continue;
|
|
881
|
+
}
|
|
882
|
+
if (isRouteFile(name)) results.push(full);
|
|
883
|
+
}
|
|
884
|
+
return results;
|
|
885
|
+
}
|
|
886
|
+
function resolveRootedDir(rootDir, routeRoot, defaultRoot) {
|
|
887
|
+
const normalized = normalizePathSegment(routeRoot) || "api";
|
|
888
|
+
if (normalized === defaultRoot || normalized.startsWith(`${defaultRoot}/`)) return join(rootDir, ...normalized.split("/"));
|
|
889
|
+
return join(rootDir, ...defaultRoot.split("/"), ...normalized.split("/"));
|
|
890
|
+
}
|
|
891
|
+
function toRouteBase(routeRoot, defaultRoot) {
|
|
892
|
+
const normalized = normalizePathSegment(routeRoot) || "api";
|
|
893
|
+
return `/${normalizePathSegment(normalized === defaultRoot || normalized.startsWith(`${defaultRoot}/`) ? normalized.slice(defaultRoot.length).replace(/^\/+/, "") : normalized)}`;
|
|
894
|
+
}
|
|
895
|
+
function getNextAppDir(rootDir) {
|
|
896
|
+
if (existsSync(join(rootDir, "src", "app"))) return "src/app";
|
|
897
|
+
return "app";
|
|
898
|
+
}
|
|
899
|
+
function routeSegmentsFromEndpointFile(relativeFile) {
|
|
900
|
+
const segments = relativeFile.split("/");
|
|
901
|
+
const name = (segments.pop() ?? "").replace(/\.(ts|js|mts|mjs)$/i, "");
|
|
902
|
+
if (name !== "index") segments.push(name);
|
|
903
|
+
return segments.filter(Boolean);
|
|
904
|
+
}
|
|
905
|
+
function stripNuxtMethodSuffix(relativeFile) {
|
|
906
|
+
return relativeFile.replace(/\.(get|post|put|patch|delete|options|head)(?=\.(ts|js|mts|mjs)$)/i, "");
|
|
907
|
+
}
|
|
908
|
+
function buildRoutePath(basePath, rawSegments) {
|
|
909
|
+
const segments = rawSegments.filter(Boolean).map((segment) => endpointSegmentFromConvention(segment)).join("/");
|
|
910
|
+
const path = [normalizePathSegment(basePath), segments].filter(Boolean).join("/");
|
|
911
|
+
return path ? `/${path}` : "/";
|
|
912
|
+
}
|
|
913
|
+
function endpointSegmentFromConvention(value) {
|
|
914
|
+
if (value.startsWith("[[...") && value.endsWith("]]")) return `{${value.slice(5, -2)}}`;
|
|
915
|
+
if (value.startsWith("[...") && value.endsWith("]")) return `{${value.slice(4, -1)}}`;
|
|
916
|
+
if (value.startsWith("[") && value.endsWith("]")) return `{${value.slice(1, -1)}}`;
|
|
917
|
+
return value;
|
|
918
|
+
}
|
|
919
|
+
function normalizeTanstackRoutePath(value) {
|
|
920
|
+
return `/${value.replace(/^\/+|\/+$/g, "").split("/").map((segment) => segment.startsWith("$") ? `{${segment.slice(1)}}` : segment).filter(Boolean).join("/")}`;
|
|
921
|
+
}
|
|
922
|
+
function extractDocBlock(source) {
|
|
923
|
+
const match = source.match(/\/\*\*([\s\S]*?)\*\//);
|
|
924
|
+
if (!match) return {};
|
|
925
|
+
const lines = match[1].split("\n").map((line) => line.replace(/^\s*\*\s?/, "").trim()).filter(Boolean).filter((line) => !line.startsWith("@"));
|
|
926
|
+
if (lines.length === 0) return {};
|
|
927
|
+
return {
|
|
928
|
+
summary: lines[0],
|
|
929
|
+
description: lines.slice(1).join(" ")
|
|
930
|
+
};
|
|
931
|
+
}
|
|
932
|
+
function extractMethods(source) {
|
|
933
|
+
const methods = /* @__PURE__ */ new Set();
|
|
934
|
+
for (const match of source.matchAll(METHOD_RE)) {
|
|
935
|
+
if (match[1] === "ALL") {
|
|
936
|
+
METHOD_NAMES.forEach((method) => methods.add(method));
|
|
937
|
+
continue;
|
|
938
|
+
}
|
|
939
|
+
methods.add(match[1]);
|
|
940
|
+
}
|
|
941
|
+
return Array.from(methods);
|
|
942
|
+
}
|
|
943
|
+
function extractNuxtMethods(source, file) {
|
|
944
|
+
const methods = extractMethods(source);
|
|
945
|
+
if (methods.length > 0) return methods;
|
|
946
|
+
const suffix = basename(file).match(/\.(get|post|put|patch|delete|options|head)\.(ts|js|mts|mjs)$/i);
|
|
947
|
+
if (suffix) return [suffix[1].toUpperCase()];
|
|
948
|
+
if (/defineEventHandler|eventHandler/.test(source)) return ["GET"];
|
|
949
|
+
return [];
|
|
950
|
+
}
|
|
951
|
+
function extractTanstackMethods(source) {
|
|
952
|
+
const methods = /* @__PURE__ */ new Set();
|
|
953
|
+
const handlersMatch = source.match(/handlers\s*:\s*\{([\s\S]*?)\}/m);
|
|
954
|
+
if (!handlersMatch) return [];
|
|
955
|
+
for (const match of handlersMatch[1].matchAll(/\b(GET|POST|PUT|PATCH|DELETE|OPTIONS|HEAD)\s*:/g)) methods.add(match[1]);
|
|
956
|
+
return Array.from(methods);
|
|
957
|
+
}
|
|
958
|
+
function humanizeSegment(value) {
|
|
959
|
+
return value.replace(/^\{/, "").replace(/\}$/, "").replace(/^\[\[?\.{3}/, "").replace(/^\[/, "").replace(/\]\]?$/, "").replace(/^\$/, "").replace(/-/g, " ").replace(/\b\w/g, (char) => char.toUpperCase());
|
|
960
|
+
}
|
|
961
|
+
|
|
962
|
+
//#endregion
|
|
963
|
+
//#region src/prompt-utils.ts
|
|
964
|
+
const require = createRequire(import.meta.url);
|
|
965
|
+
const DEFAULT_PROMPT_PROVIDER_TEMPLATES = {
|
|
966
|
+
chatgpt: "https://chatgpt.com/?q={prompt}",
|
|
967
|
+
claude: "https://claude.ai/new?q={prompt}",
|
|
968
|
+
cursor: "https://cursor.com/link/prompt?text={prompt}",
|
|
969
|
+
gemini: "https://gemini.google.com/app?q={prompt}",
|
|
970
|
+
copilot: "https://github.com/copilot?prompt={prompt}",
|
|
971
|
+
perplexity: "https://www.perplexity.ai/search/?q={prompt}"
|
|
972
|
+
};
|
|
973
|
+
const DEFAULT_OPEN_DOCS_TARGET = "markdown";
|
|
974
|
+
const DEFAULT_OPEN_DOCS_PROMPT = "Read this documentation: {url}";
|
|
975
|
+
const DEFAULT_OPEN_DOCS_PROVIDER_IDS = ["chatgpt", "claude"];
|
|
976
|
+
const DEFAULT_OPEN_DOCS_PROVIDER_PRESETS = {
|
|
977
|
+
chatgpt: {
|
|
978
|
+
name: "ChatGPT",
|
|
979
|
+
urlTemplate: "https://chatgpt.com/?q={prompt}",
|
|
980
|
+
promptUrlTemplate: DEFAULT_PROMPT_PROVIDER_TEMPLATES.chatgpt
|
|
981
|
+
},
|
|
982
|
+
claude: {
|
|
983
|
+
name: "Claude",
|
|
984
|
+
urlTemplate: "https://claude.ai/new?q={prompt}",
|
|
985
|
+
promptUrlTemplate: DEFAULT_PROMPT_PROVIDER_TEMPLATES.claude
|
|
986
|
+
},
|
|
987
|
+
cursor: {
|
|
988
|
+
name: "Cursor",
|
|
989
|
+
urlTemplate: "https://cursor.com/link/prompt?text={prompt}",
|
|
990
|
+
promptUrlTemplate: DEFAULT_PROMPT_PROVIDER_TEMPLATES.cursor
|
|
991
|
+
},
|
|
992
|
+
gemini: {
|
|
993
|
+
name: "Gemini",
|
|
994
|
+
urlTemplate: "https://gemini.google.com/app?q={prompt}",
|
|
995
|
+
promptUrlTemplate: DEFAULT_PROMPT_PROVIDER_TEMPLATES.gemini
|
|
996
|
+
},
|
|
997
|
+
copilot: {
|
|
998
|
+
name: "Copilot",
|
|
999
|
+
urlTemplate: "https://github.com/copilot?prompt={prompt}",
|
|
1000
|
+
promptUrlTemplate: DEFAULT_PROMPT_PROVIDER_TEMPLATES.copilot
|
|
1001
|
+
},
|
|
1002
|
+
perplexity: {
|
|
1003
|
+
name: "Perplexity",
|
|
1004
|
+
urlTemplate: "https://www.perplexity.ai/search/?q={prompt}",
|
|
1005
|
+
promptUrlTemplate: DEFAULT_PROMPT_PROVIDER_TEMPLATES.perplexity
|
|
1006
|
+
},
|
|
1007
|
+
github: {
|
|
1008
|
+
name: "GitHub",
|
|
1009
|
+
urlTemplate: "{githubUrl}",
|
|
1010
|
+
promptUrlTemplate: "{githubUrl}",
|
|
1011
|
+
target: "github"
|
|
1012
|
+
}
|
|
1013
|
+
};
|
|
1014
|
+
function normalizePromptProviderName(name) {
|
|
1015
|
+
return name.trim().toLowerCase();
|
|
1016
|
+
}
|
|
1017
|
+
function serializeDocsIcon(icon) {
|
|
1018
|
+
if (!icon) return void 0;
|
|
1019
|
+
if (typeof icon === "string") return icon;
|
|
1020
|
+
try {
|
|
1021
|
+
const { renderToStaticMarkup } = require("react-dom/server");
|
|
1022
|
+
return renderToStaticMarkup(icon);
|
|
1023
|
+
} catch {
|
|
1024
|
+
return;
|
|
1025
|
+
}
|
|
1026
|
+
}
|
|
1027
|
+
function serializeDocsIconRegistry(icons) {
|
|
1028
|
+
if (!icons) return void 0;
|
|
1029
|
+
const entries = Object.entries(icons).map(([name, icon]) => [name, serializeDocsIcon(icon)]).filter((entry) => typeof entry[1] === "string");
|
|
1030
|
+
return entries.length > 0 ? Object.fromEntries(entries) : void 0;
|
|
1031
|
+
}
|
|
1032
|
+
function serializeOpenDocsProviders(providers, options = {}) {
|
|
1033
|
+
if (!providers || providers.length === 0) return void 0;
|
|
1034
|
+
const serialized = providers.map((provider) => serializeOpenDocsProvider(provider, options)).filter((provider) => provider !== void 0);
|
|
1035
|
+
return serialized.length > 0 ? serialized : void 0;
|
|
1036
|
+
}
|
|
1037
|
+
function serializeOpenDocsProvider(provider, options = {}) {
|
|
1038
|
+
const normalizedId = typeof provider === "string" ? normalizePromptProviderName(provider) : typeof provider.id === "string" ? normalizePromptProviderName(provider.id) : typeof provider.name === "string" ? normalizePromptProviderName(provider.name) : typeof provider.label === "string" ? normalizePromptProviderName(provider.label) : void 0;
|
|
1039
|
+
const preset = normalizedId ? DEFAULT_OPEN_DOCS_PROVIDER_PRESETS[normalizedId] : void 0;
|
|
1040
|
+
if (typeof provider === "string") {
|
|
1041
|
+
if (!preset) return void 0;
|
|
1042
|
+
return {
|
|
1043
|
+
name: preset.name,
|
|
1044
|
+
urlTemplate: preset.urlTemplate,
|
|
1045
|
+
promptUrlTemplate: preset.promptUrlTemplate,
|
|
1046
|
+
target: preset.target ?? options.target,
|
|
1047
|
+
prompt: options.prompt
|
|
1048
|
+
};
|
|
1049
|
+
}
|
|
1050
|
+
const cursorAppTemplate = normalizedId === "cursor" && provider.mode === "app" ? "cursor://anysphere.cursor-deeplink/prompt?text={prompt}" : void 0;
|
|
1051
|
+
const name = provider.name ?? provider.label ?? preset?.name;
|
|
1052
|
+
const urlTemplate = provider.urlTemplate ?? cursorAppTemplate ?? preset?.urlTemplate;
|
|
1053
|
+
const hasCustomUrlTemplate = typeof provider.urlTemplate === "string";
|
|
1054
|
+
if (!name || !urlTemplate) return void 0;
|
|
1055
|
+
return {
|
|
1056
|
+
name,
|
|
1057
|
+
urlTemplate,
|
|
1058
|
+
promptUrlTemplate: provider.promptUrlTemplate ?? cursorAppTemplate ?? preset?.promptUrlTemplate,
|
|
1059
|
+
iconHtml: serializeDocsIcon(provider.icon),
|
|
1060
|
+
target: provider.target ?? preset?.target ?? options.target ?? (hasCustomUrlTemplate ? "page" : void 0),
|
|
1061
|
+
prompt: provider.prompt ?? options.prompt
|
|
1062
|
+
};
|
|
1063
|
+
}
|
|
1064
|
+
function parsePromptStringArray(value) {
|
|
1065
|
+
if (Array.isArray(value)) {
|
|
1066
|
+
const normalized = value.filter((entry) => typeof entry === "string").map((entry) => entry.trim()).filter(Boolean);
|
|
1067
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
1068
|
+
}
|
|
1069
|
+
if (typeof value !== "string") return void 0;
|
|
1070
|
+
const trimmed = value.trim();
|
|
1071
|
+
if (!trimmed) return void 0;
|
|
1072
|
+
if (trimmed.startsWith("[") && trimmed.endsWith("]")) {
|
|
1073
|
+
const inner = trimmed.slice(1, -1).trim();
|
|
1074
|
+
if (!inner) return void 0;
|
|
1075
|
+
const normalized = inner.split(",").map((entry) => entry.trim().replace(/^['"]|['"]$/g, "")).filter(Boolean);
|
|
1076
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
1077
|
+
}
|
|
1078
|
+
const normalized = trimmed.split(",").map((entry) => entry.trim()).filter(Boolean);
|
|
1079
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
1080
|
+
}
|
|
1081
|
+
function resolvePromptProviderChoices(availableProviders, preferredNames) {
|
|
1082
|
+
const configuredByName = new Map((availableProviders ?? []).map((provider) => [normalizePromptProviderName(provider.name), provider]));
|
|
1083
|
+
const names = preferredNames && preferredNames.length > 0 ? preferredNames : (availableProviders ?? []).map((provider) => provider.name);
|
|
1084
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1085
|
+
const resolved = [];
|
|
1086
|
+
for (const rawName of names) {
|
|
1087
|
+
const name = rawName.trim();
|
|
1088
|
+
if (!name) continue;
|
|
1089
|
+
const normalized = normalizePromptProviderName(name);
|
|
1090
|
+
if (seen.has(normalized)) continue;
|
|
1091
|
+
seen.add(normalized);
|
|
1092
|
+
const configured = configuredByName.get(normalized);
|
|
1093
|
+
const template = configured?.promptUrlTemplate ?? configured?.urlTemplate ?? DEFAULT_PROMPT_PROVIDER_TEMPLATES[normalized];
|
|
1094
|
+
if (!template) continue;
|
|
1095
|
+
resolved.push({
|
|
1096
|
+
name: configured?.name ?? name,
|
|
1097
|
+
iconHtml: configured?.iconHtml,
|
|
1098
|
+
urlTemplate: template
|
|
1099
|
+
});
|
|
1100
|
+
}
|
|
1101
|
+
return resolved;
|
|
1102
|
+
}
|
|
1103
|
+
function sanitizePromptText(text) {
|
|
1104
|
+
const lines = text.replace(/\r\n/g, "\n").replace(/\n{3,}/g, "\n\n").replace(/[ \t]+\n/g, "\n").trim().split("\n");
|
|
1105
|
+
const normalized = [];
|
|
1106
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
1107
|
+
const current = lines[index] ?? "";
|
|
1108
|
+
const previous = normalized[normalized.length - 1] ?? "";
|
|
1109
|
+
let nextNonEmpty = "";
|
|
1110
|
+
for (let cursor = index + 1; cursor < lines.length; cursor += 1) {
|
|
1111
|
+
const candidate = lines[cursor]?.trim() ?? "";
|
|
1112
|
+
if (candidate) {
|
|
1113
|
+
nextNonEmpty = candidate;
|
|
1114
|
+
break;
|
|
1115
|
+
}
|
|
1116
|
+
}
|
|
1117
|
+
if (current.trim() === "" && previous.trim().startsWith("- ") && nextNonEmpty.startsWith("- ")) continue;
|
|
1118
|
+
normalized.push(current);
|
|
1119
|
+
}
|
|
1120
|
+
return normalized.join("\n");
|
|
1121
|
+
}
|
|
1122
|
+
|
|
1123
|
+
//#endregion
|
|
1124
|
+
//#region src/sitemap-server.ts
|
|
1125
|
+
function readDocsSitemapManifest(rootDir, sitemap) {
|
|
1126
|
+
const resolved = resolveDocsSitemapConfig(sitemap);
|
|
1127
|
+
const manifestPath = path.resolve(rootDir, resolved.manifestPath);
|
|
1128
|
+
if (!existsSync(manifestPath)) return null;
|
|
1129
|
+
try {
|
|
1130
|
+
return JSON.parse(readFileSync(manifestPath, "utf-8"));
|
|
1131
|
+
} catch {
|
|
1132
|
+
return null;
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
|
|
1136
|
+
//#endregion
|
|
1137
|
+
export { resolveApiReferenceOpenApiDiscovery as C, resolveApiReferenceConfig as S, remarkCodeGroup as T, buildApiReferenceOpenApiDocument as _, DEFAULT_PROMPT_PROVIDER_TEMPLATES as a, buildApiReferenceScalarCss as b, resolvePromptProviderChoices as c, serializeDocsIconRegistry as d, serializeOpenDocsProvider as f, buildApiReferenceHtmlDocumentAsync as g, buildApiReferenceHtmlDocument as h, DEFAULT_OPEN_DOCS_TARGET as i, sanitizePromptText as l, DEFAULT_API_REFERENCE_OPENAPI_ROUTE as m, DEFAULT_OPEN_DOCS_PROMPT as n, normalizePromptProviderName as o, serializeOpenDocsProviders as p, DEFAULT_OPEN_DOCS_PROVIDER_IDS as r, parsePromptStringArray as s, readDocsSitemapManifest as t, serializeDocsIcon as u, buildApiReferenceOpenApiDocumentAsync as v, resolveApiReferenceRenderer as w, isApiReferenceOpenApiRequest as x, buildApiReferencePageTitle as y };
|