@dogsbay/format-mdx 0.2.0-beta.12 → 0.2.0-beta.121
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/adapter.d.ts +159 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +95 -0
- package/dist/adapter.js.map +1 -0
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +269 -19
- package/dist/cli.js.map +1 -1
- package/dist/extract.d.ts +32 -0
- package/dist/extract.d.ts.map +1 -0
- package/dist/extract.js +152 -0
- package/dist/extract.js.map +1 -0
- package/dist/fumadocs.d.ts +48 -0
- package/dist/fumadocs.d.ts.map +1 -0
- package/dist/fumadocs.js +472 -0
- package/dist/fumadocs.js.map +1 -0
- package/dist/index.d.ts +11 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +11 -1
- package/dist/index.js.map +1 -1
- package/dist/js-scan.d.ts +35 -0
- package/dist/js-scan.d.ts.map +1 -0
- package/dist/js-scan.js +124 -0
- package/dist/js-scan.js.map +1 -0
- package/dist/meta-nav.d.ts +29 -0
- package/dist/meta-nav.d.ts.map +1 -0
- package/dist/meta-nav.js +194 -0
- package/dist/meta-nav.js.map +1 -0
- package/dist/mintlify-nav.d.ts +31 -0
- package/dist/mintlify-nav.d.ts.map +1 -0
- package/dist/mintlify-nav.js +418 -0
- package/dist/mintlify-nav.js.map +1 -0
- package/dist/mintlify-openapi.d.ts +109 -0
- package/dist/mintlify-openapi.d.ts.map +1 -0
- package/dist/mintlify-openapi.js +363 -0
- package/dist/mintlify-openapi.js.map +1 -0
- package/dist/mintlify.d.ts +3 -0
- package/dist/mintlify.d.ts.map +1 -0
- package/dist/mintlify.js +196 -0
- package/dist/mintlify.js.map +1 -0
- package/dist/nav-extract.d.ts +43 -0
- package/dist/nav-extract.d.ts.map +1 -0
- package/dist/nav-extract.js +135 -0
- package/dist/nav-extract.js.map +1 -0
- package/dist/parse.d.ts +100 -4
- package/dist/parse.d.ts.map +1 -1
- package/dist/parse.js +1231 -150
- package/dist/parse.js.map +1 -1
- package/dist/ts-type-block.d.ts +43 -0
- package/dist/ts-type-block.d.ts.map +1 -0
- package/dist/ts-type-block.js +164 -0
- package/dist/ts-type-block.js.map +1 -0
- package/package.json +10 -8
|
@@ -0,0 +1,418 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mintlify `docs.json` / legacy `mint.json` → NavItem[].
|
|
3
|
+
*
|
|
4
|
+
* Mintlify's navigation is polymorphic and recursive. A "navigation node" is an
|
|
5
|
+
* object that carries one (schema says one; we tolerate several) of these
|
|
6
|
+
* container arrays, each of which nests another navigation node:
|
|
7
|
+
*
|
|
8
|
+
* languages · versions · tabs · dropdowns · anchors · groups · pages
|
|
9
|
+
*
|
|
10
|
+
* plus leaf `pages` entries that are bare path strings, `{ group, pages }`
|
|
11
|
+
* sub-groups, or `{ page/anchor/..., href }` external links. `versions` and
|
|
12
|
+
* `languages` wrap any other structure, so a fully-loaded site can be
|
|
13
|
+
* `versions → languages → tabs → groups → pages`.
|
|
14
|
+
*
|
|
15
|
+
* The legacy `mint.json` is flatter: `navigation` is an ARRAY of
|
|
16
|
+
* `{ group, pages }`, plus top-level `anchors: [{ name, url }]`. Both are
|
|
17
|
+
* handled here.
|
|
18
|
+
*
|
|
19
|
+
* Page labels are NOT in the config — a page is a bare slug, and its
|
|
20
|
+
* human-readable title lives in the MDX file's frontmatter. We resolve it the
|
|
21
|
+
* same way the Fumadocs nav builder does (frontmatter `title`, else a humanized
|
|
22
|
+
* last path segment).
|
|
23
|
+
*/
|
|
24
|
+
import { existsSync, readFileSync, readdirSync, realpathSync } from "node:fs";
|
|
25
|
+
import { basename, dirname, join, sep } from "node:path";
|
|
26
|
+
import YAML from "yaml";
|
|
27
|
+
import { openApiPageKey, openApiRefSlug } from "./mintlify-openapi.js";
|
|
28
|
+
/**
|
|
29
|
+
* True when `dir` looks like a Mintlify docs source: a `docs.json`/`mint.json`
|
|
30
|
+
* that actually reads as a Mintlify config, plus md/mdx pages. The config sniff
|
|
31
|
+
* (a `navigation` key or a `mintlify` `$schema`) keeps an unrelated `docs.json`
|
|
32
|
+
* — e.g. TypeDoc's output — from being claimed by the mdx importer.
|
|
33
|
+
*/
|
|
34
|
+
export function detectMintlifyDir(dir) {
|
|
35
|
+
if (!hasMdFiles(dir))
|
|
36
|
+
return false;
|
|
37
|
+
const config = readConfig(dir);
|
|
38
|
+
if (!config)
|
|
39
|
+
return false;
|
|
40
|
+
return (config.navigation != null ||
|
|
41
|
+
Array.isArray(config.anchors) ||
|
|
42
|
+
(typeof config.$schema === "string" && config.$schema.includes("mintlify")));
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Build NavItem[] from a Mintlify config, or null when no config is present or
|
|
46
|
+
* it declares no navigation.
|
|
47
|
+
*/
|
|
48
|
+
export function buildMintlifyNav(source, opts = {}) {
|
|
49
|
+
const config = readConfig(source);
|
|
50
|
+
if (!config)
|
|
51
|
+
return null;
|
|
52
|
+
const ctx = { source, prefix: opts.hrefPrefix ?? "", depth: 0, budget: { spent: 0, warned: false } };
|
|
53
|
+
const items = [];
|
|
54
|
+
// `navigation` is an object (docs.json) or an array (legacy mint.json).
|
|
55
|
+
if (config.navigation != null) {
|
|
56
|
+
items.push(...navNodeToItems(config.navigation, ctx));
|
|
57
|
+
}
|
|
58
|
+
// Legacy top-level anchors sit alongside `navigation`, not inside it.
|
|
59
|
+
for (const a of objs(config.anchors))
|
|
60
|
+
items.push(anchorItem(a, ctx));
|
|
61
|
+
return items.length > 0 ? items : null;
|
|
62
|
+
}
|
|
63
|
+
/** Depth cap for the navigation walk — far above any real config (max seen: 6). */
|
|
64
|
+
const MAX_NAV_DEPTH = 64;
|
|
65
|
+
/**
|
|
66
|
+
* Total nav nodes one build may visit.
|
|
67
|
+
*
|
|
68
|
+
* Depth alone does not bound WORK: a cyclic `$ref` with two children per level
|
|
69
|
+
* is O(2^depth) — measured 4x per two levels, each node doing a readFileSync —
|
|
70
|
+
* so a depth cap of 64 still hangs the import forever. The bug this replaced
|
|
71
|
+
* (an unguarded RangeError) at least TERMINATED. Mintlify's own docs are ~1000
|
|
72
|
+
* items, so this is ~50x the largest real config.
|
|
73
|
+
*/
|
|
74
|
+
const MAX_NAV_NODES = 50_000;
|
|
75
|
+
function readConfig(source) {
|
|
76
|
+
for (const name of ["docs.json", "mint.json"]) {
|
|
77
|
+
const p = join(source, name);
|
|
78
|
+
if (existsSync(p)) {
|
|
79
|
+
try {
|
|
80
|
+
return JSON.parse(readFileSync(p, "utf-8"));
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
return null;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* A navigation node: an array (legacy nav / a bare pages list) or an object
|
|
91
|
+
* carrying container arrays. Containers are checked in outer-to-inner order and
|
|
92
|
+
* concatenated — the schema says one type per level, but concatenating is safe
|
|
93
|
+
* and tolerant of hand-written configs that mix them.
|
|
94
|
+
*/
|
|
95
|
+
function navNodeToItems(node, ctx) {
|
|
96
|
+
if (Array.isArray(node))
|
|
97
|
+
return node.flatMap((e) => entryToItems(e, ctx));
|
|
98
|
+
if (!node || typeof node !== "object")
|
|
99
|
+
return [];
|
|
100
|
+
// Container elements must be objects — a stray null/scalar in an array must
|
|
101
|
+
// be skipped, not throw (readConfig's contract is "bad config → null nav",
|
|
102
|
+
// and buildMintlifyNav is called uncaught). `pages` is exempt: entryToItems
|
|
103
|
+
// already tolerates strings and null.
|
|
104
|
+
if (++ctx.budget.spent > MAX_NAV_NODES) {
|
|
105
|
+
if (!ctx.budget.warned) {
|
|
106
|
+
console.warn(`warning: navigation exceeded ${MAX_NAV_NODES} nodes — the rest was skipped ` +
|
|
107
|
+
"(a branching $ref cycle looks like this)");
|
|
108
|
+
ctx.budget.warned = true;
|
|
109
|
+
}
|
|
110
|
+
return [];
|
|
111
|
+
}
|
|
112
|
+
if (ctx.depth >= MAX_NAV_DEPTH) {
|
|
113
|
+
console.warn(`warning: navigation nesting exceeded ${MAX_NAV_DEPTH} levels — the rest of ` +
|
|
114
|
+
"this branch was skipped (a $ref cycle looks like this)");
|
|
115
|
+
return [];
|
|
116
|
+
}
|
|
117
|
+
const inner = { ...ctx, depth: ctx.depth + 1 };
|
|
118
|
+
const items = [];
|
|
119
|
+
// `$ref` is resolved at every container level, not just languages: the same
|
|
120
|
+
// split-file pattern is used for versions and tabs in large configs.
|
|
121
|
+
for (const l of objs(node.languages))
|
|
122
|
+
items.push(variantItem(resolveRef(l, inner), "language", inner));
|
|
123
|
+
for (const v of objs(node.versions))
|
|
124
|
+
items.push(variantItem(resolveRef(v, inner), "version", inner));
|
|
125
|
+
for (const p of objs(node.products))
|
|
126
|
+
items.push(containerItem(resolveRef(p, inner), "product", inner));
|
|
127
|
+
for (const t of objs(node.tabs))
|
|
128
|
+
items.push(containerItem(resolveRef(t, inner), "tab", inner));
|
|
129
|
+
for (const a of objs(node.anchors))
|
|
130
|
+
items.push(containerItem(resolveRef(a, inner), "anchor", inner));
|
|
131
|
+
for (const d of objs(node.dropdowns))
|
|
132
|
+
items.push(containerItem(resolveRef(d, inner), "dropdown", inner));
|
|
133
|
+
for (const g of objs(node.groups))
|
|
134
|
+
items.push(...groupItems(resolveRef(g, inner), inner));
|
|
135
|
+
// `global` holds divisions shown on EVERY page (global anchors/tabs — a
|
|
136
|
+
// changelog or blog link that persists across sections). Documented in
|
|
137
|
+
// Mintlify's navigation reference; unhandled it silently dropped those
|
|
138
|
+
// links. Recursed like any other node, since it just wraps divisions.
|
|
139
|
+
if (node.global && typeof node.global === "object") {
|
|
140
|
+
items.push(...navNodeToItems(resolveRef(node.global, inner), inner));
|
|
141
|
+
}
|
|
142
|
+
// `menu` holds `{ item, href|groups }` entries — the dropdown under a tab.
|
|
143
|
+
// Missing it cost Mintlify's own docs their entire "Guides" section: 30 real
|
|
144
|
+
// pages imported from disk but appeared in no navigation, which is also why
|
|
145
|
+
// they looked like "pages outside the nav" when auditing coverage.
|
|
146
|
+
for (const m of objs(node.menu))
|
|
147
|
+
items.push(menuItem(resolveRef(m, inner), inner));
|
|
148
|
+
if (Array.isArray(node.pages))
|
|
149
|
+
items.push(...node.pages.flatMap((p) => entryToItems(p, inner)));
|
|
150
|
+
return items.filter(Boolean);
|
|
151
|
+
}
|
|
152
|
+
/** Array elements that are non-null objects (skips stray null/scalar entries). */
|
|
153
|
+
function objs(v) {
|
|
154
|
+
return Array.isArray(v) ? v.filter((e) => e != null && typeof e === "object") : [];
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Resolve a `{ "$ref": "./fr.json" }` node by loading that file.
|
|
158
|
+
*
|
|
159
|
+
* Mintlify splits large multi-language configs across files: the `en` entry is
|
|
160
|
+
* inlined in `docs.json` and the rest are `$ref`s to siblings. Not following
|
|
161
|
+
* them cost Mintlify's own docs their ENTIRE French, Spanish and Chinese
|
|
162
|
+
* navigation — three nav entries labelled `language` with no children, while
|
|
163
|
+
* the fr/es/zh pages imported fine and were simply unreachable.
|
|
164
|
+
*
|
|
165
|
+
* Resolved relative to the docs root, like every other Mintlify path. A ref
|
|
166
|
+
* that cannot be read returns the node untouched, so it degrades to today's
|
|
167
|
+
* behaviour rather than throwing.
|
|
168
|
+
*
|
|
169
|
+
* Two guards, both learned from `mintlify-openapi.ts` closing the same holes:
|
|
170
|
+
*
|
|
171
|
+
* - CONFINEMENT. `docs.json` ships inside the untrusted repo being converted,
|
|
172
|
+
* so "the operator chose it" covers which DIRECTORY to convert, not the
|
|
173
|
+
* contents of a file in it. `{"$ref":"../../secret.json"}` put an
|
|
174
|
+
* out-of-corpus file's contents into the exported navigation as labels and
|
|
175
|
+
* hrefs.
|
|
176
|
+
* - CYCLES. A self-referential ref recursed until the stack was exhausted,
|
|
177
|
+
* producing a nav ~1800 levels deep whose depth varied by machine; it only
|
|
178
|
+
* failed to crash because the RangeError happened to land inside the
|
|
179
|
+
* try/catch below.
|
|
180
|
+
*/
|
|
181
|
+
function resolveRef(node, ctx) {
|
|
182
|
+
if (!node || typeof node !== "object" || typeof node.$ref !== "string")
|
|
183
|
+
return node;
|
|
184
|
+
const target = join(ctx.source, node.$ref.replace(/^\.\//, "").replace(/^\//, ""));
|
|
185
|
+
if (!withinSource(target, ctx.source)) {
|
|
186
|
+
console.warn(`warning: navigation $ref "${node.$ref}" points outside the docs directory — ignored`);
|
|
187
|
+
return node;
|
|
188
|
+
}
|
|
189
|
+
if (!existsSync(target))
|
|
190
|
+
return node;
|
|
191
|
+
try {
|
|
192
|
+
const loaded = JSON.parse(readFileSync(target, "utf-8"));
|
|
193
|
+
// A ref can point at an ARRAY (redirects.json is a bare list) — spreading
|
|
194
|
+
// that into an object would turn it into {0:…,1:…}.
|
|
195
|
+
if (Array.isArray(loaded))
|
|
196
|
+
return loaded;
|
|
197
|
+
// Keep any sibling keys the ref node carried (e.g. an explicit `language`).
|
|
198
|
+
const { $ref: _ref, ...rest } = node;
|
|
199
|
+
return { ...loaded, ...rest };
|
|
200
|
+
}
|
|
201
|
+
catch {
|
|
202
|
+
return node;
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/** Is `target` inside the docs root once symlinks are resolved? */
|
|
206
|
+
function withinSource(target, source) {
|
|
207
|
+
const real = (p) => {
|
|
208
|
+
try {
|
|
209
|
+
return realpathSync(p);
|
|
210
|
+
}
|
|
211
|
+
catch {
|
|
212
|
+
const parent = dirname(p);
|
|
213
|
+
return parent === p ? p : join(real(parent), basename(p));
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
const root = real(source);
|
|
217
|
+
const abs = real(target);
|
|
218
|
+
return abs === root || abs.startsWith(root + sep);
|
|
219
|
+
}
|
|
220
|
+
/** A single entry inside a `pages` array. */
|
|
221
|
+
function entryToItems(entry, ctx) {
|
|
222
|
+
if (typeof entry === "string") {
|
|
223
|
+
// A `METHOD /path` string references an OpenAPI operation generated from the
|
|
224
|
+
// container's `openapi` spec (ollama's "Endpoints" group) — it is not a
|
|
225
|
+
// file. Point at the slug the page generator uses (openApiRefSlug) so the
|
|
226
|
+
// link resolves; treating it as a file slug produced a broken `/POST /x`.
|
|
227
|
+
const oaKey = openApiPageKey(entry);
|
|
228
|
+
if (oaKey) {
|
|
229
|
+
const path = oaKey.slice(oaKey.indexOf(" ") + 1);
|
|
230
|
+
const slug = openApiRefSlug(path);
|
|
231
|
+
const last = slug.split("/").pop() || slug;
|
|
232
|
+
return [{ label: humanize(last), href: `${ctx.prefix}/${slug}` }];
|
|
233
|
+
}
|
|
234
|
+
return [pageItem(entry, ctx)];
|
|
235
|
+
}
|
|
236
|
+
if (!entry || typeof entry !== "object")
|
|
237
|
+
return [];
|
|
238
|
+
// Sub-group: `{ group, pages }`.
|
|
239
|
+
if (typeof entry.group === "string")
|
|
240
|
+
return groupItems(entry, ctx);
|
|
241
|
+
// External or explicit page link: `{ page?, href }`.
|
|
242
|
+
if (typeof entry.href === "string") {
|
|
243
|
+
const label = str(entry.page ?? entry.group ?? entry.title) ?? entry.href;
|
|
244
|
+
return [{ label, href: resolveHref(entry.href, ctx) }];
|
|
245
|
+
}
|
|
246
|
+
// A nested navigation node (e.g. a page entry that itself carries groups).
|
|
247
|
+
const nested = navNodeToItems(entry, ctx);
|
|
248
|
+
return nested;
|
|
249
|
+
}
|
|
250
|
+
/** `{ group, pages, root?, tag? }` → a group NavItem (empty label = splice up). */
|
|
251
|
+
function groupItems(g, ctx) {
|
|
252
|
+
const children = navNodeToItems(g, ctx);
|
|
253
|
+
const label = str(g.group);
|
|
254
|
+
// A group with an empty/absent name (legacy root group) has no header — its
|
|
255
|
+
// pages belong at the parent level.
|
|
256
|
+
if (!label)
|
|
257
|
+
return children;
|
|
258
|
+
const item = { label, children };
|
|
259
|
+
// `root` names a landing page for the group.
|
|
260
|
+
if (typeof g.root === "string")
|
|
261
|
+
item.href = pageHref(g.root, ctx);
|
|
262
|
+
return [item];
|
|
263
|
+
}
|
|
264
|
+
/** tab / dropdown / anchor: labelled by its own key; may be external or nest. */
|
|
265
|
+
function containerItem(node, kind, ctx) {
|
|
266
|
+
const label = str(node[kind]) ?? str(node.name) ?? kind;
|
|
267
|
+
const children = navNodeToItems(node, ctx);
|
|
268
|
+
if (children.length > 0)
|
|
269
|
+
return { label, children };
|
|
270
|
+
// Leaf: an external href, or a bare path (legacy anchor `url`).
|
|
271
|
+
const target = str(node.href) ?? str(node.url);
|
|
272
|
+
return target ? { label, href: resolveHref(target, ctx) } : { label };
|
|
273
|
+
}
|
|
274
|
+
/** version / language: labelled by its key, tag appended; wraps nested nav. */
|
|
275
|
+
function variantItem(node, kind, ctx) {
|
|
276
|
+
const base = str(node[kind]) ?? kind;
|
|
277
|
+
const tag = str(node.tag);
|
|
278
|
+
const label = tag ? `${base} (${tag})` : base;
|
|
279
|
+
const children = navNodeToItems(node, ctx);
|
|
280
|
+
const item = { label };
|
|
281
|
+
if (children.length > 0)
|
|
282
|
+
item.children = children;
|
|
283
|
+
else if (str(node.href))
|
|
284
|
+
item.href = resolveHref(node.href, ctx);
|
|
285
|
+
return item;
|
|
286
|
+
}
|
|
287
|
+
/**
|
|
288
|
+
* Mintlify `redirects` as a source → destination map, `$ref` resolved.
|
|
289
|
+
*
|
|
290
|
+
* A docs site accumulates these as pages move, and its OWN pages then link to
|
|
291
|
+
* the old paths — Mintlify serves the redirect, so the link works and nobody
|
|
292
|
+
* notices it is stale. On import the redirect does not exist, so those links
|
|
293
|
+
* 404: measured on Mintlify's own docs, 16 internal links point at a redirect
|
|
294
|
+
* source, including `/installation` on the front page (→ `/cli/install`).
|
|
295
|
+
*
|
|
296
|
+
* `redirects` is itself commonly a `$ref` to a sibling file (121 entries in
|
|
297
|
+
* `redirects.json` here), so it is resolved the same way as navigation.
|
|
298
|
+
*/
|
|
299
|
+
export function mintlifyRedirects(source) {
|
|
300
|
+
const config = readConfig(source);
|
|
301
|
+
if (!config)
|
|
302
|
+
return {};
|
|
303
|
+
const ctx = { source, prefix: "", depth: 0, budget: { spent: 0, warned: false } };
|
|
304
|
+
const raw = config.redirects;
|
|
305
|
+
const list = Array.isArray(raw)
|
|
306
|
+
? raw
|
|
307
|
+
: (() => {
|
|
308
|
+
const resolved = resolveRef(raw, ctx);
|
|
309
|
+
return Array.isArray(resolved)
|
|
310
|
+
? resolved
|
|
311
|
+
: Array.isArray(resolved?.redirects)
|
|
312
|
+
? resolved.redirects
|
|
313
|
+
: [];
|
|
314
|
+
})();
|
|
315
|
+
const map = {};
|
|
316
|
+
for (const entry of list) {
|
|
317
|
+
const from = str(entry?.source);
|
|
318
|
+
const to = str(entry?.destination);
|
|
319
|
+
if (from && to)
|
|
320
|
+
map[from.replace(/\/$/, "")] = to;
|
|
321
|
+
}
|
|
322
|
+
return map;
|
|
323
|
+
}
|
|
324
|
+
/** A `menu` entry: `{ item, href? , groups?/pages? }`. */
|
|
325
|
+
function menuItem(node, ctx) {
|
|
326
|
+
const label = str(node.item) ?? str(node.group) ?? "Menu";
|
|
327
|
+
const children = navNodeToItems(node, ctx);
|
|
328
|
+
const item = { label };
|
|
329
|
+
if (children.length > 0)
|
|
330
|
+
item.children = children;
|
|
331
|
+
else if (str(node.href))
|
|
332
|
+
item.href = resolveHref(node.href, ctx);
|
|
333
|
+
return item;
|
|
334
|
+
}
|
|
335
|
+
/** Legacy top-level anchor: `{ name, url, icon? }`. */
|
|
336
|
+
function anchorItem(a, ctx) {
|
|
337
|
+
const label = str(a.name) ?? str(a.anchor) ?? "Anchor";
|
|
338
|
+
const target = str(a.url) ?? str(a.href);
|
|
339
|
+
return target ? { label, href: resolveHref(target, ctx) } : { label };
|
|
340
|
+
}
|
|
341
|
+
/** A bare page slug → NavItem, label resolved from frontmatter title. */
|
|
342
|
+
function pageItem(slug, ctx) {
|
|
343
|
+
return { label: pageLabel(slug, ctx), href: pageHref(slug, ctx) };
|
|
344
|
+
}
|
|
345
|
+
// ── href / label helpers ────────────────────────────────
|
|
346
|
+
function resolveHref(target, ctx) {
|
|
347
|
+
if (isExternal(target) || target.startsWith("#") || target.startsWith("mailto:"))
|
|
348
|
+
return target;
|
|
349
|
+
return pageHref(target, ctx);
|
|
350
|
+
}
|
|
351
|
+
function pageHref(slug, ctx) {
|
|
352
|
+
const clean = slug.replace(/^\//, "").replace(/\.mdx?$/, "");
|
|
353
|
+
// An `index` page is routed to its folder root by Astro (root `index.mdx` → `/`,
|
|
354
|
+
// `foo/index.mdx` → `/foo`), so the nav href must match — linking to `/index`
|
|
355
|
+
// 404s while the page lives at `/`. Mirrors the Fumadocs nav builder.
|
|
356
|
+
if (clean === "index")
|
|
357
|
+
return `${ctx.prefix}/`;
|
|
358
|
+
return `${ctx.prefix}/${clean.replace(/\/index$/, "")}`;
|
|
359
|
+
}
|
|
360
|
+
function isExternal(s) {
|
|
361
|
+
return /^https?:\/\//.test(s);
|
|
362
|
+
}
|
|
363
|
+
function pageLabel(slug, ctx) {
|
|
364
|
+
const clean = slug.replace(/^\//, "").replace(/\.mdx?$/, "");
|
|
365
|
+
const file = resolvePageFile(ctx.source, clean);
|
|
366
|
+
if (file) {
|
|
367
|
+
const title = frontmatterTitle(file);
|
|
368
|
+
if (title)
|
|
369
|
+
return title;
|
|
370
|
+
}
|
|
371
|
+
const last = clean.split("/").pop() || clean;
|
|
372
|
+
return humanize(last);
|
|
373
|
+
}
|
|
374
|
+
function resolvePageFile(source, slug) {
|
|
375
|
+
for (const ext of [".mdx", ".md"]) {
|
|
376
|
+
const p = join(source, slug + ext);
|
|
377
|
+
if (existsSync(p))
|
|
378
|
+
return p;
|
|
379
|
+
// A folder index: `slug/index.mdx`.
|
|
380
|
+
const idx = join(source, slug, "index" + ext);
|
|
381
|
+
if (existsSync(idx))
|
|
382
|
+
return idx;
|
|
383
|
+
}
|
|
384
|
+
return null;
|
|
385
|
+
}
|
|
386
|
+
function frontmatterTitle(file) {
|
|
387
|
+
try {
|
|
388
|
+
const src = readFileSync(file, "utf-8");
|
|
389
|
+
const m = /^---\n([\s\S]*?)\n---/.exec(src);
|
|
390
|
+
if (m) {
|
|
391
|
+
const fm = YAML.parse(m[1]);
|
|
392
|
+
if (fm && typeof fm.title === "string")
|
|
393
|
+
return fm.title;
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
catch {
|
|
397
|
+
// fall through
|
|
398
|
+
}
|
|
399
|
+
return undefined;
|
|
400
|
+
}
|
|
401
|
+
function humanize(name) {
|
|
402
|
+
return name.replace(/[-_]/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
403
|
+
}
|
|
404
|
+
function str(v) {
|
|
405
|
+
if (typeof v !== "string")
|
|
406
|
+
return undefined;
|
|
407
|
+
const t = v.trim();
|
|
408
|
+
return t.length > 0 ? t : undefined;
|
|
409
|
+
}
|
|
410
|
+
function hasMdFiles(dir) {
|
|
411
|
+
try {
|
|
412
|
+
return readdirSync(dir).some((e) => (e.endsWith(".md") || e.endsWith(".mdx")) && e !== "llms.txt");
|
|
413
|
+
}
|
|
414
|
+
catch {
|
|
415
|
+
return false;
|
|
416
|
+
}
|
|
417
|
+
}
|
|
418
|
+
//# sourceMappingURL=mintlify-nav.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mintlify-nav.js","sourceRoot":"","sources":["../src/mintlify-nav.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,UAAU,EAAE,YAAY,EAAE,WAAW,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAC9E,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,OAAO,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAOvE;;;;;GAKG;AACH,MAAM,UAAU,iBAAiB,CAAC,GAAW;IAC3C,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACnC,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,IAAI,CAAC,MAAM;QAAE,OAAO,KAAK,CAAC;IAC1B,OAAO,CACL,MAAM,CAAC,UAAU,IAAI,IAAI;QACzB,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,OAAO,CAAC;QAC7B,CAAC,OAAO,MAAM,CAAC,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,CAC5E,CAAC;AACJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAc,EACd,OAA2B,EAAE;IAE7B,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,IAAI,CAAC;IAEzB,MAAM,GAAG,GAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,UAAU,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;IAC1G,MAAM,KAAK,GAAc,EAAE,CAAC;IAE5B,wEAAwE;IACxE,IAAI,MAAM,CAAC,UAAU,IAAI,IAAI,EAAE,CAAC;QAC9B,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,UAAU,EAAE,GAAG,CAAC,CAAC,CAAC;IACxD,CAAC;IACD,sEAAsE;IACtE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAErE,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AACzC,CAAC;AAyBD,mFAAmF;AACnF,MAAM,aAAa,GAAG,EAAE,CAAC;AAEzB;;;;;;;;GAQG;AACH,MAAM,aAAa,GAAG,MAAM,CAAC;AAE7B,SAAS,UAAU,CAAC,MAAc;IAChC,KAAK,MAAM,IAAI,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,CAAC;QAC9C,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QAC7B,IAAI,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC;YAClB,IAAI,CAAC;gBACH,OAAO,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAAC;YAC9C,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAS,cAAc,CAAC,IAAU,EAAE,GAAQ;IAC1C,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC;IAC1E,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IAEjD,4EAA4E;IAC5E,2EAA2E;IAC3E,4EAA4E;IAC5E,sCAAsC;IACtC,IAAI,EAAE,GAAG,CAAC,MAAM,CAAC,KAAK,GAAG,aAAa,EAAE,CAAC;QACvC,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YACvB,OAAO,CAAC,IAAI,CACV,gCAAgC,aAAa,gCAAgC;gBAC3E,0CAA0C,CAC7C,CAAC;YACF,GAAG,CAAC,MAAM,CAAC,MAAM,GAAG,IAAI,CAAC;QAC3B,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,IAAI,GAAG,CAAC,KAAK,IAAI,aAAa,EAAE,CAAC;QAC/B,OAAO,CAAC,IAAI,CACV,wCAAwC,aAAa,wBAAwB;YAC3E,wDAAwD,CAC3D,CAAC;QACF,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAQ,EAAE,GAAG,GAAG,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,GAAG,CAAC,EAAE,CAAC;IAEpD,MAAM,KAAK,GAAc,EAAE,CAAC;IAC5B,4EAA4E;IAC5E,qEAAqE;IACrE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;IACvG,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IACrG,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC;IACvG,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAC/F,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;IACrG,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;IACzG,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IAC1F,wEAAwE;IACxE,uEAAuE;IACvE,uEAAuE;IACvE,sEAAsE;IACtE,IAAI,IAAI,CAAC,MAAM,IAAI,OAAO,IAAI,CAAC,MAAM,KAAK,QAAQ,EAAE,CAAC;QACnD,KAAK,CAAC,IAAI,CAAC,GAAG,cAAc,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACvE,CAAC;IACD,2EAA2E;IAC3E,6EAA6E;IAC7E,4EAA4E;IAC5E,mEAAmE;IACnE,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;IACnF,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAO,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC;IACzE,OAAO,KAAK,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;AAC/B,CAAC;AAED,kFAAkF;AAClF,SAAS,IAAI,CAAC,CAAU;IACtB,OAAO,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,IAAI,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACrF,CAAC;AAED;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,SAAS,UAAU,CAAC,IAAU,EAAE,GAAQ;IACtC,IAAI,CAAC,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACpF,MAAM,MAAM,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;IACnF,IAAI,CAAC,YAAY,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,IAAI,CACV,6BAA6B,IAAI,CAAC,IAAI,+CAA+C,CACtF,CAAC;QACF,OAAO,IAAI,CAAC;IACd,CAAC;IACD,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,IAAI,CAAC;IACrC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC,CAAC;QACzD,0EAA0E;QAC1E,oDAAoD;QACpD,IAAI,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,MAAM,CAAC;QACzC,4EAA4E;QAC5E,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,IAAI,EAAE,GAAG,IAAI,CAAC;QACrC,OAAO,EAAE,GAAG,MAAM,EAAE,GAAG,IAAI,EAAE,CAAC;IAChC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,mEAAmE;AACnE,SAAS,YAAY,CAAC,MAAc,EAAE,MAAc;IAClD,MAAM,IAAI,GAAG,CAAC,CAAS,EAAU,EAAE;QACjC,IAAI,CAAC;YACH,OAAO,YAAY,CAAC,CAAC,CAAC,CAAC;QACzB,CAAC;QAAC,MAAM,CAAC;YACP,MAAM,MAAM,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;YAC1B,OAAO,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;QAC5D,CAAC;IACH,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,CAAC;IACzB,OAAO,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,UAAU,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC;AACpD,CAAC;AAED,6CAA6C;AAC7C,SAAS,YAAY,CAAC,KAAW,EAAE,GAAQ;IACzC,IAAI,OAAO,KAAK,KAAK,QAAQ,EAAE,CAAC;QAC9B,6EAA6E;QAC7E,wEAAwE;QACxE,0EAA0E;QAC1E,0EAA0E;QAC1E,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,CAAC,CAAC;QACpC,IAAI,KAAK,EAAE,CAAC;YACV,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;YAClC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,IAAI,CAAC;YAC3C,OAAO,CAAC,EAAE,KAAK,EAAE,QAAQ,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,GAAG,GAAG,CAAC,MAAM,IAAI,IAAI,EAAE,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,OAAO,CAAC,QAAQ,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;IAChC,CAAC;IACD,IAAI,CAAC,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ;QAAE,OAAO,EAAE,CAAC;IACnD,iCAAiC;IACjC,IAAI,OAAO,KAAK,CAAC,KAAK,KAAK,QAAQ;QAAE,OAAO,UAAU,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IACnE,qDAAqD;IACrD,IAAI,OAAO,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QACnC,MAAM,KAAK,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC;QAC1E,OAAO,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC;IACzD,CAAC;IACD,2EAA2E;IAC3E,MAAM,MAAM,GAAG,cAAc,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,mFAAmF;AACnF,SAAS,UAAU,CAAC,CAAO,EAAE,GAAQ;IACnC,MAAM,QAAQ,GAAG,cAAc,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACxC,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAC3B,4EAA4E;IAC5E,oCAAoC;IACpC,IAAI,CAAC,KAAK;QAAE,OAAO,QAAQ,CAAC;IAC5B,MAAM,IAAI,GAAY,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IAC1C,6CAA6C;IAC7C,IAAI,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ;QAAE,IAAI,CAAC,IAAI,GAAG,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAClE,OAAO,CAAC,IAAI,CAAC,CAAC;AAChB,CAAC;AAED,iFAAiF;AACjF,SAAS,aAAa,CACpB,IAAU,EACV,IAA+C,EAC/C,GAAQ;IAER,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;IACxD,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3C,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,CAAC;IACpD,gEAAgE;IAChE,MAAM,MAAM,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC/C,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;AACxE,CAAC;AAED,+EAA+E;AAC/E,SAAS,WAAW,CAAC,IAAU,EAAE,IAA4B,EAAE,GAAQ;IACrE,MAAM,IAAI,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC;IACrC,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IAC1B,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;IAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAY,EAAE,KAAK,EAAE,CAAC;IAChC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;SAC7C,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,iBAAiB,CAAC,MAAc;IAC9C,MAAM,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC,IAAI,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IACvB,MAAM,GAAG,GAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,CAAC;IACvF,MAAM,GAAG,GAAG,MAAM,CAAC,SAAS,CAAC;IAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC;QAC7B,CAAC,CAAC,GAAG;QACL,CAAC,CAAC,CAAC,GAAG,EAAE;YACJ,MAAM,QAAQ,GAAG,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;YACtC,OAAO,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC;gBAC5B,CAAC,CAAC,QAAQ;gBACV,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,EAAE,SAAS,CAAC;oBAClC,CAAC,CAAC,QAAQ,CAAC,SAAS;oBACpB,CAAC,CAAC,EAAE,CAAC;QACX,CAAC,CAAC,EAAE,CAAC;IACT,MAAM,GAAG,GAA2B,EAAE,CAAC;IACvC,KAAK,MAAM,KAAK,IAAI,IAAI,EAAE,CAAC;QACzB,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;QAChC,MAAM,EAAE,GAAG,GAAG,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACnC,IAAI,IAAI,IAAI,EAAE;YAAE,GAAG,CAAC,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,GAAG,EAAE,CAAC;IACpD,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,0DAA0D;AAC1D,SAAS,QAAQ,CAAC,IAAU,EAAE,GAAQ;IACpC,MAAM,KAAK,GAAG,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,MAAM,CAAC;IAC1D,MAAM,QAAQ,GAAG,cAAc,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IAC3C,MAAM,IAAI,GAAY,EAAE,KAAK,EAAE,CAAC;IAChC,IAAI,QAAQ,CAAC,MAAM,GAAG,CAAC;QAAE,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;SAC7C,IAAI,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,IAAI,CAAC,IAAI,GAAG,WAAW,CAAC,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC;AACd,CAAC;AAED,uDAAuD;AACvD,SAAS,UAAU,CAAC,CAAO,EAAE,GAAQ;IACnC,MAAM,KAAK,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,QAAQ,CAAC;IACvD,MAAM,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IACzC,OAAO,MAAM,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,WAAW,CAAC,MAAM,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;AACxE,CAAC;AAED,yEAAyE;AACzE,SAAS,QAAQ,CAAC,IAAY,EAAE,GAAQ;IACtC,OAAO,EAAE,KAAK,EAAE,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC;AACpE,CAAC;AAED,2DAA2D;AAE3D,SAAS,WAAW,CAAC,MAAc,EAAE,GAAQ;IAC3C,IAAI,UAAU,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,MAAM,CAAC,UAAU,CAAC,SAAS,CAAC;QAC9E,OAAO,MAAM,CAAC;IAChB,OAAO,QAAQ,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,GAAQ;IACtC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC7D,iFAAiF;IACjF,8EAA8E;IAC9E,sEAAsE;IACtE,IAAI,KAAK,KAAK,OAAO;QAAE,OAAO,GAAG,GAAG,CAAC,MAAM,GAAG,CAAC;IAC/C,OAAO,GAAG,GAAG,CAAC,MAAM,IAAI,KAAK,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,EAAE,CAAC;AAC1D,CAAC;AAED,SAAS,UAAU,CAAC,CAAS;IAC3B,OAAO,cAAc,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,SAAS,CAAC,IAAY,EAAE,GAAQ;IACvC,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IAC7D,MAAM,IAAI,GAAG,eAAe,CAAC,GAAG,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAChD,IAAI,IAAI,EAAE,CAAC;QACT,MAAM,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;QACrC,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC;IAC1B,CAAC;IACD,MAAM,IAAI,GAAG,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,IAAI,KAAK,CAAC;IAC7C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC;AAED,SAAS,eAAe,CAAC,MAAc,EAAE,IAAY;IACnD,KAAK,MAAM,GAAG,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,EAAE,CAAC;QAClC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,GAAG,GAAG,CAAC,CAAC;QACnC,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,CAAC,CAAC;QAC5B,oCAAoC;QACpC,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,EAAE,IAAI,EAAE,OAAO,GAAG,GAAG,CAAC,CAAC;QAC9C,IAAI,UAAU,CAAC,GAAG,CAAC;YAAE,OAAO,GAAG,CAAC;IAClC,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED,SAAS,gBAAgB,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,CAAC,GAAG,uBAAuB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC5C,IAAI,CAAC,EAAE,CAAC;YACN,MAAM,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC5B,IAAI,EAAE,IAAI,OAAO,EAAE,CAAC,KAAK,KAAK,QAAQ;gBAAE,OAAO,EAAE,CAAC,KAAK,CAAC;QAC1D,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,eAAe;IACjB,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;AAC7E,CAAC;AAED,SAAS,GAAG,CAAC,CAAU;IACrB,IAAI,OAAO,CAAC,KAAK,QAAQ;QAAE,OAAO,SAAS,CAAC;IAC5C,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACnB,OAAO,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;AACtC,CAAC;AAED,SAAS,UAAU,CAAC,GAAW;IAC7B,IAAI,CAAC;QACH,OAAO,WAAW,CAAC,GAAG,CAAC,CAAC,IAAI,CAC1B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,KAAK,UAAU,CACrE,CAAC;IACJ,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import type { TreeNode, ExportPage } from "@dogsbay/types";
|
|
2
|
+
/**
|
|
3
|
+
* The OpenAPI spec reference declared in a Mintlify config, or null. Reads
|
|
4
|
+
* `docs.json` / `mint.json` `api.openapi` (string, or first of an array) and the
|
|
5
|
+
* legacy top-level `openapi`. Only an `http(s)://` value is a URL; everything
|
|
6
|
+
* else — including a ROOT-relative path like `/api-reference/openapi.json`,
|
|
7
|
+
* which Mintlify resolves against the docs root, not the filesystem root — is
|
|
8
|
+
* resolved against `source`.
|
|
9
|
+
*/
|
|
10
|
+
export declare function mintlifyOpenApiSpecRef(source: string): string | null;
|
|
11
|
+
/**
|
|
12
|
+
* Where a spec reference came from — which decides how far we trust it.
|
|
13
|
+
*
|
|
14
|
+
* `config` is `docs.json` / `mint.json`: the operator pointed us at this site,
|
|
15
|
+
* so its config is a deliberate choice. `page` is a `.mdx` file's own
|
|
16
|
+
* frontmatter — that is CONTENT, authored by whoever wrote the repo we are
|
|
17
|
+
* converting, and converting an arbitrary public repo is the whole point of
|
|
18
|
+
* the migration story. Content does not get to name a network endpoint or a
|
|
19
|
+
* file outside the corpus.
|
|
20
|
+
*/
|
|
21
|
+
export type SpecRefOrigin = "config" | "page";
|
|
22
|
+
/**
|
|
23
|
+
* Fetch the raw spec document, unparsed.
|
|
24
|
+
*
|
|
25
|
+
* An OpenAPI spec is a CANONICAL SOURCE ARTIFACT, not prose: round-tripping it
|
|
26
|
+
* through the TreeNode IR is lossy by construction ($ref/component schemas
|
|
27
|
+
* inline, security schemes and callbacks vanish). Exporters that can consume a
|
|
28
|
+
* spec directly should pass THIS through rather than rebuild it from endpoint
|
|
29
|
+
* nodes. Returns null when the spec cannot be read.
|
|
30
|
+
*/
|
|
31
|
+
export declare function readOpenApiSpecSource(specRef: string): Promise<{
|
|
32
|
+
text: string;
|
|
33
|
+
filename: string;
|
|
34
|
+
} | null>;
|
|
35
|
+
export interface EndpointMapResult {
|
|
36
|
+
/** `"<method> <path>"` (lowercase method) → the `endpoint` TreeNode(s). */
|
|
37
|
+
map: Map<string, TreeNode[]>;
|
|
38
|
+
/** The same keys → the page title format-openapi gives the operation. */
|
|
39
|
+
titles?: Map<string, string>;
|
|
40
|
+
/** Spec load/parse failure message, or null. Lets the caller distinguish a
|
|
41
|
+
* failed fetch (blame the spec source) from a genuine no-match (blame the
|
|
42
|
+
* page). Without this, every page reads "no matching operation" on a 404. */
|
|
43
|
+
loadError: string | null;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Parse a spec into an endpoint map. A fetch/parse error must degrade to blank
|
|
47
|
+
* pages (never crash the import), but is reported via `loadError` rather than
|
|
48
|
+
* silently swallowed.
|
|
49
|
+
*/
|
|
50
|
+
export declare function buildMintlifyEndpointMap(specRef: string): Promise<EndpointMapResult>;
|
|
51
|
+
/**
|
|
52
|
+
* Normalise a page's `openapi` frontmatter value to a map key, or null when the
|
|
53
|
+
* page is not an OpenAPI page. Accepts `"post /partners/ban"` (method + path);
|
|
54
|
+
* a leading named-spec token (`"api POST /x"`) is tolerated by taking the last
|
|
55
|
+
* two whitespace-separated tokens.
|
|
56
|
+
*/
|
|
57
|
+
export declare function openApiPageKey(value: unknown): string | null;
|
|
58
|
+
/**
|
|
59
|
+
* The spec a PAGE names in its own `openapi:` frontmatter, or null.
|
|
60
|
+
*
|
|
61
|
+
* Mintlify lets a page point at a specific spec inline:
|
|
62
|
+
*
|
|
63
|
+
* openapi: "/openapi.json GET /project/update-status/{statusId}"
|
|
64
|
+
*
|
|
65
|
+
* `openApiPageKey` already tolerates that leading token (it takes the last two
|
|
66
|
+
* tokens); this reads the token itself, which nothing did. A site whose
|
|
67
|
+
* `docs.json` has no `api.openapi` key therefore resolved NO endpoints even
|
|
68
|
+
* though every page stated exactly which spec to use — measured on Mintlify's
|
|
69
|
+
* own documentation: 100 pages imported without their endpoint content and 20
|
|
70
|
+
* of them came out completely blank, next to an `openapi.json` sitting in the
|
|
71
|
+
* repo root.
|
|
72
|
+
*
|
|
73
|
+
* Resolved the same way as a config-declared ref: a leading `/` is the DOCS
|
|
74
|
+
* root, not the filesystem root.
|
|
75
|
+
*/
|
|
76
|
+
export declare function openApiPageSpecRef(source: string, value: unknown): string | null;
|
|
77
|
+
/**
|
|
78
|
+
* The vault/site slug for a nav-referenced OpenAPI operation (a `pages` string
|
|
79
|
+
* of the form `"POST /api/generate"` under a tab/group that declares an
|
|
80
|
+
* `openapi` spec). The NAV and the GENERATED PAGE both call this, so their
|
|
81
|
+
* href and slug always agree. Path-based (`/api/generate` → `api/generate`) for
|
|
82
|
+
* clean URLs; same-path-different-method operations would collide — rare, and
|
|
83
|
+
* documented (ollama and typical REST doc sets use unique paths per page).
|
|
84
|
+
*/
|
|
85
|
+
export declare function openApiRefSlug(path: string): string;
|
|
86
|
+
/**
|
|
87
|
+
* Every distinct OpenAPI spec a Mintlify config references — the top-level
|
|
88
|
+
* `api.openapi` AND any `openapi` declared on a nav container (tab/group).
|
|
89
|
+
*
|
|
90
|
+
* Both are real source artifacts. Capturing only the top-level one meant a site
|
|
91
|
+
* like ollama (whose spec is declared on an "API Reference" tab) fell back to
|
|
92
|
+
* lossy reconstruction despite having a perfectly good spec on disk.
|
|
93
|
+
*/
|
|
94
|
+
export declare function collectMintlifyOpenApiSpecRefs(source: string,
|
|
95
|
+
/** Spec refs named by individual pages' `openapi:` frontmatter. */
|
|
96
|
+
pageSpecRefs?: readonly string[]): string[];
|
|
97
|
+
/**
|
|
98
|
+
* Generate an ExportPage for every OpenAPI operation referenced ONLY by the nav
|
|
99
|
+
* (a `METHOD /path` `pages` string under a container that declares `openapi`) —
|
|
100
|
+
* these pages exist in no `.mdx` file (unlike the frontmatter case), so without
|
|
101
|
+
* this the nav links are dead and the API section is empty. ollama's docs.json
|
|
102
|
+
* is exactly this shape (an "Endpoints" group of 12 such strings under a tab
|
|
103
|
+
* with `openapi: /openapi.yaml`).
|
|
104
|
+
*/
|
|
105
|
+
export declare function collectMintlifyOpenApiNavPages(source: string): Promise<{
|
|
106
|
+
pages: ExportPage[];
|
|
107
|
+
loadError: string | null;
|
|
108
|
+
}>;
|
|
109
|
+
//# sourceMappingURL=mintlify-openapi.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mintlify-openapi.d.ts","sourceRoot":"","sources":["../src/mintlify-openapi.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AAc3D;;;;;;;GAOG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAMpE;AAED;;;;;;;;;GASG;AACH,MAAM,MAAM,aAAa,GAAG,QAAQ,GAAG,MAAM,CAAC;AA0D9C;;;;;;;;GAQG;AACH,wBAAsB,qBAAqB,CACzC,OAAO,EAAE,MAAM,GACd,OAAO,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAkBpD;AAED,MAAM,WAAW,iBAAiB;IAChC,2EAA2E;IAC3E,GAAG,EAAE,GAAG,CAAC,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC;IAC7B,yEAAyE;IACzE,MAAM,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC7B;;kFAE8E;IAC9E,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1B;AAED;;;;GAIG;AACH,wBAAsB,wBAAwB,CAC5C,OAAO,EAAE,MAAM,GACd,OAAO,CAAC,iBAAiB,CAAC,CAmB5B;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAS5D;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAchF;AAED;;;;;;;GAOG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED;;;;;;;GAOG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,MAAM;AACd,mEAAmE;AACnE,YAAY,GAAE,SAAS,MAAM,EAAO,GACnC,MAAM,EAAE,CAaV;AAED;;;;;;;GAOG;AACH,wBAAsB,8BAA8B,CAClD,MAAM,EAAE,MAAM,GACb,OAAO,CAAC;IAAE,KAAK,EAAE,UAAU,EAAE,CAAC;IAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;CAAE,CAAC,CAkC5D"}
|