@mui/internal-docs-infra 0.3.1-canary.3 → 0.3.1-canary.4
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/esm/CodeControllerContext/CodeControllerContext.js +2 -2
- package/esm/CodeExternalsContext/CodeExternalsContext.js +1 -1
- package/esm/CodeHighlighter/CodeHighlighter.js +247 -329
- package/esm/CodeHighlighter/CodeHighlighterClient.js +447 -653
- package/esm/CodeHighlighter/CodeHighlighterContext.js +2 -2
- package/esm/CodeHighlighter/CodeHighlighterFallbackContext.js +2 -2
- package/esm/CodeHighlighter/codeToFallbackProps.js +21 -37
- package/esm/CodeHighlighter/errors.js +248 -400
- package/esm/CodeHighlighter/parseControlledCode.js +12 -20
- package/esm/CodeProvider/CodeContext.js +3 -3
- package/esm/CodeProvider/CodeProvider.js +31 -40
- package/esm/abstractCreateDemo/abstractCreateDemo.js +13 -17
- package/esm/abstractCreateDemoClient/abstractCreateDemoClient.js +12 -12
- package/esm/cli/index.js +1 -1
- package/esm/cli/runValidate.js +160 -264
- package/esm/createDemoData/createDemoData.js +11 -12
- package/esm/createSitemap/createSitemap.js +2 -2
- package/esm/pipeline/getFileConventions/fileConventions.js +1 -1
- package/esm/pipeline/getFileConventions/getFileConventions.js +2 -15
- package/esm/pipeline/hastUtils/hastUtils.js +16 -17
- package/esm/pipeline/loadCodeVariant/addCodeVariantPaths.js +24 -24
- package/esm/pipeline/loadCodeVariant/applyCodeTransform.js +12 -22
- package/esm/pipeline/loadCodeVariant/calculateMainFilePath.js +30 -37
- package/esm/pipeline/loadCodeVariant/computeHastDeltas.js +107 -185
- package/esm/pipeline/loadCodeVariant/diffHast.js +18 -53
- package/esm/pipeline/loadCodeVariant/examineCodeVariant.js +24 -27
- package/esm/pipeline/loadCodeVariant/flattenCodeVariant.js +9 -10
- package/esm/pipeline/loadCodeVariant/hasAllCodeVariants.js +5 -5
- package/esm/pipeline/loadCodeVariant/loadCodeFallback.js +516 -731
- package/esm/pipeline/loadCodeVariant/loadCodeVariant.js +679 -1079
- package/esm/pipeline/loadCodeVariant/maybeCodeInitialData.js +14 -20
- package/esm/pipeline/loadCodeVariant/mergeCodeMetadata.js +53 -63
- package/esm/pipeline/loadCodeVariant/parseCode.js +40 -48
- package/esm/pipeline/loadCodeVariant/pathUtils.js +43 -64
- package/esm/pipeline/loadCodeVariant/transformSource.js +55 -125
- package/esm/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.js +160 -221
- package/esm/pipeline/loadPrecomputedCodeHighlighter/parseCreateFactoryCall.js +377 -479
- package/esm/pipeline/loadPrecomputedCodeHighlighter/parseFunctionArguments.js +171 -173
- package/esm/pipeline/loadPrecomputedCodeHighlighter/performanceLogger.js +14 -30
- package/esm/pipeline/loadPrecomputedCodeHighlighter/replacePrecomputeValue.js +19 -21
- package/esm/pipeline/loadPrecomputedCodeHighlighter/serializeFunctionArguments.js +37 -71
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/filterRuntimeExternals.js +3 -9
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/generateImportStatements.js +54 -80
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/generateResolvedExternals.js +71 -98
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/injectImportsIntoSource.js +5 -5
- package/esm/pipeline/loadPrecomputedCodeHighlighterClient/loadPrecomputedCodeHighlighterClient.js +161 -211
- package/esm/pipeline/loadPrecomputedSitemap/loadPrecomputedSitemap.js +159 -207
- package/esm/pipeline/loadServerCodeMeta/loadServerCodeMeta.js +42 -64
- package/esm/pipeline/loadServerCodeMeta/resolveModulePathWithFs.js +20 -96
- package/esm/pipeline/loadServerPageIndex/loadServerPageIndex.js +66 -85
- package/esm/pipeline/loadServerSitemap/loadServerSitemap.js +71 -118
- package/esm/pipeline/loadServerSource/loadServerSource.js +121 -148
- package/esm/pipeline/loaderUtils/externalsToPackages.js +7 -7
- package/esm/pipeline/loaderUtils/extractNameAndSlugFromUrl.js +8 -12
- package/esm/pipeline/loaderUtils/fileUrlToPortablePath.js +5 -5
- package/esm/pipeline/loaderUtils/getFileNameFromUrl.js +19 -29
- package/esm/pipeline/loaderUtils/getLanguageFromExtension.js +3 -4
- package/esm/pipeline/loaderUtils/mergeExternals.js +15 -35
- package/esm/pipeline/loaderUtils/parseImportsAndComments.js +413 -433
- package/esm/pipeline/loaderUtils/processRelativeImports.js +153 -239
- package/esm/pipeline/loaderUtils/resolveModulePath.js +544 -1303
- package/esm/pipeline/loaderUtils/rewriteImports.js +73 -111
- package/esm/pipeline/parseSource/addLineGutters.js +33 -45
- package/esm/pipeline/parseSource/grammars.js +3 -3
- package/esm/pipeline/parseSource/parseSource.js +13 -31
- package/esm/pipeline/syncPageIndex/createMarkdownNodes.js +32 -55
- package/esm/pipeline/syncPageIndex/mergeMetadataMarkdown.js +107 -160
- package/esm/pipeline/syncPageIndex/metadataToMarkdown.js +846 -1033
- package/esm/pipeline/syncPageIndex/syncPageIndex.js +291 -438
- package/esm/pipeline/transformHtmlCodePrecomputed/transformHtmlCodePrecomputed.js +213 -311
- package/esm/pipeline/transformMarkdownBlockquoteCallouts/transformMarkdownBlockquoteCallouts.js +10 -10
- package/esm/pipeline/transformMarkdownCode/transformMarkdownCode.js +133 -193
- package/esm/pipeline/transformMarkdownDemoLinks/transformMarkdownDemoLinks.js +25 -27
- package/esm/pipeline/transformMarkdownMetadata/transformMarkdownMetadata.js +572 -717
- package/esm/pipeline/transformMarkdownRelativePaths/transformMarkdownRelativePaths.js +8 -8
- package/esm/pipeline/transformTypescriptToJavascript/removeTypes.js +84 -113
- package/esm/pipeline/transformTypescriptToJavascript/transformTypescriptToJavascript.js +10 -26
- package/esm/useCode/Pre.js +58 -62
- package/esm/useCode/useCode.js +59 -61
- package/esm/useCode/useCodeUtils.js +54 -63
- package/esm/useCode/useCopyFunctionality.js +10 -9
- package/esm/useCode/useFileNavigation.js +150 -212
- package/esm/useCode/useSourceEditing.js +17 -14
- package/esm/useCode/useTransformManagement.js +23 -26
- package/esm/useCode/useUIState.js +12 -20
- package/esm/useCode/useVariantSelection.js +62 -79
- package/esm/useCopier/index.js +29 -56
- package/esm/useDemo/createCodeSandbox.js +12 -15
- package/esm/useDemo/createStackBlitz.js +14 -20
- package/esm/useDemo/exportVariant.js +200 -180
- package/esm/useDemo/exportVariantAsCra.js +22 -25
- package/esm/useDemo/useDemo.js +80 -84
- package/esm/useErrors/ErrorsContext.js +1 -1
- package/esm/useErrors/useErrors.js +3 -3
- package/esm/useLocalStorageState/useLocalStorageState.js +23 -39
- package/esm/usePreference/PreferencesProvider.js +1 -1
- package/esm/usePreference/usePreference.js +9 -11
- package/esm/useSearch/useSearch.js +290 -387
- package/esm/useUrlHashState/useUrlHashState.js +11 -14
- package/esm/withDocsInfra/withDeploymentConfig.js +26 -21
- package/esm/withDocsInfra/withDocsInfra.js +99 -101
- package/package.json +7 -4
|
@@ -1,8 +1,3 @@
|
|
|
1
|
-
import _regeneratorValues from "@babel/runtime/helpers/esm/regeneratorValues";
|
|
2
|
-
import _regenerator from "@babel/runtime/helpers/esm/regenerator";
|
|
3
|
-
import _extends from "@babel/runtime/helpers/esm/extends";
|
|
4
|
-
import _asyncToGenerator from "@babel/runtime/helpers/esm/asyncToGenerator";
|
|
5
|
-
import _createForOfIteratorHelper from "@babel/runtime/helpers/esm/createForOfIteratorHelper";
|
|
6
1
|
import { readFile, writeFile, mkdir } from 'node:fs/promises';
|
|
7
2
|
import { basename, dirname, resolve, relative, join } from 'node:path';
|
|
8
3
|
import * as lockfile from 'proper-lockfile';
|
|
@@ -14,9 +9,7 @@ import { markdownToMetadata } from "./metadataToMarkdown.js";
|
|
|
14
9
|
* @example kebabToTitleCase('hello-world') -> 'Hello World'
|
|
15
10
|
*/
|
|
16
11
|
function kebabToTitleCase(str) {
|
|
17
|
-
return str.split('-').map(
|
|
18
|
-
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
19
|
-
}).join(' ');
|
|
12
|
+
return str.split('-').map(word => word.charAt(0).toUpperCase() + word.slice(1)).join(' ');
|
|
20
13
|
}
|
|
21
14
|
|
|
22
15
|
/**
|
|
@@ -33,9 +26,8 @@ function isRouteGroup(dirName) {
|
|
|
33
26
|
* @example getParentDir('/app/(public)/(content)/react') -> '/app/(public)/(content)'
|
|
34
27
|
* When recursing, skips route groups: '/app/(public)/(content)' -> '/app'
|
|
35
28
|
*/
|
|
36
|
-
function getParentDir(path) {
|
|
37
|
-
|
|
38
|
-
var parent = dirname(path);
|
|
29
|
+
function getParentDir(path, skipRouteGroups = false) {
|
|
30
|
+
let parent = dirname(path);
|
|
39
31
|
|
|
40
32
|
// If we should skip route groups, keep going up until we find a non-route-group directory
|
|
41
33
|
if (skipRouteGroups) {
|
|
@@ -55,24 +47,15 @@ function getParentDir(path) {
|
|
|
55
47
|
*/
|
|
56
48
|
function shouldIncludePath(path, include, exclude) {
|
|
57
49
|
// Normalize path separators to forward slashes and remove Next.js route groups
|
|
58
|
-
|
|
50
|
+
const normalizedPath = path.replace(/\\/g, '/').replace(/\/\([^)]+\)/g, '');
|
|
59
51
|
|
|
60
52
|
// Check exclude patterns first
|
|
61
53
|
if (exclude && exclude.length > 0) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
var pattern = _step.value;
|
|
67
|
-
var normalizedPattern = pattern.replace(/\\/g, '/');
|
|
68
|
-
if (normalizedPath.startsWith(normalizedPattern)) {
|
|
69
|
-
return false;
|
|
70
|
-
}
|
|
54
|
+
for (const pattern of exclude) {
|
|
55
|
+
const normalizedPattern = pattern.replace(/\\/g, '/');
|
|
56
|
+
if (normalizedPath.startsWith(normalizedPattern)) {
|
|
57
|
+
return false;
|
|
71
58
|
}
|
|
72
|
-
} catch (err) {
|
|
73
|
-
_iterator.e(err);
|
|
74
|
-
} finally {
|
|
75
|
-
_iterator.f();
|
|
76
59
|
}
|
|
77
60
|
}
|
|
78
61
|
|
|
@@ -82,23 +65,14 @@ function shouldIncludePath(path, include, exclude) {
|
|
|
82
65
|
}
|
|
83
66
|
|
|
84
67
|
// Check if path matches any include pattern
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
var _pattern = _step2.value;
|
|
90
|
-
var _normalizedPattern = _pattern.replace(/\\/g, '/');
|
|
91
|
-
if (normalizedPath.startsWith(_normalizedPattern)) {
|
|
92
|
-
return true;
|
|
93
|
-
}
|
|
68
|
+
for (const pattern of include) {
|
|
69
|
+
const normalizedPattern = pattern.replace(/\\/g, '/');
|
|
70
|
+
if (normalizedPath.startsWith(normalizedPattern)) {
|
|
71
|
+
return true;
|
|
94
72
|
}
|
|
95
|
-
|
|
96
|
-
// Path doesn't match any include pattern
|
|
97
|
-
} catch (err) {
|
|
98
|
-
_iterator2.e(err);
|
|
99
|
-
} finally {
|
|
100
|
-
_iterator2.f();
|
|
101
73
|
}
|
|
74
|
+
|
|
75
|
+
// Path doesn't match any include pattern
|
|
102
76
|
return false;
|
|
103
77
|
}
|
|
104
78
|
/**
|
|
@@ -126,369 +100,265 @@ function shouldIncludePath(path, include, exclude) {
|
|
|
126
100
|
* });
|
|
127
101
|
* ```
|
|
128
102
|
*/
|
|
129
|
-
export function syncPageIndex(
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
} catch (err) {
|
|
388
|
-
_iterator5.e(err);
|
|
389
|
-
} finally {
|
|
390
|
-
_iterator5.f();
|
|
391
|
-
}
|
|
392
|
-
allPages = Array.from(updatedPagesMap.values()); // Store for parent update
|
|
393
|
-
mergedPages = allPages;
|
|
394
|
-
|
|
395
|
-
// Re-merge with the latest content, passing the COMPLETE list of pages
|
|
396
|
-
// mergeMetadataMarkdown will preserve the order from currentMarkdown
|
|
397
|
-
// Only include path in the comment when baseDir is set (otherwise it's an absolute path)
|
|
398
|
-
_relativeIndexPath2 = baseDir ? relative(resolve(baseDir), indexPath) : undefined;
|
|
399
|
-
_context2.n = 31;
|
|
400
|
-
return mergeMetadataMarkdown(currentMarkdown, {
|
|
401
|
-
title: indexTitle,
|
|
402
|
-
pages: allPages
|
|
403
|
-
}, {
|
|
404
|
-
indexWrapperComponent: indexWrapperComponent,
|
|
405
|
-
path: _relativeIndexPath2
|
|
406
|
-
});
|
|
407
|
-
case 31:
|
|
408
|
-
finalMarkdown = _context2.v;
|
|
409
|
-
if (!(!finalMarkdown || !finalMarkdown.trim())) {
|
|
410
|
-
_context2.n = 32;
|
|
411
|
-
break;
|
|
412
|
-
}
|
|
413
|
-
throw new Error("Cannot write empty content to ".concat(indexPath));
|
|
414
|
-
case 32:
|
|
415
|
-
if (!(currentContent !== finalMarkdown)) {
|
|
416
|
-
_context2.n = 35;
|
|
417
|
-
break;
|
|
418
|
-
}
|
|
419
|
-
_context2.n = 33;
|
|
420
|
-
return writeFile(indexPath, finalMarkdown, 'utf-8');
|
|
421
|
-
case 33:
|
|
422
|
-
if (!markerDir) {
|
|
423
|
-
_context2.n = 35;
|
|
424
|
-
break;
|
|
425
|
-
}
|
|
426
|
-
// Compute relative path for marker (always compute, not used for comments)
|
|
427
|
-
markerRelativePath = baseDir ? relative(resolve(baseDir), indexPath) : indexPath; // Resolve markerDir relative to baseDir (if baseDir is provided)
|
|
428
|
-
markerDirResolved = baseDir ? resolve(baseDir, markerDir) : markerDir;
|
|
429
|
-
markerPath = join(markerDirResolved, markerRelativePath);
|
|
430
|
-
markerDirPath = dirname(markerPath); // Ensure the marker directory exists
|
|
431
|
-
_context2.n = 34;
|
|
432
|
-
return mkdir(markerDirPath, {
|
|
433
|
-
recursive: true
|
|
434
|
-
});
|
|
435
|
-
case 34:
|
|
436
|
-
_context2.n = 35;
|
|
437
|
-
return writeFile(markerPath, '', 'utf-8');
|
|
438
|
-
case 35:
|
|
439
|
-
_context2.p = 35;
|
|
440
|
-
if (!release) {
|
|
441
|
-
_context2.n = 36;
|
|
442
|
-
break;
|
|
443
|
-
}
|
|
444
|
-
_context2.n = 36;
|
|
445
|
-
return release();
|
|
446
|
-
case 36:
|
|
447
|
-
return _context2.f(35);
|
|
448
|
-
case 37:
|
|
449
|
-
if (!(updateParents && !shouldStop)) {
|
|
450
|
-
_context2.n = 47;
|
|
451
|
-
break;
|
|
452
|
-
}
|
|
453
|
-
// Get the grandparent directory, skipping over Next.js route groups
|
|
454
|
-
grandParentDir = getParentDir(parentDir, true); // Only continue if we're not at the filesystem root
|
|
455
|
-
if (!(grandParentDir !== parentDir)) {
|
|
456
|
-
_context2.n = 47;
|
|
457
|
-
break;
|
|
458
|
-
}
|
|
459
|
-
// CRITICAL: Use the merged pages from Step 6, not a re-read of the file
|
|
460
|
-
// Re-reading could get a stale version if other processes are still writing
|
|
461
|
-
// mergedPages already contains ALL pages after the merge in Step 6
|
|
462
|
-
// Calculate the relative path from grandparent to this index, preserving route groups
|
|
463
|
-
relativePathFromGrandparent = relative(grandParentDir, parentDir); // Extract metadata for the current index to add to its parent
|
|
464
|
-
indexMetadata = {
|
|
465
|
-
slug: basename(parentDir),
|
|
466
|
-
path: "./".concat(relativePathFromGrandparent, "/").concat(indexFileName),
|
|
467
|
-
title: indexTitle,
|
|
468
|
-
description: 'No description available'
|
|
469
|
-
}; // Convert child pages to sections format (no subsections, just page names)
|
|
470
|
-
// Use mergedPages which contains the complete merged state
|
|
471
|
-
// Skip single-link entries (external links) as they don't have detail sections
|
|
472
|
-
if (!(mergedPages.length > 0)) {
|
|
473
|
-
_context2.n = 46;
|
|
474
|
-
break;
|
|
475
|
-
}
|
|
476
|
-
sections = {};
|
|
477
|
-
_iterator6 = _createForOfIteratorHelper(mergedPages);
|
|
478
|
-
_context2.p = 38;
|
|
479
|
-
_iterator6.s();
|
|
480
|
-
case 39:
|
|
481
|
-
if ((_step6 = _iterator6.n()).done) {
|
|
482
|
-
_context2.n = 42;
|
|
483
|
-
break;
|
|
484
|
-
}
|
|
485
|
-
childPage = _step6.value;
|
|
486
|
-
if (!childPage.skipDetailSection) {
|
|
487
|
-
_context2.n = 40;
|
|
488
|
-
break;
|
|
103
|
+
export async function syncPageIndex(options) {
|
|
104
|
+
const {
|
|
105
|
+
pagePath,
|
|
106
|
+
metadata,
|
|
107
|
+
metadataList,
|
|
108
|
+
indexFileName = 'page.mdx',
|
|
109
|
+
lockOptions = {},
|
|
110
|
+
baseDir,
|
|
111
|
+
updateParents = false,
|
|
112
|
+
include,
|
|
113
|
+
exclude,
|
|
114
|
+
onlyUpdateIndexes = false,
|
|
115
|
+
markerDir = false,
|
|
116
|
+
errorIfOutOfDate = false,
|
|
117
|
+
indexWrapperComponent
|
|
118
|
+
} = options;
|
|
119
|
+
|
|
120
|
+
// Validate that either metadata or metadataList is provided
|
|
121
|
+
if (!metadata && (!metadataList || metadataList.length === 0)) {
|
|
122
|
+
throw new Error('Either metadata or metadataList must be provided');
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Determine if we're doing a batch update
|
|
126
|
+
const isBatchUpdate = !!metadataList;
|
|
127
|
+
const metadataArray = isBatchUpdate ? metadataList : [metadata];
|
|
128
|
+
|
|
129
|
+
// Resolve the index file path
|
|
130
|
+
// For batch updates, pagePath is the index file itself
|
|
131
|
+
// For single updates, pagePath is a child page and we need the parent's index
|
|
132
|
+
const indexPath = isBatchUpdate ? resolve(pagePath) : resolve(getParentDir(dirname(pagePath), true), indexFileName);
|
|
133
|
+
const parentDir = dirname(indexPath);
|
|
134
|
+
|
|
135
|
+
// Check if this index path should be processed based on include/exclude filters
|
|
136
|
+
if (baseDir) {
|
|
137
|
+
const relativePath = relative(resolve(baseDir), resolve(parentDir));
|
|
138
|
+
if (!shouldIncludePath(relativePath, include, exclude)) {
|
|
139
|
+
// This index is outside the configured paths - skip it
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// Check if we've reached the base directory
|
|
145
|
+
const shouldStop = baseDir && resolve(parentDir) === resolve(baseDir);
|
|
146
|
+
|
|
147
|
+
// Derive index title from directory name if not provided
|
|
148
|
+
const indexTitle = options.indexTitle ?? kebabToTitleCase(basename(parentDir));
|
|
149
|
+
|
|
150
|
+
// Step 1: Read the file without acquiring a lock to check if we need to make changes
|
|
151
|
+
let existingContent = '';
|
|
152
|
+
let fileExists = true;
|
|
153
|
+
try {
|
|
154
|
+
existingContent = await readFile(indexPath, 'utf-8');
|
|
155
|
+
} catch (error) {
|
|
156
|
+
if (error.code !== 'ENOENT') {
|
|
157
|
+
throw error;
|
|
158
|
+
}
|
|
159
|
+
// File doesn't exist
|
|
160
|
+
fileExists = false;
|
|
161
|
+
|
|
162
|
+
// If onlyUpdateIndexes is true and file doesn't exist, skip this update
|
|
163
|
+
if (onlyUpdateIndexes) {
|
|
164
|
+
return;
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// If errorIfOutOfDate is true, throw an error for missing index
|
|
168
|
+
if (errorIfOutOfDate) {
|
|
169
|
+
const relativeIndexPath = baseDir ? relative(resolve(baseDir), indexPath) : indexPath;
|
|
170
|
+
throw new Error(`Index file is missing: ${relativeIndexPath}\n` + `Please run next build locally and commit the updated index files.\n` + `Don't forget to add it to the \`app/sitemap/index.ts\` to list it publicly.`);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Step 1.5: Verify the file has the autogeneration marker if it exists
|
|
175
|
+
if (fileExists && existingContent) {
|
|
176
|
+
const hasMarker = existingContent.includes("[//]: # 'This file is autogenerated");
|
|
177
|
+
if (!hasMarker) {
|
|
178
|
+
// File exists but doesn't have the autogeneration marker - skip updating it
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Step 2: Parse existing content and check if our specific page needs updating
|
|
184
|
+
const existingMarkdown = existingContent.trim() ? existingContent : undefined;
|
|
185
|
+
let existingPages = [];
|
|
186
|
+
if (existingMarkdown) {
|
|
187
|
+
const parsed = await markdownToMetadata(existingMarkdown);
|
|
188
|
+
if (parsed) {
|
|
189
|
+
existingPages = parsed.pages;
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// Step 3: Check if any of our metadata items need updating
|
|
194
|
+
let needsUpdate = false;
|
|
195
|
+
for (const metaItem of metadataArray) {
|
|
196
|
+
const existingPageIndex = existingPages.findIndex(p => p.slug === metaItem.slug);
|
|
197
|
+
if (existingPageIndex >= 0) {
|
|
198
|
+
const existingPage = existingPages[existingPageIndex];
|
|
199
|
+
// Compare metadata - if different, we need to update
|
|
200
|
+
const existingPageJson = JSON.stringify(existingPage);
|
|
201
|
+
const newPageJson = JSON.stringify(metaItem);
|
|
202
|
+
if (existingPageJson !== newPageJson) {
|
|
203
|
+
needsUpdate = true;
|
|
204
|
+
break;
|
|
205
|
+
}
|
|
206
|
+
} else {
|
|
207
|
+
// Page doesn't exist, we need to add it
|
|
208
|
+
needsUpdate = true;
|
|
209
|
+
break;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
if (!needsUpdate) {
|
|
213
|
+
// All pages are already up-to-date, no need to acquire lock or write
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
// If errorIfOutOfDate is true, throw an error instead of updating
|
|
218
|
+
if (errorIfOutOfDate) {
|
|
219
|
+
const relativeIndexPath = baseDir ? relative(resolve(baseDir), indexPath) : indexPath;
|
|
220
|
+
throw new Error(`Index file is out of date: ${relativeIndexPath}\n` + `Please run the validation command (or next build) locally and commit the updated index files.`);
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
// Step 4: Ensure the file exists before locking (proper-lockfile requires an existing file)
|
|
224
|
+
if (!fileExists) {
|
|
225
|
+
await writeFile(indexPath, '', 'utf-8');
|
|
226
|
+
}
|
|
227
|
+
let release;
|
|
228
|
+
let mergedPages = []; // Store merged pages for parent update
|
|
229
|
+
|
|
230
|
+
try {
|
|
231
|
+
// Step 5: Acquire lock on the index file
|
|
232
|
+
release = await lockfile.lock(indexPath, {
|
|
233
|
+
retries: {
|
|
234
|
+
retries: 300,
|
|
235
|
+
minTimeout: 1,
|
|
236
|
+
// Start with 1ms for fast retries
|
|
237
|
+
maxTimeout: 150,
|
|
238
|
+
randomize: true
|
|
239
|
+
},
|
|
240
|
+
stale: 30000,
|
|
241
|
+
...lockOptions
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
// Step 6: Re-read and re-merge to catch any concurrent updates from other processes
|
|
245
|
+
// This ensures we don't lose updates from other pages being processed in parallel
|
|
246
|
+
let currentContent = '';
|
|
247
|
+
try {
|
|
248
|
+
currentContent = await readFile(indexPath, 'utf-8');
|
|
249
|
+
} catch (error) {
|
|
250
|
+
if (error.code !== 'ENOENT') {
|
|
251
|
+
throw error;
|
|
252
|
+
}
|
|
253
|
+
// File was deleted while waiting - that's okay, we'll create it
|
|
254
|
+
}
|
|
255
|
+
const currentMarkdown = currentContent.trim() ? currentContent : undefined;
|
|
256
|
+
let currentPages = [];
|
|
257
|
+
if (currentMarkdown) {
|
|
258
|
+
const parsed = await markdownToMetadata(currentMarkdown);
|
|
259
|
+
if (parsed) {
|
|
260
|
+
currentPages = parsed.pages;
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
// For batch updates, merge the metadata items with existing pages
|
|
265
|
+
// Build a map keyed by path (not slug) to match mergeMetadataMarkdown's logic
|
|
266
|
+
const updatedPagesMap = new Map();
|
|
267
|
+
|
|
268
|
+
// First, add all current pages
|
|
269
|
+
for (const page of currentPages) {
|
|
270
|
+
updatedPagesMap.set(page.path, page);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
// Then update/add the new metadata items
|
|
274
|
+
for (const metaItem of metadataArray) {
|
|
275
|
+
updatedPagesMap.set(metaItem.path, metaItem);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Convert back to array - this is the COMPLETE list of pages that should exist
|
|
279
|
+
const allPages = Array.from(updatedPagesMap.values());
|
|
280
|
+
|
|
281
|
+
// Store for parent update
|
|
282
|
+
mergedPages = allPages;
|
|
283
|
+
|
|
284
|
+
// Re-merge with the latest content, passing the COMPLETE list of pages
|
|
285
|
+
// mergeMetadataMarkdown will preserve the order from currentMarkdown
|
|
286
|
+
// Only include path in the comment when baseDir is set (otherwise it's an absolute path)
|
|
287
|
+
const relativeIndexPath = baseDir ? relative(resolve(baseDir), indexPath) : undefined;
|
|
288
|
+
const finalMarkdown = await mergeMetadataMarkdown(currentMarkdown, {
|
|
289
|
+
title: indexTitle,
|
|
290
|
+
pages: allPages
|
|
291
|
+
}, {
|
|
292
|
+
indexWrapperComponent,
|
|
293
|
+
path: relativeIndexPath
|
|
294
|
+
});
|
|
295
|
+
|
|
296
|
+
// Defensive check
|
|
297
|
+
if (!finalMarkdown || !finalMarkdown.trim()) {
|
|
298
|
+
throw new Error(`Cannot write empty content to ${indexPath}`);
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
// Step 7: Write only if the final content differs from what's currently on disk
|
|
302
|
+
if (currentContent !== finalMarkdown) {
|
|
303
|
+
await writeFile(indexPath, finalMarkdown, 'utf-8');
|
|
304
|
+
|
|
305
|
+
// Create a marker file unless explicitly disabled
|
|
306
|
+
if (markerDir) {
|
|
307
|
+
// Compute relative path for marker (always compute, not used for comments)
|
|
308
|
+
const markerRelativePath = baseDir ? relative(resolve(baseDir), indexPath) : indexPath;
|
|
309
|
+
// Resolve markerDir relative to baseDir (if baseDir is provided)
|
|
310
|
+
const markerDirResolved = baseDir ? resolve(baseDir, markerDir) : markerDir;
|
|
311
|
+
const markerPath = join(markerDirResolved, markerRelativePath);
|
|
312
|
+
const markerDirPath = dirname(markerPath);
|
|
313
|
+
|
|
314
|
+
// Ensure the marker directory exists
|
|
315
|
+
await mkdir(markerDirPath, {
|
|
316
|
+
recursive: true
|
|
317
|
+
});
|
|
318
|
+
|
|
319
|
+
// Create an empty marker file
|
|
320
|
+
await writeFile(markerPath, '', 'utf-8');
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
} finally {
|
|
324
|
+
// Always release the lock
|
|
325
|
+
if (release) {
|
|
326
|
+
await release();
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
// After releasing the lock, update the parent index if needed
|
|
331
|
+
if (updateParents && !shouldStop) {
|
|
332
|
+
// Get the grandparent directory, skipping over Next.js route groups
|
|
333
|
+
const grandParentDir = getParentDir(parentDir, true);
|
|
334
|
+
|
|
335
|
+
// Only continue if we're not at the filesystem root
|
|
336
|
+
if (grandParentDir !== parentDir) {
|
|
337
|
+
// CRITICAL: Use the merged pages from Step 6, not a re-read of the file
|
|
338
|
+
// Re-reading could get a stale version if other processes are still writing
|
|
339
|
+
// mergedPages already contains ALL pages after the merge in Step 6
|
|
340
|
+
|
|
341
|
+
// Calculate the relative path from grandparent to this index, preserving route groups
|
|
342
|
+
const relativePathFromGrandparent = relative(grandParentDir, parentDir);
|
|
343
|
+
|
|
344
|
+
// Extract metadata for the current index to add to its parent
|
|
345
|
+
const indexMetadata = {
|
|
346
|
+
slug: basename(parentDir),
|
|
347
|
+
path: `./${relativePathFromGrandparent}/${indexFileName}`,
|
|
348
|
+
title: indexTitle,
|
|
349
|
+
description: 'No description available'
|
|
350
|
+
};
|
|
351
|
+
|
|
352
|
+
// Convert child pages to sections format (no subsections, just page names)
|
|
353
|
+
// Use mergedPages which contains the complete merged state
|
|
354
|
+
// Skip single-link entries (external links) as they don't have detail sections
|
|
355
|
+
if (mergedPages.length > 0) {
|
|
356
|
+
const sections = {};
|
|
357
|
+
for (const childPage of mergedPages) {
|
|
358
|
+
// Skip entries that don't have detail sections (external links, etc.)
|
|
359
|
+
if (childPage.skipDetailSection) {
|
|
360
|
+
continue;
|
|
489
361
|
}
|
|
490
|
-
return _context2.a(3, 41);
|
|
491
|
-
case 40:
|
|
492
362
|
sections[childPage.slug] = {
|
|
493
363
|
title: childPage.title || childPage.slug,
|
|
494
364
|
titleMarkdown: childPage.title ? [{
|
|
@@ -500,41 +370,24 @@ function _syncPageIndex() {
|
|
|
500
370
|
}],
|
|
501
371
|
children: {} // Don't include any subsections in parent index
|
|
502
372
|
};
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
break;
|
|
506
|
-
case 42:
|
|
507
|
-
_context2.n = 44;
|
|
508
|
-
break;
|
|
509
|
-
case 43:
|
|
510
|
-
_context2.p = 43;
|
|
511
|
-
_t4 = _context2.v;
|
|
512
|
-
_iterator6.e(_t4);
|
|
513
|
-
case 44:
|
|
514
|
-
_context2.p = 44;
|
|
515
|
-
_iterator6.f();
|
|
516
|
-
return _context2.f(44);
|
|
517
|
-
case 45:
|
|
518
|
-
indexMetadata.sections = sections;
|
|
519
|
-
case 46:
|
|
520
|
-
_context2.n = 47;
|
|
521
|
-
return syncPageIndex({
|
|
522
|
-
pagePath: indexPath,
|
|
523
|
-
metadata: indexMetadata,
|
|
524
|
-
indexFileName: indexFileName,
|
|
525
|
-
lockOptions: lockOptions,
|
|
526
|
-
baseDir: baseDir,
|
|
527
|
-
updateParents: true,
|
|
528
|
-
include: include,
|
|
529
|
-
exclude: exclude,
|
|
530
|
-
onlyUpdateIndexes: onlyUpdateIndexes,
|
|
531
|
-
markerDir: markerDir,
|
|
532
|
-
errorIfOutOfDate: errorIfOutOfDate
|
|
533
|
-
});
|
|
534
|
-
case 47:
|
|
535
|
-
return _context2.a(2);
|
|
373
|
+
}
|
|
374
|
+
indexMetadata.sections = sections;
|
|
536
375
|
}
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
376
|
+
|
|
377
|
+
// Recursively update the parent index (will create it if it doesn't exist)
|
|
378
|
+
await syncPageIndex({
|
|
379
|
+
pagePath: indexPath,
|
|
380
|
+
metadata: indexMetadata,
|
|
381
|
+
indexFileName,
|
|
382
|
+
lockOptions,
|
|
383
|
+
baseDir,
|
|
384
|
+
updateParents: true,
|
|
385
|
+
include,
|
|
386
|
+
exclude,
|
|
387
|
+
onlyUpdateIndexes,
|
|
388
|
+
markerDir,
|
|
389
|
+
errorIfOutOfDate
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
}
|
|
540
393
|
}
|