@mui/internal-docs-infra 0.11.1-canary.8 → 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 +85 -5
- 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
|
@@ -1,25 +1,569 @@
|
|
|
1
1
|
import { create, patch } from 'jsondiffpatch';
|
|
2
|
+
import { findExpandingRanges, hasExpandingRanges } from "./findExpandingRanges.mjs";
|
|
3
|
+
import { getInitialVisibleSourceLines } from "./getInitialVisibleSourceLines.mjs";
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Async-friendly variant of {@link ParseSource}. The build-time diff path
|
|
7
|
+
* may wrap the synchronous highlighter with enhancers that need to run
|
|
8
|
+
* asynchronously, so `diffHast` accepts either return shape. `comments`
|
|
9
|
+
* is the post-transform comment map (1-indexed by line in the transformed
|
|
10
|
+
* source) when the transform repositions lines; wrappers that drive
|
|
11
|
+
* enhancers should prefer it over the source's own comment map so the
|
|
12
|
+
* enhanced frame structure aligns with the patched output.
|
|
13
|
+
*/
|
|
14
|
+
|
|
2
15
|
const differ = create({
|
|
3
16
|
omitRemovedValues: true,
|
|
4
|
-
cloneDiffValues: true
|
|
17
|
+
cloneDiffValues: true,
|
|
18
|
+
// Give jsondiffpatch a stable identity per array item so it can't match a
|
|
19
|
+
// `<span class="line">` to a `<span class="collapse">` placeholder by
|
|
20
|
+
// position. Without this, the LCS matcher happily aligns the source
|
|
21
|
+
// wiped-line span at index N with the transform placeholder at index N
|
|
22
|
+
// and emits a noisy in-place mutation (rewrite className, swap
|
|
23
|
+
// `dataLn`→`dataLines`, wipe N children). With distinct hashes the
|
|
24
|
+
// placeholder becomes a clean insert and the wiped line spans become
|
|
25
|
+
// deletes.
|
|
26
|
+
objectHash: (value, index) => {
|
|
27
|
+
if (value === null || typeof value !== 'object') {
|
|
28
|
+
return `idx:${index}`;
|
|
29
|
+
}
|
|
30
|
+
const node = value;
|
|
31
|
+
if (node.type === 'element' && node.tagName === 'span') {
|
|
32
|
+
const cls = node.properties?.className;
|
|
33
|
+
const className = Array.isArray(cls) ? cls.join(' ') : cls;
|
|
34
|
+
// Collapse placeholders get a unique identity so jsondiffpatch
|
|
35
|
+
// can't morph a wiped line span into a placeholder in place.
|
|
36
|
+
if (className === 'collapse') {
|
|
37
|
+
return `collapse:${index}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// Everything else (frames, lines, text) falls back to positional
|
|
41
|
+
// identity — same as jsondiffpatch's default behavior — so we don't
|
|
42
|
+
// accidentally force unrelated nodes apart.
|
|
43
|
+
return `idx:${index}`;
|
|
44
|
+
}
|
|
5
45
|
});
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* `.line` element produced by addLineGutters. For non-empty lines the
|
|
49
|
+
* `\n` lives as a sibling text node outside the span, so an empty source
|
|
50
|
+
* line is either `<span.line></span>` (legacy) or `<span.line>\n</span>`
|
|
51
|
+
* — the latter form holds its own `\n` inside so block-level styles give
|
|
52
|
+
* the row a visible height without injecting invisible characters that
|
|
53
|
+
* would end up in the clipboard.
|
|
54
|
+
*/
|
|
55
|
+
function isEmptyLine(line) {
|
|
56
|
+
if (line.children.length === 0) {
|
|
57
|
+
return true;
|
|
58
|
+
}
|
|
59
|
+
if (line.children.length === 1) {
|
|
60
|
+
const only = line.children[0];
|
|
61
|
+
return only.type === 'text' && (only.value === '\n' || only.value === '\u200B');
|
|
62
|
+
}
|
|
63
|
+
return false;
|
|
64
|
+
}
|
|
65
|
+
function isLineElement(node) {
|
|
66
|
+
return !!node && node.type === 'element' && node.tagName === 'span' && node.properties != null && node.properties.className === 'line';
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Strip `dataLn` from `.line` elements directly under each frame. Walks
|
|
71
|
+
* `root.children → frame.children` only — never descends into a line's
|
|
72
|
+
* highlighted spans (which are the bulk of the tree).
|
|
73
|
+
*/
|
|
74
|
+
function stripLineNumbersInPlace(root) {
|
|
75
|
+
if (root.type !== 'root') {
|
|
76
|
+
return;
|
|
77
|
+
}
|
|
78
|
+
const frames = root.children;
|
|
79
|
+
for (let f = 0; f < frames.length; f += 1) {
|
|
80
|
+
const frame = frames[f];
|
|
81
|
+
if (frame.type !== 'element') {
|
|
82
|
+
continue;
|
|
83
|
+
}
|
|
84
|
+
const lines = frame.children;
|
|
85
|
+
for (let i = 0; i < lines.length; i += 1) {
|
|
86
|
+
const line = lines[i];
|
|
87
|
+
if (line.type === 'element' && line.properties != null && line.properties.className === 'line' && line.properties.dataLn !== undefined) {
|
|
88
|
+
delete line.properties.dataLn;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
/**
|
|
95
|
+
* Concatenate the plain text carried by a frame's `data.fallback` nodes
|
|
96
|
+
* (`addLineGutters` stores a single text node; `restructureFrames` may store
|
|
97
|
+
* several). Used to decide whether a transform actually rewrote a frame.
|
|
98
|
+
*/
|
|
99
|
+
function frameFallbackText(nodes) {
|
|
100
|
+
let out = '';
|
|
101
|
+
for (const node of nodes) {
|
|
102
|
+
if (node.type === 'text') {
|
|
103
|
+
out += node.value;
|
|
104
|
+
} else if (node.type === 'element') {
|
|
105
|
+
out += frameFallbackText(node.children);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return out;
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Align the transform tree's frames with the source tree's frames (by document
|
|
113
|
+
* order) and reconcile their per-frame `data.fallback` so the diff records, per
|
|
114
|
+
* frame, *whether the transform rewrote it* — without ever leaking fallback
|
|
115
|
+
* text into the delta:
|
|
116
|
+
*
|
|
117
|
+
* - **Unchanged frame** (fallback text matches the source frame's): alias the
|
|
118
|
+
* source frame's fallback nodes onto the transform frame so the differ sees
|
|
119
|
+
* an identical value and emits no fallback op. The decoded tree's inherited
|
|
120
|
+
* fallback then survives the patch untouched.
|
|
121
|
+
* - **Rewritten frame** (text differs, or no source counterpart): delete the
|
|
122
|
+
* transform frame's fallback. Because the source frame keeps its own, the
|
|
123
|
+
* differ emits a content-less *delete* (it runs with `omitRemovedValues`).
|
|
124
|
+
*
|
|
125
|
+
* That delete is the build-time record of "this frame changed": on decode the
|
|
126
|
+
* applier removes the stale inherited fallback and regenerates it from the
|
|
127
|
+
* frame's post-transform spans, while untouched frames keep their precomputed
|
|
128
|
+
* fallback. Fallback text never enters the delta, so `patch` never applies
|
|
129
|
+
* fallback array operations against a regenerated frame (which would crash).
|
|
130
|
+
* Walks `root.children` only — never descends into a frame's lines.
|
|
131
|
+
*/
|
|
132
|
+
function reconcileFrameFallbacksForDiffInPlace(transformRoot, sourceRoot) {
|
|
133
|
+
if (transformRoot.type !== 'root' || sourceRoot.type !== 'root') {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
// Pair each transform frame with the source frame at the *same document
|
|
137
|
+
// position*. `differ` identifies frames by their array index (the
|
|
138
|
+
// `objectHash` returns `idx:${index}` for them), so the LCS matcher aligns
|
|
139
|
+
// transform child `i` with source child `i` — adding or removing a frame
|
|
140
|
+
// shifts the tail on *both* sides identically. Reconciling by that same
|
|
141
|
+
// index keeps this pass in lockstep with the diff: a transform frame is only
|
|
142
|
+
// aliased to a source fallback the differ will actually compare it against,
|
|
143
|
+
// so a frame the transform added (or that has no fallback-bearing source
|
|
144
|
+
// counterpart at its position) falls through to the delete branch and
|
|
145
|
+
// regenerates instead of inheriting an unrelated frame's fallback. A prior
|
|
146
|
+
// implementation walked a separate counter over only the fallback-bearing
|
|
147
|
+
// frames, which drifted out of alignment with the diff whenever a frame was
|
|
148
|
+
// inserted/removed or a non-fallback frame sat between two fallback frames.
|
|
149
|
+
const sourceChildren = sourceRoot.children;
|
|
150
|
+
const transformChildren = transformRoot.children;
|
|
151
|
+
for (let index = 0; index < transformChildren.length; index += 1) {
|
|
152
|
+
const child = transformChildren[index];
|
|
153
|
+
if (child.type !== 'element' || !child.data || child.data.fallback === undefined) {
|
|
154
|
+
continue;
|
|
155
|
+
}
|
|
156
|
+
const sourceChild = sourceChildren[index];
|
|
157
|
+
const sourceFallback = sourceChild?.type === 'element' ? sourceChild.data?.fallback : undefined;
|
|
158
|
+
if (sourceFallback !== undefined && frameFallbackText(sourceFallback) === frameFallbackText(child.data.fallback)) {
|
|
159
|
+
// Unchanged: alias the source nodes so the diff sees an identical
|
|
160
|
+
// fallback (even if the node split differs) and emits nothing.
|
|
161
|
+
child.data.fallback = sourceFallback;
|
|
162
|
+
} else {
|
|
163
|
+
// Rewritten (or no source counterpart): drop it so the diff emits a
|
|
164
|
+
// content-less delete that the applier turns into a regeneration.
|
|
165
|
+
delete child.data.fallback;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
/**
|
|
171
|
+
* Reassign sequential 1-indexed `dataLn` values to every `.line` element
|
|
172
|
+
* directly under each frame. Used to restore numbering on `parsedSource`
|
|
173
|
+
* after the diff (addLineGutters always numbers 1..N in document order,
|
|
174
|
+
* so re-deriving is correct).
|
|
175
|
+
*/
|
|
176
|
+
function renumberLinesInPlace(root) {
|
|
177
|
+
if (root.type !== 'root') {
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
let lineNumber = 0;
|
|
181
|
+
const frames = root.children;
|
|
182
|
+
for (let f = 0; f < frames.length; f += 1) {
|
|
183
|
+
const frame = frames[f];
|
|
184
|
+
if (frame.type !== 'element') {
|
|
185
|
+
continue;
|
|
186
|
+
}
|
|
187
|
+
const children = frame.children;
|
|
188
|
+
for (let i = 0; i < children.length; i += 1) {
|
|
189
|
+
const child = children[i];
|
|
190
|
+
if (child.type === 'element' && child.properties != null && child.properties.className === 'line') {
|
|
191
|
+
lineNumber += 1;
|
|
192
|
+
child.properties.dataLn = lineNumber;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
if (root.data && 'totalLines' in root.data) {
|
|
197
|
+
root.data.totalLines = lineNumber;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* One contiguous run of wiped lines inside a single frame, expressed in
|
|
203
|
+
* positions of `frame.children`. The slice `[start, endExclusive)` covers
|
|
204
|
+
* the wiped `.line` spans, their trailing `\n` text siblings, and any
|
|
205
|
+
* absorbed originally-blank line. `count` is the number of source rows
|
|
206
|
+
* the replacement placeholder should cover.
|
|
207
|
+
*/
|
|
208
|
+
|
|
209
|
+
/**
|
|
210
|
+
* Walk a frame's children and group consecutive wiped `.line` spans
|
|
211
|
+
* (together with their trailing `\n` siblings, plus optionally one
|
|
212
|
+
* trailing originally-blank line) into runs. `counter` is a shared
|
|
213
|
+
* 1-indexed line number advanced for every `.line` element encountered
|
|
214
|
+
* (addLineGutters numbers lines 1..N in document order across frames).
|
|
215
|
+
*/
|
|
216
|
+
function collectWipedRunsInFrame(frame, wiped, counter) {
|
|
217
|
+
const runs = [];
|
|
218
|
+
const children = frame.children;
|
|
219
|
+
let i = 0;
|
|
220
|
+
while (i < children.length) {
|
|
221
|
+
const child = children[i];
|
|
222
|
+
if (!isLineElement(child)) {
|
|
223
|
+
i += 1;
|
|
224
|
+
continue;
|
|
225
|
+
}
|
|
226
|
+
counter.value += 1;
|
|
227
|
+
if (!wiped.has(counter.value)) {
|
|
228
|
+
i += 1;
|
|
229
|
+
continue;
|
|
230
|
+
}
|
|
231
|
+
const runStart = i;
|
|
232
|
+
let count = 1;
|
|
233
|
+
i += 1;
|
|
234
|
+
// Consume the trailing `\n` text sibling of this wiped line.
|
|
235
|
+
if (i < children.length) {
|
|
236
|
+
const sibling = children[i];
|
|
237
|
+
if (sibling.type === 'text' && sibling.value === '\n') {
|
|
238
|
+
i += 1;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
while (i < children.length) {
|
|
242
|
+
const peek = children[i];
|
|
243
|
+
if (!isLineElement(peek)) {
|
|
244
|
+
break;
|
|
245
|
+
}
|
|
246
|
+
counter.value += 1;
|
|
247
|
+
if (wiped.has(counter.value)) {
|
|
248
|
+
count += 1;
|
|
249
|
+
i += 1;
|
|
250
|
+
if (i < children.length) {
|
|
251
|
+
const sibling = children[i];
|
|
252
|
+
if (sibling.type === 'text' && sibling.value === '\n') {
|
|
253
|
+
i += 1;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
continue;
|
|
257
|
+
}
|
|
258
|
+
// Absorb one trailing originally-blank line into the collapsed
|
|
259
|
+
// region so the boundary doesn't leave a stray blank row, plus its
|
|
260
|
+
// own trailing `\n` sibling.
|
|
261
|
+
if (isEmptyLine(peek)) {
|
|
262
|
+
count += 1;
|
|
263
|
+
i += 1;
|
|
264
|
+
if (i < children.length) {
|
|
265
|
+
const sibling = children[i];
|
|
266
|
+
if (sibling.type === 'text' && sibling.value === '\n') {
|
|
267
|
+
i += 1;
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
// Survivor: un-advance the line counter so the outer loop
|
|
272
|
+
// re-processes this child.
|
|
273
|
+
counter.value -= 1;
|
|
274
|
+
}
|
|
275
|
+
break;
|
|
276
|
+
}
|
|
277
|
+
runs.push({
|
|
278
|
+
start: runStart,
|
|
279
|
+
endExclusive: i,
|
|
280
|
+
count
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
return runs;
|
|
284
|
+
}
|
|
285
|
+
function makePlaceholder(count) {
|
|
286
|
+
// One empty `<span/>` child per collapsed line. Consumer CSS can
|
|
287
|
+
// give each child `display: block` + `height: var(--line-height)` to
|
|
288
|
+
// size the placeholder by intrinsic layout (no `attr()` or per-count
|
|
289
|
+
// fallback rules required) and animate per-line height independently.
|
|
290
|
+
// Both diff sides emit identical children, so jsondiffpatch still
|
|
291
|
+
// matches the placeholders structurally and produces an empty sub-
|
|
292
|
+
// delta for them.
|
|
293
|
+
const children = [];
|
|
294
|
+
for (let i = 0; i < count; i += 1) {
|
|
295
|
+
children.push({
|
|
296
|
+
type: 'element',
|
|
297
|
+
tagName: 'span',
|
|
298
|
+
properties: {},
|
|
299
|
+
children: []
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
return {
|
|
303
|
+
type: 'element',
|
|
304
|
+
tagName: 'span',
|
|
305
|
+
properties: {
|
|
306
|
+
className: 'collapse',
|
|
307
|
+
dataLines: count
|
|
308
|
+
},
|
|
309
|
+
children
|
|
310
|
+
};
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
/**
|
|
314
|
+
* For each frame, find wiped-line runs and splice them in place with a
|
|
315
|
+
* single `<span class="collapse" data-lines={count}>` placeholder
|
|
316
|
+
* (carrying `count` empty `<span/>` children, one per collapsed line).
|
|
317
|
+
* Run on *both* the source and transform trees before diffing — the
|
|
318
|
+
* placeholders line up structurally, so jsondiffpatch matches them and
|
|
319
|
+
* the resulting delta cleanly represents the collapse without us
|
|
320
|
+
* having to surgically rewrite array-position keys after the fact.
|
|
321
|
+
*
|
|
322
|
+
* The source tree's wiped runs are the originals being replaced; the
|
|
323
|
+
* transform tree's wiped runs are now-empty `.line` spans (the transform
|
|
324
|
+
* blanked their content). Both runs span the same 1-indexed line numbers,
|
|
325
|
+
* but at *different* `frame.children` positions because the empty-line
|
|
326
|
+
* encoding may differ between source and transform (e.g. the transform
|
|
327
|
+
* may emit `<span.line>\n</span>` with no sibling `\n`).
|
|
328
|
+
*/
|
|
329
|
+
function compactCollapseInTreeInPlace(tree, wiped) {
|
|
330
|
+
if (tree.type !== 'root') {
|
|
331
|
+
return;
|
|
332
|
+
}
|
|
333
|
+
const counter = {
|
|
334
|
+
value: 0
|
|
335
|
+
};
|
|
336
|
+
const frames = tree.children;
|
|
337
|
+
let lastFrame;
|
|
338
|
+
for (let f = 0; f < frames.length; f += 1) {
|
|
339
|
+
const frame = frames[f];
|
|
340
|
+
if (frame.type !== 'element') {
|
|
341
|
+
continue;
|
|
342
|
+
}
|
|
343
|
+
lastFrame = frame;
|
|
344
|
+
const runs = collectWipedRunsInFrame(frame, wiped, counter);
|
|
345
|
+
if (runs.length === 0) {
|
|
346
|
+
continue;
|
|
347
|
+
}
|
|
348
|
+
// Splice from the end so earlier indices stay valid.
|
|
349
|
+
for (let r = runs.length - 1; r >= 0; r -= 1) {
|
|
350
|
+
const run = runs[r];
|
|
351
|
+
frame.children.splice(run.start, run.endExclusive - run.start, makePlaceholder(run.count));
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
// Trailing wiped lines that the transform parser elided: when the
|
|
355
|
+
// transformed source ends with `\n` (because the blanked line carried no
|
|
356
|
+
// content), `addLineGutters` doesn't emit a `.line` span for that final
|
|
357
|
+
// blank row, so the counter walk above never reaches them. Append a
|
|
358
|
+
// single placeholder to the last frame covering all such trailing rows
|
|
359
|
+
// so the diff still produces a collapsed-lines span at the end.
|
|
360
|
+
let trailingCount = 0;
|
|
361
|
+
for (const lineNumber of wiped) {
|
|
362
|
+
if (lineNumber > counter.value) {
|
|
363
|
+
trailingCount += 1;
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
if (trailingCount > 0 && lastFrame) {
|
|
367
|
+
lastFrame.children.push(makePlaceholder(trailingCount));
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
/**
|
|
372
|
+
* Diffs each transformed variant against `parsedSource` and returns
|
|
373
|
+
* a `Transforms` map where every entry carries a `delta`.
|
|
374
|
+
*
|
|
375
|
+
* NOTE: `parsedSource` is temporarily mutated for the duration of this
|
|
376
|
+
* call — `dataLn` properties are stripped from line spans before diffing
|
|
377
|
+
* (so the always-sequential gutter numbering doesn't leak into the
|
|
378
|
+
* delta) and restored in `finally`. Callers must not read from the tree
|
|
379
|
+
* concurrently, and must not invoke `diffHast` against the same
|
|
380
|
+
* `parsedSource` in parallel. Today's only caller (`loadSingleFile`)
|
|
381
|
+
* runs sequentially per variant, so the constraint is satisfied; if
|
|
382
|
+
* that ever changes, clone the source array once up front instead.
|
|
383
|
+
*/
|
|
6
384
|
export async function diffHast(source, parsedSource, filename, transforms, parseSource) {
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
385
|
+
const originalLines = source.split('\n');
|
|
386
|
+
|
|
387
|
+
// Precompute which source lines are visible when the rendered code
|
|
388
|
+
// block is in its collapsed state. Used to derive
|
|
389
|
+
// `hasCollapseInFocus` per transform without re-walking the source
|
|
390
|
+
// tree for each entry.
|
|
391
|
+
const visibleSourceLines = getInitialVisibleSourceLines(parsedSource);
|
|
392
|
+
|
|
393
|
+
// Strip `dataLn` from `parsedSource` so the diff doesn't encode the
|
|
394
|
+
// always-sequential numbering. Restored in `finally`.
|
|
395
|
+
stripLineNumbersInPlace(parsedSource);
|
|
396
|
+
|
|
397
|
+
// `parsedSource` keeps its per-frame `data.fallback`: each transform's tree
|
|
398
|
+
// is reconciled against it (see `reconcileFrameFallbacksForDiffInPlace`) so
|
|
399
|
+
// the delta encodes a content-less fallback delete only for the frames that
|
|
400
|
+
// transform rewrote. The source fallback never enters the delta and stays on
|
|
401
|
+
// the tree for `buildRootFallback`.
|
|
402
|
+
|
|
403
|
+
try {
|
|
404
|
+
const transformed = await Promise.all(Object.entries(transforms).map(async ([key, transform]) => {
|
|
405
|
+
// Rename-only entries (no delta on the input manifest) have no
|
|
406
|
+
// source-level change to diff — pass them through untouched so
|
|
407
|
+
// the downstream embed step still preserves the rename in the
|
|
408
|
+
// variant-level manifest.
|
|
409
|
+
if (!transform.delta) {
|
|
410
|
+
return {
|
|
411
|
+
[key]: {
|
|
412
|
+
...transform
|
|
413
|
+
}
|
|
414
|
+
};
|
|
415
|
+
}
|
|
416
|
+
const patched = patch(originalLines.slice(), transform.delta);
|
|
417
|
+
if (!Array.isArray(patched)) {
|
|
418
|
+
throw new Error(`Patch for ${key} did not return an array`);
|
|
419
|
+
}
|
|
420
|
+
const patchedLines = patched;
|
|
421
|
+
const transformedSource = patchedLines.join('\n');
|
|
422
|
+
const parsedTransform = await parseSource(transformedSource, transform.fileName || filename, undefined, transform.comments);
|
|
423
|
+
|
|
424
|
+
// Wiped lines = 1-indexed *source* lines the transform blanked
|
|
425
|
+
// out in place. We can't trust positional alignment across the
|
|
426
|
+
// two arrays whenever the transform inserts or deletes lines —
|
|
427
|
+
// the shifted indices would make every unchanged line past the
|
|
428
|
+
// insertion look like a wipe of whatever non-blank source line
|
|
429
|
+
// happens to share its slot.
|
|
430
|
+
//
|
|
431
|
+
// The `@expanding*` markers tell us exactly which patched-side
|
|
432
|
+
// lines are transformer-inserts. By stepping through source and
|
|
433
|
+
// patched in lockstep and *skipping* the marked patched
|
|
434
|
+
// positions, the remaining patched positions line up 1:1 with
|
|
435
|
+
// the source. Any patched line at that aligned position which
|
|
436
|
+
// is blank while the matching source line is non-blank is a
|
|
437
|
+
// genuine wipe. Source lines past the end of the realigned
|
|
438
|
+
// patched stream are treated as deletes (not wipes) — wipes
|
|
439
|
+
// mean "blanked in place", which requires a partner slot in
|
|
440
|
+
// the patched output.
|
|
441
|
+
const collapsedPatchedLines = new Set();
|
|
442
|
+
for (const [startLine, endLine] of findExpandingRanges(transform.comments)) {
|
|
443
|
+
for (let line = startLine; line <= endLine; line += 1) {
|
|
444
|
+
collapsedPatchedLines.add(line);
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
const wiped = new Set();
|
|
448
|
+
let sourceIdx = 0;
|
|
449
|
+
for (let patchedIdx = 0; patchedIdx < patchedLines.length; patchedIdx += 1) {
|
|
450
|
+
// Patched-side line numbers are 1-indexed.
|
|
451
|
+
if (collapsedPatchedLines.has(patchedIdx + 1)) {
|
|
452
|
+
continue;
|
|
453
|
+
}
|
|
454
|
+
if (sourceIdx >= originalLines.length) {
|
|
455
|
+
break;
|
|
456
|
+
}
|
|
457
|
+
if (patchedLines[patchedIdx] === '' && originalLines[sourceIdx] !== '') {
|
|
458
|
+
wiped.add(sourceIdx + 1);
|
|
459
|
+
}
|
|
460
|
+
sourceIdx += 1;
|
|
461
|
+
}
|
|
462
|
+
stripLineNumbersInPlace(parsedTransform);
|
|
463
|
+
|
|
464
|
+
// Reconcile the transform tree's per-frame `data.fallback` against the
|
|
465
|
+
// source tree so the delta carries a content-less delete only for the
|
|
466
|
+
// frames this transform rewrote (and nothing for the rest). The
|
|
467
|
+
// applier regenerates the deleted ones from their post-transform spans.
|
|
468
|
+
reconcileFrameFallbacksForDiffInPlace(parsedTransform, parsedSource);
|
|
469
|
+
|
|
470
|
+
// Collapse wiped-line runs in the transform tree into a single
|
|
471
|
+
// `<span class="collapse" data-lines={count}>` placeholder per
|
|
472
|
+
// run (with one empty `<span/>` child per collapsed line) before
|
|
473
|
+
// diffing. The source tree is left intact (it's shared
|
|
474
|
+
// across transforms), so jsondiffpatch sees the now-empty source
|
|
475
|
+
// lines being replaced by the placeholder — a clean, minimal
|
|
476
|
+
// delta with no spurious LCS matches between unrelated lines.
|
|
477
|
+
if (wiped.size > 0) {
|
|
478
|
+
compactCollapseInTreeInPlace(parsedTransform, wiped);
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
// Diff 1:1. The caller is responsible for ensuring `parseSource`
|
|
482
|
+
// produces a frame structure aligned with `parsedSource` (e.g.
|
|
483
|
+
// by wrapping it to apply the same source enhancers); without
|
|
484
|
+
// that, the diff balloons at the frame level.
|
|
485
|
+
const delta = differ.diff(parsedSource, parsedTransform);
|
|
486
|
+
|
|
487
|
+
// `compactCollapseInTreeInPlace` is the only path that ever
|
|
488
|
+
// inserts a `.collapse` placeholder into the transformed tree,
|
|
489
|
+
// and it only runs when there were wiped lines to coalesce. So
|
|
490
|
+
// `wiped.size > 0` is exactly equivalent to "this delta inserts
|
|
491
|
+
// a `.collapse` element" — no tree walk needed. Persisting the
|
|
492
|
+
// flag here means the runtime classifier never has to inspect
|
|
493
|
+
// the delta (or decompress the embedded payload) to decide
|
|
494
|
+
// whether the swap is layout-affecting.
|
|
495
|
+
//
|
|
496
|
+
// `hasExpandingRanges(transform.comments)` covers the symmetric
|
|
497
|
+
// case: transformers that *add* lines (e.g. injecting an API
|
|
498
|
+
// key constant) flag those lines in their returned comments
|
|
499
|
+
// map with `@expanding-start`/`@expanding-end` markers; the
|
|
500
|
+
// applier turns them into `data-expanding=""` line attributes
|
|
501
|
+
// that animate via the same coordinated swap path.
|
|
502
|
+
const hasCollapse = wiped.size > 0 || hasExpandingRanges(transform.comments);
|
|
503
|
+
|
|
504
|
+
// `hasCollapseInFocus` mirrors `hasCollapse` but restricted to
|
|
505
|
+
// the source region visible when the surrounding code block is
|
|
506
|
+
// collapsed. A `.collapse` placeholder outside that region
|
|
507
|
+
// can't visibly shift layout for the user, so consumers that
|
|
508
|
+
// opt into `transformLayoutShift: 'focus'` can skip the
|
|
509
|
+
// coordinated phase 1 barrier for those swaps.
|
|
510
|
+
//
|
|
511
|
+
// Wiped lines are 1-indexed *source* line numbers and slot
|
|
512
|
+
// into `visibleSourceLines` directly. For transformer-inserted
|
|
513
|
+
// lines (the symmetric `@expanding*` case) we approximate the
|
|
514
|
+
// source-side anchor as the source line *immediately preceding*
|
|
515
|
+
// the patched-side insertion run. That line either is part of
|
|
516
|
+
// the visible region (so the inserted block lands inside the
|
|
517
|
+
// focus window) or sits outside it (so the user won't see the
|
|
518
|
+
// collapse animation while collapsed). The walk reuses the
|
|
519
|
+
// same `sourceIdx` advance rule as the wipe detection above.
|
|
520
|
+
let hasCollapseInFocus = false;
|
|
521
|
+
for (const wipedLine of wiped) {
|
|
522
|
+
if (visibleSourceLines.has(wipedLine)) {
|
|
523
|
+
hasCollapseInFocus = true;
|
|
524
|
+
break;
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
if (!hasCollapseInFocus && hasExpandingRanges(transform.comments)) {
|
|
528
|
+
const expandingRanges = findExpandingRanges(transform.comments);
|
|
529
|
+
// Map each expanding range's first patched line to the
|
|
530
|
+
// source line it follows. We re-walk source/patched in
|
|
531
|
+
// lockstep up to that point (cheap relative to the diff
|
|
532
|
+
// itself).
|
|
533
|
+
for (const [startLine] of expandingRanges) {
|
|
534
|
+
let srcAnchor = 0;
|
|
535
|
+
let sIdx = 0;
|
|
536
|
+
for (let pIdx = 0; pIdx < startLine - 1; pIdx += 1) {
|
|
537
|
+
if (collapsedPatchedLines.has(pIdx + 1)) {
|
|
538
|
+
continue;
|
|
539
|
+
}
|
|
540
|
+
if (sIdx >= originalLines.length) {
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
543
|
+
sIdx += 1;
|
|
544
|
+
srcAnchor = sIdx;
|
|
545
|
+
}
|
|
546
|
+
// `srcAnchor === 0` means the insertion is at the very top
|
|
547
|
+
// of the file (before any source line). Treat that as
|
|
548
|
+
// "in focus" iff the first source line is visible.
|
|
549
|
+
const anchorLine = srcAnchor === 0 ? 1 : srcAnchor;
|
|
550
|
+
if (visibleSourceLines.has(anchorLine)) {
|
|
551
|
+
hasCollapseInFocus = true;
|
|
552
|
+
break;
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
return {
|
|
557
|
+
[key]: {
|
|
558
|
+
...transform,
|
|
559
|
+
delta,
|
|
560
|
+
hasCollapse,
|
|
561
|
+
hasCollapseInFocus
|
|
562
|
+
}
|
|
563
|
+
};
|
|
564
|
+
}));
|
|
565
|
+
return Object.assign({}, ...transformed);
|
|
566
|
+
} finally {
|
|
567
|
+
renumberLinesInPlace(parsedSource);
|
|
568
|
+
}
|
|
25
569
|
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import type { HastRoot, Transforms } from "../../CodeHighlighter/types.mjs";
|
|
2
|
+
/**
|
|
3
|
+
* Recursively walks a jsondiffpatch delta looking for any inserted hast
|
|
4
|
+
* element with `className === 'collapse'`. Used to mark a manifest entry
|
|
5
|
+
* as layout-affecting (phase 1, coordinated barrier so peers stay in
|
|
6
|
+
* lockstep) so the runtime doesn't have to decompress the embedded hast
|
|
7
|
+
* payload on every selection change to classify the swap.
|
|
8
|
+
*
|
|
9
|
+
* Walks every nested value rather than interpreting jsondiffpatch's
|
|
10
|
+
* opcodes (`[value]` for insert, `[oldValue, 0, 0]` for delete, `_t: 'a'`
|
|
11
|
+
* + `_N` keys for array ops). The collapse placeholder is only ever
|
|
12
|
+
* produced by `compactCollapseInTreeInPlace` on the *transform* side of
|
|
13
|
+
* the diff, so any hast element with className 'collapse' anywhere in
|
|
14
|
+
* the delta tree is necessarily part of an insertion or in-place rewrite.
|
|
15
|
+
*/
|
|
16
|
+
export declare function deltaContainsCollapse(delta: unknown): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Splits a `Transforms` map (as produced by `diffHast`, which always
|
|
19
|
+
* carries deltas for entries that change the source — rename-only
|
|
20
|
+
* entries pass through with no delta) into the variant-level `manifest`
|
|
21
|
+
* (no `delta`) and the `embedded` map that should ride inside
|
|
22
|
+
* `source.data.transforms`.
|
|
23
|
+
*
|
|
24
|
+
* Entries with a meaningful delta land in both the manifest (with
|
|
25
|
+
* `hasDelta: true`) and the embedded map. Rename-only entries (no
|
|
26
|
+
* delta but a renamed `fileName`) land only in the manifest with
|
|
27
|
+
* `hasDelta` omitted or `false`; consumers use this flag to hide the
|
|
28
|
+
* transform toggle while still applying the rename when the user has
|
|
29
|
+
* the matching transform preference selected. Entries with neither a
|
|
30
|
+
* delta nor a rename are dropped from both.
|
|
31
|
+
*
|
|
32
|
+
* Returns `undefined` when no entry survived — callers should treat that
|
|
33
|
+
* as "no transforms to record".
|
|
34
|
+
*
|
|
35
|
+
* This is the single source of truth for the manifest / embedded split;
|
|
36
|
+
* both `computeHastDeltas` (per-file diffs) and the variant-level embed
|
|
37
|
+
* step in `loadIsomorphicCodeVariant` go through it so the wire shape
|
|
38
|
+
* stays consistent.
|
|
39
|
+
*/
|
|
40
|
+
export declare function splitTransformsForEmbed(transforms: Transforms): {
|
|
41
|
+
manifest: Transforms;
|
|
42
|
+
embedded: Transforms;
|
|
43
|
+
} | undefined;
|
|
44
|
+
/**
|
|
45
|
+
* Embeds `embedded` transforms inside `root.data.transforms` so they ride
|
|
46
|
+
* along inside the (possibly later compressed) hast payload and stay out
|
|
47
|
+
* of the variant-level wire shape that ends up in HTML / module graph.
|
|
48
|
+
*/
|
|
49
|
+
export declare function embedTransformsInRoot(root: HastRoot, embedded: Transforms): void;
|