@mintlify/previewing 4.0.1495 → 4.0.1496

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.
@@ -70,10 +70,6 @@ const BAR_SNIPPET = `import { BarChart, Bar } from "recharts";
70
70
  <Bar dataKey="v" name="{{brand}} revenue" />
71
71
  </BarChart>
72
72
  `;
73
- const LINE_SNIPPET = `<LineChart width={400} height={200} data={[{ v: 2 }]}>
74
- <Line dataKey="v" isAnimationActive={false} />
75
- </LineChart>
76
- `;
77
73
  const writeDocs = async (root) => {
78
74
  await fse.outputJson(join(root, 'docs.json'), {
79
75
  name: 'Docs',
@@ -235,106 +231,20 @@ describe('collectPackageIslands', () => {
235
231
  expect(compiled.mdxExtracts.packageBaseUrl).toBe('/_mintlify/pkg/abc');
236
232
  expect(compiled.mdxSource.compiledSource).not.toMatch(/LineChart|RevenueChart/);
237
233
  });
238
- it('extracts the package components that <Snippet file> injects with the ids mint dev compiles', async () => {
234
+ it('reports a <Snippet file> that uses package components instead of extracting it', async () => {
239
235
  await fse.outputFile(join(testPaths.cmd, '_snippets/bar.mdx'), BAR_SNIPPET);
240
- await fse.outputFile(join(testPaths.cmd, '_snippets/line.mdx'), LINE_SNIPPET);
241
236
  await fse.outputFile(join(testPaths.cmd, 'revenue.mdx'), '# Revenue\n\n<Snippet file="bar.mdx" />\n');
242
- await fse.outputFile(join(testPaths.cmd, 'trend.mdx'), 'import { LineChart, Line } from "recharts";\n\n<Snippet file="line.mdx" />\n');
243
- const setup = await readPackagesSetup(testPaths.cmd);
244
- const collector = new PackageIslandCollector({
245
- docsRoot: testPaths.cmd,
246
- packageNames: setup?.packageNames ?? new Set(),
247
- variables: setup?.variables,
248
- });
249
- const collected = await collector.collectAll();
250
- setPackageImportOptions({
251
- packageNames: setup?.packageNames ?? new Set(),
252
- packageSnippets: collected.packageSnippets,
253
- });
254
- const islands = Object.fromEntries(collected.islands.map((island) => [
255
- island.id,
256
- { prefix: `mi-${island.id}-`, html: '<svg></svg>' },
257
- ]));
258
- const packageBuild = {
259
- buildId: 'abc',
260
- islands,
261
- packageNames: [...(setup?.packageNames ?? [])],
262
- packageSnippets: [...collected.packageSnippets],
263
- };
264
- expect(collected.pages['revenue.mdx']).toEqual({ ids: [expect.any(String)], errors: [] });
265
- expect(collected.pages['trend.mdx']).toEqual({ ids: [expect.any(String)], errors: [] });
266
- const [barId] = collected.pages['revenue.mdx']?.ids ?? [];
267
- expect(collected.islands.find((island) => island.id === barId)?.module).toContain('Acme revenue');
268
- for (const page of ['revenue.mdx', 'trend.mdx']) {
269
- const compiled = await compileLikeMintDev(page, packageBuild);
270
- expect(compiled.parseFailed).toBeUndefined();
271
- expect(Object.keys(compiled.mdxExtracts.islands ?? {})).toEqual(collected.pages[page]?.ids);
272
- expect(compiled.mdxSource.compiledSource).not.toMatch(/BarChart|LineChart/);
273
- }
274
- expect((await collector.updatePage('revenue.mdx')).pages['revenue.mdx']?.ids).toEqual([barId]);
275
- });
276
- it('resolves <Snippet file> imports against the snippet file with the ids mint dev compiles', async () => {
277
- const component = (name) => `import { BarChart, Bar } from "recharts";\n\nexport const ${name} = () => (\n <BarChart width={300} height={150} data={[{ v: 1 }]}>\n <Bar dataKey="v" name="${name}" />\n </BarChart>\n);\n`;
278
- await fse.outputFile(join(testPaths.cmd, 'snippets/chart.jsx'), component('Chart'));
279
- await fse.outputFile(join(testPaths.cmd, 'snippets/inner.jsx'), component('Inner'));
280
- await fse.outputFile(join(testPaths.cmd, 'snippets/wrong.jsx'), component('Wrong'));
281
- await fse.outputFile(join(testPaths.cmd, '_snippets/charts/x.mdx'), 'import { Chart } from "../../snippets/chart.jsx";\n\n<Chart />\n\n<Snippet file="charts/inner/y.mdx" />\n');
282
- await fse.outputFile(join(testPaths.cmd, '_snippets/charts/inner/y.mdx'), 'import { Inner } from "../../../snippets/inner.jsx";\n\n<Inner />\n');
283
- await fse.outputFile(join(testPaths.cmd, '_snippets/charts/w.mdx'), 'import { Wrong } from "../snippets/wrong.jsx";\n\n<Wrong />\n');
284
- await fse.outputFile(join(testPaths.cmd, 'guides/deep/nested/page.mdx'), '# Nested\n\n<Snippet file="charts/x.mdx" />\n');
285
- await fse.outputFile(join(testPaths.cmd, 'guides/wrong.mdx'), '# Wrong\n\n<Snippet file="charts/w.mdx" />\n');
286
- const setup = await readPackagesSetup(testPaths.cmd);
287
- const collected = await collectPackageIslands({
288
- docsRoot: testPaths.cmd,
289
- packageNames: setup?.packageNames ?? new Set(),
290
- variables: setup?.variables,
291
- });
292
- setPackageImportOptions({
293
- packageNames: setup?.packageNames ?? new Set(),
294
- packageSnippets: collected.packageSnippets,
295
- });
296
- const packageBuild = {
297
- buildId: 'abc',
298
- islands: Object.fromEntries(collected.islands.map((island) => [
299
- island.id,
300
- { prefix: `mi-${island.id}-`, html: '<svg></svg>' },
301
- ])),
302
- packageNames: [...(setup?.packageNames ?? [])],
303
- packageSnippets: [...collected.packageSnippets],
304
- };
305
- const modules = (page) => (collected.pages[page]?.ids ?? []).map((id) => collected.islands.find((island) => island.id === id)?.module);
306
- expect(modules('guides/deep/nested/page.mdx')).toEqual([
307
- expect.stringContaining('/snippets/chart.jsx'),
308
- expect.stringContaining('/snippets/inner.jsx'),
309
- ]);
310
- expect(collected.pages['guides/wrong.mdx']).toEqual({ ids: [], errors: [] });
311
- for (const page of ['guides/deep/nested/page.mdx', 'guides/wrong.mdx']) {
312
- const compiled = await compileLikeMintDev(page, packageBuild);
313
- expect(compiled.parseFailed).toBeUndefined();
314
- expect(Object.keys(compiled.mdxExtracts.islands ?? {})).toEqual(collected.pages[page]?.ids);
315
- }
316
- });
317
- it('reports a <Snippet file> cycle on the page instead of expanding it forever', async () => {
318
- await fse.outputFile(join(testPaths.cmd, '_snippets/note.mdx'), 'Note\n');
319
- await fse.outputFile(join(testPaths.cmd, '_snippets/a.mdx'), 'A\n\n<Snippet file="b.mdx" />\n');
320
- await fse.outputFile(join(testPaths.cmd, '_snippets/b.mdx'), 'B\n\n<Snippet file="a.mdx" />\n');
321
- await fse.outputFile(join(testPaths.cmd, 'loop.mdx'), '# Loop\n\n<Snippet file="a.mdx" />\n');
322
237
  const setup = await readPackagesSetup(testPaths.cmd);
323
238
  const collected = await collectPackageIslands({
324
239
  docsRoot: testPaths.cmd,
325
240
  packageNames: setup?.packageNames ?? new Set(),
326
241
  variables: setup?.variables,
327
242
  });
328
- expect(collected.pages['loop.mdx']).toEqual({
329
- ids: [],
330
- errors: [
331
- {
332
- file: 'loop.mdx',
333
- message: '<Snippet file="a.mdx"> includes itself (a.mdx -> b.mdx -> a.mdx).',
334
- },
335
- ],
243
+ expect(collected.pages['revenue.mdx']).toEqual({ ids: [], errors: [] });
244
+ expect(collected.errors).toContainEqual({
245
+ file: '_snippets/bar.mdx',
246
+ message: expect.stringContaining('<Snippet>'),
336
247
  });
337
- expect(collected.pages['charts.mdx']?.errors).toEqual([]);
338
248
  });
339
249
  it('falls back to the snippet trees of a collector for the same docs root only', async () => {
340
250
  const setup = await readPackagesSetup(testPaths.cmd);
@@ -1,6 +1,6 @@
1
1
  import { findAndRemoveImports, getFileCategory, parseFrontmatter } from '@mintlify/common';
2
2
  import { getMdx } from '@mintlify/common/server-mdx';
3
- import { createPage, preparseMdxTree } from '@mintlify/prebuild';
3
+ import { preparseMdxTree } from '@mintlify/prebuild';
4
4
  import fse from 'fs-extra';
5
5
  import { mkdtemp, readdir, rm } from 'fs/promises';
6
6
  import { tmpdir } from 'os';
@@ -152,10 +152,6 @@ describe('package snippet membership in the mint dev watcher', () => {
152
152
  await saveSnippet(file, content);
153
153
  await untilBuilt(settled);
154
154
  };
155
- const compilePage = async (file) => {
156
- const { pageContent } = await createPage(file, await fse.readFile(docs(file), 'utf8'), testPaths.cmd, [], []);
157
- await fse.outputFile(join(testPaths.props, file), pageContent);
158
- };
159
155
  const legacySnippets = async () => {
160
156
  const dir = join(testPaths.public, '_snippets');
161
157
  const names = (await fse.pathExists(dir)) ? await readdir(dir) : [];
@@ -389,48 +385,17 @@ describe('package snippet membership in the mint dev watcher', () => {
389
385
  expect(island.html).toBe(`<svg data-id="${id}"></svg>`);
390
386
  }
391
387
  });
392
- it('renders placeholders for the islands a <Snippet file> edit adds until the rebuild finishes', async () => {
393
- await fse.outputFile(docs('_snippets/badge.mdx'), 'Plain badge\n');
394
- await fse.outputFile(docs('badge-page.mdx'), '# Badge\n\n<Snippet file="badge.mdx" />\n');
395
- await start({ toggle: PLAIN_TOGGLE, wrapper: PLAIN_WRAPPER });
396
- await compilePage('badge-page.mdx');
397
- await fse.copy(docs('_snippets/badge.mdx'), join(testPaths.public, '_snippets/badge.mdx'));
398
- expect(await render('badge-page.mdx')).toEqual({});
399
- holdBuilds();
400
- const settled = builds + 1;
401
- await fse.outputFile(docs('_snippets/badge.mdx'), 'import { Switch } from "@acme/ui";\n\n<Switch />\n');
402
- await dev.onFileChange('_snippets/badge.mdx', 'snippet');
403
- await fse.copy(docs('_snippets/badge.mdx'), join(testPaths.public, '_snippets/badge.mdx'));
404
- const pending = await render('badge-page.mdx');
405
- const [id] = Object.keys(pending);
406
- expect(pending).toEqual({ [id ?? '']: { prefix: `mi-${id}-` } });
407
- releaseBuild();
408
- await untilBuilt(settled);
409
- expect(await render('badge-page.mdx')).toEqual({
410
- [id ?? '']: { prefix: `mi-${id}-`, html: `<svg data-id="${id}"></svg>` },
411
- });
412
- });
413
388
  it('keeps rendering the islands a snippet edit removes until the watcher recompiles the pages', async () => {
414
389
  await fse.outputFile(docs('snippets/switches.mdx'), 'import { Switch } from "@acme/ui";\n\n<Switch />\n');
415
390
  await fse.outputFile(docs('switch-page.mdx'), 'import Switches from "/snippets/switches.mdx";\n\n<Switches />\n');
416
- await fse.outputFile(docs('_snippets/badge.mdx'), 'import { Switch } from "@acme/ui";\n\n<Switch size="sm" />\n');
417
- await fse.outputFile(docs('badge-page.mdx'), '<Snippet file="badge.mdx" />\n');
418
391
  await start({ toggle: PLAIN_TOGGLE, wrapper: PLAIN_WRAPPER });
419
- await compilePage('badge-page.mdx');
420
- await fse.copy(docs('_snippets/badge.mdx'), join(testPaths.public, '_snippets/badge.mdx'));
421
392
  const switches = await render('switch-page.mdx');
422
- const badge = await render('badge-page.mdx');
423
- expect(Object.keys({ ...switches, ...badge })).toHaveLength(2);
393
+ expect(Object.keys(switches)).toHaveLength(1);
424
394
  holdBuilds();
425
395
  await changeSnippet('snippets/switches.mdx', 'No switch\n');
426
396
  expect(await render('switch-page.mdx')).toEqual(switches);
427
397
  await regenerate('snippets/switches.mdx');
428
398
  expect(await render('switch-page.mdx')).toEqual({});
429
- await fse.outputFile(docs('_snippets/badge.mdx'), 'Plain badge\n');
430
- await dev.onFileChange('_snippets/badge.mdx', 'snippet');
431
- expect(await render('badge-page.mdx')).toEqual(badge);
432
- await fse.copy(docs('_snippets/badge.mdx'), join(testPaths.public, '_snippets/badge.mdx'));
433
- expect(await render('badge-page.mdx')).toEqual({});
434
399
  });
435
400
  it('recompiles pages on request after a package snippet change, and keeps serving ones that failed to compile', async () => {
436
401
  markOnDemandPagesReady();
@@ -283,20 +283,6 @@ describe('PackagesDev', () => {
283
283
  await until(() => rebuilt === 2);
284
284
  expect((await props()).islands).toEqual(before);
285
285
  });
286
- it('re-extracts the islands of a <Snippet file> when the snippet changes', async () => {
287
- await fse.outputFile(join(docsRoot, 'charts.mdx'), '<Snippet file="chart.mdx" />\n');
288
- await fse.outputFile(join(docsRoot, '_snippets/chart.mdx'), page(2));
289
- await dev.init();
290
- rebuilt = 0;
291
- const before = Object.keys((await props()).islands);
292
- expect(before).toHaveLength(1);
293
- await fse.outputFile(join(docsRoot, '_snippets/chart.mdx'), page(3));
294
- await dev.onFileChange('_snippets/chart.mdx', 'snippet');
295
- await until(() => rebuilt === 1);
296
- const after = Object.keys((await props()).islands);
297
- expect(after).toHaveLength(1);
298
- expect(after).not.toEqual(before);
299
- });
300
286
  it('retries replacing the props file while another process has it open', async () => {
301
287
  const rename = fse.rename.bind(fse);
302
288
  let thrown = 0;
@@ -35,7 +35,6 @@ export declare class PackageIslandCollector {
35
35
  private readonly input;
36
36
  private snippetSources;
37
37
  private snippets;
38
- private snippetTreeMap;
39
38
  private packageSnippets;
40
39
  private packageSnippetTrees;
41
40
  private pageEntries;
@@ -24,12 +24,6 @@ const readSources = async (docsRoot, mintIgnore) => {
24
24
  }));
25
25
  return sources.flat();
26
26
  };
27
- const createLegacySnippetTreeMap = async (snippets, variables) => {
28
- if (snippets.length === 0)
29
- return {};
30
- const { createPackageSnippetTreeMap } = await import('@mintlify/common/server-mdx');
31
- return createPackageSnippetTreeMap(snippets, variables);
32
- };
33
27
  const resolveSnippets = async (snippets, variables, packages, onWarning) => {
34
28
  const parsed = [];
35
29
  for (const { filename, content } of snippets) {
@@ -64,7 +58,6 @@ export class PackageIslandCollector {
64
58
  this.input = input;
65
59
  this.snippetSources = [];
66
60
  this.snippets = [];
67
- this.snippetTreeMap = {};
68
61
  this.packageSnippets = new Set();
69
62
  this.packageSnippetTrees = new Map();
70
63
  this.pageEntries = new Map();
@@ -117,7 +110,6 @@ export class PackageIslandCollector {
117
110
  this.snippetSources = files
118
111
  .filter(({ path }) => snippetPaths.has(path))
119
112
  .map(({ path, content }) => ({ filename: withSlash(path), content }));
120
- this.snippetTreeMap = await createLegacySnippetTreeMap(classified.legacySnippets, variables);
121
113
  const previousTrees = this.packageSnippetTrees;
122
114
  const parsedTrees = new Map(classified.snippets.map(({ path, tree }) => [path, tree]));
123
115
  this.packageSnippetTrees = new Map();
@@ -207,7 +199,7 @@ export class PackageIslandCollector {
207
199
  const { path } = page;
208
200
  const content = replaceVariables(page.content, this.input.variables);
209
201
  const noIslands = { ids: [], islands: [], errors: sourceErrors };
210
- if (!mayImport(content) && !content.includes('<Snippet')) {
202
+ if (!mayImport(content)) {
211
203
  this.pageEntries.set(path, noIslands);
212
204
  return;
213
205
  }
@@ -228,7 +220,6 @@ export class PackageIslandCollector {
228
220
  packageNames: this.input.packageNames,
229
221
  packageSnippets: this.packageSnippets,
230
222
  variables: this.input.variables,
231
- snippetTreeMap: this.snippetTreeMap,
232
223
  });
233
224
  this.pageEntries.set(path, {
234
225
  ids: extraction.ids,