@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,208 @@
|
|
|
1
|
+
// The transform-application runtime, split out of `useCodeUtils` so the heavy
|
|
2
|
+
// `applyCodeTransform` path (which statically pulls `jsondiffpatch`) loads only
|
|
3
|
+
// when a block actually applies a transform. `useTransformManagement` reaches it
|
|
4
|
+
// through the `transformEngineLoader` accessor on `CodeContext` (the eager
|
|
5
|
+
// `CodeProvider` bundles it; `CodeProviderLazy` dynamic-imports it), with a
|
|
6
|
+
// built-in fallback so transforms still work without a provider. The pure,
|
|
7
|
+
// manifest-only transform helpers stay in `useCodeUtils` so read-only / no-transform
|
|
8
|
+
// blocks never pull this chunk.
|
|
9
|
+
|
|
10
|
+
// Import the transform core (which takes its hast helpers injected) rather than
|
|
11
|
+
// the `applyCodeTransform` wrapper that binds them, so this dynamic engine chunk
|
|
12
|
+
// never statically pulls `decodeHastSource` / `frameFallbackFromSpans` (and
|
|
13
|
+
// their `hastDecompress` dependency). The helpers are threaded in from the
|
|
14
|
+
// always-loaded `useCode` shell, which already has them, so they stay counted
|
|
15
|
+
// there instead of being hoisted into their own chunks.
|
|
16
|
+
import { applyCodeTransformWithComments } from "../pipeline/loadIsomorphicCodeVariant/applyCodeTransformWithComments.mjs";
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Function signature of {@link createTransformedFiles}. Used by the
|
|
20
|
+
* `transformEngineLoader` accessor and `useTransformManagement` so they can
|
|
21
|
+
* reference the engine without statically importing this (heavy) module.
|
|
22
|
+
*
|
|
23
|
+
* `deps` (the decoder + frame-fallback helper) is injected by the caller (the
|
|
24
|
+
* `useCode` shell already loads them) so this engine chunk doesn't statically
|
|
25
|
+
* depend on them.
|
|
26
|
+
*/
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Pure helper function to apply transform to a source file.
|
|
30
|
+
*
|
|
31
|
+
* @param source - The source code to transform
|
|
32
|
+
* @param fileName - The filename for the source
|
|
33
|
+
* @param transforms - Available transforms for this source
|
|
34
|
+
* @param selectedTransform - The transform to apply
|
|
35
|
+
* @param comments - Optional 1-indexed comment map for the source. Returned
|
|
36
|
+
* shifted onto the transformed source's line numbering.
|
|
37
|
+
* @returns Object with transformed source, name, and shifted comments
|
|
38
|
+
*/
|
|
39
|
+
export function applyTransformToSource(source, fileName, transforms, selectedTransform, deps, comments, fallback) {
|
|
40
|
+
if (!transforms?.[selectedTransform]) {
|
|
41
|
+
return {
|
|
42
|
+
transformedSource: source,
|
|
43
|
+
transformedName: fileName,
|
|
44
|
+
transformedComments: comments
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
try {
|
|
48
|
+
const transformData = transforms[selectedTransform];
|
|
49
|
+
|
|
50
|
+
// Apply transform — `applyCodeTransform` will look up the delta inside
|
|
51
|
+
// `source.data.transforms` if `transformData.delta` is absent (manifest
|
|
52
|
+
// mode after embedding).
|
|
53
|
+
const result = applyCodeTransformWithComments(source, transforms, selectedTransform, deps, comments, fallback);
|
|
54
|
+
const transformedName = transformData.fileName || fileName;
|
|
55
|
+
return {
|
|
56
|
+
transformedSource: result.source,
|
|
57
|
+
transformedName,
|
|
58
|
+
transformedComments: result.comments
|
|
59
|
+
};
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error(`Transform failed for ${fileName}:`, error);
|
|
62
|
+
return {
|
|
63
|
+
transformedSource: source,
|
|
64
|
+
transformedName: fileName,
|
|
65
|
+
transformedComments: comments
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Pure function to create transformed files from a variant and selected transform.
|
|
72
|
+
*
|
|
73
|
+
* @param selectedVariant - The currently selected variant
|
|
74
|
+
* @param selectedTransform - The transform to apply
|
|
75
|
+
* @returns Object with transformed files and filename mapping, or undefined if no transform
|
|
76
|
+
*/
|
|
77
|
+
export function createTransformedFiles(selectedVariant, selectedTransform,
|
|
78
|
+
// Hast helpers injected by the caller (the `useCode` shell), so this engine
|
|
79
|
+
// chunk never statically imports them. See the module comment.
|
|
80
|
+
deps,
|
|
81
|
+
// Per-file DEFLATE dictionaries hoisted from a `ContentLoading` component.
|
|
82
|
+
// A file's fallback may live here (hoisted) instead of on the variant
|
|
83
|
+
// (stripped) — applying a transform must decode `hastCompressed`, so resolve
|
|
84
|
+
// from both, preferring the hoisted copy.
|
|
85
|
+
fallbacks) {
|
|
86
|
+
// Only create transformed files when there's actually a transform selected
|
|
87
|
+
if (!selectedVariant || !selectedTransform) {
|
|
88
|
+
return undefined;
|
|
89
|
+
}
|
|
90
|
+
const files = [];
|
|
91
|
+
const filenameMap = {};
|
|
92
|
+
|
|
93
|
+
// First, check if any file has a transform manifest entry for the selected
|
|
94
|
+
// transform. A manifest entry may carry a real embedded delta (`hasDelta: true`)
|
|
95
|
+
// or be rename-only (`hasDelta: false`) — both cases are "meaningful" here
|
|
96
|
+
// because either the source changes or the filename does.
|
|
97
|
+
const variantTransforms = 'transforms' in selectedVariant ? selectedVariant.transforms : undefined;
|
|
98
|
+
let hasAnyMeaningfulTransform = false;
|
|
99
|
+
|
|
100
|
+
// Check main file for the transform key
|
|
101
|
+
if (selectedVariant.fileName && variantTransforms?.[selectedTransform]) {
|
|
102
|
+
hasAnyMeaningfulTransform = true;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Check extraFiles for the transform key
|
|
106
|
+
if (!hasAnyMeaningfulTransform && selectedVariant.extraFiles) {
|
|
107
|
+
Object.values(selectedVariant.extraFiles).forEach(fileData => {
|
|
108
|
+
if (fileData && typeof fileData === 'object' && 'transforms' in fileData && fileData.transforms?.[selectedTransform]) {
|
|
109
|
+
hasAnyMeaningfulTransform = true;
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// If no file has a meaningful transform, return empty result
|
|
115
|
+
if (!hasAnyMeaningfulTransform) {
|
|
116
|
+
return {
|
|
117
|
+
files: [],
|
|
118
|
+
filenameMap: {}
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Process main file if we have a fileName and source
|
|
123
|
+
if (selectedVariant.fileName && selectedVariant.source) {
|
|
124
|
+
const {
|
|
125
|
+
transformedSource: mainSource,
|
|
126
|
+
transformedName: mainName,
|
|
127
|
+
transformedComments: mainComments
|
|
128
|
+
} = applyTransformToSource(selectedVariant.source, selectedVariant.fileName, variantTransforms, selectedTransform, deps, selectedVariant.comments, (selectedVariant.fileName ? fallbacks?.[selectedVariant.fileName] : undefined) ?? selectedVariant.fallback);
|
|
129
|
+
const fileName = selectedVariant.fileName;
|
|
130
|
+
filenameMap[fileName] = mainName;
|
|
131
|
+
files.push({
|
|
132
|
+
name: mainName,
|
|
133
|
+
originalName: fileName,
|
|
134
|
+
source: mainSource,
|
|
135
|
+
...(mainComments && {
|
|
136
|
+
comments: mainComments
|
|
137
|
+
})
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
// Process extra files
|
|
142
|
+
if (selectedVariant.extraFiles) {
|
|
143
|
+
Object.entries(selectedVariant.extraFiles).forEach(([extraFileName, fileData]) => {
|
|
144
|
+
let source;
|
|
145
|
+
let transforms;
|
|
146
|
+
let fileComments;
|
|
147
|
+
|
|
148
|
+
// Handle different extraFile structures
|
|
149
|
+
if (typeof fileData === 'string') {
|
|
150
|
+
source = fileData;
|
|
151
|
+
transforms = undefined; // Don't inherit variant transforms for simple string files
|
|
152
|
+
} else if (fileData && typeof fileData === 'object' && 'source' in fileData) {
|
|
153
|
+
source = fileData.source;
|
|
154
|
+
transforms = fileData.transforms; // Only use explicit transforms for this file
|
|
155
|
+
fileComments = fileData.comments;
|
|
156
|
+
} else {
|
|
157
|
+
return; // Skip invalid entries
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Skip if source is undefined
|
|
161
|
+
if (!source) {
|
|
162
|
+
return;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// Apply transforms if available, otherwise use original source
|
|
166
|
+
let transformedSource = source;
|
|
167
|
+
let transformedName = extraFileName;
|
|
168
|
+
let transformedComments = fileComments;
|
|
169
|
+
if (transforms?.[selectedTransform]) {
|
|
170
|
+
try {
|
|
171
|
+
const transformData = transforms[selectedTransform];
|
|
172
|
+
// The presence of an entry in the (manifest or legacy) transforms
|
|
173
|
+
// record is enough — `applyCodeTransform` will look up the delta
|
|
174
|
+
// inside `source.data.transforms` if it isn't on the entry.
|
|
175
|
+
const result = applyCodeTransformWithComments(source, transforms, selectedTransform, deps, fileComments, fallbacks?.[extraFileName] ?? (typeof fileData === 'object' ? fileData.fallback : undefined));
|
|
176
|
+
transformedSource = result.source;
|
|
177
|
+
transformedComments = result.comments;
|
|
178
|
+
transformedName = transformData.fileName || extraFileName;
|
|
179
|
+
} catch (error) {
|
|
180
|
+
console.error(`Transform failed for ${extraFileName}:`, error);
|
|
181
|
+
// Continue with original source if transform fails
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Only update filenameMap and add to files if this doesn't conflict with existing files
|
|
186
|
+
// If a file already exists with the target name, skip this transformation to preserve original files
|
|
187
|
+
const existingFile = files.find(f => f.name === transformedName);
|
|
188
|
+
if (!existingFile) {
|
|
189
|
+
filenameMap[extraFileName] = transformedName;
|
|
190
|
+
files.push({
|
|
191
|
+
name: transformedName,
|
|
192
|
+
originalName: extraFileName,
|
|
193
|
+
source: transformedSource,
|
|
194
|
+
...(transformedComments && {
|
|
195
|
+
comments: transformedComments
|
|
196
|
+
})
|
|
197
|
+
});
|
|
198
|
+
} else {
|
|
199
|
+
// If there's a conflict, skip this file with a warning
|
|
200
|
+
console.warn(`Transform conflict: ${extraFileName} would transform to ${transformedName} but that name is already taken. Skipping this file.`);
|
|
201
|
+
}
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return {
|
|
205
|
+
files,
|
|
206
|
+
filenameMap
|
|
207
|
+
};
|
|
208
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type * as EditingEngine from "./EditingEngine.mjs";
|
|
2
|
+
/** The resolved editing-engine module: `createEditableEngine` + source-editing fns. */
|
|
3
|
+
export type EditingEngineModule = typeof EditingEngine;
|
|
4
|
+
/**
|
|
5
|
+
* Resolves the live-editing engine module. `CodeProvider` supplies one via
|
|
6
|
+
* context (eager → bundled, resolves instantly; lazy → dynamic `import()`);
|
|
7
|
+
* `useEditable` / `useSourceEditing` also have the built-in default below so
|
|
8
|
+
* editing works without a provider.
|
|
9
|
+
*/
|
|
10
|
+
export type EditingEngineLoader = () => Promise<EditingEngineModule>;
|
|
11
|
+
/** Built-in loader, used when no provider supplies an `editingEngineLoader`. */
|
|
12
|
+
export declare const defaultEditingEngineLoader: EditingEngineLoader;
|
|
13
|
+
/** Synchronously reads the cached module, or `undefined` if not yet resolved. */
|
|
14
|
+
export declare function peekEditingEngine(): EditingEngineModule | undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Resolves the editing-engine module (from the warm cache, else via the loader)
|
|
17
|
+
* and caches it. Returns the cached value synchronously when warm. Rejects if
|
|
18
|
+
* the load fails; callers decide whether to surface or swallow that.
|
|
19
|
+
*/
|
|
20
|
+
export declare function loadEditingEngine(loader?: EditingEngineLoader): EditingEngineModule | Promise<EditingEngineModule>;
|
|
21
|
+
/**
|
|
22
|
+
* Eagerly resolves and caches the editing-engine module so the next editable
|
|
23
|
+
* block attaches (and the first edit commits) synchronously instead of after a
|
|
24
|
+
* load round-trip. Fire-and-forget — fails open. Pass the provider's
|
|
25
|
+
* `editingEngineLoader` to share its page-wide deduplication.
|
|
26
|
+
*/
|
|
27
|
+
export declare function preloadEditingEngine(loader?: EditingEngineLoader): Promise<void>;
|
|
28
|
+
/** Clears the cache so the next resolve loads from scratch. For tests. */
|
|
29
|
+
export declare function resetEditingEngineCache(): void;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/** The resolved editing-engine module: `createEditableEngine` + source-editing fns. */
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Resolves the live-editing engine module. `CodeProvider` supplies one via
|
|
5
|
+
* context (eager → bundled, resolves instantly; lazy → dynamic `import()`);
|
|
6
|
+
* `useEditable` / `useSourceEditing` also have the built-in default below so
|
|
7
|
+
* editing works without a provider.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
// Set DEBUG=true to log editing-engine load failures (e.g. a chunk-load error
|
|
11
|
+
// after a rotated deploy). Off by default — a failed load fails open (the block
|
|
12
|
+
// stays read-only / the edit no-ops) per convention 9.3.
|
|
13
|
+
const DEBUG = false;
|
|
14
|
+
|
|
15
|
+
// Module-level cache of the resolved editing-engine module, shared by
|
|
16
|
+
// `useEditable` (reads `createEditableEngine`) and `useSourceEditing` (reads the
|
|
17
|
+
// source-editing fns). Because both gate on the same "is-editable" signal and
|
|
18
|
+
// load the SAME chunk, the first editable block resolves it once and every
|
|
19
|
+
// reader after that — including the first keystroke's source-editing call — sees
|
|
20
|
+
// it warm and runs synchronously.
|
|
21
|
+
let cached;
|
|
22
|
+
|
|
23
|
+
/** Built-in loader, used when no provider supplies an `editingEngineLoader`. */
|
|
24
|
+
export const defaultEditingEngineLoader = () => import("./EditingEngine.mjs");
|
|
25
|
+
|
|
26
|
+
/** Synchronously reads the cached module, or `undefined` if not yet resolved. */
|
|
27
|
+
export function peekEditingEngine() {
|
|
28
|
+
return cached;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Resolves the editing-engine module (from the warm cache, else via the loader)
|
|
33
|
+
* and caches it. Returns the cached value synchronously when warm. Rejects if
|
|
34
|
+
* the load fails; callers decide whether to surface or swallow that.
|
|
35
|
+
*/
|
|
36
|
+
export function loadEditingEngine(loader) {
|
|
37
|
+
if (cached) {
|
|
38
|
+
return cached;
|
|
39
|
+
}
|
|
40
|
+
return (loader ?? defaultEditingEngineLoader)().then(mod => {
|
|
41
|
+
cached = mod;
|
|
42
|
+
return mod;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Eagerly resolves and caches the editing-engine module so the next editable
|
|
48
|
+
* block attaches (and the first edit commits) synchronously instead of after a
|
|
49
|
+
* load round-trip. Fire-and-forget — fails open. Pass the provider's
|
|
50
|
+
* `editingEngineLoader` to share its page-wide deduplication.
|
|
51
|
+
*/
|
|
52
|
+
export async function preloadEditingEngine(loader) {
|
|
53
|
+
if (cached) {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
try {
|
|
57
|
+
await loadEditingEngine(loader);
|
|
58
|
+
} catch (error) {
|
|
59
|
+
if (DEBUG) {
|
|
60
|
+
console.error('[docs-infra] editing engine failed to preload', error);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/** Clears the cache so the next resolve loads from scratch. For tests. */
|
|
66
|
+
export function resetEditingEngineCache() {
|
|
67
|
+
cached = undefined;
|
|
68
|
+
}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
import type { VariantSource, VariantCode, Code } from "../CodeHighlighter/types.mjs";
|
|
2
|
+
import type { FallbackNode } from "../CodeHighlighter/fallbackFormat.mjs";
|
|
3
|
+
export interface SourceLineCounts {
|
|
4
|
+
totalLines: number;
|
|
5
|
+
focusedLines: number;
|
|
6
|
+
collapsible: boolean;
|
|
7
|
+
}
|
|
8
|
+
/**
|
|
9
|
+
* Extract `{ totalLines, focusedLines }` from any `VariantSource`
|
|
10
|
+
* shape. Reads precomputed metadata when available (`HastRoot.data`)
|
|
11
|
+
* and falls back to counting lines for plain string sources. For
|
|
12
|
+
* string sources, `focusedLines === totalLines` because the
|
|
13
|
+
* `@focus` enhancer never ran. Results are cached by source identity
|
|
14
|
+
* for object payloads so subsequent calls are O(1).
|
|
15
|
+
*
|
|
16
|
+
* Returns zeroes when the source is missing or malformed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function getSourceLineCounts(source: VariantSource | undefined, fallback?: FallbackNode[]): SourceLineCounts;
|
|
19
|
+
export declare function getVariantFileLineCounts(variant: VariantCode, fileName: string): SourceLineCounts | null;
|
|
20
|
+
/**
|
|
21
|
+
* Determines whether switching from `fromVariantKey` to `toVariantKey`
|
|
22
|
+
* would visibly shift layout. The `mode` mirrors the transform
|
|
23
|
+
* classifier and is configured via `useCode`'s `variantLayoutShift`
|
|
24
|
+
* option:
|
|
25
|
+
*
|
|
26
|
+
* - `'all'` — sums `totalLines` across every file (main +
|
|
27
|
+
* `extraFiles`) in both variants. Layout shift when the totals
|
|
28
|
+
* differ. Useful when the rendering surface displays the full
|
|
29
|
+
* variant simultaneously.
|
|
30
|
+
* - `'selected'` (default) — compares `totalLines` for the
|
|
31
|
+
* currently-selected file (`selectedFileName`, falling back to
|
|
32
|
+
* the source variant's main file) between the two variants.
|
|
33
|
+
* Layout shift when the line counts differ.
|
|
34
|
+
* - `'focus'` — like `'selected'` but consults `focusedLines`
|
|
35
|
+
* (the size of the visible window when the surrounding code
|
|
36
|
+
* block is collapsed) while `expanded === false`. Reverts to
|
|
37
|
+
* `'selected'`-style behavior when expanded. Recommended for
|
|
38
|
+
* demos that use `@focus`/`@padding` to collapse to a region.
|
|
39
|
+
*
|
|
40
|
+
* Returns `true` (layout shift) when:
|
|
41
|
+
* - either variant is missing,
|
|
42
|
+
* - the selected file is missing from either variant (the file
|
|
43
|
+
* list itself changes),
|
|
44
|
+
* - the relevant line count differs between the two variants.
|
|
45
|
+
*
|
|
46
|
+
* Returns `false` for same-variant swaps and when the line counts
|
|
47
|
+
* match.
|
|
48
|
+
*/
|
|
49
|
+
export declare function variantHasLayoutShift(effectiveCode: Code, fromVariantKey: string | null, toVariantKey: string | null, opts?: {
|
|
50
|
+
mode?: 'all' | 'selected' | 'focus';
|
|
51
|
+
selectedFileName?: string | undefined;
|
|
52
|
+
expanded?: boolean;
|
|
53
|
+
}): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Description of a pair of variants whose same-named file has a
|
|
56
|
+
* different `focusedLines` count. Returned by
|
|
57
|
+
* `findVariantFocusedLinesMismatches` so callers can produce
|
|
58
|
+
* actionable error messages without re-walking the variant tree.
|
|
59
|
+
*/
|
|
60
|
+
export interface VariantFocusedLinesMismatch {
|
|
61
|
+
fileName: string;
|
|
62
|
+
variantA: string;
|
|
63
|
+
variantB: string;
|
|
64
|
+
focusedLinesA: number;
|
|
65
|
+
focusedLinesB: number;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Walk every variant on `effectiveCode` and collect files that share
|
|
69
|
+
* a name across variants but disagree on `focusedLines`. Used by
|
|
70
|
+
* `useCode`'s `strictMatchingVariantFocusedLines` option to throw
|
|
71
|
+
* with a pointer to the offending variants/file so the demo author
|
|
72
|
+
* can align the `@focus` / `@padding` markers across language
|
|
73
|
+
* variants and avoid coordinated barriers while collapsed.
|
|
74
|
+
*
|
|
75
|
+
* The first variant to declare a given file name is treated as the
|
|
76
|
+
* baseline; every subsequent variant that disagrees produces a
|
|
77
|
+
* mismatch entry paired with the baseline. Returns an empty array
|
|
78
|
+
* when every shared file agrees.
|
|
79
|
+
*/
|
|
80
|
+
export declare function findVariantFocusedLinesMismatches(effectiveCode: Code): VariantFocusedLinesMismatch[];
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
import { decodeHastSource } from "../pipeline/loadIsomorphicCodeVariant/decodeHastSource.mjs";
|
|
2
|
+
const ZERO_LINE_COUNTS = {
|
|
3
|
+
totalLines: 0,
|
|
4
|
+
focusedLines: 0,
|
|
5
|
+
collapsible: false
|
|
6
|
+
};
|
|
7
|
+
function normalizeLineCounts(totalRaw, focusedRaw, collapsibleRaw) {
|
|
8
|
+
const totalNum = totalRaw == null ? NaN : Number(totalRaw);
|
|
9
|
+
const totalLines = Number.isFinite(totalNum) && totalNum >= 0 ? totalNum : 0;
|
|
10
|
+
const focusedNum = focusedRaw == null ? NaN : Number(focusedRaw);
|
|
11
|
+
const focusedLines = Number.isFinite(focusedNum) && focusedNum >= 0 ? focusedNum : totalLines;
|
|
12
|
+
return {
|
|
13
|
+
totalLines,
|
|
14
|
+
focusedLines,
|
|
15
|
+
collapsible: collapsibleRaw === true
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
function readStoredLineCounts(file) {
|
|
19
|
+
if (file.totalLines === undefined) {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
return normalizeLineCounts(file.totalLines, file.focusedLines, file.collapsible);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Cache of `{ totalLines, focusedLines }` keyed on the raw source
|
|
27
|
+
* payload. Variant sources are typically stable references across
|
|
28
|
+
* re-renders (they live on the precomputed manifest) so caching by
|
|
29
|
+
* identity is safe and avoids re-parsing compressed hast on every
|
|
30
|
+
* layout-shift classification.
|
|
31
|
+
*/
|
|
32
|
+
const sourceLineCountsCache = new WeakMap();
|
|
33
|
+
function readHastLineCounts(root) {
|
|
34
|
+
if (!root || !root.data) {
|
|
35
|
+
return ZERO_LINE_COUNTS;
|
|
36
|
+
}
|
|
37
|
+
const totalRaw = root.data.totalLines;
|
|
38
|
+
const focusedRaw = root.data.focusedLines;
|
|
39
|
+
const collapsibleRaw = root.data.collapsible;
|
|
40
|
+
return normalizeLineCounts(totalRaw, focusedRaw, collapsibleRaw);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
/**
|
|
44
|
+
* Extract `{ totalLines, focusedLines }` from any `VariantSource`
|
|
45
|
+
* shape. Reads precomputed metadata when available (`HastRoot.data`)
|
|
46
|
+
* and falls back to counting lines for plain string sources. For
|
|
47
|
+
* string sources, `focusedLines === totalLines` because the
|
|
48
|
+
* `@focus` enhancer never ran. Results are cached by source identity
|
|
49
|
+
* for object payloads so subsequent calls are O(1).
|
|
50
|
+
*
|
|
51
|
+
* Returns zeroes when the source is missing or malformed.
|
|
52
|
+
*/
|
|
53
|
+
export function getSourceLineCounts(source, fallback) {
|
|
54
|
+
if (source == null) {
|
|
55
|
+
return ZERO_LINE_COUNTS;
|
|
56
|
+
}
|
|
57
|
+
if (typeof source === 'string') {
|
|
58
|
+
const total = source.length === 0 ? 0 : source.split('\n').length;
|
|
59
|
+
return {
|
|
60
|
+
totalLines: total,
|
|
61
|
+
focusedLines: total,
|
|
62
|
+
collapsible: false
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
const cached = sourceLineCountsCache.get(source);
|
|
66
|
+
if (cached) {
|
|
67
|
+
return cached;
|
|
68
|
+
}
|
|
69
|
+
let counts;
|
|
70
|
+
if (typeof source === 'object' && ('hastJson' in source || 'hastCompressed' in source)) {
|
|
71
|
+
counts = readHastLineCounts(decodeHastSource(source, fallback) ?? undefined);
|
|
72
|
+
} else {
|
|
73
|
+
counts = readHastLineCounts(source);
|
|
74
|
+
}
|
|
75
|
+
sourceLineCountsCache.set(source, counts);
|
|
76
|
+
return counts;
|
|
77
|
+
}
|
|
78
|
+
const variantTotalLinesCache = new WeakMap();
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Sum `totalLines` across every file in a variant (main file +
|
|
82
|
+
* `extraFiles`). Used by `variantHasLayoutShift` in `'all'` mode to
|
|
83
|
+
* decide whether the aggregate height changes when switching
|
|
84
|
+
* variants. Memoized per variant identity.
|
|
85
|
+
*/
|
|
86
|
+
function sumVariantTotalLines(variant) {
|
|
87
|
+
const cached = variantTotalLinesCache.get(variant);
|
|
88
|
+
if (cached !== undefined) {
|
|
89
|
+
return cached;
|
|
90
|
+
}
|
|
91
|
+
let sum = variant.fileName ? getVariantFileLineCounts(variant, variant.fileName)?.totalLines ?? 0 : getSourceLineCounts(variant.source, variant.fallback).totalLines;
|
|
92
|
+
if (variant.extraFiles) {
|
|
93
|
+
for (const [fileName, file] of Object.entries(variant.extraFiles)) {
|
|
94
|
+
if (file == null) {
|
|
95
|
+
continue;
|
|
96
|
+
}
|
|
97
|
+
sum += getVariantFileLineCounts(variant, fileName)?.totalLines ?? 0;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
variantTotalLinesCache.set(variant, sum);
|
|
101
|
+
return sum;
|
|
102
|
+
}
|
|
103
|
+
export function getVariantFileLineCounts(variant, fileName) {
|
|
104
|
+
if ('fileName' in variant && variant.fileName === fileName) {
|
|
105
|
+
if (variant.source === undefined) {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
const stored = readStoredLineCounts(variant);
|
|
109
|
+
if (stored) {
|
|
110
|
+
return stored;
|
|
111
|
+
}
|
|
112
|
+
return getSourceLineCounts(variant.source, variant.fallback);
|
|
113
|
+
}
|
|
114
|
+
const extra = variant.extraFiles?.[fileName];
|
|
115
|
+
if (extra === undefined) {
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
if (typeof extra === 'string') {
|
|
119
|
+
const total = extra.length === 0 ? 0 : extra.split('\n').length;
|
|
120
|
+
return {
|
|
121
|
+
totalLines: total,
|
|
122
|
+
focusedLines: total,
|
|
123
|
+
collapsible: false
|
|
124
|
+
};
|
|
125
|
+
}
|
|
126
|
+
if (extra.source !== undefined) {
|
|
127
|
+
const stored = readStoredLineCounts(extra);
|
|
128
|
+
if (stored) {
|
|
129
|
+
return stored;
|
|
130
|
+
}
|
|
131
|
+
return getSourceLineCounts(extra.source, extra.fallback);
|
|
132
|
+
}
|
|
133
|
+
return null;
|
|
134
|
+
}
|
|
135
|
+
function getVariantCode(effectiveCode, variantKey) {
|
|
136
|
+
const variant = effectiveCode[variantKey];
|
|
137
|
+
if (!variant || typeof variant !== 'object' || !('source' in variant)) {
|
|
138
|
+
return null;
|
|
139
|
+
}
|
|
140
|
+
return variant;
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Determines whether switching from `fromVariantKey` to `toVariantKey`
|
|
145
|
+
* would visibly shift layout. The `mode` mirrors the transform
|
|
146
|
+
* classifier and is configured via `useCode`'s `variantLayoutShift`
|
|
147
|
+
* option:
|
|
148
|
+
*
|
|
149
|
+
* - `'all'` — sums `totalLines` across every file (main +
|
|
150
|
+
* `extraFiles`) in both variants. Layout shift when the totals
|
|
151
|
+
* differ. Useful when the rendering surface displays the full
|
|
152
|
+
* variant simultaneously.
|
|
153
|
+
* - `'selected'` (default) — compares `totalLines` for the
|
|
154
|
+
* currently-selected file (`selectedFileName`, falling back to
|
|
155
|
+
* the source variant's main file) between the two variants.
|
|
156
|
+
* Layout shift when the line counts differ.
|
|
157
|
+
* - `'focus'` — like `'selected'` but consults `focusedLines`
|
|
158
|
+
* (the size of the visible window when the surrounding code
|
|
159
|
+
* block is collapsed) while `expanded === false`. Reverts to
|
|
160
|
+
* `'selected'`-style behavior when expanded. Recommended for
|
|
161
|
+
* demos that use `@focus`/`@padding` to collapse to a region.
|
|
162
|
+
*
|
|
163
|
+
* Returns `true` (layout shift) when:
|
|
164
|
+
* - either variant is missing,
|
|
165
|
+
* - the selected file is missing from either variant (the file
|
|
166
|
+
* list itself changes),
|
|
167
|
+
* - the relevant line count differs between the two variants.
|
|
168
|
+
*
|
|
169
|
+
* Returns `false` for same-variant swaps and when the line counts
|
|
170
|
+
* match.
|
|
171
|
+
*/
|
|
172
|
+
export function variantHasLayoutShift(effectiveCode, fromVariantKey, toVariantKey, opts) {
|
|
173
|
+
if (!fromVariantKey || !toVariantKey || fromVariantKey === toVariantKey) {
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
const fromVariant = getVariantCode(effectiveCode, fromVariantKey);
|
|
177
|
+
const toVariant = getVariantCode(effectiveCode, toVariantKey);
|
|
178
|
+
if (!fromVariant || !toVariant) {
|
|
179
|
+
return false;
|
|
180
|
+
}
|
|
181
|
+
const mode = opts?.mode ?? 'selected';
|
|
182
|
+
const expanded = opts?.expanded ?? false;
|
|
183
|
+
if (mode === 'all') {
|
|
184
|
+
return sumVariantTotalLines(fromVariant) !== sumVariantTotalLines(toVariant);
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// `'selected'` / `'focus'` default to the from-variant's main file
|
|
188
|
+
// when no selection is supplied — mirrors the runtime's "render the
|
|
189
|
+
// main file by default" behavior.
|
|
190
|
+
let fileName = opts?.selectedFileName;
|
|
191
|
+
if (fileName === undefined && 'fileName' in fromVariant) {
|
|
192
|
+
fileName = fromVariant.fileName;
|
|
193
|
+
}
|
|
194
|
+
// No resolvable file name (e.g. an inline-only variant without
|
|
195
|
+
// `fileName`): fall back to the aggregate `totalLines` comparison
|
|
196
|
+
// used by `'all'` mode so wildly different variants still register
|
|
197
|
+
// as layout-shifting instead of silently returning `false`.
|
|
198
|
+
if (!fileName) {
|
|
199
|
+
return sumVariantTotalLines(fromVariant) !== sumVariantTotalLines(toVariant);
|
|
200
|
+
}
|
|
201
|
+
const fromCounts = getVariantFileLineCounts(fromVariant, fileName);
|
|
202
|
+
const toCounts = getVariantFileLineCounts(toVariant, fileName);
|
|
203
|
+
// File missing on either side means the file list itself changes,
|
|
204
|
+
// which is inherently layout-shifting.
|
|
205
|
+
if (!fromCounts || !toCounts) {
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
if (mode === 'focus' && !expanded) {
|
|
209
|
+
return fromCounts.focusedLines !== toCounts.focusedLines;
|
|
210
|
+
}
|
|
211
|
+
return fromCounts.totalLines !== toCounts.totalLines;
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Description of a pair of variants whose same-named file has a
|
|
216
|
+
* different `focusedLines` count. Returned by
|
|
217
|
+
* `findVariantFocusedLinesMismatches` so callers can produce
|
|
218
|
+
* actionable error messages without re-walking the variant tree.
|
|
219
|
+
*/
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Walk every variant on `effectiveCode` and collect files that share
|
|
223
|
+
* a name across variants but disagree on `focusedLines`. Used by
|
|
224
|
+
* `useCode`'s `strictMatchingVariantFocusedLines` option to throw
|
|
225
|
+
* with a pointer to the offending variants/file so the demo author
|
|
226
|
+
* can align the `@focus` / `@padding` markers across language
|
|
227
|
+
* variants and avoid coordinated barriers while collapsed.
|
|
228
|
+
*
|
|
229
|
+
* The first variant to declare a given file name is treated as the
|
|
230
|
+
* baseline; every subsequent variant that disagrees produces a
|
|
231
|
+
* mismatch entry paired with the baseline. Returns an empty array
|
|
232
|
+
* when every shared file agrees.
|
|
233
|
+
*/
|
|
234
|
+
export function findVariantFocusedLinesMismatches(effectiveCode) {
|
|
235
|
+
const baseline = new Map();
|
|
236
|
+
const mismatches = [];
|
|
237
|
+
const recordFile = (variantName, fileName, focusedLines) => {
|
|
238
|
+
const existing = baseline.get(fileName);
|
|
239
|
+
if (!existing) {
|
|
240
|
+
baseline.set(fileName, {
|
|
241
|
+
variantName,
|
|
242
|
+
focusedLines
|
|
243
|
+
});
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
if (existing.focusedLines !== focusedLines) {
|
|
247
|
+
mismatches.push({
|
|
248
|
+
fileName,
|
|
249
|
+
variantA: existing.variantName,
|
|
250
|
+
variantB: variantName,
|
|
251
|
+
focusedLinesA: existing.focusedLines,
|
|
252
|
+
focusedLinesB: focusedLines
|
|
253
|
+
});
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
for (const [variantName, variant] of Object.entries(effectiveCode)) {
|
|
257
|
+
if (!variant || typeof variant !== 'object' || !('source' in variant)) {
|
|
258
|
+
continue;
|
|
259
|
+
}
|
|
260
|
+
if ('fileName' in variant && variant.fileName && variant.source !== undefined) {
|
|
261
|
+
const {
|
|
262
|
+
focusedLines
|
|
263
|
+
} = getVariantFileLineCounts(variant, variant.fileName) ?? getSourceLineCounts(variant.source, variant.fallback);
|
|
264
|
+
recordFile(variantName, variant.fileName, focusedLines);
|
|
265
|
+
}
|
|
266
|
+
if ('extraFiles' in variant && variant.extraFiles) {
|
|
267
|
+
for (const [fileName, file] of Object.entries(variant.extraFiles)) {
|
|
268
|
+
if (file == null) {
|
|
269
|
+
continue;
|
|
270
|
+
}
|
|
271
|
+
if (typeof file === 'string') {
|
|
272
|
+
const total = file.length === 0 ? 0 : file.split('\n').length;
|
|
273
|
+
recordFile(variantName, fileName, total);
|
|
274
|
+
} else if (file.source !== undefined) {
|
|
275
|
+
const {
|
|
276
|
+
focusedLines
|
|
277
|
+
} = getVariantFileLineCounts(variant, fileName) ?? getSourceLineCounts(file.source, file.fallback);
|
|
278
|
+
recordFile(variantName, fileName, focusedLines);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return mismatches;
|
|
284
|
+
}
|