@mui/internal-docs-infra 0.12.1-canary.2 → 0.12.1-canary.21

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 (221) hide show
  1. package/ChunkProvider/PreloadProvider.mjs +1 -2
  2. package/ChunkProvider/usePreload.d.mts +1 -1
  3. package/ChunkProvider/usePreload.mjs +0 -1
  4. package/CodeControllerContext/CodeControllerContext.d.mts +45 -10
  5. package/CodeControllerContext/CodeControllerContext.mjs +15 -1
  6. package/CodeHighlighter/CodeHighlighterClient.d.mts +3 -2
  7. package/CodeHighlighter/CodeHighlighterClient.mjs +113 -18
  8. package/CodeHighlighter/CodeHighlighterContext.d.mts +9 -3
  9. package/CodeHighlighter/buildStringFallback.d.mts +1 -1
  10. package/CodeHighlighter/codeToFallbackProps.d.mts +1 -1
  11. package/CodeHighlighter/createClientProps.mjs +3 -0
  12. package/CodeHighlighter/fallbackCompression.d.mts +1 -1
  13. package/CodeHighlighter/parseControlledCode.d.mts +13 -4
  14. package/CodeHighlighter/parseControlledCode.mjs +41 -49
  15. package/CodeHighlighter/types.d.mts +21 -0
  16. package/CodeHighlighter/useGrammarsReady.mjs +44 -9
  17. package/CodeProvider/CodeProvider.d.mts +1 -1
  18. package/CodeProvider/CodeProviderLazy.d.mts +1 -1
  19. package/CodeProvider/createParseSourceWorkerClient.d.mts +6 -0
  20. package/CodeProvider/createParseSourceWorkerClient.mjs +83 -15
  21. package/CodeProvider/useCodeProviderValue.mjs +50 -4
  22. package/abstractCreateDemo/abstractCreateDemo.d.mts +15 -1
  23. package/abstractCreateDemo/abstractCreateDemo.mjs +8 -0
  24. package/abstractCreateDemoClient/abstractCreateDemoClient.mjs +4 -0
  25. package/abstractCreateTypes/abstractCreateTypes.d.mts +12 -1
  26. package/abstractCreateTypes/abstractCreateTypes.mjs +4 -0
  27. package/abstractCreateTypes/typesToJsx.d.mts +8 -0
  28. package/abstractCreateTypes/typesToJsx.mjs +2 -1
  29. package/cli/loadNextConfig.d.mts +9 -0
  30. package/cli/loadNextConfig.mjs +11 -2
  31. package/cli/runValidate.mjs +15 -7
  32. package/cli/validateWorker.d.mts +1 -0
  33. package/cli/validateWorker.mjs +2 -1
  34. package/createDemoData/createDemoData.d.mts +1 -1
  35. package/package.json +34 -5
  36. package/pipeline/cacheUtils/constants.d.mts +5 -0
  37. package/pipeline/cacheUtils/constants.mjs +5 -0
  38. package/pipeline/cacheUtils/hashCacheContent.d.mts +5 -0
  39. package/pipeline/cacheUtils/hashCacheContent.mjs +9 -0
  40. package/pipeline/cacheUtils/index.d.mts +9 -0
  41. package/pipeline/cacheUtils/index.mjs +7 -0
  42. package/pipeline/cacheUtils/loadFileCache.d.mts +13 -0
  43. package/pipeline/cacheUtils/loadFileCache.mjs +20 -0
  44. package/pipeline/cacheUtils/loadFileCacheEntry.d.mts +13 -0
  45. package/pipeline/cacheUtils/loadFileCacheEntry.mjs +47 -0
  46. package/pipeline/cacheUtils/resolveCachePath.d.mts +16 -0
  47. package/pipeline/cacheUtils/resolveCachePath.mjs +24 -0
  48. package/pipeline/cacheUtils/saveFileCache.d.mts +17 -0
  49. package/pipeline/cacheUtils/saveFileCache.mjs +54 -0
  50. package/pipeline/cacheUtils/types.d.mts +23 -0
  51. package/pipeline/cacheUtils/types.mjs +1 -0
  52. package/pipeline/cacheUtils/withFileCache.d.mts +40 -0
  53. package/pipeline/cacheUtils/withFileCache.mjs +81 -0
  54. package/pipeline/hastUtils/hastUtils.d.mts +1 -1
  55. package/pipeline/hastUtils/hastUtils.mjs +0 -1
  56. package/pipeline/loadIsomorphicCodeSource/loadIsomorphicCodeSource.d.mts +1 -1
  57. package/pipeline/loadIsomorphicCodeSource/loadIsomorphicCodeSource.mjs +1 -1
  58. package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.mjs +0 -1
  59. package/pipeline/loadIsomorphicCodeVariant/diffHast.d.mts +1 -1
  60. package/pipeline/loadIsomorphicCodeVariant/hasAllCodeVariants.d.mts +1 -1
  61. package/pipeline/loadIsomorphicCodeVariant/maybeCodeInitialData.d.mts +1 -1
  62. package/pipeline/loadPrecomputedSitemap/loadPrecomputedSitemap.d.mts +6 -0
  63. package/pipeline/loadPrecomputedSitemap/loadPrecomputedSitemap.mjs +2 -1
  64. package/pipeline/loadPrecomputedTypes/loadPrecomputedTypes.d.mts +6 -0
  65. package/pipeline/loadPrecomputedTypes/loadPrecomputedTypes.mjs +5 -1
  66. package/pipeline/loadServerCodeMeta/resolveModulePathWithFs.d.mts +1 -1
  67. package/pipeline/loadServerCodeMeta/resolveModulePathWithFs.mjs +0 -1
  68. package/pipeline/loadServerPageIndex/enrichPageIndex.d.mts +15 -0
  69. package/pipeline/loadServerPageIndex/enrichPageIndex.mjs +50 -0
  70. package/pipeline/loadServerPageIndex/extractPrefixAndTitle.d.mts +19 -0
  71. package/pipeline/loadServerPageIndex/extractPrefixAndTitle.mjs +80 -0
  72. package/pipeline/loadServerPageIndex/index.d.mts +5 -2
  73. package/pipeline/loadServerPageIndex/index.mjs +4 -1
  74. package/pipeline/loadServerPageIndex/loadServerPageIndex.d.mts +13 -22
  75. package/pipeline/loadServerPageIndex/loadServerPageIndex.mjs +32 -124
  76. package/pipeline/loadServerPageIndex/resolvePageIndexCacheKey.d.mts +13 -0
  77. package/pipeline/loadServerPageIndex/resolvePageIndexCacheKey.mjs +23 -0
  78. package/pipeline/loadServerTypes/highlightTypes.d.mts +3 -3
  79. package/pipeline/loadServerTypes/highlightTypesMeta.d.mts +4 -4
  80. package/pipeline/loadServerTypes/loadServerTypes.d.mts +2 -2
  81. package/pipeline/loadServerTypes/loadServerTypes.mjs +67 -7
  82. package/pipeline/loadServerTypesMeta/createOptimizedProgram.d.mts +2 -1
  83. package/pipeline/loadServerTypesMeta/formatClass.d.mts +2 -2
  84. package/pipeline/loadServerTypesMeta/formatComponent.d.mts +2 -2
  85. package/pipeline/loadServerTypesMeta/formatFunction.d.mts +2 -2
  86. package/pipeline/loadServerTypesMeta/formatHook.d.mts +2 -2
  87. package/pipeline/loadServerTypesMeta/formatRaw.d.mts +2 -2
  88. package/pipeline/loadServerTypesMeta/formatType.d.mts +1 -1
  89. package/pipeline/loadServerTypesMeta/loadServerTypesMeta.d.mts +7 -7
  90. package/pipeline/loadServerTypesMeta/loadServerTypesMeta.mjs +1 -1
  91. package/pipeline/loadServerTypesMeta/processTypes.d.mts +2 -2
  92. package/pipeline/loadServerTypesMeta/worker.d.mts +1 -1
  93. package/pipeline/loadServerTypesText/loadServerTypesText.d.mts +16 -2
  94. package/pipeline/loadServerTypesText/loadServerTypesText.mjs +30 -8
  95. package/pipeline/loadServerTypesText/normalizeTypesSourceDataForCache.d.mts +2 -0
  96. package/pipeline/loadServerTypesText/normalizeTypesSourceDataForCache.mjs +144 -0
  97. package/pipeline/loadServerTypesText/resolveTypesCacheKey.d.mts +19 -0
  98. package/pipeline/loadServerTypesText/resolveTypesCacheKey.mjs +29 -0
  99. package/pipeline/loaderUtils/parseImportsAndComments.d.mts +5 -3
  100. package/pipeline/loaderUtils/parseImportsAndComments.mjs +284 -40
  101. package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.d.mts +2 -2
  102. package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs +2 -3
  103. package/pipeline/parseSource/detectFileTypes.d.mts +16 -0
  104. package/pipeline/parseSource/detectFileTypes.mjs +44 -0
  105. package/pipeline/syncPageIndex/mergeMetadataMarkdown.d.mts +25 -1
  106. package/pipeline/syncPageIndex/mergeMetadataMarkdown.mjs +79 -49
  107. package/pipeline/syncPageIndex/metadataToMarkdown.d.mts +15 -1
  108. package/pipeline/syncPageIndex/metadataToMarkdown.mjs +32 -10
  109. package/pipeline/syncPageIndex/syncPageIndex.d.mts +12 -0
  110. package/pipeline/syncPageIndex/syncPageIndex.mjs +154 -40
  111. package/pipeline/syncTypes/generateTypesMarkdown.d.mts +2 -2
  112. package/pipeline/syncTypes/syncTypes.d.mts +7 -0
  113. package/pipeline/syncTypes/syncTypes.mjs +31 -1
  114. package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.mjs +1 -1
  115. package/pipeline/transformMarkdownCode/transformMarkdownCode.mjs +25 -15
  116. package/pipeline/transformMarkdownMetadata/transformMarkdownMetadata.mjs +3 -0
  117. package/pipeline/transformMarkdownMetadata/types.d.mts +8 -1
  118. package/useCode/EditableEngine.d.mts +1 -1
  119. package/useCode/Pre.d.mts +9 -2
  120. package/useCode/Pre.mjs +4 -3
  121. package/useCode/TransformEngine.d.mts +1 -1
  122. package/useCode/useCode.d.mts +17 -1
  123. package/useCode/useCode.mjs +22 -1
  124. package/useCode/useCopyFunctionality.d.mts +2 -2
  125. package/useCode/useEditable.browser.mjs +0 -1
  126. package/useCode/useFileNavigation.d.mts +3 -0
  127. package/useCode/useFileNavigation.mjs +3 -1
  128. package/useCode/useSourceEditing.mjs +45 -10
  129. package/useCode/useSourceEnhancing.mjs +41 -9
  130. package/useCode/useTransformManagement.d.mts +2 -2
  131. package/useCode/useTransformManagement.mjs +19 -3
  132. package/useCode/useUIState.d.mts +4 -0
  133. package/useCode/useUIState.mjs +8 -1
  134. package/useCode/useVariantSelection.d.mts +1 -1
  135. package/useCoordinated/useCoordinated.d.mts +1 -1
  136. package/useCoordinated/useCoordinatedLocalStorage.d.mts +1 -1
  137. package/useCoordinated/useCoordinatedLocalStorage.mjs +0 -1
  138. package/useCoordinated/useCoordinatedPreference.d.mts +1 -1
  139. package/useCoordinated/useCoordinatedPreference.mjs +0 -1
  140. package/useCrossTabState/index.d.mts +2 -0
  141. package/useCrossTabState/index.mjs +2 -0
  142. package/useCrossTabState/useCrossTabMirror.d.mts +26 -0
  143. package/useCrossTabState/useCrossTabMirror.mjs +108 -0
  144. package/useCrossTabState/useCrossTabState.d.mts +21 -0
  145. package/useCrossTabState/useCrossTabState.mjs +31 -0
  146. package/useDemo/exportVariant.mjs +2 -4
  147. package/useDemo/exportVariantAsCra.d.mts +1 -1
  148. package/useDemo/exportVariantAsCra.mjs +0 -1
  149. package/useDemo/useDemo.d.mts +4 -1
  150. package/useDemo/useDemo.mjs +5 -0
  151. package/useDemoController/BuildEngine.d.mts +2 -0
  152. package/useDemoController/BuildEngine.mjs +10 -0
  153. package/useDemoController/DemoRunner.d.mts +34 -0
  154. package/useDemoController/DemoRunner.mjs +83 -0
  155. package/useDemoController/ErrorBoundary.d.mts +34 -0
  156. package/useDemoController/ErrorBoundary.mjs +49 -0
  157. package/useDemoController/Runner.d.mts +44 -0
  158. package/useDemoController/Runner.mjs +71 -0
  159. package/useDemoController/absolutizeImports.d.mts +13 -0
  160. package/useDemoController/absolutizeImports.mjs +73 -0
  161. package/useDemoController/buildScope.d.mts +48 -0
  162. package/useDemoController/buildScope.mjs +270 -0
  163. package/useDemoController/collectSources.d.mts +67 -0
  164. package/useDemoController/collectSources.mjs +92 -0
  165. package/useDemoController/compileCssModule.d.mts +64 -0
  166. package/useDemoController/compileCssModule.mjs +40 -0
  167. package/useDemoController/compileCssWithPostcss.d.mts +17 -0
  168. package/useDemoController/compileCssWithPostcss.mjs +89 -0
  169. package/useDemoController/compileModule.d.mts +14 -0
  170. package/useDemoController/compileModule.mjs +17 -0
  171. package/useDemoController/constants.d.mts +13 -0
  172. package/useDemoController/constants.mjs +13 -0
  173. package/useDemoController/createRequire.d.mts +10 -0
  174. package/useDemoController/createRequire.mjs +17 -0
  175. package/useDemoController/createTranspileWorkerClient.d.mts +27 -0
  176. package/useDemoController/createTranspileWorkerClient.mjs +139 -0
  177. package/useDemoController/cssModules.d.mts +47 -0
  178. package/useDemoController/currentBrowserTarget.d.mts +16 -0
  179. package/useDemoController/currentBrowserTarget.mjs +36 -0
  180. package/useDemoController/evalCode.d.mts +12 -0
  181. package/useDemoController/evalCode.mjs +35 -0
  182. package/useDemoController/generateCssModuleSource.d.mts +11 -0
  183. package/useDemoController/generateCssModuleSource.mjs +55 -0
  184. package/useDemoController/generateElement.d.mts +21 -0
  185. package/useDemoController/generateElement.mjs +26 -0
  186. package/useDemoController/hashString.d.mts +11 -0
  187. package/useDemoController/hashString.mjs +20 -0
  188. package/useDemoController/importCode.d.mts +11 -0
  189. package/useDemoController/importCode.mjs +15 -0
  190. package/useDemoController/index.d.mts +1 -0
  191. package/useDemoController/index.mjs +1 -0
  192. package/useDemoController/instantiateElement.d.mts +24 -0
  193. package/useDemoController/instantiateElement.mjs +57 -0
  194. package/useDemoController/instantiateModule.d.mts +17 -0
  195. package/useDemoController/instantiateModule.mjs +24 -0
  196. package/useDemoController/resolveCssImports.d.mts +27 -0
  197. package/useDemoController/resolveCssImports.mjs +79 -0
  198. package/useDemoController/transformCode.d.mts +14 -0
  199. package/useDemoController/transformCode.mjs +42 -0
  200. package/useDemoController/transpileClientSingleton.d.mts +10 -0
  201. package/useDemoController/transpileClientSingleton.mjs +83 -0
  202. package/useDemoController/transpileSource.d.mts +29 -0
  203. package/useDemoController/transpileSource.mjs +36 -0
  204. package/useDemoController/transpileWorker.d.mts +14 -0
  205. package/useDemoController/transpileWorker.mjs +41 -0
  206. package/useDemoController/types.d.mts +30 -0
  207. package/useDemoController/types.mjs +1 -0
  208. package/useDemoController/useDemoController.d.mts +54 -0
  209. package/useDemoController/useDemoController.mjs +186 -0
  210. package/useDemoController/useRunner.d.mts +53 -0
  211. package/useDemoController/useRunner.mjs +118 -0
  212. package/useDemoController/useVariantBuilds.d.mts +31 -0
  213. package/useDemoController/useVariantBuilds.mjs +188 -0
  214. package/useSearch/types.d.mts +1 -1
  215. package/useType/TypesDataProvider.d.mts +1 -1
  216. package/useType/TypesDataProvider.mjs +1 -2
  217. package/useType/useType.d.mts +1 -1
  218. package/useType/useTypeProp.d.mts +1 -1
  219. package/withDocsInfra/withDeploymentConfig.mjs +57 -0
  220. package/withDocsInfra/withDocsInfra.d.mts +14 -0
  221. package/withDocsInfra/withDocsInfra.mjs +25 -11
@@ -5,56 +5,34 @@ import { markdownToMetadata, metadataToMarkdown } from "./metadataToMarkdown.mjs
5
5
  */
6
6
 
7
7
  /**
8
- * Merges new page metadata with existing markdown content, preserving the order
9
- * of pages from the existing markdown when available, unless the file contains
10
- * only the autogeneration marker (no editable section), in which case pages are
11
- * sorted alphabetically by title.
12
- *
13
- * Pages are matched by their `path` property (e.g., './button/page.mdx'), not by slug.
14
- * This allows multiple pages to have the same slug (anchor) while still being treated
15
- * as distinct pages.
16
- *
17
- * @param existingMarkdown - The existing markdown content (or undefined if none exists)
18
- * @param newMetadata - The new metadata to merge in
19
- * @param options - Optional configuration
20
- * @param options.preserveUnlisted - If true, pages in existing markdown that aren't in newMetadata will be preserved. If false (default), they are removed.
21
- * @param options.indexWrapperComponent - Optional component name to wrap the autogenerated content (e.g., 'PagesIndex')
22
- * @returns The updated markdown content with merged metadata
23
- *
24
- * @example
25
- * ```ts
26
- * const existingMarkdown = `# Components
27
- * - Button - ([Outline](#button), [Contents](./button/page.mdx)) - A button
28
- * - Checkbox - ([Outline](#checkbox), [Contents](./checkbox/page.mdx)) - A checkbox
29
- * `;
8
+ * Result of merging new metadata into existing markdown: the normalized
9
+ * `PagesMetadata` that renders to the merged markdown, plus the rendering options
10
+ * needed to reproduce that markdown.
11
+ */
12
+
13
+ /**
14
+ * Merges new page metadata with existing markdown content and returns the
15
+ * normalized `PagesMetadata` (and rendering options) without serializing to markdown.
30
16
  *
31
- * const newMetadata = {
32
- * title: 'Components',
33
- * pages: [
34
- * { slug: 'checkbox', path: './checkbox/page.mdx', title: 'Checkbox', description: 'Updated checkbox' },
35
- * { slug: 'button', path: './button/page.mdx', title: 'Button', description: 'Updated button' },
36
- * { slug: 'input', path: './input/page.mdx', title: 'Input', description: 'New input' },
37
- * ],
38
- * };
17
+ * This is the in-memory source of truth that {@link mergeMetadataMarkdown} renders.
18
+ * `syncPageIndex` reuses it to pre-populate the page-index cache, so the cached
19
+ * value matches a fresh read of the rendered markdown.
39
20
  *
40
- * const result = await mergeMetadataMarkdown(existingMarkdown, newMetadata);
41
- * // Result preserves Button, Checkbox order from existing markdown, adds Input at the end
42
- * ```
21
+ * See {@link mergeMetadataMarkdown} for the ordering and merge semantics.
43
22
  */
44
- export async function mergeMetadataMarkdown(existingMarkdown, newMetadata, options = {}) {
23
+ export async function mergeMetadataPages(existingMarkdown, newMetadata, options = {}) {
45
24
  const {
46
25
  indexWrapperComponent,
47
- path,
48
26
  preserveExistingTitleAndSlug
49
27
  } = options;
50
28
 
51
- // If no existing markdown, just convert the new metadata
52
- // Use the provided wrapper unless it's null (which means remove)
29
+ // If no existing markdown, just use the new metadata.
30
+ // Use the provided wrapper unless it's null (which means remove).
53
31
  if (!existingMarkdown) {
54
- return metadataToMarkdown(newMetadata, {
55
- indexWrapperComponent: indexWrapperComponent === null ? undefined : indexWrapperComponent,
56
- path
57
- });
32
+ return {
33
+ metadata: newMetadata,
34
+ indexWrapperComponent: indexWrapperComponent === null ? undefined : indexWrapperComponent
35
+ };
58
36
  }
59
37
 
60
38
  // Parse the existing markdown to get the current order
@@ -62,10 +40,10 @@ export async function mergeMetadataMarkdown(existingMarkdown, newMetadata, optio
62
40
 
63
41
  // If parsing failed, just use the new metadata
64
42
  if (!existingMetadata) {
65
- return metadataToMarkdown(newMetadata, {
66
- indexWrapperComponent: indexWrapperComponent === null ? undefined : indexWrapperComponent,
67
- path
68
- });
43
+ return {
44
+ metadata: newMetadata,
45
+ indexWrapperComponent: indexWrapperComponent === null ? undefined : indexWrapperComponent
46
+ };
69
47
  }
70
48
 
71
49
  // Determine effective wrapper component:
@@ -160,11 +138,63 @@ export async function mergeMetadataMarkdown(existingMarkdown, newMetadata, optio
160
138
  // Preserve the existing pageMetadata (e.g., robots config) from the current file
161
139
  pageMetadata: existingMetadata.pageMetadata
162
140
  };
163
-
164
- // Preserve the alphabetical sorting marker if it was present
165
- return metadataToMarkdown(mergedMetadata, {
166
- editableMarker: requestsAlphabeticalSort ? alphabeticalSortMarker : undefined,
141
+ return {
142
+ metadata: mergedMetadata,
167
143
  indexWrapperComponent: effectiveWrapper,
144
+ // Preserve the alphabetical sorting marker if it was present
145
+ editableMarker: requestsAlphabeticalSort ? alphabeticalSortMarker : undefined
146
+ };
147
+ }
148
+
149
+ /**
150
+ * Merges new page metadata with existing markdown content, preserving the order
151
+ * of pages from the existing markdown when available, unless the file contains
152
+ * only the autogeneration marker (no editable section), in which case pages are
153
+ * sorted alphabetically by title.
154
+ *
155
+ * Pages are matched by their `path` property (e.g., './button/page.mdx'), not by slug.
156
+ * This allows multiple pages to have the same slug (anchor) while still being treated
157
+ * as distinct pages.
158
+ *
159
+ * @param existingMarkdown - The existing markdown content (or undefined if none exists)
160
+ * @param newMetadata - The new metadata to merge in
161
+ * @param options - Optional configuration
162
+ * @param options.preserveUnlisted - If true, pages in existing markdown that aren't in newMetadata will be preserved. If false (default), they are removed.
163
+ * @param options.indexWrapperComponent - Optional component name to wrap the autogenerated content (e.g., 'PagesIndex')
164
+ * @returns The updated markdown content with merged metadata
165
+ *
166
+ * @example
167
+ * ```ts
168
+ * const existingMarkdown = `# Components
169
+ * - Button - ([Outline](#button), [Contents](./button/page.mdx)) - A button
170
+ * - Checkbox - ([Outline](#checkbox), [Contents](./checkbox/page.mdx)) - A checkbox
171
+ * `;
172
+ *
173
+ * const newMetadata = {
174
+ * title: 'Components',
175
+ * pages: [
176
+ * { slug: 'checkbox', path: './checkbox/page.mdx', title: 'Checkbox', description: 'Updated checkbox' },
177
+ * { slug: 'button', path: './button/page.mdx', title: 'Button', description: 'Updated button' },
178
+ * { slug: 'input', path: './input/page.mdx', title: 'Input', description: 'New input' },
179
+ * ],
180
+ * };
181
+ *
182
+ * const result = await mergeMetadataMarkdown(existingMarkdown, newMetadata);
183
+ * // Result preserves Button, Checkbox order from existing markdown, adds Input at the end
184
+ * ```
185
+ */
186
+ export async function mergeMetadataMarkdown(existingMarkdown, newMetadata, options = {}) {
187
+ const {
188
+ path
189
+ } = options;
190
+ const {
191
+ metadata,
192
+ indexWrapperComponent,
193
+ editableMarker
194
+ } = await mergeMetadataPages(existingMarkdown, newMetadata, options);
195
+ return metadataToMarkdown(metadata, {
196
+ editableMarker,
197
+ indexWrapperComponent,
168
198
  path
169
199
  });
170
200
  }
@@ -1,6 +1,6 @@
1
1
  import type { Root } from 'mdast';
2
2
  import type { ExtractedMetadata } from "../transformMarkdownMetadata/types.mjs";
3
- import { type Audience } from "../../createSitemap/types.mjs";
3
+ import type { Audience } from "../../createSitemap/types.mjs";
4
4
  export interface PageMetadata extends ExtractedMetadata {
5
5
  /** The slug/path for this page (e.g., 'button', 'checkbox') */
6
6
  slug: string;
@@ -66,6 +66,20 @@ export interface PagesMetadata {
66
66
  /** Name of a React component that wraps the autogenerated index content */
67
67
  indexWrapperComponent?: string;
68
68
  }
69
+ /**
70
+ * Resolves the page metadata embedded in an autogenerated index, falling back to
71
+ * the default (private, non-indexed) metadata when none is provided.
72
+ *
73
+ * Shared between rendering (`metadataToMarkdownAst`) and cache pre-population in
74
+ * `syncPageIndex` so the cached read-model matches a fresh parse of the rendered file.
75
+ */
76
+ export declare function resolveIndexPageMetadata(pageMetadata?: Record<string, unknown>): Record<string, unknown>;
77
+ /**
78
+ * Collapses runs of whitespace to single spaces and trims, the way the parser normalizes
79
+ * paragraph text. Shared so cache pre-population (which builds the read-model from in-memory
80
+ * metadata) produces the same description/title strings a fresh parse of the markdown would.
81
+ */
82
+ export declare function collapseInlineWhitespace(text: string): string;
69
83
  /**
70
84
  * Options for metadataToMarkdown and metadataToMarkdownAst functions
71
85
  */
@@ -45,6 +45,35 @@ function astNodesToMarkdown(nodes) {
45
45
  }
46
46
  return result;
47
47
  }
48
+ /**
49
+ * Resolves the page metadata embedded in an autogenerated index, falling back to
50
+ * the default (private, non-indexed) metadata when none is provided.
51
+ *
52
+ * Shared between rendering (`metadataToMarkdownAst`) and cache pre-population in
53
+ * `syncPageIndex` so the cached read-model matches a fresh parse of the rendered file.
54
+ */
55
+ export function resolveIndexPageMetadata(pageMetadata) {
56
+ if (pageMetadata && Object.keys(pageMetadata).length > 0) {
57
+ return pageMetadata;
58
+ }
59
+ return {
60
+ robots: {
61
+ index: false
62
+ },
63
+ other: {
64
+ audience: 'private'
65
+ }
66
+ };
67
+ }
68
+
69
+ /**
70
+ * Collapses runs of whitespace to single spaces and trims, the way the parser normalizes
71
+ * paragraph text. Shared so cache pre-population (which builds the read-model from in-memory
72
+ * metadata) produces the same description/title strings a fresh parse of the markdown would.
73
+ */
74
+ export function collapseInlineWhitespace(text) {
75
+ return text.replace(/[ \t\n\r]+/g, ' ').trim();
76
+ }
48
77
 
49
78
  /**
50
79
  * Options for metadataToMarkdown and metadataToMarkdownAst functions
@@ -834,14 +863,7 @@ export function metadataToMarkdownAst(data, options = {}) {
834
863
  value: `</${indexWrapperComponent}>`
835
864
  });
836
865
  }
837
- const metadataObj = pageMetadata && Object.keys(pageMetadata).length > 0 ? pageMetadata : {
838
- robots: {
839
- index: false
840
- },
841
- other: {
842
- audience: 'private'
843
- }
844
- };
866
+ const metadataObj = resolveIndexPageMetadata(pageMetadata);
845
867
  const typeAnnotation = "/** @type {import('@mui/internal-docs-infra/createSitemap/types').NextMetadata} */";
846
868
  const metadataCode = `export const metadata =\n ${typeAnnotation} (${serializeJsValue(metadataObj, 1)});`;
847
869
  // Output as raw MDX/JSX code (mdxjsEsm node type)
@@ -1559,7 +1581,7 @@ function extractPlainTextFromNode(node) {
1559
1581
  // For paragraph nodes, replace sequences of regular whitespace (spaces, tabs, newlines)
1560
1582
  // with a single space, but preserve non-breaking spaces and other special whitespace
1561
1583
  if (node.type === 'paragraph') {
1562
- return extractedText.replace(/[ \t\n\r]+/g, ' ').trim();
1584
+ return collapseInlineWhitespace(extractedText);
1563
1585
  }
1564
1586
  return extractedText;
1565
1587
  }
@@ -1596,7 +1618,7 @@ function extractTextFromNode(node) {
1596
1618
  // For paragraph nodes, replace sequences of regular whitespace (spaces, tabs, newlines)
1597
1619
  // with a single space, but preserve non-breaking spaces and other special whitespace
1598
1620
  if (node.type === 'paragraph') {
1599
- return extractedText.replace(/[ \t\n\r]+/g, ' ').trim();
1621
+ return collapseInlineWhitespace(extractedText);
1600
1622
  }
1601
1623
  return extractedText;
1602
1624
  }
@@ -86,6 +86,18 @@ export interface SyncPageIndexOptions {
86
86
  * @default false
87
87
  */
88
88
  preserveExistingTitleAndSlug?: boolean;
89
+ /**
90
+ * Directory for the sha256-validated JSON cache of page indexes. When set, each
91
+ * index written is also cached at `{cacheDir}/pages-index/{route}.json`, leaving
92
+ * it warm for the next cold `loadServerPageIndex` read. When unset, no cache is written.
93
+ */
94
+ cacheDir?: string;
95
+ /**
96
+ * Root context directory used to derive the cache key/route. Must match the
97
+ * `rootContext` used by `loadServerPageIndex` for cache keys to align.
98
+ * @default process.cwd()
99
+ */
100
+ rootContext?: string;
89
101
  }
90
102
  /**
91
103
  * Updates the parent directory's index file with metadata from a page.
@@ -1,8 +1,11 @@
1
1
  import { readFile, writeFile, mkdir } from 'node:fs/promises';
2
2
  import { basename, dirname, resolve, relative, join } from 'node:path';
3
3
  import * as lockfile from 'proper-lockfile';
4
- import { mergeMetadataMarkdown } from "./mergeMetadataMarkdown.mjs";
5
- import { markdownToMetadata } from "./metadataToMarkdown.mjs";
4
+ import { mergeMetadataPages } from "./mergeMetadataMarkdown.mjs";
5
+ import { markdownToMetadata, metadataToMarkdown, resolveIndexPageMetadata } from "./metadataToMarkdown.mjs";
6
+ import { enrichPageIndex } from "../loadServerPageIndex/enrichPageIndex.mjs";
7
+ import { resolvePageIndexCacheKey, PAGE_INDEX_CACHE_NAMESPACE } from "../loadServerPageIndex/resolvePageIndexCacheKey.mjs";
8
+ import { saveFileCache } from "../cacheUtils/index.mjs";
6
9
  /**
7
10
  * Converts a kebab-case string to Title Case
8
11
  * @example kebabToTitleCase('my-component') -> 'My Component'
@@ -75,6 +78,74 @@ function shouldIncludePath(path, include, exclude) {
75
78
  // Path doesn't match any include pattern
76
79
  return false;
77
80
  }
81
+ async function savePageIndexCache({
82
+ cacheDir,
83
+ indexPath,
84
+ rootContext,
85
+ markdown,
86
+ metadata,
87
+ defaultPageMetadata = true
88
+ }) {
89
+ const cacheMetadata = {
90
+ ...metadata,
91
+ pageMetadata: defaultPageMetadata ? resolveIndexPageMetadata(metadata.pageMetadata) : metadata.pageMetadata
92
+ };
93
+ await saveFileCache({
94
+ cacheDir,
95
+ namespace: PAGE_INDEX_CACHE_NAMESPACE,
96
+ cacheKey: resolvePageIndexCacheKey(indexPath, rootContext)
97
+ }, markdown, enrichPageIndex(cacheMetadata, indexPath, rootContext));
98
+ }
99
+
100
+ /**
101
+ * Merges the incoming metadata into the source pages (keyed by path, matching
102
+ * mergeMetadataMarkdown's logic) and renders the index markdown exactly as it is
103
+ * persisted. Shared by the writer and the `errorIfOutOfDate` validation path so the two
104
+ * always agree on what the index should contain - otherwise validation could render
105
+ * differently from the writer and flag an up-to-date file (or miss a stale one).
106
+ */
107
+ async function renderIndexPages(sourceMarkdown, sourcePages, metadataArray, {
108
+ indexTitle,
109
+ indexWrapperComponent,
110
+ preserveExistingTitleAndSlug,
111
+ relativeIndexPath
112
+ }) {
113
+ // Build a map keyed by path (not slug) to match mergeMetadataMarkdown's logic.
114
+ const updatedPagesMap = new Map();
115
+ // First, add all source pages.
116
+ for (const page of sourcePages) {
117
+ updatedPagesMap.set(page.path, page);
118
+ }
119
+ // Then update/add the new metadata items.
120
+ for (const metaItem of metadataArray) {
121
+ updatedPagesMap.set(metaItem.path, metaItem);
122
+ }
123
+ // The COMPLETE list of pages that should exist.
124
+ const allPages = Array.from(updatedPagesMap.values());
125
+
126
+ // mergeMetadataPages preserves the order from sourceMarkdown and returns the normalized
127
+ // metadata that renders to finalMarkdown - reused by the writer to populate the cache
128
+ // without re-parsing what it just wrote.
129
+ const merged = await mergeMetadataPages(sourceMarkdown, {
130
+ title: indexTitle,
131
+ pages: allPages
132
+ }, {
133
+ indexWrapperComponent,
134
+ preserveExistingTitleAndSlug
135
+ });
136
+ const finalMarkdown = await metadataToMarkdown(merged.metadata, {
137
+ editableMarker: merged.editableMarker,
138
+ indexWrapperComponent: merged.indexWrapperComponent,
139
+ // Only include path in the comment when baseDir is set (otherwise it's an absolute path).
140
+ path: relativeIndexPath
141
+ });
142
+ return {
143
+ allPages,
144
+ merged,
145
+ finalMarkdown
146
+ };
147
+ }
148
+
78
149
  /**
79
150
  * Updates the parent directory's index file with metadata from a page.
80
151
  *
@@ -115,7 +186,9 @@ export async function syncPageIndex(options) {
115
186
  markerDir = false,
116
187
  errorIfOutOfDate = false,
117
188
  indexWrapperComponent,
118
- preserveExistingTitleAndSlug
189
+ preserveExistingTitleAndSlug,
190
+ cacheDir,
191
+ rootContext = process.cwd()
119
192
  } = options;
120
193
 
121
194
  // Validate that either metadata or metadataList is provided
@@ -186,13 +259,29 @@ export async function syncPageIndex(options) {
186
259
  // Step 2: Parse existing content and check if our specific page needs updating
187
260
  const existingMarkdown = existingContent.trim() ? existingContent : undefined;
188
261
  let existingPages = [];
262
+ let existingMetadata = null;
189
263
  if (existingMarkdown) {
190
- const parsed = await markdownToMetadata(existingMarkdown);
191
- if (parsed) {
192
- existingPages = parsed.pages;
264
+ existingMetadata = await markdownToMetadata(existingMarkdown);
265
+ if (existingMetadata) {
266
+ existingPages = existingMetadata.pages;
193
267
  }
194
268
  }
195
269
 
270
+ // Refresh the page-index cache from the committed markdown for the "nothing to write"
271
+ // exits, so the next cold loadServerPageIndex read stays warm without re-parsing.
272
+ const saveExistingIndexCache = async () => {
273
+ if (cacheDir && existingMetadata) {
274
+ await savePageIndexCache({
275
+ cacheDir,
276
+ indexPath,
277
+ rootContext,
278
+ markdown: existingContent,
279
+ metadata: existingMetadata,
280
+ defaultPageMetadata: false
281
+ });
282
+ }
283
+ };
284
+
196
285
  // Step 3: Check if any of our metadata items need updating
197
286
  let needsUpdate = false;
198
287
  for (const metaItem of metadataArray) {
@@ -213,14 +302,36 @@ export async function syncPageIndex(options) {
213
302
  }
214
303
  }
215
304
  if (!needsUpdate) {
216
- // All pages are already up-to-date, no need to acquire lock or write
305
+ await saveExistingIndexCache();
306
+
307
+ // All pages are already up-to-date, no need to acquire lock or write the index.
217
308
  return;
218
309
  }
219
310
 
220
- // If errorIfOutOfDate is true, throw an error instead of updating
311
+ // If errorIfOutOfDate is true, the writer would refuse to touch the file. The coarse
312
+ // per-page comparison above compares the raw in-memory metadata, which contains fields
313
+ // that never reach the persisted index (volatile AST node positions, or metadata that
314
+ // mergeMetadataPages fills in from the existing markdown). Those produce false positives.
315
+ // Determine whether the index is genuinely out of date by rendering the exact markdown
316
+ // the writer would produce and comparing it to what is committed on disk. Only fail when
317
+ // the rendered output actually differs. This is validation only - it never writes, so it
318
+ // works from the pre-lock read (existingMarkdown/existingPages) rather than re-reading
319
+ // under a lock like the writer does.
221
320
  if (errorIfOutOfDate) {
222
- const relativeIndexPath = baseDir ? relative(resolve(baseDir), indexPath) : indexPath;
223
- 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.`);
321
+ const relativeIndexPath = baseDir ? relative(resolve(baseDir), indexPath) : undefined;
322
+ const {
323
+ finalMarkdown
324
+ } = await renderIndexPages(existingMarkdown, existingPages, metadataArray, {
325
+ indexTitle,
326
+ indexWrapperComponent,
327
+ preserveExistingTitleAndSlug,
328
+ relativeIndexPath
329
+ });
330
+ if (existingContent !== finalMarkdown) {
331
+ throw new Error(`Index file is out of date: ${relativeIndexPath ?? indexPath}\n` + `Please run the validation command (or next build) locally and commit the updated index files.`);
332
+ }
333
+ await saveExistingIndexCache();
334
+ return;
224
335
  }
225
336
 
226
337
  // Step 4: Ensure the file exists before locking (proper-lockfile requires an existing file)
@@ -266,39 +377,24 @@ export async function syncPageIndex(options) {
266
377
  }
267
378
  }
268
379
 
269
- // For batch updates, merge the metadata items with existing pages
270
- // Build a map keyed by path (not slug) to match mergeMetadataMarkdown's logic
271
- const updatedPagesMap = new Map();
272
-
273
- // First, add all current pages
274
- for (const page of currentPages) {
275
- updatedPagesMap.set(page.path, page);
276
- }
277
-
278
- // Then update/add the new metadata items
279
- for (const metaItem of metadataArray) {
280
- updatedPagesMap.set(metaItem.path, metaItem);
281
- }
282
-
283
- // Convert back to array - this is the COMPLETE list of pages that should exist
284
- const allPages = Array.from(updatedPagesMap.values());
285
-
286
- // Store for parent update
287
- mergedPages = allPages;
288
-
289
- // Re-merge with the latest content, passing the COMPLETE list of pages
290
- // mergeMetadataMarkdown will preserve the order from currentMarkdown
291
- // Only include path in the comment when baseDir is set (otherwise it's an absolute path)
380
+ // Re-merge with the latest content re-read under the lock, passing the COMPLETE list
381
+ // of pages. The returned normalized metadata is reused below to populate the cache
382
+ // without re-parsing what we just wrote.
292
383
  const relativeIndexPath = baseDir ? relative(resolve(baseDir), indexPath) : undefined;
293
- const finalMarkdown = await mergeMetadataMarkdown(currentMarkdown, {
294
- title: indexTitle,
295
- pages: allPages
296
- }, {
384
+ const {
385
+ allPages,
386
+ merged,
387
+ finalMarkdown
388
+ } = await renderIndexPages(currentMarkdown, currentPages, metadataArray, {
389
+ indexTitle,
297
390
  indexWrapperComponent,
298
- path: relativeIndexPath,
299
- preserveExistingTitleAndSlug
391
+ preserveExistingTitleAndSlug,
392
+ relativeIndexPath
300
393
  });
301
394
 
395
+ // Store for parent update
396
+ mergedPages = allPages;
397
+
302
398
  // Defensive check
303
399
  if (!finalMarkdown || !finalMarkdown.trim()) {
304
400
  throw new Error(`Cannot write empty content to ${indexPath}`);
@@ -307,7 +403,23 @@ export async function syncPageIndex(options) {
307
403
  // Step 7: Write only if the final content differs from what's currently on disk
308
404
  if (currentContent !== finalMarkdown) {
309
405
  await writeFile(indexPath, finalMarkdown, 'utf-8');
406
+ }
310
407
 
408
+ // Pre-populate the page-index cache from the in-memory merged metadata so the
409
+ // next cold loadServerPageIndex read skips parsing. The cached read-model must
410
+ // match enrichPageIndex(markdownToMetadata(finalMarkdown)); resolveIndexPageMetadata
411
+ // mirrors the default metadata block that metadataToMarkdown embeds when rendering,
412
+ // so a fresh parse and this build agree. Fails fast on a write error.
413
+ if (cacheDir) {
414
+ await savePageIndexCache({
415
+ cacheDir,
416
+ indexPath,
417
+ rootContext,
418
+ markdown: finalMarkdown,
419
+ metadata: merged.metadata
420
+ });
421
+ }
422
+ if (currentContent !== finalMarkdown) {
311
423
  // Create a marker file unless explicitly disabled
312
424
  if (markerDir) {
313
425
  // Compute relative path for marker (always compute, not used for comments)
@@ -399,7 +511,9 @@ export async function syncPageIndex(options) {
399
511
  exclude,
400
512
  onlyUpdateIndexes,
401
513
  markerDir,
402
- errorIfOutOfDate
514
+ errorIfOutOfDate,
515
+ cacheDir,
516
+ rootContext
403
517
  });
404
518
  }
405
519
  }
@@ -1,5 +1,5 @@
1
- import { type TypesMeta } from "../loadServerTypesMeta/index.mjs";
2
- import { type OrganizeTypesResult } from "../loadServerTypesText/organizeTypesByExport.mjs";
1
+ import type { TypesMeta } from "../loadServerTypesMeta/index.mjs";
2
+ import type { OrganizeTypesResult } from "../loadServerTypesText/organizeTypesByExport.mjs";
3
3
  /**
4
4
  * Options for generating types markdown.
5
5
  */
@@ -62,6 +62,13 @@ export interface SyncTypesOptions {
62
62
  * Each entry has a `pattern` (regex string) and `replacement` string.
63
63
  */
64
64
  descriptionReplacements?: DescriptionReplacement[];
65
+ /**
66
+ * Directory for the sha256-validated JSON cache of the types pipeline. When set, after
67
+ * writing types.md syncTypes pre-populates `{cacheDir}/types-text/{route}.json` with the
68
+ * parsed `TypesSourceData`, leaving it warm for the next cold `loadServerTypesText` read.
69
+ * @default undefined (disabled)
70
+ */
71
+ cacheDir?: string;
65
72
  }
66
73
  /**
67
74
  * Syncs types for a component/hook/function.
@@ -7,6 +7,9 @@ import { loadServerTypesMeta } from "../loadServerTypesMeta/index.mjs";
7
7
  import { namespaceParts as defaultNamespacePartsOrder } from "../loadServerTypesText/order.mjs";
8
8
  import { generateTypesMarkdown } from "./generateTypesMarkdown.mjs";
9
9
  import { syncPageIndex } from "../syncPageIndex/index.mjs";
10
+ import { normalizeTypesSourceDataForCache } from "../loadServerTypesText/normalizeTypesSourceDataForCache.mjs";
11
+ import { TYPES_TEXT_CACHE_NAMESPACE, resolveTypesCacheKey, buildTypesTextCacheContent } from "../loadServerTypesText/resolveTypesCacheKey.mjs";
12
+ import { saveFileCache } from "../cacheUtils/index.mjs";
10
13
  const functionName = 'Sync Types';
11
14
  /**
12
15
  * Helper to process a single TypesMeta and add it to parts, exports, or types.
@@ -174,7 +177,8 @@ export async function syncTypes(options) {
174
177
  const {
175
178
  typesMarkdownPath,
176
179
  rootContext,
177
- updateParentIndex
180
+ updateParentIndex,
181
+ cacheDir
178
182
  } = options;
179
183
 
180
184
  // Derive relative path for logging
@@ -242,6 +246,30 @@ export async function syncTypes(options) {
242
246
  updated = true;
243
247
  }
244
248
 
249
+ // Pre-populate the types.md parse cache from the in-memory meta-derived data — no re-parse.
250
+ // Normalize it to the same JSON shape loadServerTypesText would cache after parsing the
251
+ // generated markdown, so cache hits and cold parses are byte-for-byte equivalent. This runs even
252
+ // when types.md is already up to date so validation can warm the parse cache. Fails fast on a
253
+ // write error.
254
+ if (cacheDir) {
255
+ const typesTextData = normalizeTypesSourceDataForCache({
256
+ exports: organizedExports,
257
+ additionalTypes: organizedAdditionalTypes,
258
+ variantOnlyAdditionalTypes: organizedVariantOnlyAdditionalTypes,
259
+ externalTypes,
260
+ typeNameMap: typeNameMap ?? {},
261
+ variantTypeNames,
262
+ variantTypeNameMaps,
263
+ allDependencies: [typesMarkdownPath],
264
+ updated: false
265
+ });
266
+ await saveFileCache({
267
+ cacheDir,
268
+ namespace: TYPES_TEXT_CACHE_NAMESPACE,
269
+ cacheKey: resolveTypesCacheKey(typesMarkdownPath, rootContext)
270
+ }, buildTypesTextCacheContent(markdown, options.ordering), typesTextData);
271
+ }
272
+
245
273
  // Track allDependencies locally so we can add typesMarkdownPath in production
246
274
  const dependencies = [...allDependencies];
247
275
  if (process.env.NODE_ENV === 'production') {
@@ -283,6 +311,8 @@ export async function syncTypes(options) {
283
311
  markerDir: updateParentIndex.markerDir,
284
312
  onlyUpdateIndexes: updateParentIndex.onlyUpdateIndexes ?? false,
285
313
  errorIfOutOfDate: updateParentIndex.errorIfOutOfDate,
314
+ cacheDir: updateParentIndex.cacheDir,
315
+ rootContext,
286
316
  // Auto-generated title/slug from types should not override user-set values
287
317
  preserveExistingTitleAndSlug: true
288
318
  });
@@ -301,7 +301,7 @@ export const transformHtmlCodeBlock = (options = {}) => {
301
301
 
302
302
  // Parse the source to extract @highlight comments
303
303
  // When displayComments is true, we only collect comments but don't strip them
304
- const parseResult = await parseImportsAndComments(sourceCode, derivedFilename || 'code.txt', {
304
+ const parseResult = parseImportsAndComments(sourceCode, derivedFilename || 'code.txt', {
305
305
  removeCommentsWithPrefix: displayComments ? undefined : [EMPHASIS_COMMENT_PREFIX, FOCUS_COMMENT_PREFIX, ...IGNORE_COMMENT_PREFIXES],
306
306
  notableCommentsPrefix: [EMPHASIS_COMMENT_PREFIX, FOCUS_COMMENT_PREFIX]
307
307
  });