fumadocs-mdx 11.4.1 → 11.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -161,9 +161,17 @@ __export(watcher_exports, {
161
161
  });
162
162
  function watcher(configPath, config) {
163
163
  const deps = [configPath];
164
+ function add(dir) {
165
+ if (Array.isArray(dir)) deps.push(...dir);
166
+ else deps.push(dir);
167
+ }
164
168
  for (const collection of config.collections.values()) {
165
- if (Array.isArray(collection.dir)) deps.push(...collection.dir);
166
- else deps.push(collection.dir);
169
+ if (collection.type === "docs") {
170
+ add(collection.docs.dir);
171
+ add(collection.meta.dir);
172
+ } else {
173
+ add(collection.dir);
174
+ }
167
175
  }
168
176
  return (0, import_chokidar.watch)(deps, {
169
177
  ignoreInitial: true,
@@ -202,12 +210,15 @@ function buildConfig(config) {
202
210
  if (!v) {
203
211
  continue;
204
212
  }
205
- if (typeof v === "object" && "_doc" in v && v._doc === "collections") {
206
- collections.set(
207
- k,
208
- v
209
- );
210
- continue;
213
+ if (typeof v === "object" && "type" in v) {
214
+ if (v.type === "docs") {
215
+ collections.set(k, v);
216
+ continue;
217
+ }
218
+ if (v.type === "doc" || v.type === "meta") {
219
+ collections.set(k, v);
220
+ continue;
221
+ }
211
222
  }
212
223
  if (k === "default") {
213
224
  globalConfig = v;
@@ -277,9 +288,8 @@ async function loadConfig(configPath) {
277
288
 
278
289
  // src/map/index.ts
279
290
  var path3 = __toESM(require("path"), 1);
280
- var fs2 = __toESM(require("fs"), 1);
291
+ var fs3 = __toESM(require("fs"), 1);
281
292
  var import_promises = require("fs/promises");
282
- var import_gray_matter = __toESM(require("gray-matter"), 1);
283
293
 
284
294
  // src/utils/config-cache.ts
285
295
  var import_node_crypto = require("crypto");
@@ -320,65 +330,89 @@ function getTypeFromPath(path6) {
320
330
  // src/map/generate.ts
321
331
  async function generateJS(configPath, config, outputPath, configHash, getFrontmatter) {
322
332
  const outDir2 = path2.dirname(outputPath);
323
- const imports = [
324
- {
333
+ let asyncInit = false;
334
+ const lines = [
335
+ getImportCode({
325
336
  type: "named",
326
- names: ["toRuntime"],
337
+ names: ["_runtime"],
327
338
  specifier: "fumadocs-mdx"
328
- }
339
+ }),
340
+ getImportCode({
341
+ type: "namespace",
342
+ specifier: toImportPath(configPath, outDir2),
343
+ name: "_source"
344
+ })
329
345
  ];
330
- let asyncInit = false;
331
- const lines = [];
332
346
  config._runtime.files.clear();
333
347
  const entries = Array.from(config.collections.entries());
348
+ async function getEntries(collectionName, collection, files) {
349
+ const items = files.map(async (file, i) => {
350
+ config._runtime.files.set(file.absolutePath, collectionName);
351
+ const importId = `${collectionName}_${collection.type}_${i}`;
352
+ lines.unshift(
353
+ getImportCode({
354
+ type: "namespace",
355
+ name: importId,
356
+ specifier: `${toImportPath(file.absolutePath, outDir2)}?collection=${collectionName}&hash=${configHash}`
357
+ })
358
+ );
359
+ return `{ info: ${JSON.stringify(file)}, data: ${importId} }`;
360
+ });
361
+ return Promise.all(items);
362
+ }
363
+ async function getAsyncEntries(files) {
364
+ if (!asyncInit) {
365
+ lines.unshift(
366
+ getImportCode({
367
+ type: "named",
368
+ specifier: "fumadocs-mdx/runtime/async",
369
+ names: ["_runtimeAsync", "buildConfig"]
370
+ }),
371
+ "const [err, _sourceConfig] = buildConfig(_source)",
372
+ "if (!_sourceConfig) throw new Error(err)"
373
+ );
374
+ asyncInit = true;
375
+ }
376
+ const entries2 = files.map(async (file) => {
377
+ const frontmatter = await getFrontmatter(file.absolutePath);
378
+ return JSON.stringify({
379
+ info: file,
380
+ data: frontmatter
381
+ });
382
+ });
383
+ return Promise.all(entries2);
384
+ }
334
385
  const declares = entries.map(async ([k, collection]) => {
335
- const files = await getCollectionFiles(collection);
336
- if (collection.type === "doc" && collection.async) {
337
- if (!asyncInit) {
338
- imports.push(
339
- {
340
- type: "namespace",
341
- specifier: toImportPath(configPath, outDir2),
342
- name: "_source"
343
- },
344
- {
345
- type: "named",
346
- specifier: "fumadocs-mdx/runtime/async",
347
- names: ["asyncFiles", "buildConfig"]
348
- }
349
- );
350
- lines.unshift(
351
- "const [err, _sourceConfig] = buildConfig(_source)",
352
- "if (err) throw new Error(err)"
386
+ if (collection.type === "docs") {
387
+ const docs = await getCollectionFiles(collection.docs);
388
+ const metas = await getCollectionFiles(collection.meta);
389
+ if (collection.docs.async) {
390
+ const docsEntries2 = (await getAsyncEntries(docs)).join(", ");
391
+ const metaEntries2 = (await getEntries(k, collection.meta, metas)).join(
392
+ ", "
353
393
  );
354
- asyncInit = true;
394
+ return `export const ${k} = _runtimeAsync.docs<typeof _source.${k}>([${docsEntries2}], [${metaEntries2}], "${k}", _sourceConfig)`;
355
395
  }
356
- const entries2 = files.map(async (file) => {
357
- const frontmatter = await getFrontmatter(file.absolutePath);
358
- return JSON.stringify({
359
- frontmatter,
360
- file
361
- });
362
- });
363
- return `export const ${k} = asyncFiles([${(await Promise.all(entries2)).join(", ")}], "${k}", _sourceConfig)`;
396
+ const docsEntries = (await getEntries(k, collection.docs, docs)).join(
397
+ ", "
398
+ );
399
+ const metaEntries = (await getEntries(k, collection.meta, metas)).join(
400
+ ", "
401
+ );
402
+ return `export const ${k} = _runtime.docs<typeof _source.${k}>([${docsEntries}], [${metaEntries}])`;
364
403
  }
365
- const items = files.map(async (file, i) => {
366
- config._runtime.files.set(file.absolutePath, k);
367
- const importId = `${k}_${i}`;
368
- imports.push({
369
- type: "namespace",
370
- name: importId,
371
- specifier: `${toImportPath(file.absolutePath, outDir2)}?collection=${k}&hash=${configHash}`
372
- });
373
- return `toRuntime("${collection.type}", ${importId}, ${JSON.stringify(file)})`;
374
- });
375
- const resolvedItems = await Promise.all(items);
376
- return `export const ${k} = [${resolvedItems.join(", ")}];`;
404
+ const files = await getCollectionFiles(collection);
405
+ if (collection.type === "doc" && collection.async) {
406
+ return `export const ${k} = _runtimeAsync.doc<typeof _source.${k}>([${(await getAsyncEntries(files)).join(", ")}], "${k}", _sourceConfig)`;
407
+ }
408
+ return `export const ${k} = _runtime.${collection.type}<typeof _source.${k}>([${(await getEntries(k, collection, files)).join(", ")}]);`;
377
409
  });
378
410
  const resolvedDeclares = await Promise.all(declares);
379
- return [...imports.map(getImportCode), ...lines, ...resolvedDeclares].join(
380
- "\n"
381
- );
411
+ return [
412
+ `// @ts-nocheck -- skip type checking`,
413
+ ...lines,
414
+ ...resolvedDeclares
415
+ ].join("\n");
382
416
  }
383
417
  async function getCollectionFiles(collection) {
384
418
  const files = /* @__PURE__ */ new Map();
@@ -414,76 +448,72 @@ function getImportCode(info) {
414
448
  return `import ${specifier}`;
415
449
  }
416
450
  function toImportPath(file, dir) {
417
- let importPath = path2.relative(dir, file);
451
+ const ext = path2.extname(file);
452
+ let importPath = path2.relative(
453
+ dir,
454
+ ext === ".ts" ? file.substring(0, file.length - ext.length) : file
455
+ );
418
456
  if (!path2.isAbsolute(importPath) && !importPath.startsWith(".")) {
419
457
  importPath = `./${importPath}`;
420
458
  }
421
459
  return importPath.replaceAll(path2.sep, "/");
422
460
  }
423
- function generateTypes(configPath, config, outputPath) {
424
- const importPath = JSON.stringify(
425
- toImportPath(configPath, path2.dirname(outputPath))
426
- );
427
- const lines = [
428
- 'import type { GetOutput } from "fumadocs-mdx/config"'
429
- ];
430
- for (const name of config.collections.keys()) {
431
- lines.push(
432
- `export declare const ${name}: GetOutput<typeof import(${importPath}).${name}>`
433
- );
434
- }
435
- return lines.join("\n");
461
+
462
+ // src/utils/read-frontmatter.ts
463
+ var fs2 = __toESM(require("fs"), 1);
464
+ var import_gray_matter = __toESM(require("gray-matter"), 1);
465
+ async function readFrontmatter(file) {
466
+ const readStream = fs2.createReadStream(file, {
467
+ highWaterMark: 250
468
+ });
469
+ return new Promise((res, rej) => {
470
+ let idx = 0;
471
+ let str = "";
472
+ readStream.on("data", (_chunk) => {
473
+ const chunk = _chunk.toString();
474
+ if (idx === 0 && !chunk.startsWith("---")) {
475
+ res({});
476
+ readStream.close();
477
+ return;
478
+ }
479
+ str += chunk;
480
+ idx++;
481
+ if (str.includes("\n---")) {
482
+ res(
483
+ (0, import_gray_matter.default)({
484
+ content: str
485
+ }).data
486
+ );
487
+ readStream.close();
488
+ }
489
+ });
490
+ readStream.on("end", () => res({}));
491
+ readStream.on("error", (e) => rej(e));
492
+ });
436
493
  }
437
494
 
438
495
  // src/map/index.ts
439
496
  async function start(dev, configPath, outDir2) {
497
+ void (0, import_promises.rm)(path3.resolve(outDir2, `index.js`), { force: true });
498
+ void (0, import_promises.rm)(path3.resolve(outDir2, `index.d.ts`), { force: true });
440
499
  let configHash = await getConfigHash(configPath);
441
500
  let config = await loadConfigCached(configPath, configHash);
442
- const jsOut = path3.resolve(outDir2, `index.js`);
443
- const typeOut = path3.resolve(outDir2, `index.d.ts`);
501
+ const outPath = path3.resolve(outDir2, `index.ts`);
444
502
  const frontmatterCache = /* @__PURE__ */ new Map();
445
503
  let hookUpdate = false;
446
- async function readFrontmatter(file) {
447
- hookUpdate = true;
448
- const cached = frontmatterCache.get(file);
449
- if (cached) return cached;
450
- const readStream = fs2.createReadStream(file, {
451
- highWaterMark: 250
452
- });
453
- return new Promise((res, rej) => {
454
- let idx = 0;
455
- let str = "";
456
- readStream.on("data", (_chunk) => {
457
- const chunk = _chunk.toString();
458
- if (idx === 0 && !chunk.startsWith("---")) {
459
- res({});
460
- readStream.close();
461
- return;
462
- }
463
- str += chunk;
464
- idx++;
465
- if (str.includes("\n---")) {
466
- res(
467
- (0, import_gray_matter.default)({
468
- content: str
469
- }).data
470
- );
471
- readStream.close();
472
- }
504
+ fs3.mkdirSync(outDir2, { recursive: true });
505
+ fs3.writeFileSync(
506
+ outPath,
507
+ await generateJS(configPath, config, outPath, configHash, (file) => {
508
+ hookUpdate = true;
509
+ const cached = frontmatterCache.get(file);
510
+ if (cached) return cached;
511
+ return readFrontmatter(file).then((res) => {
512
+ frontmatterCache.set(file, res);
513
+ return res;
473
514
  });
474
- readStream.on("end", () => res({}));
475
- readStream.on("error", (e) => rej(e));
476
- }).then((res) => {
477
- frontmatterCache.set(file, res);
478
- return res;
479
- });
480
- }
481
- fs2.mkdirSync(outDir2, { recursive: true });
482
- fs2.writeFileSync(
483
- jsOut,
484
- await generateJS(configPath, config, jsOut, configHash, readFrontmatter)
515
+ })
485
516
  );
486
- fs2.writeFileSync(typeOut, generateTypes(configPath, config, typeOut));
487
517
  console.log("[MDX] initialized map file");
488
518
  if (dev) {
489
519
  const { watcher: watcher2 } = await Promise.resolve().then(() => (init_watcher(), watcher_exports));
@@ -498,17 +528,15 @@ async function start(dev, configPath, outDir2) {
498
528
  if (isConfigFile) {
499
529
  configHash = await getConfigHash(configPath);
500
530
  config = await loadConfigCached(configPath, configHash);
501
- await (0, import_promises.writeFile)(typeOut, generateTypes(configPath, config, typeOut));
502
- console.log("[MDX] Updated map types");
503
531
  }
504
532
  if (isConfigFile || event !== "change" || hookUpdate) {
505
533
  if (event === "change") frontmatterCache.delete(file);
506
534
  await (0, import_promises.writeFile)(
507
- jsOut,
535
+ outPath,
508
536
  await generateJS(
509
537
  configPath,
510
538
  config,
511
- jsOut,
539
+ outPath,
512
540
  configHash,
513
541
  readFrontmatter
514
542
  )
@@ -588,12 +616,22 @@ function createMDX({
588
616
 
589
617
  // src/postinstall.ts
590
618
  var path5 = __toESM(require("path"), 1);
591
- var fs3 = __toESM(require("fs"), 1);
619
+ var fs4 = __toESM(require("fs"), 1);
592
620
  async function postInstall(configPath = findConfigFile()) {
593
- const typeOut = path5.resolve(".source/index.d.ts");
621
+ const jsOut = path5.resolve(".source/index.ts");
594
622
  const config = await loadConfig(configPath);
595
- fs3.mkdirSync(path5.dirname(typeOut), { recursive: true });
596
- fs3.writeFileSync(typeOut, generateTypes(configPath, config, typeOut));
623
+ const hash = await getConfigHash(configPath);
624
+ fs4.mkdirSync(path5.dirname(jsOut), { recursive: true });
625
+ fs4.writeFileSync(
626
+ jsOut,
627
+ await generateJS(
628
+ configPath,
629
+ config,
630
+ path5.resolve(".source/index.ts"),
631
+ hash,
632
+ readFrontmatter
633
+ )
634
+ );
597
635
  console.log("[MDX] types generated");
598
636
  }
599
637
  // Annotate the CommonJS export names for ESM import in node: