@mui/internal-docs-infra 0.11.1-canary.9 → 0.11.1
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/ChunkProvider/ChunkContext.d.mts +10 -0
- package/ChunkProvider/ChunkContext.mjs +15 -0
- package/ChunkProvider/ChunkProvider.d.mts +14 -0
- package/ChunkProvider/ChunkProvider.mjs +38 -0
- package/ChunkProvider/PreloadContext.d.mts +14 -0
- package/ChunkProvider/PreloadContext.mjs +18 -0
- package/ChunkProvider/PreloadProvider.d.mts +13 -0
- package/ChunkProvider/PreloadProvider.mjs +33 -0
- package/ChunkProvider/index.d.mts +7 -0
- package/ChunkProvider/index.mjs +7 -0
- package/ChunkProvider/types.d.mts +23 -0
- package/ChunkProvider/types.mjs +1 -0
- package/ChunkProvider/usePreload.d.mts +8 -0
- package/ChunkProvider/usePreload.mjs +21 -0
- package/CodeControllerContext/CodeControllerContext.d.mts +11 -0
- package/CodeControllerContext/CodeControllerContext.mjs +2 -1
- package/CodeHighlighter/CodeHighlighter.d.mts +15 -1
- package/CodeHighlighter/CodeHighlighter.mjs +97 -319
- package/CodeHighlighter/CodeHighlighterChunk.d.mts +42 -0
- package/CodeHighlighter/CodeHighlighterChunk.mjs +77 -0
- package/CodeHighlighter/CodeHighlighterClient.mjs +597 -128
- package/CodeHighlighter/CodeHighlighterContext.d.mts +57 -1
- package/CodeHighlighter/CodeHighlighterFallbackContext.d.mts +14 -2
- package/CodeHighlighter/CodeHighlighterFallbackContext.mjs +1 -3
- package/CodeHighlighter/CodeInitialSourceLoader.d.mts +10 -0
- package/CodeHighlighter/CodeInitialSourceLoader.mjs +108 -0
- package/CodeHighlighter/CodeSourceLoader.d.mts +11 -0
- package/CodeHighlighter/CodeSourceLoader.mjs +128 -0
- package/CodeHighlighter/buildCodeHighlighterChunkProps.d.mts +47 -0
- package/CodeHighlighter/buildCodeHighlighterChunkProps.mjs +61 -0
- package/CodeHighlighter/buildStringFallback.d.mts +29 -0
- package/CodeHighlighter/buildStringFallback.mjs +42 -0
- package/CodeHighlighter/codeToFallbackProps.d.mts +31 -2
- package/CodeHighlighter/codeToFallbackProps.mjs +347 -42
- package/CodeHighlighter/createClientProps.d.mts +17 -0
- package/CodeHighlighter/createClientProps.mjs +78 -0
- package/CodeHighlighter/errors.d.mts +6 -0
- package/CodeHighlighter/errors.mjs +10 -0
- package/CodeHighlighter/fallbackCompression.d.mts +96 -0
- package/CodeHighlighter/fallbackCompression.mjs +253 -0
- package/CodeHighlighter/fallbackFormat.d.mts +137 -0
- package/CodeHighlighter/fallbackFormat.mjs +422 -0
- package/CodeHighlighter/index.d.mts +4 -1
- package/CodeHighlighter/index.mjs +3 -1
- package/CodeHighlighter/mergeComments.d.mts +38 -0
- package/CodeHighlighter/mergeComments.mjs +80 -0
- package/CodeHighlighter/prepareInitialSource.d.mts +42 -0
- package/CodeHighlighter/prepareInitialSource.mjs +292 -0
- package/CodeHighlighter/resolveFallbackCritical.d.mts +23 -0
- package/CodeHighlighter/resolveFallbackCritical.mjs +44 -0
- package/CodeHighlighter/types.d.mts +272 -8
- package/CodeHighlighter/useCodeFallback.d.mts +94 -0
- package/CodeHighlighter/useCodeFallback.mjs +204 -0
- package/CodeHighlighter/useGrammarsReady.d.mts +18 -0
- package/CodeHighlighter/useGrammarsReady.mjs +45 -0
- package/CodeHighlighter/useSpeculativeCodePreload.d.mts +26 -0
- package/CodeHighlighter/useSpeculativeCodePreload.mjs +40 -0
- package/CodeHighlighter/useSpeculativeEditingPreload.d.mts +33 -0
- package/CodeHighlighter/useSpeculativeEditingPreload.mjs +58 -0
- package/CodeHighlighter/useSpeculativeGrammarPreload.d.mts +23 -0
- package/CodeHighlighter/useSpeculativeGrammarPreload.mjs +31 -0
- package/CodeHighlighter/useSpeculativeUseCodePreload.d.mts +22 -0
- package/CodeHighlighter/useSpeculativeUseCodePreload.mjs +41 -0
- package/CodeProvider/CodeContext.d.mts +47 -12
- package/CodeProvider/CodeContext.mjs +7 -0
- package/CodeProvider/CodeProvider.d.mts +4 -2
- package/CodeProvider/CodeProvider.mjs +40 -102
- package/CodeProvider/CodeProviderLazy.d.mts +40 -0
- package/CodeProvider/CodeProviderLazy.mjs +96 -0
- package/CodeProvider/constants.d.mts +26 -0
- package/CodeProvider/constants.mjs +24 -0
- package/CodeProvider/createParseSourceWorkerClient.d.mts +6 -0
- package/CodeProvider/createParseSourceWorkerClient.mjs +22 -2
- package/CodeProvider/index.d.mts +2 -1
- package/CodeProvider/index.mjs +9 -1
- package/CodeProvider/parseSourceWorker.mjs +33 -0
- package/CodeProvider/useCodeProviderValue.d.mts +54 -0
- package/CodeProvider/useCodeProviderValue.mjs +188 -0
- package/CoordinatedLazy/ChunkServerLoader.d.mts +25 -0
- package/CoordinatedLazy/ChunkServerLoader.mjs +97 -0
- package/CoordinatedLazy/CoordinatedContentContext.d.mts +15 -0
- package/CoordinatedLazy/CoordinatedContentContext.mjs +22 -0
- package/CoordinatedLazy/CoordinatedFallbackContext.d.mts +11 -0
- package/CoordinatedLazy/CoordinatedFallbackContext.mjs +13 -0
- package/CoordinatedLazy/CoordinatedGateContext.d.mts +14 -0
- package/CoordinatedLazy/CoordinatedGateContext.mjs +19 -0
- package/CoordinatedLazy/CoordinatedLazy.d.mts +14 -0
- package/CoordinatedLazy/CoordinatedLazy.mjs +86 -0
- package/CoordinatedLazy/CoordinatedLazyClient.d.mts +24 -0
- package/CoordinatedLazy/CoordinatedLazyClient.mjs +65 -0
- package/CoordinatedLazy/LazyContent.d.mts +26 -0
- package/CoordinatedLazy/LazyContent.mjs +80 -0
- package/CoordinatedLazy/LazyContentServer.d.mts +18 -0
- package/CoordinatedLazy/LazyContentServer.mjs +25 -0
- package/CoordinatedLazy/buildChunkRenderInputs.d.mts +8 -0
- package/CoordinatedLazy/buildChunkRenderInputs.mjs +35 -0
- package/CoordinatedLazy/createCoordinatedLazy.d.mts +32 -0
- package/CoordinatedLazy/createCoordinatedLazy.mjs +127 -0
- package/CoordinatedLazy/index.d.mts +14 -0
- package/CoordinatedLazy/index.mjs +18 -0
- package/CoordinatedLazy/resolveChunkRender.d.mts +26 -0
- package/CoordinatedLazy/resolveChunkRender.mjs +73 -0
- package/CoordinatedLazy/types.d.mts +408 -0
- package/CoordinatedLazy/types.mjs +1 -0
- package/CoordinatedLazy/useChunk.d.mts +30 -0
- package/CoordinatedLazy/useChunk.mjs +135 -0
- package/CoordinatedLazy/useCoordinatedFallback.d.mts +12 -0
- package/CoordinatedLazy/useCoordinatedFallback.mjs +40 -0
- package/CoordinatedLazy/useCoordinatedSwap.d.mts +16 -0
- package/CoordinatedLazy/useCoordinatedSwap.mjs +124 -0
- package/LICENSE +1 -1
- package/abstractCreateDemo/abstractCreateDemo.d.mts +54 -3
- package/abstractCreateDemo/abstractCreateDemo.mjs +47 -7
- package/abstractCreateDemo/resolveDemoFlag.d.mts +20 -0
- package/abstractCreateDemo/resolveDemoFlag.mjs +25 -0
- package/abstractCreateStream/abstractCreateStream.d.mts +18 -0
- package/abstractCreateStream/abstractCreateStream.mjs +45 -0
- package/abstractCreateStream/index.d.mts +2 -0
- package/abstractCreateStream/index.mjs +1 -0
- package/abstractCreateStream/types.d.mts +34 -0
- package/abstractCreateStream/types.mjs +1 -0
- package/abstractCreateTypes/TypeCode.mjs +12 -11
- package/abstractCreateTypes/typesToJsx.mjs +30 -9
- package/cli/ensureDemoClients.mjs +4 -148
- package/cli/ensureDemoPages.d.mts +45 -0
- package/cli/ensureDemoPages.mjs +99 -0
- package/cli/fileUtils/index.d.mts +11 -0
- package/cli/fileUtils/index.mjs +48 -0
- package/cli/findDemoIndexFiles.d.mts +15 -0
- package/cli/findDemoIndexFiles.mjs +121 -0
- package/cli/index.mjs +1 -1
- package/cli/loadNextConfig.d.mts +25 -0
- package/cli/loadNextConfig.mjs +60 -1
- package/cli/runBrowser.mjs +1 -1
- package/cli/runValidate.mjs +44 -1
- package/package.json +84 -4
- package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasis.mjs +30 -0
- package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasisLazy.d.mts +17 -0
- package/pipeline/enhanceCodeEmphasis/enhanceCodeEmphasisLazy.mjs +52 -0
- package/pipeline/hastUtils/frameFallbackFromSpans.d.mts +18 -0
- package/pipeline/hastUtils/frameFallbackFromSpans.mjs +24 -0
- package/pipeline/hastUtils/hast.d.mts +27 -0
- package/pipeline/hastUtils/hastCompression.d.mts +3 -1
- package/pipeline/hastUtils/hastCompression.mjs +9 -1
- package/pipeline/hastUtils/hastDecompress.mjs +10 -4
- package/pipeline/hastUtils/hastDictionary.mjs +9 -0
- package/pipeline/hastUtils/hastUtils.d.mts +4 -3
- package/pipeline/hastUtils/hastUtils.mjs +24 -12
- package/pipeline/hastUtils/index.d.mts +2 -1
- package/pipeline/hastUtils/index.mjs +2 -1
- package/pipeline/hastUtils/stripHighlightingSpans.d.mts +6 -2
- package/pipeline/hastUtils/stripHighlightingSpans.mjs +22 -10
- package/pipeline/lintJavascriptDemoFocus/lintJavascriptDemoFocus.mjs +10 -7
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.d.mts +31 -13
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransform.mjs +50 -55
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransformWithComments.d.mts +78 -0
- package/pipeline/loadIsomorphicCodeVariant/applyCodeTransformWithComments.mjs +405 -0
- package/pipeline/loadIsomorphicCodeVariant/computeHastDeltas.d.mts +5 -5
- package/pipeline/loadIsomorphicCodeVariant/computeHastDeltas.mjs +36 -66
- package/pipeline/loadIsomorphicCodeVariant/decodeHastSource.d.mts +23 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeHastSource.mjs +92 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeSource.d.mts +19 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeSource.mjs +25 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeSourceToText.d.mts +17 -0
- package/pipeline/loadIsomorphicCodeVariant/decodeSourceToText.mjs +26 -0
- package/pipeline/loadIsomorphicCodeVariant/diffHast.d.mts +26 -2
- package/pipeline/loadIsomorphicCodeVariant/diffHast.mjs +563 -19
- package/pipeline/loadIsomorphicCodeVariant/embedTransforms.d.mts +49 -0
- package/pipeline/loadIsomorphicCodeVariant/embedTransforms.mjs +152 -0
- package/pipeline/loadIsomorphicCodeVariant/findExpandingRanges.d.mts +51 -0
- package/pipeline/loadIsomorphicCodeVariant/findExpandingRanges.mjs +161 -0
- package/pipeline/loadIsomorphicCodeVariant/flattenCodeVariant.mjs +6 -3
- package/pipeline/loadIsomorphicCodeVariant/getAvailableTransforms.d.mts +12 -0
- package/pipeline/loadIsomorphicCodeVariant/getAvailableTransforms.mjs +44 -0
- package/pipeline/loadIsomorphicCodeVariant/getInitialVisibleSourceLines.d.mts +16 -0
- package/pipeline/loadIsomorphicCodeVariant/getInitialVisibleSourceLines.mjs +74 -0
- package/pipeline/loadIsomorphicCodeVariant/loadCodeFallback.mjs +17 -5
- package/pipeline/loadIsomorphicCodeVariant/loadIsomorphicCodeVariant.mjs +229 -15
- package/pipeline/loadIsomorphicCodeVariant/transformSource.d.mts +2 -2
- package/pipeline/loadIsomorphicCodeVariant/transformSource.mjs +56 -22
- package/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.d.mts +18 -0
- package/pipeline/loadPrecomputedCodeHighlighter/loadPrecomputedCodeHighlighter.mjs +11 -7
- package/pipeline/loadServerTypes/hastTypeUtils.d.mts +2 -2
- package/pipeline/loadServerTypes/hastTypeUtils.mjs +4 -4
- package/pipeline/loadServerTypes/loadServerTypes.mjs +1 -1
- package/pipeline/loadServerTypesMeta/extractJSDocText.d.mts +14 -0
- package/pipeline/loadServerTypesMeta/extractJSDocText.mjs +60 -0
- package/pipeline/loadServerTypesMeta/processTypes.mjs +43 -46
- package/pipeline/loadServerTypesText/order.mjs +1 -1
- package/pipeline/loadServerTypesText/parseTypesMarkdown.mjs +3 -1
- package/pipeline/loaderUtils/index.d.mts +0 -1
- package/pipeline/loaderUtils/index.mjs +0 -1
- package/pipeline/loaderUtils/parseImportsAndComments.d.mts +5 -1
- package/pipeline/loaderUtils/parseImportsAndComments.mjs +19 -9
- package/pipeline/loaderUtils/resolveModulePath.mjs +23 -1
- package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.d.mts +12 -0
- package/pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs +17 -13
- package/pipeline/parseSource/addLineGutters.mjs +45 -11
- package/pipeline/parseSource/calculateFrameRanges.d.mts +22 -0
- package/pipeline/parseSource/calculateFrameRanges.mjs +69 -25
- package/pipeline/parseSource/detectGrammarScopes.d.mts +13 -0
- package/pipeline/parseSource/detectGrammarScopes.mjs +35 -0
- package/pipeline/parseSource/extendSyntaxTokens.mjs +501 -43
- package/pipeline/parseSource/frameVisibility.d.mts +47 -0
- package/pipeline/parseSource/frameVisibility.mjs +114 -0
- package/pipeline/parseSource/grammarCache.d.mts +33 -0
- package/pipeline/parseSource/grammarCache.mjs +73 -0
- package/pipeline/parseSource/grammarLoaders.d.mts +14 -0
- package/pipeline/parseSource/grammarLoaders.mjs +24 -0
- package/pipeline/parseSource/grammarMaps.d.mts +21 -1
- package/pipeline/parseSource/grammarMaps.mjs +36 -0
- package/pipeline/parseSource/isFrameSpan.d.mts +19 -0
- package/pipeline/parseSource/isFrameSpan.mjs +24 -0
- package/pipeline/parseSource/parseSource.d.mts +41 -6
- package/pipeline/parseSource/parseSource.mjs +184 -36
- package/pipeline/parseSource/redistributeFrameFallbacks.d.mts +40 -0
- package/pipeline/parseSource/redistributeFrameFallbacks.mjs +138 -0
- package/pipeline/parseSource/restructureFrames.d.mts +5 -0
- package/pipeline/parseSource/restructureFrames.mjs +179 -16
- package/pipeline/syncPageIndex/metadataToMarkdown.mjs +6 -2
- package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.d.mts +26 -0
- package/pipeline/transformHtmlCodeBlock/transformHtmlCodeBlock.mjs +181 -114
- package/pipeline/transformHtmlCodeInline/removeSuffixFromHighlightedNodes.d.mts +12 -0
- package/pipeline/transformHtmlCodeInline/removeSuffixFromHighlightedNodes.mjs +52 -0
- package/pipeline/transformHtmlCodeInline/transformHtmlCodeInline.mjs +22 -1
- package/pipeline/transformTypescriptToJavascript/removeTypes.d.mts +5 -8
- package/pipeline/transformTypescriptToJavascript/removeTypes.mjs +27 -93
- package/useCode/EditableEngine.d.mts +233 -0
- package/useCode/EditableEngine.mjs +1712 -0
- package/useCode/EditingEngine.d.mts +13 -0
- package/useCode/EditingEngine.mjs +14 -0
- package/useCode/Pre.browser.mjs +5 -1
- package/useCode/Pre.d.mts +127 -1
- package/useCode/Pre.mjs +417 -165
- package/useCode/SourceEditingEngine.d.mts +50 -0
- package/useCode/SourceEditingEngine.mjs +461 -0
- package/useCode/TransformEngine.d.mts +39 -0
- package/useCode/TransformEngine.mjs +208 -0
- package/useCode/editingEngineCache.d.mts +29 -0
- package/useCode/editingEngineCache.mjs +68 -0
- package/useCode/sourceLineCounts.d.mts +80 -0
- package/useCode/sourceLineCounts.mjs +284 -0
- package/useCode/subscribeToggleNudge.d.mts +3 -0
- package/useCode/subscribeToggleNudge.mjs +95 -0
- package/useCode/transformEngineCache.d.mts +21 -0
- package/useCode/transformEngineCache.mjs +60 -0
- package/useCode/useCode.d.mts +140 -1
- package/useCode/useCode.mjs +250 -19
- package/useCode/useCodeUtils.d.mts +131 -20
- package/useCode/useCodeUtils.mjs +267 -194
- package/useCode/useCopyFunctionality.d.mts +13 -1
- package/useCode/useCopyFunctionality.mjs +39 -9
- package/useCode/useEditable.browser.mjs +10 -2
- package/useCode/useEditable.d.mts +27 -106
- package/useCode/useEditable.integration.browser.d.mts +1 -0
- package/useCode/useEditable.integration.browser.mjs +870 -0
- package/useCode/useEditable.mjs +198 -1247
- package/useCode/useEditableUtils.d.mts +50 -1
- package/useCode/useEditableUtils.mjs +29 -0
- package/useCode/useFileNavigation.d.mts +91 -3
- package/useCode/useFileNavigation.mjs +201 -41
- package/useCode/useHighlightGate.d.mts +17 -0
- package/useCode/useHighlightGate.mjs +147 -0
- package/useCode/useSourceEditing.d.mts +8 -0
- package/useCode/useSourceEditing.mjs +158 -314
- package/useCode/useSourceEnhancing.d.mts +5 -1
- package/useCode/useSourceEnhancing.mjs +22 -36
- package/useCode/useTransformManagement.d.mts +93 -5
- package/useCode/useTransformManagement.mjs +496 -28
- package/useCode/useTransitionPhase.d.mts +24 -0
- package/useCode/useTransitionPhase.mjs +49 -0
- package/useCode/useUIState.d.mts +2 -2
- package/useCode/useUIState.mjs +8 -8
- package/useCode/useVariantSelection.d.mts +130 -6
- package/useCode/useVariantSelection.mjs +529 -93
- package/useCodeWindow/useCodeWindow.d.mts +19 -2
- package/useCodeWindow/useCodeWindow.mjs +98 -71
- package/useCoordinated/coordinatePreference.d.mts +439 -0
- package/useCoordinated/coordinatePreference.mjs +951 -0
- package/useCoordinated/coordinatePreference.testUtils.d.mts +21 -0
- package/useCoordinated/coordinatePreference.testUtils.mjs +69 -0
- package/useCoordinated/createSettleGate.d.mts +96 -0
- package/useCoordinated/createSettleGate.mjs +171 -0
- package/useCoordinated/index.d.mts +8 -0
- package/useCoordinated/index.mjs +8 -0
- package/useCoordinated/layoutShiftGate.d.mts +24 -0
- package/useCoordinated/layoutShiftGate.mjs +79 -0
- package/useCoordinated/pageSettleGate.d.mts +11 -0
- package/useCoordinated/pageSettleGate.mjs +13 -0
- package/useCoordinated/scheduleTasks.d.mts +23 -0
- package/useCoordinated/scheduleTasks.mjs +45 -0
- package/useCoordinated/useCoordinated.d.mts +193 -0
- package/useCoordinated/useCoordinated.mjs +469 -0
- package/useCoordinated/useCoordinatedLazy.d.mts +17 -0
- package/useCoordinated/useCoordinatedLazy.mjs +38 -0
- package/useCoordinated/useCoordinatedLocalStorage.d.mts +16 -0
- package/useCoordinated/useCoordinatedLocalStorage.mjs +22 -0
- package/useCoordinated/useCoordinatedPreference.d.mts +20 -0
- package/useCoordinated/useCoordinatedPreference.mjs +26 -0
- package/useCoordinated/useSettleGate.d.mts +11 -0
- package/useCoordinated/useSettleGate.mjs +34 -0
- package/useDemo/exportVariant.d.mts +12 -5
- package/useDemo/exportVariant.mjs +59 -5
- package/useDemo/useDemo.d.mts +5 -2
- package/useScrollAnchor/useScrollAnchor.mjs +28 -5
- package/useStream/index.d.mts +6 -0
- package/useStream/index.mjs +6 -0
- package/useStream/streamChunks.d.mts +23 -0
- package/useStream/streamChunks.mjs +85 -0
- package/useStream/types.d.mts +45 -0
- package/useStream/types.mjs +1 -0
- package/useStream/useStream.d.mts +57 -0
- package/useStream/useStream.mjs +119 -0
- package/useStream/useStreamController.d.mts +15 -0
- package/useStream/useStreamController.mjs +90 -0
- package/withDocsInfra/withDocsInfra.d.mts +19 -0
- package/withDocsInfra/withDocsInfra.mjs +13 -5
- package/pipeline/loaderUtils/convertCommentsToOneIndexed.d.mts +0 -8
- package/pipeline/loaderUtils/convertCommentsToOneIndexed.mjs +0 -16
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type * as React from 'react';
|
|
2
|
+
import type { CreateChunkConfig } from "../CoordinatedLazy/types.mjs";
|
|
3
|
+
/**
|
|
4
|
+
* Options bound by {@link createStreamFactory}. Extends the chunk config with
|
|
5
|
+
* an optional client provider (e.g. a `ChunkProvider` supplying client loaders,
|
|
6
|
+
* or a `PreloadProvider`) wrapped around the chunk.
|
|
7
|
+
*
|
|
8
|
+
* All loader functions on the config are expected to be dynamically imported by
|
|
9
|
+
* the caller's module, so they can be bundled (and never called) on the client;
|
|
10
|
+
* add `import 'server-only'` to a loader module to keep a sensitive loader off
|
|
11
|
+
* the client entirely.
|
|
12
|
+
*/
|
|
13
|
+
export interface AbstractCreateStreamOptions<T extends {} = {}, P = unknown, O = unknown> extends CreateChunkConfig<T, P, O> {
|
|
14
|
+
/** Client provider wrapped around the chunk (loaders, preload dedup, etc.). */
|
|
15
|
+
ClientProvider?: React.ComponentType<{
|
|
16
|
+
children: React.ReactNode;
|
|
17
|
+
}>;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Per-call metadata, injected by the build-time loader (mirrors
|
|
21
|
+
* `CreateDemoMeta`). `precompute` is the chunk's build-time data, rendered
|
|
22
|
+
* directly without a client fetch.
|
|
23
|
+
*/
|
|
24
|
+
export interface CreateStreamMeta<P = unknown, O = unknown> {
|
|
25
|
+
name?: string;
|
|
26
|
+
slug?: string;
|
|
27
|
+
displayName?: string;
|
|
28
|
+
/** Skip build-time precomputation for this call. */
|
|
29
|
+
skipPrecompute?: boolean;
|
|
30
|
+
/** Build-time precomputed value, rendered as the chunk's data. */
|
|
31
|
+
precompute?: P;
|
|
32
|
+
/** Default loader options for this call. */
|
|
33
|
+
loaderOptions?: O;
|
|
34
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -4,6 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import { decompressHast, hastToJsx } from "../pipeline/hastUtils/index.mjs";
|
|
5
5
|
import { useCodeComponents } from "../useCode/CodeComponentsContext.mjs";
|
|
6
6
|
import { fallbackToHast, fallbackToText } from "../pipeline/hastUtils/fallbackFormat.mjs";
|
|
7
|
+
import { requestIdle } from "../useCoordinated/scheduleTasks.mjs";
|
|
7
8
|
/**
|
|
8
9
|
* Find the children of the first `<code>` element in a parsed HAST tree.
|
|
9
10
|
*/
|
|
@@ -50,10 +51,15 @@ export function TypeCode({
|
|
|
50
51
|
const [isVisible, setIsVisible] = React.useState(effectiveMode !== 'visible');
|
|
51
52
|
const [codeElement, setCodeElement] = React.useState(null);
|
|
52
53
|
|
|
53
|
-
//
|
|
54
|
-
|
|
54
|
+
// Re-seed visibility state during render when the effective mode changes
|
|
55
|
+
// (the 'store previous prop value, set state during render' pattern). The
|
|
56
|
+
// IntersectionObserver effect still owns runtime true/false toggling because
|
|
57
|
+
// it runs after this render-time seed.
|
|
58
|
+
const [prevEffectiveMode, setPrevEffectiveMode] = React.useState(effectiveMode);
|
|
59
|
+
if (prevEffectiveMode !== effectiveMode) {
|
|
60
|
+
setPrevEffectiveMode(effectiveMode);
|
|
55
61
|
setIsVisible(effectiveMode !== 'visible');
|
|
56
|
-
}
|
|
62
|
+
}
|
|
57
63
|
|
|
58
64
|
// Convert compact fallback to HAST for rendering.
|
|
59
65
|
const fallbackHastRoot = React.useMemo(() => fallback ? fallbackToHast(fallback) : undefined, [fallback]);
|
|
@@ -143,14 +149,9 @@ export function TypeCode({
|
|
|
143
149
|
}
|
|
144
150
|
|
|
145
151
|
// 'idle' and 'visible' both defer to idle time to avoid blocking the main thread.
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
});
|
|
150
|
-
return () => cancelIdleCallback(id);
|
|
151
|
-
}
|
|
152
|
-
const id = setTimeout(parse, 0);
|
|
153
|
-
return () => clearTimeout(id);
|
|
152
|
+
return requestIdle(parse, {
|
|
153
|
+
timeout: 2000
|
|
154
|
+
});
|
|
154
155
|
}, [isVisible, hastJson, hastCompressed, effectiveMode, textDictionary]);
|
|
155
156
|
const highlighted = React.useMemo(() => hast !== null ? hastToJsx(hast, components) : null, [hast, components]);
|
|
156
157
|
const content = highlighted ?? fallbackJsx;
|
|
@@ -157,6 +157,12 @@ function getOrCreateProcessor(enhancers) {
|
|
|
157
157
|
/**
|
|
158
158
|
* Deserialize a HAST input that may be a live tree, JSON string, or dictionary-compressed base64.
|
|
159
159
|
* Returns the parsed tree and whether it's a fresh copy (no clone needed).
|
|
160
|
+
*
|
|
161
|
+
* This function decompresses using the **static dictionary only** (no textContent).
|
|
162
|
+
* It must only receive payloads that were compressed without a text dictionary.
|
|
163
|
+
* The deferred rendering path (`hastToJsxDeferred`) re-compresses with a text
|
|
164
|
+
* dictionary derived from the fallback HAST and passes the fallback as a prop
|
|
165
|
+
* so the client can reconstruct the same dictionary for decompression.
|
|
160
166
|
*/
|
|
161
167
|
function deserializeHast(input) {
|
|
162
168
|
if (typeof input === 'object' && input !== null) {
|
|
@@ -293,28 +299,43 @@ function hastToJsxDeferred(hastOrJson, components, enhancers, highlightAt) {
|
|
|
293
299
|
return hastToJsxBase(hast, components);
|
|
294
300
|
}
|
|
295
301
|
|
|
296
|
-
// Build links-only fallback from enhanced inner children
|
|
302
|
+
// Build links-only fallback from enhanced inner children.
|
|
303
|
+
// This is passed to the client component as a prop in compact format,
|
|
304
|
+
// serving two purposes:
|
|
305
|
+
// 1. Converted to HAST and rendered as the initial display until the full highlight is ready.
|
|
306
|
+
// 2. Its text is used as DEFLATE dictionary for decompression.
|
|
297
307
|
const linksOnlyRoot = stripHighlightingSpans({
|
|
298
308
|
type: 'root',
|
|
299
309
|
children: [...codeElement.children]
|
|
300
310
|
});
|
|
301
311
|
const fallback = hastToFallback(linksOnlyRoot);
|
|
302
|
-
const textContent = fallbackToText(fallback);
|
|
303
312
|
|
|
304
|
-
//
|
|
305
|
-
//
|
|
306
|
-
//
|
|
307
|
-
//
|
|
313
|
+
// Derive dictionary text from the fallback, then compress the full
|
|
314
|
+
// highlighted HAST with that dictionary. On the client, TypeCode
|
|
315
|
+
// calls fallbackToText(fallback) to reconstruct the same dictionary.
|
|
316
|
+
// Serialize the enhanced HAST (post-enhancer) for the client. DEFLATE-compressing it
|
|
317
|
+
// (with the fallback text as the dictionary) only shrinks the server→client wire, so
|
|
318
|
+
// do it ONLY on the server. On the client there is no wire — the JSON is consumed
|
|
319
|
+
// in-process by TypeCode — so skip the synchronous, main-thread compress and hand it
|
|
320
|
+
// the JSON directly; TypeCode reads `hastJson` without decompressing (it only rebuilds
|
|
321
|
+
// the DEFLATE dictionary from `fallback` when it actually has a `hastCompressed`
|
|
322
|
+
// payload). `typeof window` is the isomorphic server check.
|
|
308
323
|
const enhancedJson = JSON.stringify(hast);
|
|
309
|
-
const
|
|
324
|
+
const hastPayload = typeof window === 'undefined' ? {
|
|
325
|
+
hastCompressed: compressHast(enhancedJson, fallbackToText(fallback))
|
|
326
|
+
} : {
|
|
327
|
+
hastJson: enhancedJson
|
|
328
|
+
};
|
|
310
329
|
|
|
311
330
|
// Find the <pre> element for wrapper props
|
|
312
331
|
const preElement = findPreElement(hast);
|
|
313
332
|
const PreComponent = components?.pre ?? 'pre';
|
|
314
333
|
|
|
315
|
-
// Build pre > TypeCode wrapper explicitly
|
|
334
|
+
// Build pre > TypeCode wrapper explicitly.
|
|
335
|
+
// fallback crosses the boundary as a serialized prop — no separate
|
|
336
|
+
// text dictionary string is needed.
|
|
316
337
|
return /*#__PURE__*/React.createElement(PreComponent, hastPropsToReactProps(preElement?.properties), /*#__PURE__*/React.createElement(TypeCode, {
|
|
317
|
-
|
|
338
|
+
...hastPayload,
|
|
318
339
|
highlightAt,
|
|
319
340
|
fallback,
|
|
320
341
|
codeProps: hastPropsToReactProps(codeElement.properties)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
|
-
import { readFile, writeFile
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { parseCreateFactoryCall } from "../pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs";
|
|
4
4
|
import { serializeFunctionArguments } from "../pipeline/parseCreateFactoryCall/serializeFunctionArguments.mjs";
|
|
5
|
+
import { findDemoIndexFiles } from "./findDemoIndexFiles.mjs";
|
|
6
|
+
import { fileExists, formatWithPrettier } from "./fileUtils/index.mjs";
|
|
5
7
|
const CLIENT_FILE_NAME = 'client.ts';
|
|
6
|
-
const INDEX_FILE_NAME = 'index.ts';
|
|
7
8
|
const CLIENT_PROVIDER_IDENTIFIER = 'ClientProvider';
|
|
8
9
|
const CLIENT_RELATIVE_IMPORT = './client';
|
|
9
10
|
/**
|
|
@@ -171,117 +172,6 @@ function insertClientProviderImport(source, importsAndComments) {
|
|
|
171
172
|
return `${source.slice(0, cursor)}\n${importLine}${source.slice(cursor)}`;
|
|
172
173
|
}
|
|
173
174
|
|
|
174
|
-
/**
|
|
175
|
-
* Converts a Turbopack-style glob (e.g. `./app/**\/demos/*\/index.ts`) to a
|
|
176
|
-
* RegExp that matches absolute filesystem paths. Mirrors the logic used by
|
|
177
|
-
* `withDocsInfra` for webpack rule generation. Pass-through when the input is
|
|
178
|
-
* already a RegExp (webpack-rule `test` regexes).
|
|
179
|
-
*/
|
|
180
|
-
function patternToRegExp(pattern) {
|
|
181
|
-
if (pattern instanceof RegExp) {
|
|
182
|
-
return pattern;
|
|
183
|
-
}
|
|
184
|
-
const SEP = '\u0000SEP\u0000';
|
|
185
|
-
const NOT_SEP = '\u0000NOT_SEP\u0000';
|
|
186
|
-
const DOUBLE_STAR = '\u0000DOUBLE_STAR\u0000';
|
|
187
|
-
const body = pattern.replace(/^\.\//, '') // drop leading ./
|
|
188
|
-
.replace(/\*\*\//g, DOUBLE_STAR).replace(/\*/g, NOT_SEP).replace(/\./g, '\\.').replace(new RegExp(DOUBLE_STAR, 'g'), `(?:${NOT_SEP}${SEP})*`).replace(/\//g, SEP).replace(new RegExp(NOT_SEP, 'g'), '[^/\\\\]+').replace(new RegExp(SEP, 'g'), '[/\\\\]');
|
|
189
|
-
return new RegExp(`(?:^|[/\\\\])${body}$`);
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
/**
|
|
193
|
-
* Finds the longest fixed-prefix directory in a glob pattern so we can avoid
|
|
194
|
-
* walking the entire workspace. Webpack `test` regexes have no extractable
|
|
195
|
-
* prefix, so we fall back to walking from `baseDir`.
|
|
196
|
-
*/
|
|
197
|
-
function patternBaseDir(pattern, baseDir) {
|
|
198
|
-
if (pattern instanceof RegExp) {
|
|
199
|
-
return baseDir;
|
|
200
|
-
}
|
|
201
|
-
const stripped = pattern.replace(/^\.\//, '');
|
|
202
|
-
const segments = stripped.split('/');
|
|
203
|
-
const fixed = [];
|
|
204
|
-
for (const segment of segments) {
|
|
205
|
-
if (segment.includes('*')) {
|
|
206
|
-
break;
|
|
207
|
-
}
|
|
208
|
-
fixed.push(segment);
|
|
209
|
-
}
|
|
210
|
-
return path.join(baseDir, ...fixed);
|
|
211
|
-
}
|
|
212
|
-
async function findIndexFilesForPatterns(baseDir, patterns) {
|
|
213
|
-
// Map from absolute index.ts path → matching pattern (first wins).
|
|
214
|
-
const results = new Map();
|
|
215
|
-
// Group patterns by their fixed prefix to share filesystem walks.
|
|
216
|
-
const prefixes = new Map();
|
|
217
|
-
for (const pattern of patterns) {
|
|
218
|
-
const prefix = patternBaseDir(pattern, baseDir);
|
|
219
|
-
const existing = prefixes.get(prefix);
|
|
220
|
-
if (existing) {
|
|
221
|
-
existing.push(pattern);
|
|
222
|
-
} else {
|
|
223
|
-
prefixes.set(prefix, [pattern]);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
const compiledPatterns = patterns.map(pattern => ({
|
|
227
|
-
pattern,
|
|
228
|
-
regex: patternToRegExp(pattern)
|
|
229
|
-
}));
|
|
230
|
-
await Promise.all(Array.from(prefixes.keys()).map(async prefix => {
|
|
231
|
-
const indexFiles = await collectIndexFiles(prefix);
|
|
232
|
-
for (const filePath of indexFiles) {
|
|
233
|
-
if (results.has(filePath)) {
|
|
234
|
-
continue;
|
|
235
|
-
}
|
|
236
|
-
for (const {
|
|
237
|
-
pattern,
|
|
238
|
-
regex
|
|
239
|
-
} of compiledPatterns) {
|
|
240
|
-
if (regex.test(filePath)) {
|
|
241
|
-
results.set(filePath, pattern);
|
|
242
|
-
break;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
}
|
|
246
|
-
}));
|
|
247
|
-
return results;
|
|
248
|
-
}
|
|
249
|
-
async function collectIndexFiles(dir) {
|
|
250
|
-
const out = [];
|
|
251
|
-
let entries;
|
|
252
|
-
try {
|
|
253
|
-
entries = await readdir(dir, {
|
|
254
|
-
withFileTypes: true
|
|
255
|
-
});
|
|
256
|
-
} catch (error) {
|
|
257
|
-
if (error.code === 'ENOENT') {
|
|
258
|
-
return out;
|
|
259
|
-
}
|
|
260
|
-
throw error;
|
|
261
|
-
}
|
|
262
|
-
await Promise.all(entries.map(async entry => {
|
|
263
|
-
if (entry.name === 'node_modules' || entry.name.startsWith('.')) {
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
266
|
-
const full = path.join(dir, entry.name);
|
|
267
|
-
if (entry.isDirectory()) {
|
|
268
|
-
const sub = await collectIndexFiles(full);
|
|
269
|
-
out.push(...sub);
|
|
270
|
-
} else if (entry.isFile() && entry.name === INDEX_FILE_NAME) {
|
|
271
|
-
out.push(full);
|
|
272
|
-
}
|
|
273
|
-
}));
|
|
274
|
-
return out;
|
|
275
|
-
}
|
|
276
|
-
async function fileExists(filePath) {
|
|
277
|
-
try {
|
|
278
|
-
await access(filePath);
|
|
279
|
-
return true;
|
|
280
|
-
} catch {
|
|
281
|
-
return false;
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
|
|
285
175
|
/**
|
|
286
176
|
* Ensures every demo `index.ts` matched by the configured demo patterns has a
|
|
287
177
|
* sibling `client.ts` and that the `index.ts` wires it up via `ClientProvider`.
|
|
@@ -306,7 +196,7 @@ export async function ensureDemoClients(options) {
|
|
|
306
196
|
// Group requirements by import specifier so each pattern uses its declared value.
|
|
307
197
|
const patterns = requirements.map(entry => entry.pattern);
|
|
308
198
|
const requireClientByPattern = new Map(requirements.map(entry => [entry.pattern, entry.requireClient]));
|
|
309
|
-
const indexFiles = await
|
|
199
|
+
const indexFiles = await findDemoIndexFiles(baseDir, patterns);
|
|
310
200
|
const updatedFiles = [];
|
|
311
201
|
const errors = [];
|
|
312
202
|
await Promise.all(Array.from(indexFiles.entries()).map(async ([indexPath, pattern]) => {
|
|
@@ -348,38 +238,4 @@ export async function ensureDemoClients(options) {
|
|
|
348
238
|
updatedFiles,
|
|
349
239
|
errors
|
|
350
240
|
};
|
|
351
|
-
}
|
|
352
|
-
|
|
353
|
-
/**
|
|
354
|
-
* Cached prettier module reference. Resolved lazily on first use so the
|
|
355
|
-
* dependency stays optional — if the consumer doesn't have prettier installed,
|
|
356
|
-
* we silently return the unformatted content.
|
|
357
|
-
*/
|
|
358
|
-
|
|
359
|
-
let prettierModulePromise;
|
|
360
|
-
async function loadPrettier() {
|
|
361
|
-
if (!prettierModulePromise) {
|
|
362
|
-
prettierModulePromise = import('prettier').catch(() => null);
|
|
363
|
-
}
|
|
364
|
-
return prettierModulePromise;
|
|
365
|
-
}
|
|
366
|
-
|
|
367
|
-
/**
|
|
368
|
-
* Formats `content` with the project's prettier configuration for `filePath`.
|
|
369
|
-
* Falls back to the original content when prettier is not installed or fails.
|
|
370
|
-
*/
|
|
371
|
-
async function formatWithPrettier(content, filePath) {
|
|
372
|
-
const prettier = await loadPrettier();
|
|
373
|
-
if (!prettier) {
|
|
374
|
-
return content;
|
|
375
|
-
}
|
|
376
|
-
try {
|
|
377
|
-
const config = await prettier.resolveConfig(filePath);
|
|
378
|
-
return await prettier.format(content, {
|
|
379
|
-
...config,
|
|
380
|
-
filepath: filePath
|
|
381
|
-
});
|
|
382
|
-
} catch {
|
|
383
|
-
return content;
|
|
384
|
-
}
|
|
385
241
|
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import type { DemoPageRequirement } from "./loadNextConfig.mjs";
|
|
2
|
+
export interface EnsureDemoPagesOptions {
|
|
3
|
+
/** Workspace root used to resolve glob patterns. */
|
|
4
|
+
baseDir: string;
|
|
5
|
+
/** Patterns extracted from next.config that opted into `page.tsx` generation. */
|
|
6
|
+
requirements: DemoPageRequirement[];
|
|
7
|
+
}
|
|
8
|
+
export interface EnsureDemoPagesResult {
|
|
9
|
+
/** Total number of demo `index.ts` files matched across all patterns. */
|
|
10
|
+
demoCount: number;
|
|
11
|
+
/** Workspace-relative paths of files that were created. */
|
|
12
|
+
updatedFiles: string[];
|
|
13
|
+
/** Errors encountered during the run. */
|
|
14
|
+
errors: {
|
|
15
|
+
filePath: string;
|
|
16
|
+
message: string;
|
|
17
|
+
}[];
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Generates the contents for an auto-created demo `page.tsx`. The page renders
|
|
21
|
+
* the demo's named export from the sibling `index.ts` inside a `Page` component,
|
|
22
|
+
* so the demo renders as its own route.
|
|
23
|
+
*
|
|
24
|
+
* Exported for tests and reuse.
|
|
25
|
+
*/
|
|
26
|
+
export declare function generatePageFileContent(exportName: string): string;
|
|
27
|
+
/**
|
|
28
|
+
* Reads the demo's export name from a demo `index.ts` by reusing the same
|
|
29
|
+
* `create*` factory parser the precomputed code highlighter loader uses to load
|
|
30
|
+
* variants. Returns `null` when no named `export const X = create*(...)` is
|
|
31
|
+
* found (e.g. an anonymous default export), since a re-export page needs a name
|
|
32
|
+
* to import.
|
|
33
|
+
*
|
|
34
|
+
* Exported for tests.
|
|
35
|
+
*/
|
|
36
|
+
export declare function findDemoExportName(source: string, filePath: string): Promise<string | null>;
|
|
37
|
+
/**
|
|
38
|
+
* Ensures every demo `index.ts` matched by the configured demo patterns has a
|
|
39
|
+
* sibling `page.tsx` that renders the demo as the route's default export.
|
|
40
|
+
*
|
|
41
|
+
* Existing `page.tsx`/`page.ts` files are left untouched so developers can
|
|
42
|
+
* customise the page (e.g. wrap the demo with additional layout). Returns the
|
|
43
|
+
* list of files that were created, plus any errors encountered.
|
|
44
|
+
*/
|
|
45
|
+
export declare function ensureDemoPages(options: EnsureDemoPagesOptions): Promise<EnsureDemoPagesResult>;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { parseAllCreateFactoryCalls } from "../pipeline/parseCreateFactoryCall/parseCreateFactoryCall.mjs";
|
|
4
|
+
import { findDemoIndexFiles } from "./findDemoIndexFiles.mjs";
|
|
5
|
+
import { fileExists, formatWithPrettier } from "./fileUtils/index.mjs";
|
|
6
|
+
const PAGE_TS_FILE_NAME = 'page.ts';
|
|
7
|
+
const PAGE_TSX_FILE_NAME = 'page.tsx';
|
|
8
|
+
const UNKNOWN_EXPORT_NAME = 'unknown';
|
|
9
|
+
/**
|
|
10
|
+
* Generates the contents for an auto-created demo `page.tsx`. The page renders
|
|
11
|
+
* the demo's named export from the sibling `index.ts` inside a `Page` component,
|
|
12
|
+
* so the demo renders as its own route.
|
|
13
|
+
*
|
|
14
|
+
* Exported for tests and reuse.
|
|
15
|
+
*/
|
|
16
|
+
export function generatePageFileContent(exportName) {
|
|
17
|
+
return [`import * as React from 'react';`, `import { ${exportName} } from '.';`, ``, `export default function Page() {`, ` return <${exportName} />;`, `}`, ``].join('\n');
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Reads the demo's export name from a demo `index.ts` by reusing the same
|
|
22
|
+
* `create*` factory parser the precomputed code highlighter loader uses to load
|
|
23
|
+
* variants. Returns `null` when no named `export const X = create*(...)` is
|
|
24
|
+
* found (e.g. an anonymous default export), since a re-export page needs a name
|
|
25
|
+
* to import.
|
|
26
|
+
*
|
|
27
|
+
* Exported for tests.
|
|
28
|
+
*/
|
|
29
|
+
export async function findDemoExportName(source, filePath) {
|
|
30
|
+
const factories = await parseAllCreateFactoryCalls(source, filePath, {
|
|
31
|
+
allowExternalVariants: true
|
|
32
|
+
});
|
|
33
|
+
const exportName = Object.keys(factories).find(name => name !== UNKNOWN_EXPORT_NAME);
|
|
34
|
+
return exportName ?? null;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Ensures every demo `index.ts` matched by the configured demo patterns has a
|
|
39
|
+
* sibling `page.tsx` that renders the demo as the route's default export.
|
|
40
|
+
*
|
|
41
|
+
* Existing `page.tsx`/`page.ts` files are left untouched so developers can
|
|
42
|
+
* customise the page (e.g. wrap the demo with additional layout). Returns the
|
|
43
|
+
* list of files that were created, plus any errors encountered.
|
|
44
|
+
*/
|
|
45
|
+
export async function ensureDemoPages(options) {
|
|
46
|
+
const {
|
|
47
|
+
baseDir,
|
|
48
|
+
requirements
|
|
49
|
+
} = options;
|
|
50
|
+
if (requirements.length === 0) {
|
|
51
|
+
return {
|
|
52
|
+
demoCount: 0,
|
|
53
|
+
updatedFiles: [],
|
|
54
|
+
errors: []
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const patterns = requirements.map(entry => entry.pattern);
|
|
58
|
+
const indexFiles = await findDemoIndexFiles(baseDir, patterns);
|
|
59
|
+
const updatedFiles = [];
|
|
60
|
+
const errors = [];
|
|
61
|
+
await Promise.all(Array.from(indexFiles.keys()).map(async indexPath => {
|
|
62
|
+
try {
|
|
63
|
+
const dir = path.dirname(indexPath);
|
|
64
|
+
const pageTsPath = path.join(dir, PAGE_TS_FILE_NAME);
|
|
65
|
+
const pageTsxPath = path.join(dir, PAGE_TSX_FILE_NAME);
|
|
66
|
+
|
|
67
|
+
// Only generate the page when neither a .ts nor .tsx page exists. Existing
|
|
68
|
+
// pages are left alone so developers can wrap the demo with extra layout.
|
|
69
|
+
const [pageTsExists, pageTsxExists] = await Promise.all([fileExists(pageTsPath), fileExists(pageTsxPath)]);
|
|
70
|
+
if (pageTsExists || pageTsxExists) {
|
|
71
|
+
return;
|
|
72
|
+
}
|
|
73
|
+
const indexSource = await readFile(indexPath, 'utf-8');
|
|
74
|
+
const exportName = await findDemoExportName(indexSource, indexPath);
|
|
75
|
+
if (!exportName) {
|
|
76
|
+
errors.push({
|
|
77
|
+
filePath: path.relative(baseDir, indexPath),
|
|
78
|
+
message: 'Could not determine the demo export name from a create* factory call.'
|
|
79
|
+
});
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const generated = generatePageFileContent(exportName);
|
|
83
|
+
const formatted = await formatWithPrettier(generated, pageTsxPath);
|
|
84
|
+
await writeFile(pageTsxPath, formatted, 'utf-8');
|
|
85
|
+
updatedFiles.push(path.relative(baseDir, pageTsxPath));
|
|
86
|
+
} catch (error) {
|
|
87
|
+
errors.push({
|
|
88
|
+
filePath: path.relative(baseDir, indexPath),
|
|
89
|
+
message: error?.message ?? String(error)
|
|
90
|
+
});
|
|
91
|
+
}
|
|
92
|
+
}));
|
|
93
|
+
updatedFiles.sort();
|
|
94
|
+
return {
|
|
95
|
+
demoCount: indexFiles.size,
|
|
96
|
+
updatedFiles,
|
|
97
|
+
errors
|
|
98
|
+
};
|
|
99
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Returns whether a path exists on disk. Used to decide whether an
|
|
3
|
+
* auto-generated sibling file (e.g. `client.ts`, `page.ts`) already exists so
|
|
4
|
+
* the validate passes never overwrite developer-authored files.
|
|
5
|
+
*/
|
|
6
|
+
export declare function fileExists(filePath: string): Promise<boolean>;
|
|
7
|
+
/**
|
|
8
|
+
* Formats `content` with the project's prettier configuration for `filePath`.
|
|
9
|
+
* Falls back to the original content when prettier is not installed or fails.
|
|
10
|
+
*/
|
|
11
|
+
export declare function formatWithPrettier(content: string, filePath: string): Promise<string>;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { access } from 'node:fs/promises';
|
|
2
|
+
/**
|
|
3
|
+
* Returns whether a path exists on disk. Used to decide whether an
|
|
4
|
+
* auto-generated sibling file (e.g. `client.ts`, `page.ts`) already exists so
|
|
5
|
+
* the validate passes never overwrite developer-authored files.
|
|
6
|
+
*/
|
|
7
|
+
export async function fileExists(filePath) {
|
|
8
|
+
try {
|
|
9
|
+
await access(filePath);
|
|
10
|
+
return true;
|
|
11
|
+
} catch {
|
|
12
|
+
return false;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Cached prettier module reference. Resolved lazily on first use so the
|
|
18
|
+
* dependency stays optional — if the consumer doesn't have prettier installed,
|
|
19
|
+
* formatting is skipped and the unformatted content is returned.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
let prettierModulePromise;
|
|
23
|
+
async function loadPrettier() {
|
|
24
|
+
if (!prettierModulePromise) {
|
|
25
|
+
prettierModulePromise = import('prettier').catch(() => null);
|
|
26
|
+
}
|
|
27
|
+
return prettierModulePromise;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Formats `content` with the project's prettier configuration for `filePath`.
|
|
32
|
+
* Falls back to the original content when prettier is not installed or fails.
|
|
33
|
+
*/
|
|
34
|
+
export async function formatWithPrettier(content, filePath) {
|
|
35
|
+
const prettier = await loadPrettier();
|
|
36
|
+
if (!prettier) {
|
|
37
|
+
return content;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const config = await prettier.resolveConfig(filePath);
|
|
41
|
+
return await prettier.format(content, {
|
|
42
|
+
...config,
|
|
43
|
+
filepath: filePath
|
|
44
|
+
});
|
|
45
|
+
} catch {
|
|
46
|
+
return content;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Converts a Turbopack-style glob (e.g. `./app/**\/demos/*\/index.ts`) to a
|
|
3
|
+
* RegExp that matches absolute filesystem paths. Mirrors the logic used by
|
|
4
|
+
* `withDocsInfra` for webpack rule generation. Pass-through when the input is
|
|
5
|
+
* already a RegExp (webpack-rule `test` regexes).
|
|
6
|
+
*/
|
|
7
|
+
export declare function patternToRegExp(pattern: string | RegExp): RegExp;
|
|
8
|
+
/**
|
|
9
|
+
* Walks the workspace once per fixed glob prefix and returns a map from each
|
|
10
|
+
* matched demo `index.ts` absolute path to the first pattern that matched it.
|
|
11
|
+
*
|
|
12
|
+
* Shared by `ensureDemoClients` and `ensureDemoPages` so demo discovery stays
|
|
13
|
+
* consistent between the `requireClient` and `requirePage` validate passes.
|
|
14
|
+
*/
|
|
15
|
+
export declare function findDemoIndexFiles(baseDir: string, patterns: (string | RegExp)[]): Promise<Map<string, string | RegExp>>;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { readdir } from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
const INDEX_FILE_NAME = 'index.ts';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Converts a Turbopack-style glob (e.g. `./app/**\/demos/*\/index.ts`) to a
|
|
7
|
+
* RegExp that matches absolute filesystem paths. Mirrors the logic used by
|
|
8
|
+
* `withDocsInfra` for webpack rule generation. Pass-through when the input is
|
|
9
|
+
* already a RegExp (webpack-rule `test` regexes).
|
|
10
|
+
*/
|
|
11
|
+
export function patternToRegExp(pattern) {
|
|
12
|
+
if (pattern instanceof RegExp) {
|
|
13
|
+
return pattern;
|
|
14
|
+
}
|
|
15
|
+
// Sentinels are wrapped in NUL bytes, which cannot occur in a file path or
|
|
16
|
+
// glob. That makes them un-forgeable: the two-pass token substitution below
|
|
17
|
+
// can never synthesize a sentinel by concatenating literal input with inserted
|
|
18
|
+
// replacement output (e.g. an input segment ending in "NOT_" fusing with a
|
|
19
|
+
// freshly-inserted separator). Built via fromCharCode so the source carries no
|
|
20
|
+
// literal NUL bytes.
|
|
21
|
+
const NUL = String.fromCharCode(0);
|
|
22
|
+
const SEP = `${NUL}SEP${NUL}`;
|
|
23
|
+
const NOT_SEP = `${NUL}NOT_SEP${NUL}`;
|
|
24
|
+
const DOUBLE_STAR = `${NUL}DOUBLE_STAR${NUL}`;
|
|
25
|
+
const body = pattern.replace(/^\.\//, '') // drop leading ./
|
|
26
|
+
.replace(/\*\*\//g, DOUBLE_STAR).replace(/\*/g, NOT_SEP).replace(/\./g, '\\.').replace(new RegExp(DOUBLE_STAR, 'g'), `(?:${NOT_SEP}${SEP})*`).replace(/\//g, SEP).replace(new RegExp(NOT_SEP, 'g'), '[^/\\\\]+').replace(new RegExp(SEP, 'g'), '[/\\\\]');
|
|
27
|
+
return new RegExp(`(?:^|[/\\\\])${body}$`);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Finds the longest fixed-prefix directory in a glob pattern so we can avoid
|
|
32
|
+
* walking the entire workspace. Webpack `test` regexes have no extractable
|
|
33
|
+
* prefix, so we fall back to walking from `baseDir`.
|
|
34
|
+
*/
|
|
35
|
+
function patternBaseDir(pattern, baseDir) {
|
|
36
|
+
if (pattern instanceof RegExp) {
|
|
37
|
+
return baseDir;
|
|
38
|
+
}
|
|
39
|
+
const stripped = pattern.replace(/^\.\//, '');
|
|
40
|
+
const segments = stripped.split('/');
|
|
41
|
+
const fixed = [];
|
|
42
|
+
for (const segment of segments) {
|
|
43
|
+
if (segment.includes('*')) {
|
|
44
|
+
break;
|
|
45
|
+
}
|
|
46
|
+
fixed.push(segment);
|
|
47
|
+
}
|
|
48
|
+
return path.join(baseDir, ...fixed);
|
|
49
|
+
}
|
|
50
|
+
async function collectIndexFiles(dir) {
|
|
51
|
+
const out = [];
|
|
52
|
+
let entries;
|
|
53
|
+
try {
|
|
54
|
+
entries = await readdir(dir, {
|
|
55
|
+
withFileTypes: true
|
|
56
|
+
});
|
|
57
|
+
} catch (error) {
|
|
58
|
+
if (error.code === 'ENOENT') {
|
|
59
|
+
return out;
|
|
60
|
+
}
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
await Promise.all(entries.map(async entry => {
|
|
64
|
+
if (entry.name === 'node_modules' || entry.name.startsWith('.')) {
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
const full = path.join(dir, entry.name);
|
|
68
|
+
if (entry.isDirectory()) {
|
|
69
|
+
const sub = await collectIndexFiles(full);
|
|
70
|
+
out.push(...sub);
|
|
71
|
+
} else if (entry.isFile() && entry.name === INDEX_FILE_NAME) {
|
|
72
|
+
out.push(full);
|
|
73
|
+
}
|
|
74
|
+
}));
|
|
75
|
+
return out;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Walks the workspace once per fixed glob prefix and returns a map from each
|
|
80
|
+
* matched demo `index.ts` absolute path to the first pattern that matched it.
|
|
81
|
+
*
|
|
82
|
+
* Shared by `ensureDemoClients` and `ensureDemoPages` so demo discovery stays
|
|
83
|
+
* consistent between the `requireClient` and `requirePage` validate passes.
|
|
84
|
+
*/
|
|
85
|
+
export async function findDemoIndexFiles(baseDir, patterns) {
|
|
86
|
+
// Map from absolute index.ts path → matching pattern (first wins).
|
|
87
|
+
const results = new Map();
|
|
88
|
+
// Group patterns by their fixed prefix to share filesystem walks.
|
|
89
|
+
const prefixes = new Map();
|
|
90
|
+
for (const pattern of patterns) {
|
|
91
|
+
const prefix = patternBaseDir(pattern, baseDir);
|
|
92
|
+
const existing = prefixes.get(prefix);
|
|
93
|
+
if (existing) {
|
|
94
|
+
existing.push(pattern);
|
|
95
|
+
} else {
|
|
96
|
+
prefixes.set(prefix, [pattern]);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
const compiledPatterns = patterns.map(pattern => ({
|
|
100
|
+
pattern,
|
|
101
|
+
regex: patternToRegExp(pattern)
|
|
102
|
+
}));
|
|
103
|
+
await Promise.all(Array.from(prefixes.keys()).map(async prefix => {
|
|
104
|
+
const indexFiles = await collectIndexFiles(prefix);
|
|
105
|
+
for (const filePath of indexFiles) {
|
|
106
|
+
if (results.has(filePath)) {
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
for (const {
|
|
110
|
+
pattern,
|
|
111
|
+
regex
|
|
112
|
+
} of compiledPatterns) {
|
|
113
|
+
if (regex.test(filePath)) {
|
|
114
|
+
results.set(filePath, pattern);
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}));
|
|
120
|
+
return results;
|
|
121
|
+
}
|
package/cli/index.mjs
CHANGED
|
@@ -8,4 +8,4 @@ function getVersion() {
|
|
|
8
8
|
}
|
|
9
9
|
yargs().scriptName('docs-infra').usage('$0 <command> [args]').command(runValidate).command(runBrowser).demandCommand(1, 'You need at least one command before moving on').strict().help()
|
|
10
10
|
// MUI_VERSION is set through the code-infra build command.
|
|
11
|
-
.version("0.11.
|
|
11
|
+
.version("0.11.1" || getVersion()).parse(hideBin(process.argv));
|