@dogsbay/format-mdx 0.2.0-beta.10 → 0.2.0-beta.102

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.
Files changed (52) hide show
  1. package/dist/adapter.d.ts +159 -0
  2. package/dist/adapter.d.ts.map +1 -0
  3. package/dist/adapter.js +95 -0
  4. package/dist/adapter.js.map +1 -0
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +269 -19
  7. package/dist/cli.js.map +1 -1
  8. package/dist/extract.d.ts +32 -0
  9. package/dist/extract.d.ts.map +1 -0
  10. package/dist/extract.js +152 -0
  11. package/dist/extract.js.map +1 -0
  12. package/dist/fumadocs.d.ts +48 -0
  13. package/dist/fumadocs.d.ts.map +1 -0
  14. package/dist/fumadocs.js +470 -0
  15. package/dist/fumadocs.js.map +1 -0
  16. package/dist/index.d.ts +11 -1
  17. package/dist/index.d.ts.map +1 -1
  18. package/dist/index.js +11 -1
  19. package/dist/index.js.map +1 -1
  20. package/dist/js-scan.d.ts +35 -0
  21. package/dist/js-scan.d.ts.map +1 -0
  22. package/dist/js-scan.js +124 -0
  23. package/dist/js-scan.js.map +1 -0
  24. package/dist/meta-nav.d.ts +29 -0
  25. package/dist/meta-nav.d.ts.map +1 -0
  26. package/dist/meta-nav.js +194 -0
  27. package/dist/meta-nav.js.map +1 -0
  28. package/dist/mintlify-nav.d.ts +31 -0
  29. package/dist/mintlify-nav.d.ts.map +1 -0
  30. package/dist/mintlify-nav.js +418 -0
  31. package/dist/mintlify-nav.js.map +1 -0
  32. package/dist/mintlify-openapi.d.ts +107 -0
  33. package/dist/mintlify-openapi.d.ts.map +1 -0
  34. package/dist/mintlify-openapi.js +357 -0
  35. package/dist/mintlify-openapi.js.map +1 -0
  36. package/dist/mintlify.d.ts +3 -0
  37. package/dist/mintlify.d.ts.map +1 -0
  38. package/dist/mintlify.js +196 -0
  39. package/dist/mintlify.js.map +1 -0
  40. package/dist/nav-extract.d.ts +43 -0
  41. package/dist/nav-extract.d.ts.map +1 -0
  42. package/dist/nav-extract.js +135 -0
  43. package/dist/nav-extract.js.map +1 -0
  44. package/dist/parse.d.ts +100 -4
  45. package/dist/parse.d.ts.map +1 -1
  46. package/dist/parse.js +1228 -149
  47. package/dist/parse.js.map +1 -1
  48. package/dist/ts-type-block.d.ts +43 -0
  49. package/dist/ts-type-block.d.ts.map +1 -0
  50. package/dist/ts-type-block.js +164 -0
  51. package/dist/ts-type-block.js.map +1 -0
  52. package/package.json +10 -8
@@ -0,0 +1,357 @@
1
+ /**
2
+ * Mintlify OpenAPI page generation.
3
+ *
4
+ * A Mintlify API-reference page is often just frontmatter — no body:
5
+ *
6
+ * ---
7
+ * openapi: post /partners/ban
8
+ * sidebarTitle: Ban partner
9
+ * ---
10
+ *
11
+ * The page content (endpoint card, params, request/response) is generated by
12
+ * Mintlify from the OpenAPI spec declared in `docs.json` (`api.openapi`, a URL
13
+ * or a local file). Without resolving that directive, every such page imports
14
+ * blank. This module reads the spec once and hands back the `endpoint` TreeNode
15
+ * for a given `METHOD path`, reusing `@dogsbay/format-openapi` (which already
16
+ * maps operations to endpoint nodes the Astro serializer renders as full API
17
+ * pages).
18
+ */
19
+ import { existsSync, readFileSync, realpathSync } from "node:fs";
20
+ import { join, resolve as resolvePath, dirname, basename, sep } from "node:path";
21
+ import { parseOpenApiSpec } from "@dogsbay/format-openapi";
22
+ const HTTP_METHODS = new Set([
23
+ "get",
24
+ "post",
25
+ "put",
26
+ "patch",
27
+ "delete",
28
+ "head",
29
+ "options",
30
+ "trace",
31
+ ]);
32
+ /**
33
+ * The OpenAPI spec reference declared in a Mintlify config, or null. Reads
34
+ * `docs.json` / `mint.json` `api.openapi` (string, or first of an array) and the
35
+ * legacy top-level `openapi`. Only an `http(s)://` value is a URL; everything
36
+ * else — including a ROOT-relative path like `/api-reference/openapi.json`,
37
+ * which Mintlify resolves against the docs root, not the filesystem root — is
38
+ * resolved against `source`.
39
+ */
40
+ export function mintlifyOpenApiSpecRef(source) {
41
+ const config = readConfig(source);
42
+ if (!config)
43
+ return null;
44
+ const ref = firstString(config.api?.openapi) ?? firstString(config.openapi) ?? null;
45
+ return ref ? resolveSpecRef(source, ref) : null;
46
+ }
47
+ /** Is `abs` inside `root` once symlinks are resolved? Separator-aware. */
48
+ function withinRoot(abs, root) {
49
+ const real = (p) => {
50
+ try {
51
+ return realpathSync(p);
52
+ }
53
+ catch {
54
+ const parent = dirname(p);
55
+ return parent === p ? p : join(real(parent), basename(p));
56
+ }
57
+ };
58
+ const realRoot = real(resolvePath(root));
59
+ const realAbs = real(resolvePath(abs));
60
+ return realAbs === realRoot || realAbs.startsWith(realRoot + sep);
61
+ }
62
+ /**
63
+ * A spec ref → a URL, a source-relative filesystem path, or null when it is
64
+ * not allowed.
65
+ *
66
+ * Two refusals, both silent-by-default before:
67
+ *
68
+ * - **Escaping the corpus.** `join(source, ref.replace(/^\//, ""))` strips a
69
+ * leading slash but leaves `../` intact, so `openapi: "/../../secrets.json
70
+ * GET /x"` read a file outside the docs root and put its contents into the
71
+ * imported page. The check now compares realpaths and requires a separator,
72
+ * matching the include resolver in `cli/src/commands/convert.ts`.
73
+ * - **A page naming a URL.** Only a config-declared spec may be fetched. A
74
+ * page-declared `https://…` made the converter issue a request from
75
+ * wherever it runs — a CI runner or a hosted service sits inside a network
76
+ * the repo's author cannot otherwise reach.
77
+ */
78
+ function resolveSpecRef(source, ref, origin = "config") {
79
+ if (/^https?:\/\//.test(ref)) {
80
+ if (origin === "page") {
81
+ console.warn(` warning: ignoring OpenAPI spec URL declared in page frontmatter ` +
82
+ `(${ref}) — only docs.json/mint.json may name a remote spec.`);
83
+ return null;
84
+ }
85
+ return ref;
86
+ }
87
+ const abs = join(source, ref.replace(/^\//, ""));
88
+ if (!withinRoot(abs, source)) {
89
+ console.warn(` warning: ignoring OpenAPI spec path that escapes the docs root (${ref}).`);
90
+ return null;
91
+ }
92
+ return abs;
93
+ }
94
+ /**
95
+ * Fetch the raw spec document, unparsed.
96
+ *
97
+ * An OpenAPI spec is a CANONICAL SOURCE ARTIFACT, not prose: round-tripping it
98
+ * through the TreeNode IR is lossy by construction ($ref/component schemas
99
+ * inline, security schemes and callbacks vanish). Exporters that can consume a
100
+ * spec directly should pass THIS through rather than rebuild it from endpoint
101
+ * nodes. Returns null when the spec cannot be read.
102
+ */
103
+ export async function readOpenApiSpecSource(specRef) {
104
+ try {
105
+ let text;
106
+ if (/^https?:\/\//.test(specRef)) {
107
+ const res = await fetch(specRef, { signal: AbortSignal.timeout(30_000) });
108
+ if (!res.ok)
109
+ return null;
110
+ text = await res.text();
111
+ }
112
+ else {
113
+ text = readFileSync(specRef, "utf-8");
114
+ }
115
+ const base = specRef.split(/[?#]/)[0].split("/").pop() || "openapi";
116
+ const filename = /\.(json|ya?ml)$/i.test(base)
117
+ ? base
118
+ : `${base}.${text.trimStart().startsWith("{") ? "json" : "yaml"}`;
119
+ return { text, filename };
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ /**
126
+ * Parse a spec into an endpoint map. A fetch/parse error must degrade to blank
127
+ * pages (never crash the import), but is reported via `loadError` rather than
128
+ * silently swallowed.
129
+ */
130
+ export async function buildMintlifyEndpointMap(specRef) {
131
+ const map = new Map();
132
+ try {
133
+ const { pages } = await parseOpenApiSpec(specRef);
134
+ for (const page of pages) {
135
+ const ep = page.tree.find((n) => n.type === "endpoint");
136
+ if (!ep)
137
+ continue;
138
+ const method = String(ep.props?.method ?? "").toLowerCase();
139
+ const path = String(ep.props?.path ?? "");
140
+ if (method && path)
141
+ map.set(`${method} ${path}`, [ep]);
142
+ }
143
+ return { map, loadError: null };
144
+ }
145
+ catch (err) {
146
+ return { map, loadError: err instanceof Error ? err.message : String(err) };
147
+ }
148
+ }
149
+ /**
150
+ * Normalise a page's `openapi` frontmatter value to a map key, or null when the
151
+ * page is not an OpenAPI page. Accepts `"post /partners/ban"` (method + path);
152
+ * a leading named-spec token (`"api POST /x"`) is tolerated by taking the last
153
+ * two whitespace-separated tokens.
154
+ */
155
+ export function openApiPageKey(value) {
156
+ if (typeof value !== "string")
157
+ return null;
158
+ const parts = value.trim().split(/\s+/);
159
+ if (parts.length < 2)
160
+ return null;
161
+ const path = parts[parts.length - 1];
162
+ const method = parts[parts.length - 2].toLowerCase();
163
+ if (!HTTP_METHODS.has(method))
164
+ return null;
165
+ if (!path.startsWith("/"))
166
+ return null;
167
+ return `${method} ${path}`;
168
+ }
169
+ /**
170
+ * The spec a PAGE names in its own `openapi:` frontmatter, or null.
171
+ *
172
+ * Mintlify lets a page point at a specific spec inline:
173
+ *
174
+ * openapi: "/openapi.json GET /project/update-status/{statusId}"
175
+ *
176
+ * `openApiPageKey` already tolerates that leading token (it takes the last two
177
+ * tokens); this reads the token itself, which nothing did. A site whose
178
+ * `docs.json` has no `api.openapi` key therefore resolved NO endpoints even
179
+ * though every page stated exactly which spec to use — measured on Mintlify's
180
+ * own documentation: 100 pages imported without their endpoint content and 20
181
+ * of them came out completely blank, next to an `openapi.json` sitting in the
182
+ * repo root.
183
+ *
184
+ * Resolved the same way as a config-declared ref: a leading `/` is the DOCS
185
+ * root, not the filesystem root.
186
+ */
187
+ export function openApiPageSpecRef(source, value) {
188
+ if (typeof value !== "string")
189
+ return null;
190
+ const parts = value.trim().split(/\s+/);
191
+ // Three tokens minimum: <spec> <METHOD> <path>. Two is method+path with no
192
+ // spec, which is the config-declared case.
193
+ if (parts.length < 3)
194
+ return null;
195
+ const ref = parts[0];
196
+ // Only treat it as a spec when it looks like one — a URL, a path, or a
197
+ // json/yaml filename. Anything else is a NAMED spec (Mintlify also allows
198
+ // `openapi: "api POST /x"` referring to a named entry), which this does not
199
+ // resolve and which the existing key parser already tolerates.
200
+ const looksLikeSpec = /^https?:\/\//.test(ref) || ref.startsWith("/") || /\.(json|ya?ml)$/i.test(ref);
201
+ return looksLikeSpec ? resolveSpecRef(source, ref, "page") : null;
202
+ }
203
+ /**
204
+ * The vault/site slug for a nav-referenced OpenAPI operation (a `pages` string
205
+ * of the form `"POST /api/generate"` under a tab/group that declares an
206
+ * `openapi` spec). The NAV and the GENERATED PAGE both call this, so their
207
+ * href and slug always agree. Path-based (`/api/generate` → `api/generate`) for
208
+ * clean URLs; same-path-different-method operations would collide — rare, and
209
+ * documented (ollama and typical REST doc sets use unique paths per page).
210
+ */
211
+ export function openApiRefSlug(path) {
212
+ return path.replace(/^\//, "").replace(/\/$/, "");
213
+ }
214
+ /**
215
+ * Every distinct OpenAPI spec a Mintlify config references — the top-level
216
+ * `api.openapi` AND any `openapi` declared on a nav container (tab/group).
217
+ *
218
+ * Both are real source artifacts. Capturing only the top-level one meant a site
219
+ * like ollama (whose spec is declared on an "API Reference" tab) fell back to
220
+ * lossy reconstruction despite having a perfectly good spec on disk.
221
+ */
222
+ export function collectMintlifyOpenApiSpecRefs(source,
223
+ /** Spec refs named by individual pages' `openapi:` frontmatter. */
224
+ pageSpecRefs = []) {
225
+ const config = readConfig(source);
226
+ const refs = new Set(pageSpecRefs);
227
+ if (!config)
228
+ return [...refs];
229
+ const top = firstString(config.api?.openapi) ?? firstString(config.openapi);
230
+ const topResolved = top ? resolveSpecRef(source, top) : null;
231
+ if (topResolved)
232
+ refs.add(topResolved);
233
+ if (config.navigation) {
234
+ const found = new Map();
235
+ walkForOpenApiRefs(config.navigation, undefined, source, found);
236
+ for (const ref of found.keys())
237
+ refs.add(ref);
238
+ }
239
+ return [...refs];
240
+ }
241
+ /**
242
+ * Generate an ExportPage for every OpenAPI operation referenced ONLY by the nav
243
+ * (a `METHOD /path` `pages` string under a container that declares `openapi`) —
244
+ * these pages exist in no `.mdx` file (unlike the frontmatter case), so without
245
+ * this the nav links are dead and the API section is empty. ollama's docs.json
246
+ * is exactly this shape (an "Endpoints" group of 12 such strings under a tab
247
+ * with `openapi: /openapi.yaml`).
248
+ */
249
+ export async function collectMintlifyOpenApiNavPages(source) {
250
+ const config = readConfig(source);
251
+ if (!config?.navigation)
252
+ return { pages: [], loadError: null };
253
+ const globalSpec = firstString(config.api?.openapi) ?? firstString(config.openapi);
254
+ // refs: specRef → set of "method path" keys referenced under it.
255
+ const refs = new Map();
256
+ walkForOpenApiRefs(config.navigation, globalSpec, source, refs);
257
+ if (refs.size === 0)
258
+ return { pages: [], loadError: null };
259
+ const pages = [];
260
+ const seen = new Set();
261
+ let loadError = null;
262
+ for (const [specRef, keys] of refs) {
263
+ const { map, loadError: err } = await buildMintlifyEndpointMap(specRef);
264
+ if (err)
265
+ loadError = err;
266
+ for (const key of keys) {
267
+ const endpoint = map.get(key);
268
+ if (!endpoint)
269
+ continue;
270
+ const path = key.slice(key.indexOf(" ") + 1);
271
+ const slug = openApiRefSlug(path);
272
+ if (seen.has(slug))
273
+ continue;
274
+ seen.add(slug);
275
+ const ep = endpoint[0];
276
+ const title = ep.props?.summary ||
277
+ `${String(ep.props?.method ?? "").toUpperCase()} ${path}`;
278
+ pages.push({ slug, title, tree: endpoint, headings: [] });
279
+ }
280
+ }
281
+ return { pages, loadError };
282
+ }
283
+ /** Walk a navigation node, tracking the inherited `openapi` spec, collecting
284
+ * `METHOD /path` page strings keyed by their governing (resolved) spec ref. */
285
+ function walkForOpenApiRefs(node, inheritedSpec, source, out, inPages = false) {
286
+ if (Array.isArray(node)) {
287
+ for (const e of node)
288
+ walkForOpenApiRefs(e, inheritedSpec, source, out, inPages);
289
+ return;
290
+ }
291
+ if (!node || typeof node !== "object") {
292
+ // A bare `METHOD /path` string — ONLY meaningful inside a `pages` array.
293
+ // Scanning every string made prose like `"See POST /users"` in a tab
294
+ // description generate a phantom API page.
295
+ if (!inPages)
296
+ return;
297
+ const key = typeof node === "string" ? openApiPageKey(node) : null;
298
+ if (key && inheritedSpec) {
299
+ const resolved = resolveSpecRef(source, inheritedSpec);
300
+ if (resolved) {
301
+ if (!out.has(resolved))
302
+ out.set(resolved, new Set());
303
+ out.get(resolved).add(key);
304
+ }
305
+ }
306
+ return;
307
+ }
308
+ const declared = firstString(node.openapi);
309
+ const spec = declared ?? inheritedSpec;
310
+ // A container that DECLARES a spec registers it even when its children are
311
+ // ordinary .mdx pages — otherwise a nav-declared spec was only captured when
312
+ // a `METHOD /path` string happened to sit under it.
313
+ if (declared) {
314
+ const resolved = resolveSpecRef(source, declared);
315
+ if (resolved && !out.has(resolved))
316
+ out.set(resolved, new Set());
317
+ }
318
+ for (const [key, v] of Object.entries(node)) {
319
+ if (v && typeof v === "object") {
320
+ walkForOpenApiRefs(v, spec, source, out, key === "pages" || inPages);
321
+ }
322
+ else if (typeof v === "string" && key === "pages") {
323
+ walkForOpenApiRefs(v, spec, source, out, true);
324
+ }
325
+ }
326
+ }
327
+ function readConfig(source) {
328
+ for (const name of ["docs.json", "mint.json"]) {
329
+ const p = join(source, name);
330
+ if (existsSync(p)) {
331
+ try {
332
+ return JSON.parse(readFileSync(p, "utf-8"));
333
+ }
334
+ catch {
335
+ return null;
336
+ }
337
+ }
338
+ }
339
+ return null;
340
+ }
341
+ function firstString(v) {
342
+ if (typeof v === "string" && v.length > 0)
343
+ return v;
344
+ if (Array.isArray(v)) {
345
+ for (const e of v) {
346
+ const s = firstString(typeof e === "object" && e ? e.openapi ?? e.source : e);
347
+ if (s)
348
+ return s;
349
+ }
350
+ }
351
+ if (v && typeof v === "object") {
352
+ // `api.openapi` may be `{ source: "..." }` in some configs.
353
+ return firstString(v.source ?? v.openapi);
354
+ }
355
+ return undefined;
356
+ }
357
+ //# sourceMappingURL=mintlify-openapi.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mintlify-openapi.js","sourceRoot":"","sources":["../src/mintlify-openapi.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { MdxAdapter } from "./adapter.js";
2
+ export declare const mintlifyAdapter: MdxAdapter;
3
+ //# sourceMappingURL=mintlify.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mintlify.d.ts","sourceRoot":"","sources":["../src/mintlify.ts"],"names":[],"mappings":"AAoBA,OAAO,KAAK,EAAoB,UAAU,EAAE,MAAM,cAAc,CAAC;AA8KjE,eAAO,MAAM,eAAe,EAAE,UAoB7B,CAAC"}
@@ -0,0 +1,196 @@
1
+ /**
2
+ * `<Update label="2.1.218" description="July 22, 2026">` wraps every release
3
+ * in a Mintlify changelog, with the entries as ordinary markdown bullets
4
+ * inside.
5
+ *
6
+ * Unmapped it is PRESERVED as raw MDX, which means its inner markdown is
7
+ * never parsed — a 5,000-line changelog renders as one run-on paragraph of
8
+ * literal `*` characters (observed: 4,000+ bullets, zero list items). Mapping
9
+ * it with `children: "blocks"` is what makes the bullets parse.
10
+ *
11
+ * `details` rather than a callout: a changelog is hundreds of releases, and
12
+ * collapsing each one is the difference between a usable page and a wall.
13
+ * Both attributes ride into the title, because a version without its date
14
+ * loses the thing a reader scans for.
15
+ */
16
+ const update = {
17
+ type: "details",
18
+ container: true,
19
+ children: "blocks",
20
+ propsFromAttrs: (attrs) => {
21
+ const label = attrs.label?.trim();
22
+ const description = attrs.description?.trim();
23
+ const title = [label, description].filter(Boolean).join(" — ");
24
+ // `<Update>` also carries `tags={[…]}` and `rss={{ title, description }}`.
25
+ // Reading only label/description dropped them with no ledger entry, and on
26
+ // the raw path they had survived byte-exact — 71 tags on one changelog page
27
+ // alone. Carried through as props so the information is not lost; an
28
+ // exporter that has nowhere to put them declares that in its capabilities.
29
+ const extra = {};
30
+ for (const key of ["tags", "rss"]) {
31
+ const value = attrs[key]?.trim();
32
+ if (value)
33
+ extra[key] = value;
34
+ }
35
+ return { variant: "note", ...(title ? { title } : {}), ...extra };
36
+ },
37
+ };
38
+ /**
39
+ * Self-closing marketing/experiment wrappers. Both carry NO documentation
40
+ * content — `<ContactSalesCard surface="bedrock" />` is a CTA, and
41
+ * `<Experiment flag="…" treatment={<ContactSalesCard …/>} />` is an A/B
42
+ * wrapper whose treatment is that same CTA.
43
+ *
44
+ * They were already being dropped by the built-in strip list; declaring them
45
+ * here makes the drop an ADAPTER DECISION recorded in the ledger, rather than
46
+ * a side effect of a component nobody had considered.
47
+ */
48
+ /**
49
+ * `container: true` matches the BUILTIN strip entries for the same tags
50
+ * (`parse.ts` AgentInstructions/Experiment/ContactSalesCard). With
51
+ * `container: false` a paired `<Experiment>…</Experiment>` had its body kept
52
+ * and a stray `</Experiment>` html node leaked into the tree — invisible while
53
+ * the adapter was opt-in, and the default for every Mintlify site once adapter
54
+ * auto-selection landed.
55
+ */
56
+ const stripped = { type: "", container: true, strip: true };
57
+ /**
58
+ * `<ParamField body="url" type="string" required>` / `<ResponseField …>` — the
59
+ * parameter vocabulary of every hand-written Mintlify API page.
60
+ *
61
+ * Unmapped these were PRESERVED as `mdx-raw`, which is honest but not useful:
62
+ * an exporter that cannot render `<ParamField>` strips the tag and keeps only
63
+ * the description, so the reader is left with a page of unattributed sentences
64
+ * — the parameter NAME, TYPE, REQUIRED flag and DEFAULT all vanish. On the dub
65
+ * corpus that is 331 fields across the API reference.
66
+ *
67
+ * The mapping is evidence-backed, not guessed: the attribute set is fixed and
68
+ * documented, and the name arrives in whichever of `body`/`query`/`path`/
69
+ * `header` names the location — so the location is real information too, and
70
+ * rides into the term rather than being discarded.
71
+ *
72
+ * `deflist` because that IS the shape: a term (the parameter) and its
73
+ * definition (the prose). Every exporter already handles it, and the ones that
74
+ * lack a definition-list syntax degrade it visibly (bold term + indented body)
75
+ * rather than dropping it.
76
+ */
77
+ const PARAM_LOCATIONS = ["body", "query", "path", "header"];
78
+ /**
79
+ * `<Expandable title="properties">` wraps the NESTED fields of an object
80
+ * parameter. Unmapped it was preserved as raw MDX, so every exporter that
81
+ * cannot render it stripped the tag and orphaned the children — on dub that is
82
+ * 198 of 458 fields (43%), and 568 of 1753 (32%) on mintlify-docs, each losing
83
+ * its name and type exactly like the top-level fields did before ParamField
84
+ * was mapped.
85
+ *
86
+ * It has no content of its own beyond the title, so it UNWRAPS: its children
87
+ * are already `deflist`s and belong in the flow. The nesting is conveyed by the
88
+ * dotted field names Mintlify authors use (`user.name`), so flattening reads
89
+ * correctly rather than losing a distinction.
90
+ */
91
+ const expandable = {
92
+ type: "",
93
+ container: true,
94
+ toNode: (_attrs, innerSource, ctx) => ctx.parseBlocks(innerSource),
95
+ };
96
+ const paramField = {
97
+ type: "deflist",
98
+ container: true,
99
+ toNode: (attrs, innerSource, ctx) => {
100
+ const location = PARAM_LOCATIONS.find((k) => attrs[k] !== undefined);
101
+ const name = (location ? attrs[location] : attrs.name) ?? "";
102
+ if (!name)
103
+ return "preserve";
104
+ const bits = [];
105
+ if (attrs.type)
106
+ bits.push(attrs.type);
107
+ if (location)
108
+ bits.push(location);
109
+ // A bare attribute arrives as the string "true".
110
+ if (attrs.required === "true" || attrs.required === "")
111
+ bits.push("required");
112
+ if (attrs.deprecated === "true" || attrs.deprecated === "")
113
+ bits.push("deprecated");
114
+ if (attrs.default)
115
+ bits.push(`default: ${attrs.default}`);
116
+ const body = ctx.parseBlocks(innerSource);
117
+ const dt = {
118
+ type: "dt",
119
+ inline: [
120
+ { type: "code", text: name },
121
+ ...(bits.length > 0 ? [{ type: "text", text: ` — ${bits.join(", ")}` }] : []),
122
+ ],
123
+ };
124
+ return {
125
+ type: "deflist",
126
+ children: [dt, ...(body.length > 0 ? [{ type: "dd", children: body }] : [])],
127
+ };
128
+ },
129
+ };
130
+ /**
131
+ * `<HeroCard filename title description href />` — a linked image card that
132
+ * Mintlify's own docs define IN THE PAGE:
133
+ *
134
+ * export const HeroCard = ({ filename, title, description, href }) => {
135
+ * return (<a href={href}><img src={…}/>…</a>)
136
+ * }
137
+ *
138
+ * The definition is a multi-statement arrow, so the snippet substitution that
139
+ * handles `props => (<JSX/>)` cannot expand it, and every USAGE fell through to
140
+ * `mdx-raw` — 32 of them across the corpus, each rendering as a code block of
141
+ * its own JSX on the site's front page.
142
+ *
143
+ * Mapped rather than expanded: a Dogsbay `card` carries the title, description
144
+ * and href faithfully. What is lost is the hero IMAGE, whose src is built by
145
+ * template-interpolating `filename` into a GitHub raw URL — that is JavaScript,
146
+ * and reconstructing it would hard-code one site's asset convention into a
147
+ * general adapter. The card is the content; the image was decoration.
148
+ */
149
+ /**
150
+ * IT DECLINES ANYTHING THAT IS NOT THAT SHAPE. `HeroCard` is not part of
151
+ * Mintlify's documented vocabulary the way `Update`/`ParamField`/`Expandable`
152
+ * are — it is a component one site defines in its own pages, and the name is
153
+ * generic enough that another site will define its own with different props
154
+ * (`image`, `cta`, `variant`). Coercing those into a card whose title and href
155
+ * are empty would be worse than leaving them raw, so an unrecognised shape
156
+ * returns "preserve" — byte-exact `mdx-raw` plus a ledger entry — and a site
157
+ * that wants its own mapping uses `--components`, which exists for exactly this.
158
+ */
159
+ const heroCard = {
160
+ type: "card",
161
+ container: false,
162
+ toNode: (attrs) => {
163
+ const title = attrs.title?.trim();
164
+ const href = attrs.href?.trim();
165
+ // The documented shape carries at least a title and a destination.
166
+ if (!title || !href)
167
+ return "preserve";
168
+ const description = attrs.description?.trim();
169
+ return {
170
+ type: "card",
171
+ props: { title, href, ...(description ? { description } : {}) },
172
+ };
173
+ },
174
+ };
175
+ export const mintlifyAdapter = {
176
+ name: "mintlify",
177
+ components: {
178
+ HeroCard: heroCard,
179
+ Update: update,
180
+ ParamField: paramField,
181
+ Expandable: expandable,
182
+ ResponseField: paramField,
183
+ ContactSalesCard: stripped,
184
+ Experiment: stripped,
185
+ },
186
+ // NOT self-closing, despite an earlier note here saying so. The segmenter
187
+ // decides pairing from THIS list, not from a mapping's `container` flag, so
188
+ // declaring them self-closing meant `<Experiment name="x">…</Experiment>`
189
+ // was never paired: the body stayed in the page and the stray closing tag
190
+ // was emitted as raw HTML, while the ledger recorded it as "stripped".
191
+ // Flipping `container: true` on the mapping did not fix it, because nothing
192
+ // reads `container` at segmentation time. The builtin (no-adapter) path
193
+ // handled these correctly, so the declaration was a regression against it.
194
+ selfClosingTags: [],
195
+ };
196
+ //# sourceMappingURL=mintlify.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mintlify.js","sourceRoot":"","sources":["../src/mintlify.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Static sidebar extraction from a hardcoded Fumadocs page tree.
3
+ *
4
+ * Passing a hand-built `PageTree.Root` to `DocsLayout tree={…}` is a
5
+ * documented first-class Fumadocs pattern; sites that use it (better-auth's
6
+ * sidebar-content.tsx) keep the REAL sidebar in a TSX data literal and let
7
+ * meta.json go stale. Page trees must be serializable by design, so the
8
+ * literal is statically readable: this module captures the exported array
9
+ * and maps it to NavItem[] — no execution, ever (icons and other JSX
10
+ * values ride through the balanced scanner and are dropped).
11
+ *
12
+ * The mapping is shape-tolerant rather than better-auth-specific: an entry
13
+ * contributes a nav item when it has a string `title`/`name`/`label`;
14
+ * `href`/`url` become the link; the first array-valued key among
15
+ * `list`/`subpages`/`children`/`items`/`pages` becomes the children.
16
+ *
17
+ * Href prefix: sites hardcode their mount point (`/docs/introduction`).
18
+ * When every internal href shares the same first path segment it is
19
+ * stripped and replaced with the importer's own `hrefPrefix` (auto-detected
20
+ * — pass `stripPrefix` to override).
21
+ */
22
+ import type { NavItem } from "@dogsbay/types";
23
+ export interface NavExtractOptions {
24
+ /** Name of the exported array (default "contents"). */
25
+ exportName?: string;
26
+ /** Prefix for emitted hrefs (e.g. "/docs" of the TARGET site). */
27
+ hrefPrefix?: string;
28
+ /**
29
+ * Leading path segment to strip from the source's hardcoded hrefs
30
+ * (e.g. "/docs"). Auto-detected when omitted: stripped when every
31
+ * internal href shares the same first segment.
32
+ */
33
+ stripPrefix?: string;
34
+ }
35
+ /**
36
+ * Extract NavItem[] from TSX source containing an exported data-literal
37
+ * page tree. Returns null when the export is missing or doesn't scan —
38
+ * callers fall back to the meta.json walk (never guess).
39
+ */
40
+ export declare function extractNavFromTsx(source: string, opts?: NavExtractOptions): NavItem[] | null;
41
+ /** File-reading convenience for the CLI layer. */
42
+ export declare function extractNavFromTsxFile(filePath: string, opts?: NavExtractOptions): NavItem[] | null;
43
+ //# sourceMappingURL=nav-extract.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nav-extract.d.ts","sourceRoot":"","sources":["../src/nav-extract.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAGH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAI9C,MAAM,WAAW,iBAAiB;IAChC,uDAAuD;IACvD,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,kEAAkE;IAClE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;OAIG;IACH,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB;AAmFD;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,MAAM,EAAE,MAAM,EACd,IAAI,GAAE,iBAAsB,GAC3B,OAAO,EAAE,GAAG,IAAI,CA6BlB;AAED,kDAAkD;AAClD,wBAAgB,qBAAqB,CACnC,QAAQ,EAAE,MAAM,EAChB,IAAI,GAAE,iBAAsB,GAC3B,OAAO,EAAE,GAAG,IAAI,CAMlB"}